如果指定文件被更改,如何执行CMake目标?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果指定文件被更改,如何执行CMake目标?相关的知识,希望对你有一定的参考价值。

我正在尝试在我的C ++项目中使用ANTLR。我为指定的语法创建了运行ANTLR生成器的目标,并使主要的prjct依赖于它。

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以某种方式仅为过时语法生成解析器。

答案

如果正确构造对它的调用,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过期时文件(S)。

另一答案

add_custom_command会不会这样做?在这里,您可以指定DEPENDS [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])
另一答案

除了提出的自定义目标解决方案,如果您的目标依赖于某些生成的源,常见的工作流程如下:

添加生成源文件的目标。我建议使用完整路径以避免错误。

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

因此,在提议的示例中,只有在更改了一些$ {DEPENDENCIES}文件时才会启动$ {GENERATION COMMAND}。

另一答案

我有完全相同的问题。在阅读了如何生成makefile之后(因为cmake文档有很多不足之处),看起来最好的解决方案是使用OUTPUT表单的add_custom_command。这是我的例子

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时,将在决定重新生成源之前检查命令和语法文件的更改。

以上是关于如果指定文件被更改,如何执行CMake目标?的主要内容,如果未能解决你的问题,请参考以下文章

CMake基础教程(30)CMake构建系统概览

如果头文件被更改然后恢复,如何停止/欺骗cmake不重建?

当 CMake 中的生成器或输入发生更改时,如何仅构建自动生成的代码?

CMAKE使用手记

由于 cmake 项目中的源更改,查找所有受影响的目标

依赖项更改时重建 CMake 目标