如何在构建前通过Makefile将git版本写入.h头文件?
Makefile注入Git版本号的实现方案
原写法失效原因
- Makefile 中目标下缩进的每一行命令(recipe)默认运行在独立的shell进程中,你在
build目标内对CFLAGS的赋值是临时shell变量,仅在当前行生效,进入target目标的编译流程时赋值已经丢失 - 要在Makefile中捕获shell命令的输出结果,需要使用Make内置的
$(shell 命令)函数,不能直接写命令内容
最优无外部脚本实现
方案1:解析Makefile时一次性获取版本
适合全量构建场景,版本号只在Makefile加载时计算一次:
# 捕获Git版本号 GIT_FULL_VERSION := $(shell dotnet-gitversion /showvariable FullSemVer) # 注入编译宏,注意添加转义双引号保证版本号被识别为字符串 CFLAGS += -DBUILD=\"$(GIT_FULL_VERSION)\" target: object.o cc $(CFLAGS) $^ -o $@
方案2:每次构建都刷新版本号
需要每次执行构建命令都拉取最新的版本号时,使用目标专属变量实现:
# 只有构建target目标时才执行版本获取逻辑,每次构建都会重新计算 target: GIT_FULL_VERSION := $(shell dotnet-gitversion /showvariable FullSemVer) target: CFLAGS += -DBUILD=\"$(GIT_FULL_VERSION)\" target: object.o cc $(CFLAGS) $^ -o $@
方案3:仅Git记录变更时更新版本(性能最优)
避免每次构建都执行dotnet-gitversion,只有Git相关文件变化时才更新版本:
# 监听Git核心文件的变更 .version: $(wildcard .git/HEAD .git/index .git/refs/heads/*) dotnet-gitversion /showvariable FullSemVer > $@ # 从版本缓存文件读取版本号 GIT_FULL_VERSION := $(shell cat .version) CFLAGS += -DBUILD=\"$(GIT_FULL_VERSION)\" # 版本文件作为编译依赖 target: object.o .version cc $(CFLAGS) $< -o $@
注意:宏定义处的转义双引号是必须的,否则版本号中的.、+等特殊字符会触发C语法错误
其他可行思路
你提到的外部脚本更新版本文件的思路可以完全整合到Makefile中,不需要额外维护.sh脚本,本质就是上述方案3的实现逻辑,完全可以在Makefile范围内完成所有操作,不需要外部依赖。
内容的提问来源于stack exchange,提问作者Bart Friederichs
相关产品推荐
相关产品推荐

