使用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.make
和bar.make
合并到一个makefile和规则中的原因有两个:
首先,在我的实际设置中,bar.make
依赖于更多的中间目标,而这些目标反过来依赖于foo.make
。因此,在创建foo.make
时,无法制作bar.make
的内容。
其次,在我的实际设置中,foo.make
和bar.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_variables
和makefile_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的内容。
答案 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
。