Makefile中规则的执行
Makefile每一行规则都是新起一个shell来执行的,我们可以通过下面的简单例子观察一下
check: test1 test2
@$(foreach var,$^,./$(var);)
@echo "every line rule is a new shell"
通过 strace -e execve -f make
的输出看到,每一行都是通过 sh -c
来执行的:
execve("/usr/bin/make", ["make", "check"], [/* 73 vars */]) = 0
[pid 4732] execve("/bin/sh", ["/bin/sh", "-c", "./test2; ./test1; "], [/* 78 vars */]) = 0 <----------------sh进程
[pid 4733] execve("./test2", ["./test2"], [/* 78 vars */]) = 0 <----------------test2进程
[pid 4733] +++ exited with 255 +++ <----------------test2进程返回-1
[pid 4734] execve("./test1", ["./test1"], [/* 78 vars */]) = 0 <----------test1进程, sh先执行完test2,再执行test1
[pid 4732] +++ exited with 0 +++ <----------------sh进程退出,返回值为0
[pid 4735] execve("/bin/sh", ["/bin/sh", "-c", "echo \"every line rule is a new s"...], [/* 78 vars */]) = 0 <----第二行规则的sh进程,这里因为echo是builtin的命令,所以没有再新起进程
every line rule is a new shell
[pid 4735] +++ exited with 0 +++
+++ exited with 0 +++ <---------------make进程本身结束
- makefile 执行时,根据规则串行执行,上一行命令没有执行完不会执行下一行
- makefile 执行每一行命令都为其开辟一个 sh 进程,如果一行命令中有多个程序需要执行, sh 为其创建子进程执行
- sh 检查他创建的子进程的返回值, 当其中一个返回错误时,sh 并不会立即返回而是接着执行下一个程序。最终每一行命令的返回值是 sh 进程的返回值,并不能反应它子进程的返回值。所以检查命令的返回值需要选对对象。
- make 检查 sh 进程的返回值,如果发生错误则返回。make 并不关心 sh 子进程的返回值的
Makefile中命令返回值检查
上面的 test2 程序返回值明显错了,但是 make 还是接着往下执行了,这时候应该怎么加返回值检测呢? 有两种选择,一个是使得 sh 返回 test2 的错误码;另一种 make 中提供了控制函数 $(error TEXT…)
, 沿用上面的示例分别加上返回值检测
方式一
check: test1 test2
@$(foreach var,$^,./$(var)||exit 1;)
@echo "every line rule is a new shell"
方式一
check: test1 test2
@$(foreach var,$^,./$(var)||$(error );) //error 后面有个空格的
@echo "every line rule is a new shell"