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.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-: $(TARGET__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
仅在 之后被声明 .
- 如果我把
makefile_with_prerequisite_variables
下面 MYDEF
和makefile_with_eval_call_statements
放在一起,那么MYDEF
中定义的食谱就没有了适当的先决条件,因为 $(TARGET__PREREQUISITES)
变量随后会被 makefile_with_prerequisite_variables
. 声明为
总而言之,我需要包含两个不同的 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
。
使用 make 的“'Remaking Makefiles'”功能,我正在生成带有 include
指令的部分 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.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-: $(TARGET__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
仅在 之后被声明 . - 如果我把
makefile_with_prerequisite_variables
下面MYDEF
和makefile_with_eval_call_statements
放在一起,那么MYDEF
中定义的食谱就没有了适当的先决条件,因为$(TARGET__PREREQUISITES)
变量随后会被makefile_with_prerequisite_variables
. 声明为
总而言之,我需要包含两个不同的 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
。