在执行依赖规则

时间:2018-03-18 09:47:49

标签: makefile gnu-make

我的makefile使用自动生成的依赖项。为此,我在我的顶级makefile中有类似于:

# Makefile
include target1.deps
include target2.deps

all: target2.deps
    cat $^

target2.deps: target1.deps
target1.deps:
    echo "target2.deps:" > $@
    echo "  touch target2.deps" >> $@

最初,target1.depstarget2.deps不存在。首次实例化make时,它会解析整个Makefile并搜索生成这些包含文件的方法。在构建它们之后,它会重新调用自身,导致重新分析Makefile并包含此次包含的文件。至少,这是我的理解。

问题在于,当我运行上面的Makefile时,Make first builds target1.deps,然后执行all规则的主体,从不构建或包含target2.deps。这会导致cat错误:cat: target2.deps: No such file or directory

这似乎与我相矛盾。我明确告诉Make all取决于target2.deps,但它会在满足其先决条件之前尝试执行规则!

预期的行为是target1.deps应该构建并包含,然后target2.deps应该使用{中包含的规则构建并包含 {1}},然后应运行target1.deps。我如何实现这一目标?

上下文:由于这是非常抽象的,这是我的目标:我有一个目标all,它是从模板index.html生成的,但我不知道任何关于它的依赖关系。我需要找出(a)在构建index.html.in之前我需要创建哪些文件,以及(b)在运行时哪些文件index.html将依赖。

例如index.html包含一些从index.html中提取的内联css - 因此我需要在构建global.css之前构建global.css。另一方面,index.html链接到index.html,因此在我构建about.html之后,我还要构建index.html。我将前者称为“构建依赖项”,将后者称为“运行时依赖项”。所以我的makefile看起来像这样:

about.html

我想要发生的是让Make遵循以下步骤:

  1. 构建include index.html.build_deps include index.html.runtime_deps all: index.html $(runtime_deps_index.html) %.build_deps: %.in ./extract_build_deps %< -o %@ %.runtime_deps: % ./extract_runtime_deps %< -o %@ %: %.in ./compile_template %< -o $@
  2. 包括index.html.build_deps
  3. 构建index.html.build_deps(现在是global.css的已知先决条件)
  4. 构建index.html
  5. 构建index.html
  6. 包括index.html.runtime_deps
  7. 构建about.html(包含在index.html.runtime_deps
  8. 中的$(runtime_deps_index.html)
  9. 已达到目标index.html.runtime_deps
  10. 实际发生的事情:

    1. 看到all可以直接从index.html.build_deps构建;这样做。
    2. 看到index.html.in可以从index.html.runtime_deps构建,可以从index.html构建。
    3. 制作版本index.html.in。它错误,因为尚未构建index.html
    4. 如果global.css在构建之后包含Make,那么它就会知道index.html.build_deps依赖关系。但是因为它在扩展其中任何一个之前尝试构建所有包含文件,所以它不知道依赖性。我想添加依赖项“index.html.runtime_deps取决于已包含的index.html.build_deps ,但我不确定如何指定这样的依赖项。

1 个答案:

答案 0 :(得分:3)

@Dario是正确的。更具体一点,这些是以下步骤:

  1. 阅读makefile。
  2. 尝试构建target1.deps。
  3. 找到目标target1.deps并执行配方。
  4. 配方成功,但是观察到文件target1.deps仍然不存在,因此make不会将目标标记为已更新。
  5. 尝试构建target2.deps。
  6. 它的目标取决于target1.deps,它已经构建了,但没有配方,所以make不会将target2.deps标记为已更新(因为它从未更新过,因此到目前为止正如make可以告诉 - 它没有运行任何更新它的配方。)
  7. 因此,make决定所包含的makefile中没有一个实际更新,也不会重新执行。
  8. 然后想要建立all;它看到all取决于target2.deps,但已经考虑了该目标,并认为它不需要重建,所以现在make已完成所有工作。
  9. 您可以运行make -d并按照决定制定。