You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让CMake在构建前更新version.h并触发main.cpp每次编译?

问题描述

我有一个存储版本信息的头文件version.h,希望每次构建前CMake都能确保该文件的版本信息是最新的。作为测试,我设置CMake在每次构建前执行touch操作更新该文件,本应触发所有包含它的源文件(如main.cpp)每次都重新编译,但实际main.cpp仅隔次编译。

推测原因是CMake在更新version.h之前就已判断是否需要编译main.cpp:

  1. 若version.h比main.obj新则标记main.cpp需要编译;
  2. 执行touch更新version.h;
  3. 编译标记的文件。

导致编译后main.obj比version.h新时,下次构建不会编译main.cpp,反之则会。我使用的是Visual Studio 2022和Ninja,请问如何修改配置以实现每次构建都更新version.h并让main.cpp重新编译?

解决方案

核心思路是让CMake优先完成version.h的更新,再检查源文件的编译依赖,以下是两种可靠的实现方式:

方法一:自定义目标强制前置更新

  1. 创建一个始终执行的自定义目标,用于更新version.h(示例用touch,实际可替换为生成版本信息的脚本):
add_custom_target(UpdateVersionHeader ALL
    COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_SOURCE_DIR}/version.h
    COMMENT "Updating version.h timestamp"
)
  1. 将你的可执行目标与该自定义目标绑定依赖,确保构建前先更新头文件:
add_executable(MyApp main.cpp)
add_dependencies(MyApp UpdateVersionHeader)
  1. 标记version.h为生成文件,让CMake明确它是动态更新的产物:
set_source_files_properties(${CMAKE_SOURCE_DIR}/version.h PROPERTIES GENERATED TRUE)

Ninja会严格按照依赖顺序执行:先运行UpdateVersionHeader更新version.h,再检查main.cpp的依赖状态,此时version.h时间戳已晚于main.obj,必然触发重新编译。

方法二:显式标记源文件依赖

如果方法一仍有问题,可以给main.cpp添加强制依赖属性,明确其目标文件必须跟随version.h更新:

set_source_files_properties(main.cpp PROPERTIES OBJECT_DEPENDS ${CMAKE_SOURCE_DIR}/version.h)

结合方法一的自定义更新目标,可确保每次version.h变化时,main.cpp都会被重新编译。

注意事项

  • 路径要使用CMAKE_SOURCE_DIR或CMAKE_CURRENT_SOURCE_DIR,避免相对路径导致的依赖判断错误;
  • 实际场景中,可将touch替换为生成真实版本信息的脚本(比如从Git commit、编译时间生成内容),逻辑完全通用;
  • Visual Studio 2022 + Ninja组合对上述CMake配置支持良好,无需额外调整IDE设置。

内容的提问来源于stack exchange,提问作者Magnar Myrtveit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 00:32:30