什么是" @ false"和" @ true"在makefile中?

时间:2018-04-10 14:27:11

标签: makefile

我在makefile中遇到过这种结构:

clean:
    @echo "Cleaning"
ifeq "DEV" "$(VERSION)"
    $(MAKE) clean -C bin/
else
    @echo "Unsupported"
    @false
endif

@false在做什么?

P.S。

谷歌搜索带来了我,例如here - 他们使用它但他们无法解释它。

2 个答案:

答案 0 :(得分:2)

默认情况下,当您运行Makefile的那部分(即make clean)时,状态代码将为0(成功),因为echo不会失败。 @false调用内置的shell(现在为几天)false,它只会失败,所以最后一个命令失败(通常将状态代码设置为1)。

因此,如果在使用不支持的模式运行$?后检查状态代码(make),则可以看到失败。我会说这是一个很好的编码实践。 @true是相同的,但返回0 - 它是不需要的,因为其他命令的成功无论如何都将返回0。

bash中的一个示例用例:

make clean VERSION=somethingThatIsntSupported
if [ $? -gt 0 ]; then echo "Oh no! Make failed, are you sure that version is OK?"; fi

当然这里有点多余,但if的内容可能很复杂。

答案 1 :(得分:2)

我将在这里扩展@kabanus的回答(这是为了评论......)

首先,@符号只是告诉make不要将命令回显到stdout。因此,配方false@false将执行相同的操作,除了第一个将回显正在运行的命令。

接下来,当make构建目标时,它将逐行运行每个配方。如果配方行返回非零(false),它将停止构建目标(它不会执行超出该配方的任何配方)。同样,它会认为目标构建失败,任何依赖它的东西也会失败,因此通常会失败,返回非零状态。

因此,如果您使用makefile执行make bar

foo:
    @echo this will be printed (foo)
    @false
    @echo this will not be printed (foo)

bar: foo
    @echo this will not be printed (bar)

foo中的第二个回显不会出现,因为make会在其上方的配方中失败并中止构建foobar也不会被构建,因为它的依赖关系没有建立,所以你不会看到来自bar的回声。

请注意,如果你确实有一个你知道的配方行可能会失败,但你想忽略,你可以通过在它前面添加一个 - 来解决这个问题:

foo:
    @echo this will be printed (foo)
    -@false
    @echo this will also be printed (foo)

这两个回声都会发生。它将运行false,它什么也不做,但由于-符号而忽略了它的返回值。有关详细信息,请参阅this SO question

最后,make命令的返回值也会影响&&||运算符以及if语句。通常在脚本中你会看到类似的东西:

 make foo && cp foo /tftpboot/foo && echo success

如果make返回false,则不会尝试cpecho。如果人们期望这种行为,那么在失败时让返回非零是一种好习惯。