Makefile执行顺序异常:rm -rf未及时完成引发报错?
问题修复方案
问题根源
Makefile的执行分为解析阶段和命令执行阶段:
- 解析阶段会先处理所有变量、函数(包括
$(eval)、$(call))的展开 - 命令执行阶段才会依次运行目标下的shell命令
你遇到的问题就是$(eval $(call get_sha1...))在解析阶段就已经执行,而mkdir是在后续的命令阶段才创建目录,导致获取SHA1时目录还不存在。
修复方法
方法1:将SHA1获取逻辑移到命令执行阶段(推荐)
把获取SHA1的操作放到目标的shell命令序列中,利用shell的顺序执行特性,确保目录创建、克隆完成后再获取SHA1:
do_the_work: mkdir -p out/my_work_dir git clone <仓库地址> out/my_work_dir # 直接在shell中获取SHA1并传递给后续操作 SHA1=$$(git -C out/my_work_dir rev-parse HEAD) && \ echo "当前仓库SHA1: $$SHA1" && \ # 这里写依赖SHA1的后续操作,比如: # cp some_file out/my_work_dir/$$SHA1.file
方法2:用前置目标确保目录就绪后再执行SHA1获取
通过创建一个标记文件作为前置依赖,确保目录创建和克隆完成后,再执行SHA1获取逻辑:
# 定义获取SHA1的函数(仅在命令阶段调用) define get_sha1 SHA1=$(shell git -C $(1) rev-parse HEAD) export SHA1 endef do_the_work: out/my_work_dir/.cloned # 此时目录已存在,安全调用get_sha1 $(call get_sha1, out/my_work_dir) @echo "SHA1: $(SHA1)" # 后续依赖SHA1的操作 # 前置目标:确保目录创建和克隆完成 out/my_work_dir/.cloned: mkdir -p out/my_work_dir git clone <仓库地址> out/my_work_dir # 创建标记文件,避免重复克隆 touch $@
关键注意事项
- 避免在解析阶段执行依赖文件系统状态的操作(比如访问还未创建的目录)
- 如果必须使用Makefile函数获取SHA1,一定要确保操作依赖的前置目标已经完成
- 用
$$表示shell中的变量,避免被Makefile提前解析
内容的提问来源于stack exchange,提问作者Danijel
相关产品推荐
相关产品推荐

