为什么[...]语法在`test`不能在Makefile中起作用?

时间:2018-10-12 14:17:10

标签: if-statement makefile

我在Linux Mint 19上。我对Makefile完全陌生。

这是有问题的部分:

[ $(shell id --user) -eq 0 ] && ( echo && echo "distrib target has to be run as normal user" && echo && exit 1 )

会引发此错误:

[ 1000 -eq 0 ] && ( echo && echo "distrib target has to be run as normal user" && echo && exit 1 )
Makefile:25: recipe for target 'distrib' failed
make: *** [distrib] Error 1

相反,直接使用test命令被证明可以完全正常工作:

if test $(shell id --user) -eq 0; then ( echo && echo "distrib target has to be run as normal user" && echo && exit 1 ) fi

我想问为什么,我违反了一些Makefile规则吗?

1 个答案:

答案 0 :(得分:1)

这与makefile没有任何关系,它与shell脚本以及在退出代码方面使用&&if之间的区别有关。您正在这里比较苹果和桔子。

test[无关。如果您在[语句中使用if编写版本,您将获得与test相同的行为,并且如果您使用{通过{1}}模型,您将获得与test相同的行为。

在您的shell中运行此程序

&&

现在在您的shell中运行它:

[

您将看到前者给出了非0的退出代码,而后者给出了0(成功)的退出代码。 [ 1000 -eq 0 ] && echo hi echo $? 就是这样工作的;它“吞噬”该条件的退出代码。

Make总是查看shell脚本的退出代码来确定它是否失败。

通常在make脚本中,您希望重新排列表达式以使用if [ 1000 -eq 0 ]; then echo hi; fi echo $? 而不是if。这样可以确保如果脚本提前退出,则会以成功代码而不是失败代码退出。您可以这样编写脚本:

||

请注意,我使用&&而不是[ $$(id -u) -ne 0 ] || ( echo && echo "distrib target has to be run as normal user" && echo && exit 1 ) ;配方已经在外壳中运行,并且在配方中使用make $$(id -u)函数是一种反模式。另外,$(shell id --user)选项是POSIX标准选项,而shell仅在-u的GNU实用程序版本中可用。