我在makefile中遇到过这种结构:
clean:
@echo "Cleaning"
ifeq "DEV" "$(VERSION)"
$(MAKE) clean -C bin/
else
@echo "Unsupported"
@false
endif
@false
在做什么?
P.S。
谷歌搜索带来了我,例如here - 他们使用它但他们无法解释它。
答案 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会在其上方的配方中失败并中止构建foo
。 bar
也不会被构建,因为它的依赖关系没有建立,所以你不会看到来自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,则不会尝试cp
或echo
。如果人们期望这种行为,那么在失败时让返回非零是一种好习惯。