Makefile手册中"+=",":=","?="操作符的区别
Makefile手册中"+=",":=","?="操作符的区别
1."?="操作符
在GNUmake中,有一个变量在之前没有被赋值的情况下才会对这个变量进行赋值的操作,被称为条件赋值操作符"?="。因此
FOO ?= bar
其等价于
ifeq ($(origin FOO), undefined)
FOO = bar
endif
含义:如果变量"FOO"在之前没有被定义,就对此变量赋值"bar",否则不改变它的值。
2."+="操作符
通常,一个通用变量在定义之后的其他一个地方,可以对其值进行追加。这是非常有用的。我们可以在定义时(也可以不定义而直接追加)给它赋一个基本值,后续根据需要可随时对它的值进行追加(增加它的值)。在 Makefile 中使用"+="(追加方式)来实现对一个变量值的追加操作。因此
objects = main.o foo.o bar.o utils.o
objects += another.o
其等价于
objects = main.o foo.o bar.o utils.o
objects = main.o foo.o bar.o utils.o another.o
"+="操作符在不同的情况下,含义是不一样的
1.如果被追加值的变量之前没有定义,那么,“+=”会自动变成“=”,此变量就被定义为一个递归展开式的变量。如果之前存在这个变量定义,那么“+=”就继承之前定义时的变量风格。
2.直接展开式变量的追加过程:变量使用“:=”定义之后“+=”操作将会首先替换展开之前此变量的值,然后在末尾添加需要追加的值,并使用“:=”重新给此变量赋值。实际的过程像
下边那样:
variable := value
variable += more
就是:
variable := value
variable := $(variable) more
3.递归展开式变量的追加过程:一个变量使用“=”定义之后“+=”操作时不对之前此变量值中的任何引用进行替换展开,而是按照文本的扩展方式(之前等号右边的文本未发生变化)替换,尔后在末尾添加需要追加的值,并使用“=”给此变量重新赋值。实际的过程和上边的相类似:
variable = value
variable += more
就是:
temp = value
variable = $(temp) more
当然了,上边的过程并不会存在中间变量:“temp”,使用它的目的时方便描述。这种情况时如果“value”中存在某种引用,情况就有些不同了。看我们通常一个会用到的例子:
3.":="操作符
为了避免“递归展开式”变量即使用"="定义的变量存在的问题和不方便。GNU make 支持另外一种风格的变量,称为“直接展开”式。这种风格的变量使用":="定义。在使用":="定义变量时,变量值中对其他变量或者函数的引用在定义变量时被展开(对变量进行替换)所以变量被定义后就是一个实际需要的文本串,其中不再包含任何变量的引用。因此
x := foo
y := $(x) bar
x := later
其等价于
y := foo bar
x := later
和递归展开式变量不同:此风格变量在定义时就完成了对所引用变量和函数的展开,因此不能实现对其后定义变量的引用。如:
y := $(x) bar
x := later
其等价于
y := bar
x := later
由于变量"x"的定义出现在"y"定义之后。因此在"y"的定义中,"x"的值为空。"y"的值为"bar"而不是"later bar"。这一点也是直接展开式和递归展开式变量的不同点。