Understanding CMake Policy CMP0088 for Bison Parser Generation
What is CMP0088?
CMP0088 is a CMake policy that controls where the Bison parser generator is run and where it generates implicit files during the build process. It was introduced in CMake version 3.14 to address a change in how Bison is executed.
Understanding the Policy
CMake 3.14 and Later (Preferred Behavior)
- To ensure build tree separation and avoid modifying the source tree, Bison is now preferred to run in the current build directory (
CMAKE_CURRENT_BINARY_DIR
). - The
WORKING_DIRECTORY
argument of theadd_custom_command
invocation is set toCMAKE_CURRENT_BINARY_DIR
. - Implicit files are generated in the build directory, keeping the source tree clean.
- To ensure build tree separation and avoid modifying the source tree, Bison is now preferred to run in the current build directory (
- The
BISON_TARGET
macro would run Bison in the current source directory (CMAKE_CURRENT_SOURCE_DIR
). - Implicit files generated by Bison (like header files) would also be placed in the source directory.
- The
Compatibility for Older Projects
- The CMP0088 policy provides compatibility for projects that haven't been updated to expect the new behavior.
- OLD Behavior (Deprecated)
Uses the current source directory for both running Bison and generating implicit files. This is the default behavior if the policy is not explicitly set. - NEW Behavior (Recommended)
Uses the current build directory for both running Bison and generating implicit files.
- OLD Behavior (Deprecated)
How to Set the Policy
Use the cmake_policy
command in your CMakeLists.txt file to explicitly set the policy:
cmake_policy(CMP0088 NEW) # Use the new behavior (recommended)
# OR
cmake_policy(CMP0088 OLD) # Use the old behavior (for compatibility)
Important Note
- While CMake 3.24.2 doesn't warn when the policy is not set, it defaults to the OLD behavior. This behavior is deprecated and might be removed in future CMake versions. It's strongly recommended to set the policy explicitly (ideally to NEW) to avoid potential issues and ensure consistent builds across different CMake versions.
Scenario 1: Using the New Behavior (Recommended)
# CMakeLists.txt
cmake_minimum_required(VERSION 3.14) # Requires CMake 3.14 or later
# No need to set CMP0088 explicitly as NEW is the default for CMake 3.14+
find_package(BISON REQUIRED) # Find and require Bison
bison_target(my_parser parser.y parser.c)
add_executable(my_program main.cpp parser.c)
target_link_libraries(my_program Bison::Bison)
In this example:
- The
bison.y
file is processed in the build directory, and the generatedparser.c
file is placed there as well. BISON_TARGET
is used without setting CMP0088, as NEW is the default behavior for CMake 3.14 and later.- CMake version 3.14 or later is required.
Scenario 2: Using the Old Behavior (For Compatibility)
# CMakeLists.txt
cmake_minimum_required(VERSION 3.0) # Requires CMake 3.0 or later
# Explicitly set CMP0088 to OLD for compatibility with older projects
cmake_policy(CMP0088 OLD)
find_package(BISON REQUIRED) # Find and require Bison
bison_target(my_parser parser.y parser.c)
add_executable(my_program main.cpp parser.c)
target_link_libraries(my_program Bison::Bison)
Here:
- The
bison.y
file and generatedparser.c
will be placed in the source directory. - The policy is explicitly set to OLD to match the behavior of older CMake versions.
- While a lower CMake version is allowed, it's generally recommended to upgrade to benefit from newer features.
- Consider migrating your project to use the NEW behavior for better build tree organization and reduced risk of modifying source code unintentionally.
- If you're unsure about your project's compatibility, start with the NEW behavior and test thoroughly.
Custom Commands with Explicit Working Directory
If you're using a version of CMake older than 3.14 or have specific reasons to avoid the BISON_TARGET
macro, you can use a custom command to run Bison:
find_package(BISON REQUIRED)
message(STATUS "Running Bison in ${CMAKE_CURRENT_SOURCE_DIR}") # Informative message
add_custom_command(
OUTPUT parser.c # Output file
COMMAND ${BISON_EXECUTABLE} -d -o parser.c parser.y
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} # Set working directory
COMMENT "Generating parser.c"
)
add_executable(my_program main.cpp parser.c)
target_link_libraries(my_program Bison::Bison)
- Be aware that manually managing the working directory requires more code compared to
BISON_TARGET
. - This approach lets you control the exact command arguments passed to Bison and the working directory.
CMake Generator Expressions (CMake 3.13 or newer)
If your project uses CMake 3.13 or later, you can leverage generator expressions with BISON_TARGET
to influence the behavior:
find_package(BISON REQUIRED)
set(OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") # Set output directory
bison_target(my_parser
parser.y
${OUTPUT_DIR}/parser.c # Use generator expression for output path
)
add_executable(my_program main.cpp ${OUTPUT_DIR}/parser.c)
target_link_libraries(my_program Bison::Bison)
- It keeps the code cleaner compared to custom commands, but requires a slightly newer CMake version.
- This approach allows you to specify the output directory for the generated file within the
BISON_TARGET
invocation.
- For more granular control over output locations (CMake 3.13+), generator expressions with
BISON_TARGET
are an option. - If compatibility with older CMake versions is critical, consider the custom command approach.
- Use
CMP0088
with the NEW behavior whenever possible for recommended build practice.