configure_file在cmake配置阶段将version.h.in转换为version.h:扫描@var@占位符,用同名cmake变量值替换,生成文件至构建目录,并需通过target_include_directories将其加入头文件搜索路径。

configure_file 是怎么把 version.h.in 变成 version.h 的
它不是编译时运行,而是在 cmake 配置阶段(即你执行 cmake .. 时)就完成变量替换。CMake 会扫描模板文件中所有 @VAR@ 形式的占位符,用当前作用域中同名 CMake 变量的值去替换——注意,只认 @ 包裹的写法,${VAR} 在 configure_file 中默认不生效(除非加 @ONLY 参数且变量已定义)。
常见错误现象:
- 生成的
version.h里还留着@VERSION@——说明VERSION变量没在configure_file前定义,或拼写不一致 - 头文件被生成到源码目录而非构建目录——导致 Git 脏、多构建目录冲突;正确路径应是
${CMAKE_CURRENT_BINARY_DIR}/version.h - 修改了
version.h.in但重新cmake后没更新——因为 CMake 认为输入没变,需手动删CMakeCache.txt或用cmake -P强制重跑
如何让 VERSION 变量支持命令行传入(比如 cmake -DVERSION=2.1.0 ..)
直接用 set(VERSION "1.0.0" CACHE STRING "Project version"),这样用户就能通过 -DVERSION=... 覆盖默认值。配合 configure_file 就能动态生效。
使用场景:
- CI/CD 流水线中用 Git tag 自动设版本:
cmake -DVERSION=$(git describe --tags) .. - 本地调试时快速切版本:
cmake -DVERSION=dev-$(date +%s) .. - 区分 release/debug 构建:
if(CMAKE_BUILD_TYPE STREQUAL "Debug") set(VERSION "${VERSION}-debug")
注意:如果没加 CACHE,-D 传参会被忽略;如果加了但没给默认值,首次运行会报错提示缺失。
为什么 version.h 必须用 target_include_directories 加入头搜索路径
configure_file 生成的 version.h 默认在构建目录(如 build/),而源码里 #include "version.h" 默认只搜源码目录和显式指定的路径。不加 target_include_directories,编译器根本找不到它。
CMake 4.3.2 Windows x86_64 历史版本安装包,适合旧项目兼容、构建环境回退、CMakeLists.txt 迁移验证、Visual Studio/Ninja/Makefile 生成器测试和 C/C++ 项目维护。
关键参数差异:
-
PRIVATE:仅该 target 内部可用,不影响依赖它的其他 target -
PUBLIC:该 target 和所有链接它的 target 都能用——适合库项目暴露版本接口 - 路径必须用
${CMAKE_CURRENT_BINARY_DIR},不能写死./build/version.h,否则跨平台或 out-of-source 构建失败
Git 提交哈希和编译时间怎么塞进 version.h
用 execute_process 调 git 命令获取哈希,用 string(TIMESTAMP) 获取时间,再统一注入变量:
string(TIMESTAMP BUILD_TIME "%Y-%m-%d %H:%M:%S")
execute_process(COMMAND git rev-parse --short HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(GIT_COMMIT "${GIT_COMMIT}")
configure_file(version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
模板 version.h.in 中写:
#define BUILD_TIME "@BUILD_TIME@" #define GIT_COMMIT "@GIT_COMMIT@"
容易踩的坑:
- 没装 Git 或不在 Git 仓库里运行
cmake→execute_process失败,GIT_COMMIT为空;建议加RESULT_VARIABLE判断并 fallback - Windows 上
git命令可能不在 PATH,需用find_program(GIT git)先定位 - 时间戳用
UTC参数避免时区混乱:string(TIMESTAMP BUILD_TIME "%Y-%m-%d %H:%M:%S" UTC)
最常被忽略的是:version.h 一旦生成,后续 make 或 ninja 不会自动重生成——哪怕你改了 Git 分支或系统时间。真要每次编译都刷新,得用自定义命令 + add_custom_target 驱动,而不是依赖 configure_file。










