2016-08-19 151 views
1

我正在阅读GNU make手册,并对变量继承机制感到困惑。让我先讲解基础知识。GNU make中的高级变量继承


我从手动章从环境6.10变量引用:

变量在使可以来自其中使运行环境。 使得在启动时看到的每个环境变量都转换为使变量具有相同的名称和值。

想象一下,我打开一个shell(称之为“shell 1”)并定义了两个变量。然后我启动使有两个选项,“op1”和“op2”。程序使自己读取一个makefile并构造第三个变量,称为“varC”。我们得到的情况,如下图所示:

enter image description here


我继续从手动报价:

使运行的配方,变量在Makefile中定义被放置到每个外壳的环境中。

这就是我现在要做的。目标的第一个配方行被执行,其中使打开一个临时shell(称之为“shell 2”)。我认为所有变量“varA”,“varB”和“varC”都出现在这个shell中,因此可以被配方行使用。虽然我不是100%确定的。

enter image description here


手动继续哪里食谱要求的情况下使递归:

默认情况下,只有从环境或命令行来变量传递给递归调用。您可以使用export指令来传递其他变量。

下一个食谱行是递归调用$(MAKE)。顶层使得打开一个临时shell(称之为“shell 3”)来运行这个子制造实例。由于varC未明确导出,因此我认为它不在shell 3中,也不在子版本中。我对么?

enter image description here

我贴这个主题,即可获得经验丰富的makefile作家澄清。我是这个主题的新手,但我正在尽最大努力研究该手册并在此之后开始使用。所有帮助非常感谢:-)

PS:如果您发布了答案,请提及您的答案是否适用于Linux,Windows或两者。

回答

1

我只会回答Windows,因为我在这里没有Unix环境。它应该已经给出了它在GNU make中的工作原理。

起初我会假设你所说的环境变量的生命周期与正在运行的shell的生命周期有关,所以它不是一个系统环境变量。

在Windows上有两个程序来设置变量:SETSETX。可能有更多的细节,但为了简单起见,SET将仅为当前shell及其子进程设置变量,并且SETX将设置系统环境变量。我只会使用SET,因为我不想处理系统环境变量。

我会给一个经验的答案。我做这个设置的测试:

\---level1 
    | Makefile 
    | 
    \---level2 
     | Makefile 
     | 
     \---level3 
       Makefile 

(第一级) - Makefile文件

LEVEL = LEVEL1 
LEVEL1VAR = VAR1 
varB = 12 
export varB 

.PHONY: foo 

foo: 
    @echo $(LEVEL) var level 1 : $(LEVEL1VAR) 
    @echo $(LEVEL) varA is $(varA) 
    @echo $(LEVEL) varB is $(varB) 
    cd level2 & $(MAKE) foo 

(第二级) - Makefile文件

LEVEL = LEVEL2 
LEVEL2VAR = VAR2 
MKID = MKID2 

varC = 13 
export varC 

.PHONY: foo 

foo: 
    @echo $(LEVEL) var level 1 : $(LEVEL1VAR) 
    @echo $(LEVEL) var level 2 : $(LEVEL2VAR) 
    @echo $(LEVEL) varA is $(varA) 
    @echo $(LEVEL) varB is $(varB) 
    cd level3 & $(MAKE) foo 

3级 - Makefile文件

LEVEL = LEVEL3 
LEVEL3VAR = VAR3 

.PHONY: foo 

foo: 
    @echo $(LEVEL) var level 1 : $(LEVEL1VAR) 
    @echo $(LEVEL) var level 2 : $(LEVEL2VAR) 
    @echo $(LEVEL) var level 3 : $(LEVEL3VAR) 
    @echo $(LEVEL) varA is $(varA) 
    @echo $(LEVEL) varB is $(varB) 
    @echo $(LEVEL) varC is $(varC) 

在测试开始时,我在level1文件夹中打开一个shell(Windows命令提示符)。我创建一个变量varA与值11:

SET varA=11

然后我所说的第一生成文件,这将调用第二个,这将调用第三。

make foo

这里是输出:

LEVEL1 var level 1 : VAR1 
LEVEL1 varA is 11 
LEVEL1 varB is 12 
cd level2 & make foo 
LEVEL2 var level 1 : 
LEVEL2 var level 2 : VAR2 
LEVEL2 varA is 11 
LEVEL2 varB is 12 
cd level3 & make foo 
LEVEL3 var level 1 : 
LEVEL3 var level 2 : 
LEVEL3 var level 3 : VAR3 
LEVEL3 varA is 11 
LEVEL3 varB is 12 
LEVEL3 varC is 13 

因此,我们可以看到:

  • shell变量可以使
  • 的所有子调用访问
  • 导出的Makefile变量可以是从这个Makefile的化妆的
  • 非出口的Makefile变量不能从这个Makefile的make的子调用访问所有子调用ccessed

您可以轻松地再现这个例子执行更多测试。

请注意,您实际上可以包含另一个Makefile并因此获取其变量和规则,请参见GNU make: Include。如果您没有真正关注发生的情况,我不建议使用它,因为如果它们在包含的Makefile中与包含的Makefile中的名称相同,则可以覆盖规则。

+0

真棒!非常感谢Tim。你的回答是优雅而有启发性的! –

2

我想你overdissecting段落:

当“制作”运行一个命令脚本,在makefile 定义的变量被放置到命令的环境。这允许你通过 传递值来'调用'调用。默认情况下,只有来自环境或命令行的变量才会传递给递归调用。您可以使用'export'指令来传递其他变量。

所有这些都在一起,所以只有在传入环境或命令行中设置的环境变量或者在Makefile中显式“导出”的环境变量才放置在被调用的命令环境中该命令是$(MAKE)或别的东西)。

一个有趣的转角情况是在传入环境和Makefile中设置的变量(但未显式导出)。 Makefile值然后覆盖传入的环境值,AND也被导出(因为它位于传入环境中,尽管值不同)。

的Makefile:

TEST = test 
default: 
     @echo TEST="\"$$TEST\"" 

结果:

$ make 
TEST="" 
$ TEST=xx make 
TEST="test" 
$ make TEST=xx 
TEST="xx"