Make赋值命令不符合预期:延迟与立即赋值未按文档表现
Makefile延迟/立即变量求值不符合预期的问题
测试用Makefile代码
A = $(shell date) B := $(shell date) all: @echo $(A) sleep 2s; @echo $(A) sleep 2s; @echo $(A) @echo $(B)
预期与实际结果
根据Make文档说明,B属于立即展开变量(:=),会在Make启动时立即求值;A属于延迟展开变量(=),会在每次被调用时重新求值。
原本预期echo $(B)会输出最早的时间,而三次echo $(A)会依次输出递增的时间,但实际所有输出的时间值完全相同:
Wed Jun 11 12:44:46 CEST 2025 sleep 2s; Wed Jun 11 12:44:46 CEST 2025 sleep 2s; Wed Jun 11 12:44:46 CEST 2025 Wed Jun 11 12:44:46 CEST 2025
已测试Make版本3.1和4.1,在Rocky OS和Ubuntu系统上均得到相同结果。
问题原因与解决方法
原因
Make在解析规则的命令列表时,会提前将所有变量展开为最终的shell命令,之后才把整个命令序列交给shell一次性执行。也就是说,三次$(A)在Make解析阶段就已经被展开为同一个date的输出值,后续shell执行时只是重复输出这个固定值,自然不会随时间变化。B作为立即展开变量,值在Make启动时就已确定,所以也和其他输出时间一致。
解决方法
要实现每次输出不同的时间,需要让date命令在shell执行阶段才被调用,而非Make解析阶段,有两种常用方式:
- 使用shell转义:用
$$(date)代替$(shell date),让shell负责执行date命令:
all: @echo $$(date) sleep 2s; @echo $$(date) sleep 2s; @echo $$(date) @echo $(shell date)
- 拆分规则步骤:将每个
echo命令拆分为独立的目标步骤,Make会在执行每个步骤前重新展开变量:
A = $(shell date) B := $(shell date) all: step1 step2 step3 step4 step1: @echo $(A) step2: sleep 2s; @echo $(A) step3: sleep 2s; @echo $(A) step4: @echo $(B)
内容的提问来源于stack exchange,提问作者Inquisitive
相关产品推荐
相关产品推荐

