【问题标题】:Force CMake to generate configure_file target every build强制 CMake 在每次构建时生成 configure_file 目标
【发布时间】:2015-06-25 17:44:35
【问题描述】:

我的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__;

【问题讨论】:

标签: c++ cmake


【解决方案1】:

我将我的版本字符串生成转移到它自己的 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.hVersion.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 stringsHow can I pass git SHA1 to compiler as definition using cmake?

【讨论】:

  • 感谢您更新的答案,彻底解决了我的问题!我刚刚在我的Version.h.in 中用@_date@ 替换了__DATE__
  • @uranix 很高兴听到它有帮助。为了完整起见,我添加了一些关于 Ninja 的 cmets 以及如何强制编译某些东西作为预链接器步骤。
【解决方案2】:

只需提交一个对我来说似乎更简单的替代答案,并且如果您在任何 *nix 操作系统下都可以解决问题:

touch Version.h.in 作为预构建命令运行,或者在您的 IDE 中实现,在您的 shell 中运行您的 cmake 命令之前手动执行,或者在您的 CI(它可能没用)中,允许系统地生成版本。 h 文件,即使它没有被修改。

【讨论】:

  • 如果你使用cmake -E touch &lt;file&gt;,你至少会得到一个与操作系统无关的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 2020-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多