目录
01-符号=
、符号:=
、符号+=
区分符号=
和符号:=
在 Makefile
中,符号 :=
和 =
都用于定义变量,但它们的行为方式不同,主要体现在变量值的计算和展开时机上。
1. :=
(简单赋值,立即展开)
- 特点:使用
:=
定义的变量会在赋值时立即计算和展开右边的值,然后将结果赋给变量。 - 用途:当变量的值在定义时已经确定,并且不会再依赖于其他变量的值发生变化时,适合使用
:=
。
示例:
FOO := $(BAR)
BAR := hello
- 这里
FOO
的值在定义时就会被计算。当FOO := $(BAR)
被执行时,BAR
的值(hello
)被立即展开并赋值给FOO
。 - 最终结果:
FOO = hello
2. =
(递归赋值,延迟展开)
- 特点:使用
=
定义的变量不会立即计算右边的值,而是延迟到变量被引用时才计算和展开右边的内容。 - 用途:当变量的值可能依赖于其他变量的值发生变化时,适合使用
=
。
示例:
FOO = $(BAR)
BAR = hello
- 这里
FOO
的值在定义时不会被计算,而是保留$(BAR)
作为变量的值。 - 当
FOO
被引用时,BAR
的值才会被计算并展开。 - 最终结果:
FOO = hello
3. 两者的区别总结
符号 | 行为 | 展开时机 | 典型用途 |
---|---|---|---|
:= |
简单赋值,立即计算和展开 | 定义时展开 | 值已确定、不依赖其他变量的情况 |
= |
递归赋值,保留引用,延迟展开 | 使用时展开 | 依赖于其他变量或需要动态计算的情况 |
4. 对比示例
BAR = hello
FOO = $(BAR)
BAZ := $(BAR)
BAR = world
all:
@echo FOO = $(FOO)
@echo BAZ = $(BAZ)
- 结果:
FOO = world BAZ = hello
解释:
FOO
使用了=
定义,它延迟展开,因此FOO
的值在BAR
被重新赋值后变成world
。BAZ
使用了:=
定义,它在赋值时立即展开BAR
的值,因此固定为hello
。
5. 性能方面的考虑
:=
性能更高:由于变量值在定义时已展开,后续使用时无需再进行计算。=
更灵活:允许变量的值依赖其他变量动态变化。
总结建议
- 使用
:=
:如果变量的值是固定的,或在定义时已确定,可以使用:=
提高效率和简洁性。 - 使用
=
:如果变量的值需要动态变化,或依赖于其他变量的值,使用=
提供更多的灵活性。
根据具体需求选择适当的赋值方式,可以编写更高效、清晰的 Makefile
!
符号+=
符号+=
为追加赋值,变量的值会被追加到现有的值后面。
比如:
FOO := hello
FOO += world
上面这条两条语句使得变量FOO的值为 hello world
02-需要知道的几个基本常识
02-1-Makefile文件并不是顺序执行,而是先解析再执行
关于这一点的最直接的例子就是伪目标的定义和声明语句:
PHONY := __build
......
......
......
.PHONY : $(PHONY)
变量PHONY用于存储Makefile中的所有伪目标名,但是直到文Makefile的最后一行才对存储在变量PHONY中的所有伪目标名进行声明,但是中间的语句会用到这些伪目标名,这就充分证明了Makefile文件并不是顺序执行,而是先解析再执行。
关于伪目标的详细解释,请看本文第03点的第2小点的第⑵点。
02-2-make命令执行时到底是执行哪个Makefile文件
如果make命令是下面这种形式:
make 目标名
那么make就会进入当前目录查找名为Makefile的文件开始执行构建。
如果make命令是下面这种形式:
make -C<