【问题标题】:defer prerequisite expansion until after a (different) target creation将先决条件扩展推迟到(不同的)目标创建之后
【发布时间】:2018-03-14 19:39:07
【问题描述】:

我希望能够在 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 规则实际执行之后?

更新:我尝试了.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 没有再次扩展,因为 .SECONDEXPANSION: 和目标列表考虑 target2 不包括 prereq

【问题讨论】:

  • 对不起,我现在意识到它不能按预期工作。但是要明确一点:“二次扩展”并不是要扩展两次,而是在匹配规则的那一刻扩展(即:仍然只有一次)。问题似乎是在创建 target1 之前仍然执行了二次扩展。
  • 我删除了之前的答案并添加了一个全新的潜在解决方案。我希望它有所帮助。

标签: makefile gnu-make gnu


【解决方案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

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

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

【讨论】:

    【解决方案2】:

    您可以将 target2 的完整规则写入单独的文件,然后 -include 它:

    具体的机制将取决于您的具体用例,使用这种方法可能无法实现我们所需要的,但它支持多种样式来自动生成依赖项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      • 1970-01-01
      • 2021-03-20
      相关资源
      最近更新 更多