Как заставить цель CMake исполниться, если указанный файл был изменен? - PullRequest
15 голосов
/ 23 октября 2011

Я пытаюсь использовать ANTLR в своем проекте C ++. Я поставил цель запустить генератор ANTLR для указанной грамматики и сделал основной объект зависимым от нее.

ADD_CUSTOM_TARGET(GenerateParser
    COMMAND ${ANTLR_COMMAND} ${PROJECT_SOURCE_DIR}/src/MyGrammar.g 
                             -o ${PROJECT_SOURCE_DIR}/src/MyGrammar
)

ADD_LIBRARY(MainProject ${LIBRARY_TYPE} ${TARGET_SOURCES} ${TARGET_OPTIONS})
ADD_DEPENDENCIES(MainProject GenerateParser)

Проблема в том, что генератор ANTLR работает каждый раз, когда я собираю проект, и потребляет достаточно времени. Как я могу заставить его работать, только если моя грамматика была изменена? Или, может быть, можно заставить ANTLR каким-то образом генерировать парсер только для устаревшей грамматики.

Ответы [ 4 ]

12 голосов
/ 23 ноября 2011

add_custom_command выполнит , если вы правильно сконструируете вызов.

Примерно так должно работать:

ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_SOURCE_DIR}/src/MyGrammar
  COMMAND ${ANTLR_COMMAND} ${PROJECT_SOURCE_DIR}/src/MyGrammar.g
    -o ${PROJECT_SOURCE_DIR}/src/MyGrammar
  DEPENDS ${PROJECT_SOURCE_DIR}/src/MyGrammar.g
)

ADD_CUSTOM_TARGET(GenerateParser ALL
   DEPENDS ${PROJECT_SOURCE_DIR}/src/MyGrammar
)

ADD_LIBRARY(MainProject ${LIBRARY_TYPE} ${TARGET_SOURCES} ${TARGET_OPTIONS})
ADD_DEPENDENCIES(MainProject GenerateParser)

Здесь настраиваемая цель будет «собираться» каждый раз, но единственное, что она сделает, - это построит настраиваемую команду, от которой зависит ее вывод, но если и только если вывод настраиваемой команды устарел по отношению в его файл (ы) ЗАВИСИМОСТИ.

4 голосов
/ 03 января 2014

Помимо предлагаемого решения с пользовательской целью, если ваша цель зависит от некоторых сгенерированных источников, общий рабочий процесс выглядит следующим образом:

Добавьте цель, которая генерирует ваш исходный файл.Я рекомендую использовать полные пути, чтобы избежать ошибок.

add_custom_command(OUTPUT ${GENERATED_SOURCE_FILE}
    COMMAND ${GENERATION COMMAND}
    DEPENDS ${DEPENDENCIES}
)

Установите GENERATED свойства вашего сгенерированного исходного файла.Таким образом, cmake не будет жаловаться на отсутствующий исходный файл.

set_source_files_properties(${GENERATED_SOURCE_FILE} PROPERTIES
    GENERATED TRUE
)

Добавьте сгенерированный источник к вашей цели как обычно.

add_executable(${YOUR_TARGET} SOURCES ${GENERATED_SOURCE_FILE})

Так что в предложенном примере $ {GENERATION COMMAND} будет толькозапускаться при изменении некоторых файлов $ {DEPENDENCIES}.

3 голосов
/ 24 октября 2011

Будет ли add_custom_command добиваться цели? Здесь вы можете указать DEPENDS [зависимости ...], который будет выполнять команду только при изменении зависимого файла.

http://www.cmake.org/cmake/help/cmake2.6docs.html#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 ...]
                 [WORKING_DIRECTORY dir]
                 [COMMENT comment] [VERBATIM] [APPEND])
0 голосов
/ 15 апреля 2018

У меня был точно такой же вопрос. После прочтения того, как были сгенерированы make-файлы (поскольку документация cmake оставляет желать лучшего), похоже, что лучшим решением является использование add_custom_command формы OUTPUT. Вот мой пример

add_custom_command(OUTPUT
                   # In my cmake file I list every file generated
                   ${PROJECT_SOURCE_DIR}/src/MyGrammar/file1
                   ${PROJECT_SOURCE_DIR}/src/MyGrammar/file2
                   COMMAND ${ANTLR_COMMAND} ${PROJECT_SOURCE_DIR}/src/MyGrammar.g
                   -o {PROJECT_SOURCE_DIR}/src/MyGrammar

                   # In my case I used a script checked into source control, 
                   # so I want to know when it changes too
                   DEPENDS ${ANTLR_COMMAND} ${PROJECT_SOURCE_DIR}/src/MyGrammar.g)

# cmake caches are problematic, so list the files in a variable
set(generated_sources src/MyGrammar/file1 src/MyGrammar/file2)
add_library(yourlib ${list_of_source_files} ${generated_sources})

Затем при сборке cmake проверит файлы команд и грамматики на наличие изменений, прежде чем принять решение о повторной генерации источников.

...