为何CMake add_custom_command()中执行git rev-parse命令失败?
CMake中add_custom_command读取Git提交哈希失败的原因与解决方法
问题差异解析
你遇到的核心问题是错误使用了add_custom_command不支持的OUTPUT_VARIABLE参数——这个参数是execute_process的专属选项,add_custom_command根本不识别它,因此会把OUTPUT_VARIABLE GIT_COMMIT_HASH当成git rev-parse HEAD命令的额外参数传递给Git,导致Git将GIT_COMMIT_HASH视为文件路径,进而报错“该路径不存在”。
而第一个命令看似正常运行,只是巧合:git tag --points-at HEAD GIT_TAG这个语法本身合法(Git会把GIT_TAG当作要校验的标签名,若仓库中不存在该标签,Git仅返回空结果但不抛出错误),但实际上也没有将标签结果存入GIT_TAG变量,你只是误以为它成功了。
解决方法
根据需求场景,有两种正确的实现方式:
1. 配置阶段获取Git信息(常用)
如果只需要在CMake配置时获取一次Git哈希和标签,直接用execute_process即可,它支持OUTPUT_VARIABLE参数捕获命令输出:
# 获取提交哈希 execute_process( COMMAND git rev-parse HEAD WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE # 去除末尾换行符 ) # 获取指向HEAD的标签 execute_process( COMMAND git tag --points-at HEAD WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_TAG OUTPUT_STRIP_TRAILING_WHITESPACE ) # 可选:打印验证 message(STATUS "当前Git提交哈希: ${GIT_COMMIT_HASH}") message(STATUS "指向HEAD的Git标签: ${GIT_TAG}")
2. 构建阶段实时获取Git信息
如果需要每次构建时都获取最新的Git提交(比如配置后代码有新提交),可以通过add_custom_target生成临时文件,再读取文件内容:
# 构建时执行Git命令,将哈希写入临时文件 add_custom_target(update_git_hash ALL COMMAND ${CMAKE_COMMAND} -E echo "$(git rev-parse HEAD)" > ${CMAKE_BINARY_DIR}/git_hash.txt WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMENT "获取最新Git提交哈希" ) # 读取文件内容到变量(若要让代码编译时能使用,建议结合configure_file生成头文件) file(READ ${CMAKE_BINARY_DIR}/git_hash.txt GIT_COMMIT_HASH) string(STRIP ${GIT_COMMIT_HASH} GIT_COMMIT_HASH) # 示例:生成头文件供代码调用 configure_file( ${CMAKE_SOURCE_DIR}/version.h.in ${CMAKE_BINARY_DIR}/version.h @ONLY )
对应的version.h.in内容:
#define GIT_COMMIT_HASH "@GIT_COMMIT_HASH@"
内容的提问来源于stack exchange,提问作者naumio
相关产品推荐
相关产品推荐

