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

Makefile中$(shell)与直接执行命令的区别及sleep用法差异

Makefile中$(shell)与直接执行命令的区别

问题1:$(shell)和直接执行命令的核心差异

Makefile的执行分为两个关键阶段,这是两者区别的根源:

  1. 解析阶段:Make加载并解析整个Makefile,处理变量定义、执行所有函数调用(包括$(shell)),但不会运行规则里的命令。
  2. 执行阶段:Make确定要构建的目标后,将规则中已经解析完成的命令逐行交给shell执行。

两者的具体区别:

  • 执行时机不同:
    • $(shell)是在解析阶段执行,只要Make解析到它(不管是变量定义还是命令行里),就会立刻调用shell运行对应命令,把输出作为函数返回值。
    • 规则里的直接命令(比如sleep 1)要等到执行阶段,Make开始运行目标的命令时,才会交给shell执行。
  • 作用场景不同:
    • $(shell)常用于在解析阶段获取外部命令输出,用来给变量赋值或生成动态规则内容。
    • 直接命令用于执行阶段完成实际构建操作,比如编译、文件拷贝等。
  • 对变量的影响不同:如果$(shell)放在递归展开变量(比如AA = $(shell date))里,每次引用变量时都会重新执行$(shell);而直接命令不会改变变量的展开时机。

问题2:sleep 1和$(shell sleep 1)的区别

结合提供的代码和输出,具体差异一目了然:

  • $(shell sleep 1):
    在解析阶段执行,会让Make进程本身暂停1秒,执行完后返回空字符串,所以规则里的这一行最终会变成空命令(什么都不做)。在目标a中,每次遇到它,Make都会先等1秒再处理下一行,所以后续的echo $(AA)会获取到更新后的时间,导致输出的三个时间依次递增。
  • sleep 1:
    在执行阶段由shell执行,会让shell进程暂停1秒,但此时目标b里的$(AA)已经在解析阶段完成了三次展开,值已经固定,所以即使sleep了1秒,后续echo的还是同一个时间,最终输出三个相同的时间。

示例代码

AA = $(shell date)
a:
    @echo $(AA)
    $(shell sleep 1)
    @echo $(AA)
    $(shell sleep 1)
    @echo $(AA)

b:
    @echo $(AA)
    @sleep 1
    @echo $(AA)
    @sleep 1
    @echo $(AA)

运行输出

>make a
Wed Apr 26 20:24:14 PDT 2023
Wed Apr 26 20:24:15 PDT 2023
Wed Apr 26 20:24:16 PDT 2023

>make b
Wed Apr 26 20:24:18 PDT 2023
Wed Apr 26 20:24:18 PDT 2023
Wed Apr 26 20:24:18 PDT 2023

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 14:20:28