2013-01-15 22 views
18

如果文件不存在,是否有退出并出现错误的情况?我目前在做这样的事情:测试makefile目标文件是否存在,如果不存在则退出

all: foo 

foo: 
    test -s /opt/local/bin/gsort || echo "GNU sort does not exist! Exiting..." && exit 

运行make运行的all目标,它运行foo

期望的是,如果test -s条件失败,那么将执行echo/exit语句。

但是,即使存在/usr/bin/gsort,我也会得到echo语句的结果,但exit命令不会运行。这与我希望完成的事情相反。

什么是正确的方式来做类似上面的事情?

+0

如果我尝试在命令行上,具有了''||括号中,拿到1分的外壳,使得它的工作如预期的右手边。我不知道在makefile中它是否相同。如果没有括号,即使测试结果为肯定,也会执行“退出”。 – HonkyTonk

回答

15

exit独自返回最后执行的命令的状态。在这种情况下,它返回零,这意味着一切正常。

这是因为||&&equal precedence,和Shell解释,就好像如果你想信号故障,你必须以非零值退出它写

(test ... || echo ...) && exit 

的命令,例如exit 1。 如果你想呼应退出,只是把分离序列中的命令由;

all: foo 

foo: 
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; exit 1; } 
5

在尽一切命令行运行在自己的子shell。所以运行exit只是退出该子shell - 而不是整个makefile。默认情况下,如果任何子shell返回一个不成功的退出状态(按照约定,0表示成功,所以其他任何操作都会暂停执行),则会停止执行make。最简单的方法是只使用test命令的退出状态:轻微

all: foo 

foo: 
    test -s /opt/local/bin/gsort 

打印诊断消息复杂的事情,因为像echo命令将返回0退出状态,造成make觉得一切都很好。要解决这个问题,你需要运行后,它的命令,这将使子shell一个非零退出状态:

all: foo 

foo: 
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; exit 1; } 

甚至只是

all: foo 

foo: 
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; false; } 
24

我意识到这是一个有点旧的,但你甚至不需要使用subshel​​l来测试Make中是否存在文件。

这也取决于你希望/期望它运行。

使用通配符功能,像这样:

all: foo 
foo: 
ifeq (,$(wildcard /opt/local/bin/gsort)) 
    $(error GNU Sort does not exist!) 
endif 

是一个很好的办法做到这一点。请注意,ifeq子句不缩进,因为它在目标本身之前被评估。

如果您希望这对每一个目标无条件地发生,你可以将它的目标之外:

ifeq (,$(wildcard /opt/local/bin/gsort)) 
$(error GNU Sort does not exist!) 
endif 
1

简单地做:

all: /opt/local/bin/gsort 

如果/opt/local/bin/gsort丢失,你会得到一个“no rule to make target`/ opt/local/bin/gsort'”的错误信息。

但是,如果你也想用它一些很好的解释做:

/opt/local/bin/gsort: 
    echo "GNU sort does not exist! Exiting..." 
    false 

在GNU/make如果目标没有宣布.PHONEY并没有任何相关性,该规则将某个文件调用匹配该目标不存在。

仅当/opt/local/bin/gsort不存在时,上面的代码才会触发false命令,将返回非0值,并且make将失败。

+0

有没有办法做到这一点,使继续检查每个丢失的文件,然后返回false?这样,如果有人错过了很多文件,所有文件都会显示出来,而不是一次显示一个文件。 – thepiercingarrow

1

既然你检查gsort可执行文件是否存在,你可以使用whichtype shell命令为,如:

all: foo 
    : 

foo: 
    which gsort || exit 1 
    # or 
    type gsort || exit 1 

你不需要的错误消息,因为它会自动打印:

/bin/sh的:行0:类型:gsort:找不到

这是显而易见的。


替代地使用test[(见:help test/help [语法),例如

test -x /opt/local/bin/gsort || { echo Error msg; exit 1; } 

它检查给定文件是否存在并且是可执行的,否则显示消息并退出。圆括号对于通过对命令进行分组来覆盖运算符的正常优先级(从左到右)很重要(有关更多信息,请参阅man bash中的Compound Commands部分)。


另一种方法是使用规则的目标,以检查文件是否存在,并作为依赖添加到all,例如

all: /opt/local/bin/gsort 
    @echo Success. 

/opt/local/bin/gsort: 
    @echo "GNU sort does not exist! Exiting..." 
    exit 1 

结果:

$ make 
GNU sort does not exist! Exiting... 
exit 1 
make: *** [/opt/local/bin/gsort] Error 1 
相关问题