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

时间:2016-08-29 11:55:33

标签: makefile gnu-make

使用make''Remaking Makefiles''功能我使用include指令生成部分makefile(参见Makefile: defining rules and prerequisites in recipes)。现在我无法看到如何表达包含的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?< / p>

我无法将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-$1: $(TARGET_$1_PREREQUISITES)
    [...]
endf
-include makefile_with_eval_call_statements

makefile_with_prerequisite_variablesmakefile_with_eval_call_statements的内容无法进入单个makefile片段:

  • 如果我将makefile_with_eval_call_statements 置于 MYDEF上方与makefile_with_prerequisite_variables一起,则$eval( $call( MYDEF))中的MYDEF语句将无效,因为{{1} }仅在之后声明
  • 如果我将makefile_with_prerequisite_variables 放在 MYDEF下与makefile_with_eval_call_statements一起,则MYDEF中定义的食谱将没有正确的先决条件,因为{ {1}}变量随后将被$(TARGET_$1_PREREQUISITES)
  • 声明为

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

1 个答案:

答案 0 :(得分:1)

首先,您可以通过转义$(FOO)的值来轻松修复此简单示例中的makefile创建,以便在创建bar.make时不会扩展它,而是延迟到#39}。读入。所以:

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

然而,在您更复杂的现实生活文件中,这可能还不够。

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,你不再需要使用-include技巧。即使使用生成的makefile,也可以使用include