Как сделать цель CMake выполненной, был ли изменен указанный файл?
Я пытаюсь использовать ANTLR в моем проекте на С++. Я сделал цель для запуска 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 каким-то образом генерирует парсер только для устаревшей грамматики.
Ответы
Ответ 1
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)
Здесь пользовательская цель будет "строить" каждый раз, но единственное, что она сделает, это создать пользовательскую команду, на выходе которой она зависит, но тогда и только тогда, когда вывод пользовательской команды устарел с уважением к его файлам DEPENDS.
Ответ 2
Будет ли 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])
Ответ 3
Помимо предлагаемого решения с настраиваемой целью, если ваша цель зависит от некоторых сгенерированных источников, общий рабочий процесс следующий:
Добавить цель, которая генерирует исходный файл. Я рекомендую использовать полные пути, чтобы избежать ошибок.
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}.