测试文件是否存在于makefile目标中,如果不存在则退出

时间:2013-01-15 23:18:16

标签: makefile gnu

如果文件不存在,有没有办法退出并出现错误?我目前正在做这样的事情:

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命令不会运行。这与我希望完成的事情相反。

执行上述操作的正确方法是什么?

5 个答案:

答案 0 :(得分:27)

我意识到这一点有点陈旧,但您甚至不需要使用子shell来测试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 :(得分:18)

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; }

答案 2 :(得分:7)

make中的每个命令行都在自己的子shell中运行。因此,运行exit只退出该子shell - 而不是整个makefile。默认情况下,如果任何子shell返回不成功的退出状态,make执行将停止(按照惯例,0表示成功,因此其他任何内容都将停止执行)。最简单的方法就是使用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; }

答案 3 :(得分:2)

简单地说:

all: /opt/local/bin/gsort

如果缺少/opt/local/bin/gsort,您将无法制定目标`/ opt / local / bin / gsort'"错误信息。

但如果您还想要一些很好的解释:

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

在GNU / Make中,如果未声明目标.PHONEY并且没有任何依赖关系,则如果与该目标不匹配的文件不存在,则将调用该规则。

以上代码仅在false不存在时触发/opt/local/bin/gsort命令,返回非0值,make将失败。

答案 4 :(得分:2)

由于您正在检查是否存在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; }

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

另一种方法是使用规则的目标来检查文件是否存在并添加为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