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

Makefile:声明包含文件之间的依赖关系,makefile,gnu-make,Makefile,Gnu Make,使用make的“重新生成生成文件”功能,我使用include指令生成生成生成文件的一部分(请参阅)。现在,我无法理解如何表达包含的makefile之间的依赖关系。它们似乎都是一次评估出来的 考虑以下说明我的问题的最小生成文件: all: -include foo.make -include bar.make foo.make: Makefile echo FOO:=blub bla baz > foo.make bar.make: Makefile foo.make

使用make的“重新生成生成文件”功能,我使用
include
指令生成生成生成文件的一部分(请参阅)。现在,我无法理解如何表达包含的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
存在时计算一次。make包括在内,并且可以定义变量
bar

我无法将
foo.make
bar.make
合并到单个makefile中的原因有两个:

首先,在我的实际设置中,
bar.make
依赖于更多的中间目标,而这些中间目标反过来又依赖于
foo.make
。因此,在创建
foo.make
时,还不能创建
bar.make
的内容

其次,在我的实际设置中,
foo.make
bar.make
不仅定义变量,而且定义/endef块。所以我必须写:

-include makefile_with_prerequisite_variables
define MYDEF
sometarget-$1: $(TARGET_$1_PREREQUISITES)
    [...]
endf
-include makefile_with_eval_call_statements
带有前提条件变量的
makefile\u和带有eval\u call\u语句的
makefile\u的内容不能包含在单个makefile片段中:

  • 如果我在
    MYDEF
    上面放置
    makefile\u和
    以及
    makefile\u和前提变量
    ,那么
    $eval($call(MYDEF))
    语句将无法工作,因为
    MYDEF
    只是在后面声明的
  • 如果我将
    makefile\u和前提条件变量
    放在
    MYDEF
    下面,再加上
    makefile\u和评估调用语句
    ,那么
    MYDEF
    中定义的配方将没有适当的前提条件,因为
    $(目标条件1)
    变量随后将由
    makefile\u和前提条件变量声明

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

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

bar.make: Makefile foo.make
        echo 'BAR:=$$(FOO)' > $@
但是,在更复杂的实际makefile中,这可能还不够

gnumake的工作原理如下:首先解析所有makefile。然后,对于每个包含的makefile,将其视为目标并尝试构建它(例如,就像用户调用了
makeinclude1.mk include2.mk include3.mk…
)。最后,如果重建了包含的任何makefile,请重新执行我们自己,从头开始整个过程

GNU make不是这样工作的:解析makefiles,尝试重建包含的第一个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
的包含,因此它不会尝试构建它。只有在第一次重新执行后,才会看到包含的
条。制作
并尝试构建它


有一件事:如果你得到了最新版本的GNU,你就不再需要使用
-include
技巧了。即使生成了makefiles,您也可以使用
include

您又一次保存了我的一天!如果我能给你更多的选票,我会的。你的两个建议都很有价值。谢谢!