Подтвердить что ты не робот

Как сделать цель 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 каким-то образом генерирует парсер только для устаревшей грамматики.

4b9b3361

Ответ 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}.