如何获取makefile函数来停止当前目标?

时间:2017-10-18 18:24:46

标签: makefile gnu-make

我在makefile中有一个函数,如果文件不存在,我想停止整个make运行,或者至少执行目标:

vaultfile = ./vault

$(shell test -f $(1) || exit 1)

define get_token
$(shell test -f $1 && cat $1 || exit 2)
endef

a: token = $(call get_token,$(vaultfile),tokenname)
a:
        echo ==== $(token)
.PHONY=a

以上不起作用,在文件丢失时无声地失败

$ rm vault
$ make
echo ==== 
====
$ echo f > vault
$ make
echo ==== f
==== f

我希望这个功能在函数中,因为大多数目标都没有调用函数(显然会有更多的IRL)。

我如何使这项工作?

2 个答案:

答案 0 :(得分:0)

首先是一些事情:

.PHONY=a

没有做任何事情:变量.PHONY并不特别。要声明目标虚假,您需要将其列为.PHONY伪目标的先决条件:

.PHONY: a

第二,这一行:

$(shell test -f $(1) || exit 1)

没有做任何事情:此处未设置make变量$(1),因此test始终失败,但这并不重要,因为退出代码被忽略,请参阅下文

make shell函数的退出代码不会导致make失败,它会被忽略。要使make认为配方失败,您必须让命令行本身以非零值退出。

一个好的经验法则是,如果你发现自己在配方中使用了make shell功能,那么你做错了什么并且你不了解make如何扩展变量和函数。配方已经传递给shell,因此您根本不需要使用shell功能。

token变量的第一步扩展之后,让我们看一下您的食谱将会是什么:

    echo ==== $(call get_token,$(vaultfile),tokenname)

现在扩展call函数后(注意函数的第二个参数tokenname完全被忽略),你得到:

    echo ==== $(shell test -f ./vault && cat ./vault || exit 2)

现在make展开shell函数,该函数调用shell来运行命令并用输出替换扩展...但是忽略退出代码。让我们说./vault不存在:然后这个shell命令什么都不输出,并且make运行这个规则:

    echo ==== 

停止整个make运行的最佳方法是使用error函数。您可以使用make函数完成所有工作,如下所示:

vaultfile = ./vault

get_token = $(if $(wildcard $1),`cat $1`,$(error File $1 does not exist))

a: token = $(call get_token,$(vaultfile),tokenname)
a:
        echo ==== $(token)

让我们看一下call展开的结果:

    echo ==== $(if $(wildcard ,/vault),`cat ./vault`,$(error File ./vault does not exist))

现在make评估if函数,条件是wildcard函数,如果存在则将扩展为./vault,如果不存在则扩展为空字符串。 if函数将非空字符串视为" true"一个空字符串为" false",所以如果该文件存在,它将扩展为:

    echo ==== `cat ./vault`

如果文件不存在,它将运行error功能,立即停止制作,打印该错误信息。

答案 1 :(得分:0)

谢谢MadScientist

我最终得到的简化版本是:(格式化以便于阅读)

vaultfile = ./vault

define get_token
$(shell \
$(if $(wildcard $1), \
echo "Decoded $1" \
, \
$(error File $1 does not exist)
)
)
endef

a: token = $(call get_token,$(vaultfile))
a:
        echo ==== $(token)