在使用 make
编译时常常出现类似这样的提示:
make[6]: [copyapi] Error 1 (ignored)
找到目标 copyapi
的定义,发现使用了 $(RM)
和 $(CP)
两个变量,而这两个变量定义如下:
RM = -@rm -f
CP = -@cp
rm
和 cp
两个命令前都加了减号(-
),表示忽略错误(加 @
表示不打印命令本身)。
在学习 makefile 时一定学过命令前加减号表示忽略错误,但看到 Error 1 (ignored)
这样的提示时,却没有想到是什么原因导致的,逆向思维有待提高。
看看 GNU make 手册 5.5 Errors in Recipes 对此的描述:
After each shell invocation returns,
make
looks at its exit status. If the shell completed successfully (the exit status is zero), the next line in the recipe is executed in a new shell; after the last line is finished, the rule is finished.If there is an error (the exit status is nonzero),
make
gives up on the current rule, and perhaps on all rules.Sometimes the failure of a certain recipe line does not indicate a problem. For example, you may use the
mkdir
command to ensure that a directory exists. If the directory already exists,mkdir
will report an error, but you probably wantmake
to continue regardless.To ignore errors in a recipe line, write a ‘
-
’ at the beginning of the line’s text (after the initial tab). The ‘-
’ is discarded before the line is passed to the shell for execution.…
When errors are to be ignored, because of either a ‘
-
’ or the ‘-i
’ flag,make
treats an error return just like success, except that it prints out a message that tells you the status code the shell exited with, and says that the error has been ignored.
而在调用 make
时传入 -i
或 --ignore-errors
标志将忽略所有的错误,没有前置条件的特殊目标 .IGNORE
也具有同样效果。但使用 -
具有更好的扩展性。
上述特性需要与另一标志 -k
或 --keep-going
区别开来。-k
并不会忽略遇到的错误,而是继续其它目标的编译,直到所有目标都执行之后再返回错误。这有助于一次性发现所有错误、做出相应修改并再次编译。这也是 Emacs 的 compile
命令默认使用 -k
标志的原因。
最后需要注意的是,即使编译出现错误,目标文件的时间戳还是会更新。假如源文件没有修改就再次编译,出错的目标文件将不会更新,也就是不会重新编译。此时需要手动删除此目标文件再次编译解决,也可通过增加 .DELETE_ON_ERROR
目标实现自动删除的目的。
关于 @
符号可参考 5.2 Recipe Echoing 的描述。
以上。