CMake и Flex/Bison

Я преобразовываю свою систему сборки из configure/make в систему cmake

В системе есть несколько автогенерированных файлов, от bison/flex. Исходными командами makefile являются:

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

Я столкнулся с этой древней ссылкой, которая, как представляется, объясняет, как это сделать, но когда я запускаю cmake со следующими пользовательскими командами, ничего не происходит (нет ошибок сообщений, генерации файлов)

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)

Я новичок в cmake, так что это немного запутывает меня. Кто-нибудь знает, какая рабочая команда custom_ будет?

Ответ 1

Формат вашего add_custom_command не совсем прав, но они кажутся почти правильными. Существуют две версии add_custom_command, и тот, который вы хотите, это тот, который создает выходной файл (части внутри квадратных скобок необязательны):

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])

Идея состоит в том, что пользовательская команда выполняется только в том случае, если файл, указанный как OUTPUT этой команды, используется как вход в другом месте в том же CMakeLists.txt(например, в вызове add_library или add_executable).

Таким образом, пользовательская команда будет работать только во время сборки (т.е. при запуске make), а не во время настройки (когда вы запускаете CMake), и только если вы создаете цель, которая прямо или косвенно нуждается в OUTPUT.

Чтобы исправить ваши команды, я думаю, что следующее должно работать (непроверено):

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})

Ответ 2

Новая жара для использования бизонов на самом деле задокументирована на cmake.org Итак, для простого проекта парсера:

bison_target(parser fl.ypp fl.tab.cpp)
add_executable(fl ${BISON_parser_OUTPUTS})

- это то, что вы сделали бы. Аналогично для Flex.