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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 21:23:15