我将我的版本字符串生成转移到它自己的 CMake 脚本中,我在 add_custom_command()/add_custom_target() 中使用 ${CMAKE_COMMAND} -P ... 调用它,并使我的目标使用它依赖于它。
在您的情况下,假设您有一个这样的 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?