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

如何基于git describe输出触发Make目标的条件重建?

解决方法

核心思路是引入强制执行的空依赖,同时保留仅当内容变化时才更新version.c的逻辑,既保证Git版本变化时能触发更新,又避免无意义的重复构建。

具体修改步骤

  1. 删除原Makefile中的.PHONY: version.c声明,新增一个FORCE伪目标
  2. 将FORCE设为version.c的依赖项,保证每次构建都会执行version.c的生成逻辑
  3. 原有cmp对比逻辑已经可以保证仅当版本号变化时才覆盖version.c,因此version.c的修改时间只会在版本实际变化时更新,不会触发不必要的后续编译。

修改后的完整Makefile

SOURCEFILES = $(wildcard *.c) version.c
PROGRAMS = $(addprefix build/,$(SOURCEFILES:.c=.out))

# 新增FORCE伪目标,没有依赖和生成规则,每次都会被认为已更新
.PHONY: all clean FORCE

all: $(PROGRAMS)

clean:
	rm -fR build

build/%.out: build/%.o Makefile
	mkdir -p build
	gcc -g $< -o $@

build/%.o: %.c Makefile
	mkdir -p build
	gcc -Wall -Werror -g -c $< -o $@

# 增加FORCE作为依赖,保证每次都会执行生成规则
version.c: version.c.in Makefile FORCE
	cp $< $@_temp
	sed -i "s/@BUILDVERSION@/$$(git describe --always --dirty=-dirty)/g" $@_temp
	@cmp -s $@_temp $@ || mv $@_temp $@
	rm -f $@_temp

原理解释

  • FORCE作为伪目标,没有对应的生成文件,每次构建都会被make判定为"已更新",因此version.c的生成规则每次都会执行
  • 生成规则中只有新生成的version.c_temp和原有version.c内容不一致时,才会覆盖原有version.c,此时version.c的修改时间才会更新,触发依赖它的.o、.out文件重新构建
  • 如果版本号没有变化,version.c的修改时间不会变化,后续的编译、链接步骤都不会执行,避免了无意义的重复构建

也有方案尝试把.git/index、.git/refs下的相关文件作为version.c的依赖来实现自动触发,但这种方案覆盖场景不全(比如新增标签、修改Git配置等操作不会修改这些文件),且实现复杂,FORCE方案是更通用稳定的选择。

内容的提问来源于stack exchange,提问作者Benedikt Schmidt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 09:57:01