Makefile:声明包含文件之间的依赖关系

Makefile: Declaring dependencies between included files

使用 make 的“'Remaking Makefiles'”功能,我正在生成带有 include 指令的部分 makefile(参见 )。现在我无法看到如何表达包含的 makefile 之间的依赖关系。他们似乎都被一次评估了。

考虑以下说明我的问题的最小 makefile:

all:

-include foo.make
-include bar.make

foo.make: Makefile
    echo FOO:=blub bla baz > foo.make

bar.make: Makefile foo.make
    echo BAR:=$(FOO) > bar.make

如果我现在运行 make我会得到:

$ cat foo.make
FOO:=blub bla baz
$ cat bar.make
BAR:=

为什么?既然bar.make依赖于foo.make,难道bar.make的求值不应该等到它成功包含了foo.make才对吗?

以及如何解决此问题并确保 bar.make 稍后重新评估或仅在 foo.make 存在时评估,包括在内并可以定义变量 BAR

我无法将 foo.makebar.make 组合成一个 makefile 和规则的原因有两个:

首先,在我的实际设置中,bar.make 依赖于更多的中间目标,而这些中间目标又传递地依赖于 foo.make。所以在可以创建foo.make的时候,还不能制作bar.make的内容。

其次,在我的实际设置中,foo.makebar.make 不仅定义了变量,还定义了 eval() define/endef 块。所以我必须写:

-include makefile_with_prerequisite_variables
define MYDEF
sometarget-: $(TARGET__PREREQUISITES)
    [...]
endf
-include makefile_with_eval_call_statements

makefile_with_prerequisite_variablesmakefile_with_eval_call_statements 的内容不能放在单个 makefile 片段中:

总而言之,我需要包含两个不同的 makefile,其中一个依赖于另一个。我不知道如何表达这种关系,这样一个 makefile 的内容只会在另一个 makefile 是最新的并包含到主 makefile 中后创建。

首先,您在这个简单示例中创建的 makefile 可以通过转义 $(FOO) 的值轻松修复,这样它就不会在创建 bar.make 时展开,而是推迟到读入时才进行扩展。所以:

bar.make: Makefile foo.make
        echo 'BAR:=$$(FOO)' > $@

但是,这在您更复杂的现实生活中的 makefile 中可能还不够。

GNU make 是这样工作的:首先解析所有的 makefile。然后对于每个包含的 makefile,将其视为目标并尝试构建它(例如,就好像用户调用了 make include1.mk include2.mk include3.mk ...)。然后在最后,如果任何包含的 makefile 被重建,重新执行我们自己并从头开始整个过程​​。

GNU make NOT 是这样工作的:解析 makefile,尝试重建第一个包含的 makefile,如果重建了,则重新执行;如果它没有重建继续下一个包含的 makefile,等等

如果你必须有这种类型的订单,你可以使用一个简单的技巧是将 bar.make 的包含放入 foo.make:

all:

-include foo.make

foo.make: Makefile
        printf -- '-include bar.make' > $@
        echo FOO:=blub bla baz >> $@

bar.make: Makefile foo.make
        echo 'BAR:=$$(FOO)' > $@

这样做可以确保如果 foo.make 不存在,make 将看不到 bar.make 的包含,因此它不会尝试构建它。只有在第一次重新执行后才会看到 bar.make 的包含并尝试构建它。

一件事:如果您获得最新版本的 GNU make,您就不再需要使用 -include 技巧。即使使用生成的 makefile,您也可以只使用 include