Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake and Flex/Bison

I am converting my build system from configure/make to a cmake system

The system has some autogenerated files, from bison/flex. The original makefile commands are:

bison --defines=tokens.h --output=parser.cpp parser.y
flex --outfile=scanner.cpp scanner.l

I came across this ancient link which seems to explain how to do it, but when i run cmake with the following custom commands, nothing appears to happen (no error messages, no file generation)

FIND_PACKAGE(BISON REQUIRED)
IF(BISON_FOUND)
    ADD_CUSTOM_COMMAND(
      SOURCE ${CMAKE_SOURCE_DIR}/src/rcdgen/parser.y
      COMMAND ${BISON_EXECUTABLE}
      ARGS --defines=${CMAKE_SOURCE_DIR}/src/rcdgen/tokens.h
           -o ${CMAKE_SOURCE_DIR}/src/rcdgen/parser.cpp
           ${CMAKE_SOURCE_DIR}/src/rcdgen/parser.y
      COMMENT "Generating parser.cpp"
      OUTPUT ${CMAKE_SOURCE_DIR}/src/rcdgen/parser.cpp
    )
ENDIF(BISON_FOUND)

FIND_PACKAGE(FLEX REQUIRED)
IF(FLEX_FOUND)
    ADD_CUSTOM_COMMAND(
      SOURCE ${CMAKE_SOURCE_DIR}/src/rcdgen/scanner.l
      COMMAND ${FLEX_EXECUTABLE}
      ARGS -o${CMAKE_SOURCE_DIR}/src/rcdgen/parser.cpp
           ${CMAKE_SOURCE_DIR}/src/rcdgen/scanner.l
      COMMENT "Generating scanner.cpp"
      OUTPUT ${CMAKE_SOURCE_DIR}/src/rcdgen/scanner.cpp
    )
ENDIF(FLEX_FOUND)

I am new to cmake, so it's a bit confusing to me. Does anyone have any idea what a working custom_command would be?

like image 756
LordAro Avatar asked Oct 16 '13 08:10

LordAro


2 Answers

The new hotness for bison usage is actually documented in FindBison So for a simple parser project:

find_package(BISON)
BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp
             DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/parser.h)
add_executable(Foo main.cpp ${BISON_MyParser_OUTPUTS})

is what you'd do. Likewise for Flex.

like image 64
cardiff space man Avatar answered Nov 06 '22 11:11

cardiff space man


The format of your add_custom_commands is not quite right, but they appear to be almost correct. There are two versions of add_custom_command, and the one you want is the one which produces an output file (the parts inside square brackets are optional):

add_custom_command(OUTPUT output1 [output2 ...]
                   COMMAND command1 [ARGS] [args1...]
                   [COMMAND command2 [ARGS] [args2...] ...]
                   [MAIN_DEPENDENCY depend]
                   [DEPENDS [depends...]]
                   [IMPLICIT_DEPENDS <lang1> depend1
                                    [<lang2> depend2] ...]
                   [WORKING_DIRECTORY dir]
                   [COMMENT comment] [VERBATIM] [APPEND])

The idea is that the custom command only executes if the file specified as the OUTPUT of this command is used as an input elsewhere in the same CMakeLists.txt (e.g. in an add_library or add_executable call).

The custom command therefore will only run at build time (i.e. when you run make), not at configure time (when you run CMake), and only if you're building a target which directly or indirectly needs the OUTPUT file.

To fix your commands, I think the following should work (untested):

FIND_PACKAGE(BISON REQUIRED)
SET(BisonOutput ${CMAKE_SOURCE_DIR}/src/rcdgen/parser.cpp)
IF(BISON_FOUND)
    ADD_CUSTOM_COMMAND(
      OUTPUT ${BisonOutput}
      COMMAND ${BISON_EXECUTABLE}
              --defines=${CMAKE_SOURCE_DIR}/src/rcdgen/tokens.h
              --output=${BisonOutput}
              ${CMAKE_SOURCE_DIR}/src/rcdgen/parser.y
      COMMENT "Generating parser.cpp"
    )
ENDIF()

FIND_PACKAGE(FLEX REQUIRED)
SET(FlexOutput ${CMAKE_SOURCE_DIR}/src/rcdgen/scanner.cpp)
IF(FLEX_FOUND)
    ADD_CUSTOM_COMMAND(
      OUTPUT ${FlexOutput}
      COMMAND ${FLEX_EXECUTABLE}
              --outfile=${FlexOutput}
              ${CMAKE_SOURCE_DIR}/src/rcdgen/scanner.l
      COMMENT "Generating scanner.cpp"
    )
ENDIF()

ADD_LIBRARY(MyLib ${BisonOutput} ${FlexOutput})
like image 45
Fraser Avatar answered Nov 06 '22 10:11

Fraser