CMake:每次构建时输出一些命令并重新配置依赖于此值的文件

时间:2016-02-09 19:43:55

标签: cmake

我想启动一些命令并将其输出存储到某个变量中。然后重新配置依赖于此变量的输入文件。

例如,我想通过运行hg id -i获得当前的mercurial修订版。可以在构建之间更改此命令的输出。因此,我必须每次都运行此命令并将输出存储到某个变量中。

因此,因为我必须在每次构建时运行此命令,所以execute_process不适合我。但是add_custom_command也不合适,因为它无法将命令的输出保存到变量中。

假设我可以(以某种方式)获得hg id -i的输出并将其存储到REVISION变量中。然后我想用版本:

重新生成配置文件
configure_file(version.cpp.in version.cpp)

version.cpp.in

的内容
volatile const char* revision = "Revision: ${REVISION}";

作为一种解决方法,我可以定义REVISION,但我希望在源文件中包含修订号。

P.S。这里的Mercurial和版本号只是一个例子。所以,请不要建议Mercurial的keyword扩展等等。

2 个答案:

答案 0 :(得分:2)

您可以在cmake命令中以脚本模式调用add_custom_target

<强> configure_version.cmake

execute_process(COMMAND hg id -i
    OUTPUT_VARIABLE REVISION)
configure_file(${input_file} ${output_file})

<强>的CMakeLists.txt

add_custom_target(version_target
    COMMAND ${CMAKE_COMMAND}
        -Dinput_file=${CMAKE_CURRENT_SOURCE_DIR}/version.cpp.in
        -Doutput_file=${CMAKE_CURRENT_BINARY_DIR}/version.cpp
        -P ${CMAKE_CURRENT_SOURCE_DIR}/configure_version.cmake
    )

脚本不会在add_custom_command内调用,因为每次构建都需要调用它。因此,您应该在add_dependencies文件的使用者和脚本的目标之间添加目标级依赖version.cpp){{{ 1}})。

需要在脚本中传递version_target的输入和输出文件路径,因为脚本不知道configure_file个变量。或者,您可以自行配置脚本文件。

答案 1 :(得分:0)

最后我使用以下解决方案:

CMakeLists.txt

...
# Versioning
# Try to find hg executable, retrive revision if found and generate version.cpp from template
set(VERSIONING_FILES src/versioning.cmake src/version.cpp.in)
find_program(HG hg DOC "Mercurial executable file")
# invalidate template
add_custom_target(versioning ALL COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_SOURCE_DIR}/src/version.cpp.in
    SOURCES ${VERSIONING_FILES})
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/src/version.cpp
    COMMAND ${CMAKE_COMMAND} -DVERSION_INPUT=${CMAKE_SOURCE_DIR}/src/version.cpp.in -DVERSION_OUTPUT=${CMAKE_SOURCE_DIR}/src/version.cpp -DHG=${HG} -P ${CMAKE_SOURCE_DIR}/src/versioning.cmake
    DEPENDS ${CMAKE_SOURCE_DIR}/src/version.cpp.in)
...

<强>的src / versioning.cmake

if (HG)
    execute_process(COMMAND ${HG} id OUTPUT_VARIABLE REVISION OUTPUT_STRIP_TRAILING_WHITESPACE)
else ()
    set(REVISION "<undefined>")
endif ()
configure_file(${VERSION_INPUT} ${VERSION_OUTPUT})
execute_process(COMMAND ${CMAKE_COMMAND} -E touch ${VERSION_OUTPUT})    # invalidate output to force rebuild this source file even if it was not changed.

# vim: set ts=4 sw=4 ai tw=0 et syntax=cmake :

src / version.cpp.in 的内容:

volatile const char* REVISION = "$ Build revision: ${REVISION} $";
volatile const char* ROOT_DIRECTORY = "$ Build directory: ${CMAKE_BINARY_DIR} $";
volatile const char* BUILD_DATE = "$ Build date: " __DATE__ " " __TIME__ " $";