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

为何依赖无变更时Makefile的.bin配方仍会重复执行?

Make重复执行配方的原因及解决方法

问题场景

配置文件如下:

$ ls
base.mk  file.ext  Makefile

$ cat Makefile
include base.mk
algorithm = another-alg

$ cat base.mk
source = file.ext
binary = $(algorithm)
algorithm = the-alg
.bin: $(binary)
    touch .bin
$(binary): $(source)
    echo "compiling..." > $(binary)

执行make .bin首次能正常编译,但再次执行时,配方会重复运行,预期应该提示.bin无需更新。实际运行输出:

$ make .bin
echo "compiling..." > another-alg
touch .bin

$ make .bin
echo "compiling..." > another-alg
touch .bin

若不在Makefile中重新赋值algorithm,则能得到预期行为,但需求是通过引入base.mk并调整变量来复用通用逻辑,创建多个相似项目。

问题原因

核心问题是Make解析规则时的变量展开时机:

  • Make在解析规则的目标和依赖时,会立即展开变量,而非延迟到执行阶段。
  • 当前配置中,Makefile先include base.mk,此时base.mk内的执行顺序是:先定义binary = $(algorithm),再设置algorithm = the-alg,接着解析.bin: $(binary)规则——此时$(binary)会立即展开为当前的algorithm值the-alg,因此.bin的依赖被固定为the-alg。
  • 之后Makefile重新赋值algorithm = another-alg,虽然编译的目标变成了another-alg,但.bin的依赖依然是不存在的the-alg。每次运行make .bin时,Make都会认为.bin的依赖缺失,从而重复触发编译流程。

解决方法

最直接的解决方案是调整变量赋值顺序,先在Makefile中设置algorithm,再引入base.mk:

# 修改后的Makefile
algorithm = another-alg
include base.mk

这样,当include base.mk时,algorithm已经是another-alg,解析.bin: $(binary)规则时,$(binary)会立即展开为another-alg,.bin的依赖变为实际存在的编译产物,后续运行时Make就能正确识别文件时间戳,避免重复执行。

如果无法调整赋值顺序,也可以在base.mk中使用eval延迟解析规则,确保变量在最终赋值后再生成规则:

# 修改后的base.mk
source = file.ext
algorithm = the-alg

# 定义规则模板
define BIN_RULE
.bin: $(binary)
	touch .bin
$(binary): $(source)
	echo "compiling..." > $(binary)
endef

# 延迟展开规则,确保使用最新的algorithm值
binary = $(algorithm)
$(eval $(BIN_RULE))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 03:22:07