我在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规则吗?
答案 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实用程序版本中可用。