2016-08-29 67 views
1

使用make的''Remaking Makefiles''功能我使用include指令(请参阅Makefile: defining rules and prerequisites in recipes)生成部分makefile。现在我一直无法看到如何表达包含的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成一个单一的生成文件和规则的原因有两方面:

首先,我真正的设置,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以上MYDEFmakefile_with_prerequisite_variables然后在$eval($call(MYDEF))语句组合在一起它不会工作,因为MYDEF仅在之后被宣布。
  • 如果我把makefile_with_prerequisite_variables下面MYDEFmakefile_with_eval_call_statements在一起,然后在MYDEF定义的食谱不会有正确的prerequisits因为$(TARGET_$1_PREREQUISITES)变量,然后由makefile_with_prerequisite_variables声明之后

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

回答

1

首先,通过转义$(FOO)的值,可以很容易地修复在此简单示例中创建的生成文件,以便在创建bar.make时不会扩展它,而是延迟到读入为止。所以:

bar.make: Makefile foo.make 
     echo 'BAR:=$$(FOO)' > [email protected] 

然而,这可能不是你的更复杂的现实生活中的makefile就足够了。

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

GNU make does NOT像这样工作:解析makefiles,尝试重建第一个包含的makefile,如果重建,重新执行;如果它不被重建在去下包含makefile文件等

一个简单的技巧,如果你必须有这种类型的顺序,你可以用的是把包括bar.makefoo.make

all: 

-include foo.make 

foo.make: Makefile 
     printf -- '-include bar.make' > [email protected] 
     echo FOO:=blub bla baz >> [email protected] 

bar.make: Makefile foo.make 
     echo 'BAR:=$$(FOO)' > [email protected] 

通过这样做,您可以确保如果foo.make不存在,make将看不到bar.make的包含,因此它不会尝试构建它。只有在第一次重新执行后,才会看到bar.make的包含并尝试构建它。有一件事:如果你得到最新版本的GNU让你不再需要使用-include这个技巧。即使使用生成的makefile,您也可以使用include

+0

你又一次拯救了我的一天!如果我能给你更多的赞扬,我会。你的建议都非常有价值。非常感谢! – josch