强制CMake在每次构建时生成configure_file目标

ura*_*nix 6 c++ cmake

我的CMakeLists.txt文件中有以下命令

configure_file([...]/Version.h.in [...]/Version.h @ONLY)
Run Code Online (Sandbox Code Playgroud)

如何在每次构建时运行它,但不仅仅是在Version.h.in更改时?我需要它,因为它中Version.h__DATE__宏,实际上应该被视为每个构建的新内容,即使它保持不变.

Version.h.in模样

static const char VERSION[] = "Bla-bla-bla " @FOOBAR@ " built on " __DATE__;
Run Code Online (Sandbox Code Playgroud)

Flo*_*ian 5

我将版本字符串生成转移到自己的CMake脚本中,${CMAKE_COMMAND} -P ...add_custom_command()/中调用该脚本,add_custom_target()并使使用它的目标依赖于它。

就您而言,假设您有一个如下DateToVersionH.cmake脚本:

string(TIMESTAMP _date "%d %m %Y %H:%M")
file(WRITE ${VERSION_FILE_NAME} "#define MY_VERSION \"Bla-bla-bla ${FOOBAR} built on ${_date}\"\n")
Run Code Online (Sandbox Code Playgroud)

您可以执行以下操作:

add_custom_command(
    TARGET MyExe
    PRE_BUILD
    COMMAND ${CMAKE_COMMAND} -DVERSION_FILE_NAME=Version.h -DFOOBAR="${FOOBAR}" -P "${CMAKE_CURRENT_LIST_DIR}/DateToVersionH.cmake"
)
Run Code Online (Sandbox Code Playgroud)

另请参阅使用CMake获取构建时svn修订版

如果您的make环境在调用必要的步骤之前检查了所有“需要重建的内容”,这可能还不够(例如,在Ninja中,仅重新扫描自定义命令的输出;有关更多详细信息,请参见Ninja文档中的restat规则变量)而这种讨论导致引进的BYPRODUCTS选件add_custom_command() )。

因此,您可以在调用实际make之前简单地将其添加到构建shell脚本中,然后删除包含版本信息的目标文件。

或者,您在链接之前强制重新编译对象。假设您有一个Version.c包含以下内容的代码,则将Version.h如下所示:

include_directories(${CMAKE_CURRENT_BINARY_DIR})
execute_process(COMMAND "${CMAKE_COMMAND}" -DVERSION_FILE_NAME=Version.h -DFOOBAR="${FOOBAR}" -P "${CMAKE_CURRENT_LIST_DIR}/DateToVersionH.cmake")
add_library(MyVersionObj OBJECT Version.c)

add_executable(MyExe ... $<TARGET_OBJECTS:MyVersionObj>)

add_custom_command(
    TARGET MyExe
    PRE_LINK 
    COMMAND "${CMAKE_COMMAND}" -DVERSION_FILE_NAME=Version.h -DFOOBAR="${FOOBAR}" -P "${CMAKE_CURRENT_LIST_DIR}/DateToVersionH.cmake"
    COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --config $<CONFIG> --target "MyVersionObj"
)
Run Code Online (Sandbox Code Playgroud)

考虑一下,仅删除目标文件并利用当前__DATE__解决方案是最简单的解决方案。

有关另一个“ git版本解决方案”,请参阅CMake:自动将git标签用作版本字符串,以及如何使用cmake将git SHA1作为定义传递给编译器?