为什么 GNU 在错误时以 0 退出?

Why does GNU make exit with 0 on errors?

生成文件:

foo.o: foo.cpp
    g++ -o foo.o foo.cpp

foo.cpp:

aslkfdj

输出:

$ g++ -o foo.o foo.cpp; echo $?
foo.cpp:1:1: error: ‘aslkfdj’ does not name a type
 aslkfdj
 ^
1

$ make; echo $?
g++ -o foo.o foo.cpp
foo.cpp:1:1: error: ‘aslkfdj’ does not name a type
 aslkfdj
 ^
Makefile:2: recipe for target 'foo.o' failed
make: *** [foo.o] Error 1
0
$ 

我希望 make 的退出代码为 2,因为 g++ returns 非零,cf.

$ man make|grep exits -A2
       GNU make exits with a status of zero if all makefiles were successfully parsed and no targets that were built failed.  A sta‐
       tus of one will be returned if the -q flag was used and make determines that a target needs to be rebuilt.  A status  of  two
       will be returned if any errors were encountered.

我做错了什么?

郑重声明,我在 Xubuntu 15.10 上得到了相同的退出代码:

$ make --version
GNU Make 4.0
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

在一些旧的 OS X 服务器上:

$ make --version
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for i386-apple-darwin10.0

Make 明确指出它识别了错误,因此应该 return 错误退出代码。

然而,在某些情况下,这无论如何都会导致意外结果。例如,如果有别名重新定义 makeecho,它可能导致 echo $? 不报告来自 make 的错误。要检查是否是这种情况,当然可以 运行 alias 检查,type make 查看是否有任何 aliases/shell 函数可以覆盖名称,或者简单地反斜杠别名 (即 运行 \make -f ; \echo $? - 没有文件名的 -f 将使 make 失败而无需任何 makefile)。

一个相关的场景是 make 不是 make 的实际可执行文件。例如,您可以有一个 shell 脚本来包装 make,但不转发退出代码。要检测这种情况,您可以 运行 which make 查看哪个可执行文件确实是 运行(除非别名有效)

在我的例子中,这是因为如下一行:

CXX      := -c++

前导-让Make忽略了退出状态,不应该存在。