GNU Make 4.4下如何让指定Makefile规则优先执行?
GNU Make 4.4下优先执行规则的替代方案
原方案失效原因
GNU Make 4.4调整了-include的处理逻辑:对于.PHONY类型的被包含目标,不再自动触发构建流程——因为phony目标不对应实际文件,make判定无需为不存在的"dummy文件"执行构建规则,直接跳过了该步骤,导致原方案失效。
替代解决方案
方案1:利用递归make实现前置执行
通过MAKE_RESTARTS变量判断是否是首次启动make,首次启动时先执行目标规则,再递归调用make执行最终目标:
# 首次运行时先执行dummy,再递归启动make ifeq ($(MAKE_RESTARTS),) all: dummy $(MAKE) $@ else # 递归启动后直接执行最终目标 all: foo endif .PHONY: dummy dummy: echo "Generating" foo: echo "FOO"
执行make后,输出会恢复为4.3版本的结果:
echo "Generating" Generating echo "FOO" FOO
方案2:针对Git版本信息场景的精准依赖管理
你的实际需求是仅当Git版本信息变化时才更新头文件,避免全量重建,更适合用「生成文件的内容校验+显式依赖」方案:
# 生成Git版本头文件,仅当内容变化时更新 gitversion.h: # 临时生成版本内容 @echo "#define GIT_VERSION \"$(shell git describe --tags --dirty 2>/dev/null || echo unknown)\"" > $@.tmp # 对比临时文件与原文件,仅当内容不同时替换 @if ! cmp -s $@.tmp $@; then mv $@.tmp $@; else rm $@.tmp; fi # 将生成的头文件作为目标的依赖,确保先执行生成规则 foo: gitversion.h echo "FOO" all: foo .PHONY: all
这个方案的优势:
- 自动优先执行
gitversion.h的生成规则(make会先检查依赖是否需要更新) - 只有当Git版本信息变化时,才会更新
gitversion.h,触发依赖它的目标重建 - 完全适配GNU Make 4.4及以上版本,无需依赖
-include的旧逻辑
方案3:使用.FORCE强制触发前置规则(简单场景)
如果不需要内容校验,只是单纯要强制某个规则先执行,可以用.FORCE标记,配合递归调用:
.PHONY: .FORCE dummy all .FORCE: all: .FORCE $(MAKE) foo dummy: .FORCE echo "Generating" foo: dummy echo "FOO"
内容的提问来源于stack exchange,提问作者DrMcCoy
相关产品推荐
相关产品推荐

