将先决条件扩展推迟到(不同的)目标创建之后

时间:2018-03-14 19:39:08

标签: makefile gnu-make gnu

我希望能够在GNU make中另一个规则的先决条件中使用规则中创建的目标的结果。例如:

PREREQ = $(shell echo "reading target1" >&2; cat target1)

target1:
        echo "prereq" > $@

target2: target1 $(PREREQ)
        echo foo > $@

target2应取决于从prereq文件中读取的target1,但在执行target1配方之前,该文件不在文件中。

当然这是一个非常人为的例子,我肯定有很多关于如何重构这个特定例子的建议,但我不打算重构这个例子。这只是我更复杂问题的简化示例,我需要从文件内容中派生先决条件,直到执行Makefile中的配方才创建该文件的内容。

问题是,[如何]我可以扩展$(PREREQ)(因此执行$(shell cat target1)延迟直到target1规则实际执行后才会生效?

更新:我尝试.SECONDARYEXPANSION:,但似乎没有做到这一点:

$ make -d target2
...
reading target1
cat: target1: No such file or directory
...
Updating goal targets....
Considering target file 'target2'.
 File 'target2' does not exist.
  Considering target file 'target1'.
   File 'target1' does not exist.
   Finished prerequisites of target file 'target1'.
  Must remake target 'target1'.
echo "prereq" > target1
[ child management ]
  Successfully remade target file 'target1'.
 Finished prerequisites of target file 'target2'.
Must remake target 'target2'.
echo foo > target2
[ child management ]
Successfully remade target file 'target2'.

正如您所看到的,“阅读目标”仅在一开始就打印一次,表明由于PREREQ和目标列表考虑<{1}}未再次展开 .SECONDEXPANSION:的em> ed不包含target2

2 个答案:

答案 0 :(得分:1)

推迟扩展先决条件$(PREREQ)可以通过有条件地创建target2并依赖递归来实现:

ifndef expand-prereq
target2: target1
    $(MAKE) --no-print-directory -f $(lastword $(MAKEFILE_LIST)) $@ expand-prereq=y
else
target2: target1 $(PREREQ)
    echo foo > $@
endif

第一次为此makefile运行make时,未定义变量expand-prereq,因此,第一个targe2规则是作为条件的结果生成的。这种虚拟规则可以在不扩展target1的情况下更新$(PREREQ)。 匹配此规则会导致target1被更新(因为target1是此规则的先决条件)并且make被称为递归,用于相同的makefile和{{ 1}}作为目标。

第二次target2被(递归地)调用,变量make是通过命令行参数expand-prereq定义的,因此第二个expand-prereq=y规则是这次由target2分支生成。此规则是实际生成目标else的规则。请注意,在匹配此规则之前,target2已经创建为第一个虚拟规则的副作用,因此target1的扩展发生在创建$(PREREQ)之后(你是什么)正在寻找)。

答案 1 :(得分:0)

您可以将target2的完整规则写入单独的文件并-include

确切的机制将取决于您的具体用例,使用此方法可能无法实现我们所需的功能,但它支持各种样式以实现自动依赖关系生成。