我的 CMakeLists.txt
文件中有以下命令
configure_file([...]/Version.h.in [...]/Version.h @ONLY)
如何让它在每次构建时都运行,而不仅仅是在 Version.h.in
更改时运行?我需要它,因为 Version.h
中有 __DATE__
宏,实际上每个构建都应该被视为新的,即使它保持不变也是如此。
Version.h.in
看起来像
static const char VERSION[] = "Bla-bla-bla " @FOOBAR@ " built on " __DATE__;
最佳答案
我将我的版本字符串生成转移到它自己的 CMake 脚本中,我在 add_custom_command()
/ 中使用
并使我使用它的目标依赖于它。${CMAKE_COMMAND} -P ...
调用该脚本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")
你可以这样做:
add_custom_command(
TARGET MyExe
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -DVERSION_FILE_NAME=Version.h -DFOOBAR="${FOOBAR}" -P "${CMAKE_CURRENT_LIST_DIR}/DateToVersionH.cmake"
)
另见 use CMake to get build-time svn revision
如果您的 make 环境在调用必要步骤之前检查所有“需要重建”(例如,在 Ninja 中,仅重新扫描自定义命令的输出;有关更多详细信息,请参阅 Ninja documentation restat
规则变量和 this discussion 导致在 add_custom_command() 中引入 BYPRODUCTS
选项。
因此您可以简单地添加到您的构建 shell 脚本中 - 在调用实际 make 之前 - 删除包含版本信息的目标文件。
或者您在链接之前强制重新编译对象。这将 - 假设你有一个包含 Version.h
的 Version.c
- 看起来像这样:
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"
)
考虑一下,删除目标文件并使用您当前的__DATE__
解决方案是最简单的解决方案。
另一种“git 版本解决方案”参见CMake: Automatically use git tags as version strings和 How can I pass git SHA1 to compiler as definition using cmake?
关于c++ - 强制 CMake 在每次构建时生成 configure_file 目标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31057208/