Makefile递归展开变量中shell date不更新问题咨询
问题原因
你对递归展开变量的理解方向没错,但忽略了make处理规则命令的关键时机:
- 递归展开变量里的
${shell date ...},会在make解析规则命令行的阶段就完成全部展开,而非每条shell命令执行时才触发。 - 换句话说,make在准备执行
test规则前,会先把规则里所有的${LOCAL_TIME}一次性替换成shell函数的执行结果(同一个时间戳),再把替换后的完整命令序列交给shell执行。sleep 2是在shell执行阶段才运行的,但此时变量替换早已完成,所以两次输出的时间完全一致。
解决方案
要实现每次echo都获取最新时间,核心是让shell而非make负责时间的获取,以下是几种常用方案:
方案1:直接在命令中调用date
跳过make变量,直接在shell命令里执行date:
test: @echo `date +"%Y:%m:%d:%H:%M:%S"` sleep 2 @echo `date +"%Y:%m:%d:%H:%M:%S"`
反引号是shell的命令替换语法,make不会解析这部分内容,交给shell执行时会每次重新获取时间。
方案2:定义shell命令变量,让shell解析
把变量定义为shell命令字符串,执行时通过转义让shell处理:
LOCAL_TIME=date +"%Y:%m:%d:%H:%M:%S" test: @echo $$($(LOCAL_TIME)) sleep 2 @echo $$($(LOCAL_TIME))
$$会被make转义成单个$,传给shell后变成$(LOCAL_TIME),触发shell的命令替换,每次执行都会重新调用date。- 这里的
LOCAL_TIME是简单展开变量,仅存储命令字符串,而非预执行的结果。
方案3:用make的宏实现动态展开(进阶)
如果想保留make变量机制,可以用define定义宏,每次调用宏时重新执行shell函数:
define PRINT_LOCAL_TIME @echo $(shell date +"%Y:%m:%d:%H:%M:%S") endef test: $(PRINT_LOCAL_TIME) sleep 2 $(PRINT_LOCAL_TIME)
每次调用PRINT_LOCAL_TIME宏时,make都会重新执行shell函数获取最新时间,再生成对应的echo命令。
内容的提问来源于stack exchange,提问作者Krishna Chaitanya Musirippa
相关产品推荐
相关产品推荐

