30

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

all: foo

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

Runningmake运行all目标,该目标运行foo.

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

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

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

4

5 回答 5

37

我意识到这在这一点上有点老了,但你甚至不需要使用 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
于 2013-07-18T00:57:23.043 回答
23

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

这是因为||&&具有相同的优先级,并且 shell 将命令解释为就好像它是编写的一样

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

如果您想发出失败信号,您必须以非零值退出,例如exit 1. 如果你想回显退出,只需按顺序将命令分开;

all: foo

foo:
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; exit 1; }
于 2013-01-15T23:56:04.610 回答
9

make 中的每个命令行都在其自己的子 shell 中运行。所以运行exit只是退出那个子shell——而不是整个makefile。默认情况下,make如果任何子 shell 返回不成功的退出状态,则执行将停止(按照惯例,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; }
于 2013-01-16T14:32:26.160 回答
3

只需这样做:

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命令,会返回一个非0值,make会失败。/opt/local/bin/gsort

于 2016-02-21T11:10:50.340 回答
3

由于您正在检查gsort可执行文件是否存在,因此您可以使用whichor typeshell 命令,例如:

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
于 2016-03-26T02:18:21.563 回答