如何在Makefile中抑制和忽略输出?

56
我知道在Makefile中,使用@前缀可以阻止来自shell命令的输出,同时使用-前缀可以忽略shell命令产生的错误。是否有一种方法可以将两者结合起来,即使用一个前缀既可以阻止输出又可以忽略错误?我认为@-或者-@并不起作用。

1
@--@ 都可以正常工作。同样适用于 + 修饰符。 - Eldar Abusalimov
2个回答

74

实际上,@--@都可以工作,但会打印出一个make: [target] Error 1 (ignored)警告。

相反,您可以使用

@command || true

或者,因为在shell中:true的缩写,所以

@command ||:

通常这样做会更好,因为它避免了Make发出混淆的警告:忽略了一个不可见命令中的错误。

考虑两种最常见的情况,你可能想忽略命令的返回值:

  1. 构建的一部分已经损坏,但你仍然希望继续,这时候你需要学习一下。构建已经损坏并需要修复,而不是以难以维护的方式缝合。
  2. 尽管命令执行了你要求的操作,但返回一个非零退出代码,在这种情况下,你不希望Make发出警告。

对于第二种情况,请考虑在命令产生的日志文件中搜索警告的示例。如果grep没有找到匹配项,它将返回错误,这并不是你想要的:

.PHONY: all one two three

all: at-warning at-success or-success or-warning

at-%: %.log
    @echo Making $@
    @-grep ^Warning $<

or-%: %.log
    @echo Making $@
    @grep ^Warning $< ||:

success.log:
    echo 'Success!' > $@

warning.log:
    echo 'Warning: foo' > $@

clean::
    rm -f {success,warning.log}

输出:

echo 'Warning: foo' > warning.log
Making at-warning
Warning: foo
Making at-success
make: [at-success] Error 1 (ignored)
Making or-success
Making or-warning
Warning: foo

使用@-会在成功时产生一个毫无意义的被忽略的错误警告,而|| true则可以处理警告和没有警告的情况而不报错。

从理论上讲,使用|| true比使用@-要慢,但是这种额外开销在设计良好、维护良好的构建系统中不太可能成为瓶颈。大多数时间应该花在构建或检查时间戳上,当没有东西需要构建时,不是在运行成千上万个快速命令,所有这些命令的返回值都被忽略,这才会对性能产生可测量的影响。


这种策略会强制GNU make使用shell来调用命令,这将增加构建过程的开销。在某些平台上(例如Windows),这可能是相当显著的。 - Eric Melski

10

GNU make允许您同时使用@-

all:
        @-exit 1

使用 gmake 3.81 运行会产生以下输出:

gmake: [all] Error 1 (ignored)

正如你所看到的,命令没有被回显,错误也按预期被忽略了。


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