为什么[...]语法在`test`不能在Makefile中起作用? [英] Why [ ... ] syntax doesn't work in a Makefile while `test` does?
问题描述
我在Linux Mint 19上.我对Makefiles完全陌生.
I am on Linux Mint 19. I am entirely new to Makefiles.
这是有问题的部分:
[ $(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
命令被证明可以完全正常工作:
On the contrary, using test
command directly proves to be working entirely:
if test $(shell id --user) -eq 0; then ( echo && echo "distrib target has to be run as normal user" && echo && exit 1 ) fi
我想问为什么,我违反了一些Makefile规则吗?
I want to ask why that is, did I break some Makefile rule?
推荐答案
这与makefile没有任何关系,它与shell脚本以及使用&&
与if
的区别退出代码.您正在这里比较苹果和桔子.
This doesn't have anything to do with makefiles, it has to do with shell scripting and the difference between using &&
vs. if
in terms of the exit code. You are comparing apples and oranges here.
与test
和[
无关.如果在if
语句中使用[
编写版本,则将获得与test
相同的行为,并且如果使用&&
模型编写test
版本,则将获得行为与[
相同.
It's not related to test
vs [
. If you write the version using [
inside an if
statement you'll get the same behavior as you do with test
, and if you write the test
version with the &&
model you'll get the same behavior as you do with [
.
在您的shell中运行它:
Run this in your shell:
[ 1000 -eq 0 ] && echo hi
echo $?
现在在您的shell中运行它:
Now run this in your shell:
if [ 1000 -eq 0 ]; then echo hi; fi
echo $?
您将看到前者给出了非0的退出代码,而后者给出了0(成功)的退出代码.这就是if
的工作方式;它吞噬"该条件的退出代码.
You'll see the former gives a non-0 exit code, while the latter gives a 0 (success) exit code. That's how if
works; it "swallows" the exit code of the condition.
Make总是查看shell脚本的退出代码来确定它是否失败.
Make always looks at the exit code of the shell script to decide if it failed or not.
通常在make脚本中,您要重新排列表达式以使用||
而不是&&
.这样可以确保如果脚本提前退出,则会以成功代码而不是失败代码退出.您可以这样编写脚本:
Generally in make scripting you want to re-arrange your expressions to use ||
rather than &&
. That ensures that if the script exits early it exits with a success code not a failure code. You can write your script like this:
[ $$(id -u) -ne 0 ] || ( echo && echo "distrib target has to be run as normal user" && echo && exit 1 )
请注意,我使用的是$$(id -u)
而不是$(shell id --user)
;配方已经在外壳中运行,并且在配方中使用make shell
函数是一种反模式.另外,-u
选项是POSIX标准选项,而--user
仅在id
的GNU实用程序版本中可用.
Note I use $$(id -u)
not $(shell id --user)
; the recipe is run in the shell already and it's an anti-pattern to use the make shell
function in a recipe. Also, the -u
option is a POSIX standard option while --user
is only available in the GNU utilities version of id
.
这篇关于为什么[...]语法在`test`不能在Makefile中起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!