问题
I am writing a small parser, but have problems of using cmake.
My purpose is: flex F.l => F.cc, bison B.y => B.cc, my_program.cc + F.cc + B.cc => library
My first attempt:
FIND_PACKAGE(FLEX REQUIRED)
if (FLEX_FOUND)
ADD_CUSTOM_TARGET(
flex_target
COMMAND ${FLEX_EXECUTABLE}
--header-file=${CMAKE_CURRENT_SOURCE_DIR}/F.h
--outfile=${CMAKE_CURRENT_SOURCE_DIR}/F.cc
${CMAKE_CURRENT_SOURCE_DIR}/F.l
COMMENT "Generating F.cc"
)
endif(FLEX_FOUND)
FIND_PACKAGE(BISON REQUIRED)
if (BISON_FOUND)
ADD_CUSTOM_TARGET(
bison_target
COMMAND ${BISON_EXECUTABLE}
--defines=${CMAKE_CURRENT_SOURCE_DIR}/B.h
--output=${CMAKE_CURRENT_SOURCE_DIR}/B.cc
${CMAKE_CURRENT_SOURCE_DIR}/B.y
COMMENT "Generating B.cc"
)
endif(BISON_FOUND)
add_library(my_library my_program.cc F.cc B.cc)
add_dependencies(my_library bison_target)
add_dependencies(my_library flex_target)
Everything is OK except that flex & bison commands are called every time when I run make, even F.l and B.y files are NOT changed.
Then I try to switch to use ADD_CUSTOM_COMMAND instead of ADD_CUSTOM_TARGET.
FIND_PACKAGE(FLEX REQUIRED)
if (FLEX_FOUND)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/F.cc
SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/F.l
COMMAND ${FLEX_EXECUTABLE}
--header-file=${CMAKE_CURRENT_SOURCE_DIR}/F.h
--outfile=${CMAKE_CURRENT_SOURCE_DIR}/F.cc
${CMAKE_CURRENT_SOURCE_DIR}/F.l
COMMENT "Generating F.cc"
)
endif(FLEX_FOUND)
FIND_PACKAGE(BISON REQUIRED)
if (BISON_FOUND)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/B.cc
SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/B.y
COMMAND ${BISON_EXECUTABLE}
--defines=${CMAKE_CURRENT_SOURCE_DIR}/B.h
--output=${CMAKE_CURRENT_SOURCE_DIR}/B.cc
${CMAKE_CURRENT_SOURCE_DIR}/B.y
COMMENT "Generating B.cc"
)
endif(BISON_FOUND)
add_library(my_library my_program.cc F.cc B.cc)
Note that it seems that I can't add dependencies for ADD_CUSTOM_COMMAND.
Then when I run make it seems that flex & bison will only run ONCE. It won't run second time even .l and .y files are changed.
Is there a way to achieve my goal?
Thanks.
回答1:
CMake has module for both Flex and Bison, so you could do this:
find_package(FLEX REQUIRED)
find_package(BISON REQUIRED)
flex_target(lexer F.l "${CMAKE_CURRENT_BINARY_DIR}/F.cc")
bison_target(parser B.y "${CMAKE_CURRENT_BINARY_DIR}/B.cc")
add_library(my_library STATIC
${sources}
"${CMAKE_CURRENT_BINARY_DIR}/F.cc"
"${CMAKE_CURRENT_BINARY_DIR}/B.cc"
)
Note that both flex_target
and bison_target
use add_custom_command
internally.
Edit: For completeness, as @vre points out in comments, there's FindFLEX
provides add_flex_bison_dependency
command:
add_flex_bison_dependency(lexer parser)
Which makes lexer
depend on parser
, in order to allow former use tokens from later.
回答2:
- Yes, you need to use
add_custom_command
. - Do not output into source dir, use inary dir for that.
- List input file in the
DEPENDS
section to make CMake track changes and re-run the command whenever it changes.
See the add_custom_command documentation for more info.
来源:https://stackoverflow.com/questions/50827935/how-to-write-a-working-cmake-file-for-flex-bison