Makefile中=, :=, ?=和+=的含义
在Makefile语法中,时不时会见到各种“=”号的赋值语句,除了常见的“=”和“:=”,还有“?=”等
那么这些赋值等号分别表示什么含义呢?
1. 含义
1.1 " = " (普通赋值)
-
“=”是最普通的等号,然而在Makefile中确实最容易搞错的赋值等号,使用“=”进行赋值,变量的值是整个makefile中最后被指定的值。不太容易理解,举个例子如下:
VIR_X = foo VIR_Y = $(VIR_X) bar VIR_X = xyz
经过上面的赋值后,最后VIR_Y的值是xyz bar,而不是foo bar。在make时,会把整个makefile展开,拉通决定变量的值
总结:
- 这种赋值方式会将右边的值赋给左边的变量。
- 如果右侧的值包含了其他变量,那么这些变量会在实际使用时被替换为它们的值。
- 变量的值在Makefile的整个执行过程中都是可变的,即如果在后面的某个地方改变了这个变量的值,那么前面已经展开的地方也会受到影响。
1.2 " := " (立即赋值)
-
相比于前面“最普通”的“=”,“:=”就容易理解多了。“:=”就表示直接赋值,赋予当前位置的值。同样举个例子说明
VIR_X := foo VIR_Y := $(VIR_X) bar VIR_X := xyz
最后变量VIR_Y的值是foo bar,即根据当前位置进行赋值。因此相比于“=”,“:=”才是真正意义上的直接赋值。
总结:
- 立即赋值,也称为静态赋值,它会将右边的值立即展开并赋给左边的变量。
- 如果右侧的值包含了其他变量,那么这些变量会在赋值时立即被替换为它们的当前值。
- 变量的值一旦被赋值,就不再改变,即使在后面的Makefile中改变了这个变量的值。
1.3 " ?= " (条件赋值)
-
“?=”表示如果该变量没有被赋值,则赋予等号后的值。举例:
VIR ?= new_value
如果VIR在之前没有被赋值,那么VIR的值就为new_value.
VIR := old_value VIR ?= new_value
这种情况下,VIR的值就是old_value
总结:
- 条件赋值,也称为默认赋值,它会在变量尚未被赋值时将右边的值赋给左边的变量。
- 如果变量已经被赋值,那么这个赋值操作将被忽略。
- 这通常用于为变量提供默认值,而不覆盖用户或环境已经设置的值。
1.4 " += " (追加赋值)
-
“+=”和平时写代码的理解是一样的,表示将等号后面的值添加到前面的变量上。举例:
VIR = foo VIR += bar
最后结果为foobar.
总结:
- 追加赋值,它会在变量现有的值后面追加新的值。
- 如果变量之前没有被赋值,那么+=的行为类似于=。
- 注意,如果变量之前是用:=赋值的,那么+=会保留之前的立即赋值行为。
2. 实例
我们来做个简单的实验,新建一个Makefile,内容为:
ifdef DEFINE_VRE
VRE = “Hello World!”
else
endif
ifeq ($(OPT),define)
VRE ?= “Hello World! First!”
endif
ifeq ($(OPT),add)
VRE += “Kelly!”
endif
ifeq ($(OPT),recover)
VRE := “Hello World! Again!”
endif
all:
@echo $(VRE)
敲入以下make命令:
make DEFINE_VRE=true OPT=define 输出:Hello World!
make DEFINE_VRE=true OPT=add 输出:Hello World! Kelly!
make DEFINE_VRE=true OPT=recover 输出:Hello World! Again!
make DEFINE_VRE= OPT=define 输出:Hello World! First!
make DEFINE_VRE= OPT=add 输出:Kelly!
make DEFINE_VRE= OPT=recover 输出:Hello World! Again!
从上面的结果中我们可以清楚的看到他们的区别了
- = 是最基本的赋值
- := 是赋予当前位置的值
- ?= 是如果没有被赋值过就赋予等号后面的值
- += 是添加等号后面的值