在规则执行时定义make变量

时间:2009-12-15 17:52:50

标签: makefile gnu-make

在我的GNUmakefile中,我希望有一个使用临时目录的规则。例如:

out.tar: TMP := $(shell mktemp -d)
        echo hi $(TMP)/hi.txt
        tar -C $(TMP) cf $@ .
        rm -rf $(TMP)

如上所述,上述规则在解析规则时创建临时目录。这意味着,即使我没有直接创建.tar,也会创建许多临时目录。我想避免我的/ tmp乱丢未使用的临时目录。

是否有办法使该变量仅在触发规则时定义,而不是在定义时定义?

我的主要想法是将mktemp和tar转储到shell脚本中,但这看起来有点难看。

4 个答案:

答案 0 :(得分:268)

在您的示例中,只要评估TMP规则,就会设置out.tar变量(并创建临时目录)。为了仅在实际触发out.tar时创建目录,您需要将目录创建向下移动到以下步骤中:

out.tar : 
    $(eval TMP := $(shell mktemp -d))
    @echo hi $(TMP)/hi.txt
    tar -C $(TMP) cf $@ .
    rm -rf $(TMP)

eval函数计算字符串,就好像它已手动输入到makefile中一样。在这种情况下,它会将TMP变量设置为shell函数调用的结果。

修改(以回应评论):

要创建唯一变量,您可以执行以下操作:

out.tar : 
    $(eval $@_TMP := $(shell mktemp -d))
    @echo hi $($@_TMP)/hi.txt
    tar -C $($@_TMP) cf $@ .
    rm -rf $($@_TMP)

这会将目标的名称(在本例中为out.tar)添加到变量中,从而生成名为out.tar_TMP的变量。希望这足以防止冲突。

答案 1 :(得分:50)

执行此操作的一种相对简单的方法是将整个序列编写为shell脚本。

out.tar:
   set -e ;\
   TMP=$$(mktemp -d) ;\
   echo hi $$TMP/hi.txt ;\
   tar -C $$TMP cf $@ . ;\
   rm -rf $$TMP ;\

我在此处整合了一些相关提示:https://stackoverflow.com/a/29085684/86967

答案 2 :(得分:26)

另一种可能性是在规则触发时使用单独的行设置Make变量。

例如,这是一个包含两个规则的makefile。如果规则触发,则会创建临时目录并将TMP设置为临时目录名称。

PHONY = ruleA ruleB display

all: ruleA

ruleA: TMP = $(shell mktemp -d testruleA_XXXX)
ruleA: display

ruleB: TMP = $(shell mktemp -d testruleB_XXXX)
ruleB: display

display:
    echo ${TMP}

运行代码会产生预期的结果:

$ ls
Makefile
$ make ruleB
echo testruleB_Y4Ow
testruleB_Y4Ow
$ ls
Makefile  testruleB_Y4Ow

答案 3 :(得分:2)

我不喜欢“不要”的答案,但是...不。

make的变量是全局变量,应该在makefile的“解析”阶段而不是执行阶段进行评估。

在这种情况下,只要变量是单个目标的局部变量,就遵循@nobar's answer并将其设为shell变量。

特定于目标的变量也被其他make实现视为有害:katiMozilla pymake。由于它们的存在,可以根据是独立构建目标还是将其作为具有特定于目标的变量的父目标的依赖项来构建不同的目标。 您将不知道它是哪种方式,因为您不知道已经构建了什么。