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

Makefile 将先决条件扩展推迟到(不同)目标创建之后,makefile,gnu-make,gnu,Makefile,Gnu Make,Gnu,我希望能够在GNU make中的另一个规则的先决条件中使用在规则中创建的目标的结果。例如: PREREQ = $(shell echo "reading target1" >&2; cat target1) target1: echo "prereq" > $@ target2: target1 $(PREREQ) echo foo > $@ target2应取决于从target1文件中读取的prereq,但在执行target1配方

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

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

target1:
        echo "prereq" > $@

target2: target1 $(PREREQ)
        echo foo > $@
target2
应取决于从
target1
文件中读取的
prereq
,但在执行
target1
配方之前,该文件不在文件中

假设这是一个非常做作的例子,我肯定有很多关于如何重构这个例子的建议,但我不打算重构这个例子。这只是我更复杂问题的一个简化示例,其中我需要从文件的内容中派生先决条件,该文件在执行
Makefile
中的配方之前未创建

问题是,[如何]扩展
$(PREREQ)
(因此,
$(shell cat target1)
的执行推迟到实际执行
target1
规则之后

更新:我尝试了
。第二次扩展:
,但这似乎不起作用:

$ 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
没有再次展开。第二次展开:
,并且为
target2
考虑的目标列表不包括
PREREQ

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


确切的机制将取决于您的特定用例,使用这种方法很可能无法实现我们所需的功能,但它支持自动生成依赖项的各种样式。

推迟先决条件
$(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
未定义,因此,第一个
target2
规则作为条件的结果生成。这种伪规则使更新
target1
成为可能,而无需扩展
$(prereq)
。 匹配此规则将导致更新
target1
(因为
target1
是此规则的先决条件),并针对同一makefile递归调用
make
,并将
target2
作为目标


第二次
make
是(递归)调用时,变量
expand-prereq
是通过命令行参数
expand-prereq=y
定义的,因此第二个
target2
规则是这次
else
分支的结果。此规则是实际生成target
target2
的规则。请注意,在此之前可以执行此规则匹配后,
target1
已经作为第一个虚拟规则的副作用创建,因此
$(PREREQ)
的扩展发生在创建了
target1
之后(您正在寻找的内容)。

抱歉,我现在意识到它没有按预期工作。但需要明确的是:“二次扩展”并不意味着扩展两次,而是在匹配规则时进行扩展(即:仍然只有一次)。问题似乎是在创建
target1
之前仍然碰巧执行了二次扩展。我删除了以前的答案,并添加了一个新的潜在解决方案。我希望这会有所帮助。