Makefile: --ignore-errors与--keep-going的区别

10

我正在阅读Makefile文档,我不清楚--ignore-errors--keep-going之间的区别。

有人可以请明确两者之间的区别吗?对我来说,两者似乎在出现错误后都会继续运行。

虽然从文档中没有明确说明,但--ignore-errors可能具有配方级别的作用域,如果一个配方行失败了,下一行将继续执行。--keep-going可能具有目标级别的作用域,如果任何目标配方失败,配方的执行将在那里结束,但仍将尝试完成其他先决条件/目标。这只是一种可能的看法,需要澄清。

1个回答

15

https://www.gnu.org/software/make/manual/make.html#Errors

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 want make 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.

For example,

clean:
        -rm -f *.o

This causes make to continue even if rm is unable to remove a file.

When you run make with the -i or --ignore-errors flag, errors are ignored in all recipes of all rules. A rule in the makefile for the special target .IGNORE has the same effect, if there are no prerequisites. These ways of ignoring errors are obsolete because - is more flexible.

换句话说,make --ignore-errors的行为就像在所有命令前面加上一个-
当由于使用了--i标志而需要忽略错误时,make会将错误返回视为成功,但会打印一个消息,告诉你shell退出的状态码,并说明已忽略该错误。 当发生未被make告知要忽略的错误时,意味着当前目标无法正确地重新制作,且直接或间接地依赖它的任何其他目标都无法正确制作。 对于这些目标,将不再执行进一步的命令,因为它们的前提条件尚未满足。通常在这种情况下,make立即放弃,返回非零状态。但是,如果指定了-k--keep-going标志,则make会在放弃并返回非零状态之前继续考虑待处理目标的其他先决条件,并在必要时重新制作它们。例如,在编译一个对象文件出现错误后,make -k会继续编译其他对象文件,即使它已经知道链接它们是不可能的。请参见Summary of Options。通常的行为假定您的目的是使指定的目标保持最新状态;一旦make了解到这是不可能的,它可能会立即报告失败。-k选项表示真正的目的是尽可能多地测试程序中所做的更改,以便在下一次尝试编译之前找到几个独立的问题,以便您可以更正它们。这就是为什么Emacs的compile命令默认传递-k标志的原因。

让我们来看这个例子:

target: intermediate-1 intermediate-2 intermediate-3
        cat intermediate-1 intermediate-2 intermediate-3 > target

intermediate-1:
        echo "oh no, I'm failing!"
        false

intermediate-2:
        echo 'hello' > intermediate-2

intermediate-3:
        echo 'world' > intermediate-3

通常情况下,当你运行make target命令(且文件不存在)时,它会首先尝试创建intermediate-1目标。由于其中一个关联的命令false返回非零退出状态,该目标失败了。此时,make立即放弃并不再查看intermediate-2intermediate-3
但是,如果你使用make --keep-going target命令,则会注意到intermediate-1的失败,但继续创建intermediate-2intermediate-3目标,这两个目标成功了(分别创建包含"hello"和"world"的文件)。
最终,make仍然放弃并报告无法创建target目标的失败,但它已经尝试创建所有中间目标,即使另一个前提条件已经失败并且知道在此次make运行中不会使用这些目标。
如果你同时使用这两个标志(make --ignore-errors --keep-going),那么--keep-going实际上会被忽略。--keep-going只影响make在遇到中间目标错误时的行为,但--ignore-errors表示make永远不会遇到错误。

非常棒的答案,至少在2022年第一部分仍然有效,谢谢! - Carlos Pastor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接