对于 Make 中的变量赋值,我看到 := 和 = 运算符。他们之间有什么区别?
简单的分配:=
一个简单的赋值表达式只在第一次出现时计算一次。例如,如果在第一次遇到时将 CC :=${GCC} ${FLAGS}
评估为 gcc -W
,那么每次出现 ${CC}
时,它将被替换为 gcc -W
。
递归赋值 =
每次在代码中遇到变量时都会计算递归赋值表达式。例如,只有在执行类似 ${CC} file.c
的操作时才会评估类似 CC = ${GCC} {FLAGS}
的语句。但是,如果变量 GCC
被重新赋值,即 GCC=c++
,那么 ${CC}
将在重新赋值后转换为 c++ -W
。
条件赋值 ?=
条件赋值仅在变量没有值时才为其赋值
附加 +=
假设 CC = gcc
然后附加运算符像 CC += -w
一样使用,那么 CC
现在的值是 gcc -W
有关更多信息,请查看这些 tutorials
这在 GNU Make 文档中标题为 6.2 The Two Flavors of Variables 的部分中进行了描述。
简而言之,用 :=
定义的变量会展开一次,但用 =
定义的变量会在每次使用时展开。
make
的主要工作)的开销比这种内部变量解析要大得多。
对我来说,在实践中查看它的最佳方式是在这个 Makefile 片段中:
简单的分配
XX := $(shell date) // date will be executed once
tt:
@echo $(XX)
$(shell sleep 2)
@echo $(XX)
跑步
make tt
将产生:
sex 22 jan 2021 14:56:08 -03
sex 22 jan 2021 14:56:08 -03
(相同的值)
扩展任务
XX = $(shell date) // date will be executed every time you use XX
tt:
@echo $(XX)
$(shell sleep 2)
@echo $(XX)
跑步
make tt
将产生:
sex 22 jan 2021 14:56:08 -03
sex 22 jan 2021 14:56:10 -03
不同的价值观
这是一个老问题,但这个例子可以帮助我在忘记时理解差异。
使用以下 Makefile 运行 make
将立即退出:
a = $(shell sleep 3)
使用以下 Makefile 运行 make
将休眠 3 秒,然后退出:
a := $(shell sleep 3)
在前一个 Makefile 中,a
直到它在 Makefile 的其他地方使用才被评估,而在后者中,a
即使没有被使用也会立即被评估。
每次使用递归赋值 =
时都会对其进行评估,但不是按照配方命令中遇到它的顺序,而是在运行任何配方命令之前。
基于以下示例:
default: target1 target2
target1 target2:
@echo "Running at: `gdate +%s.%N`"
@echo "Simple assignment: $(SIMPLE_ASSIGNMENT)"
@echo "Recursive assignment: $(RECURSIVE_ASSIGNMENT)"
sleep 1
@echo "Running at: `gdate +%s.%N`"
@echo "Simple assignment: $(SIMPLE_ASSIGNMENT)"
@echo "Recursive assignment: $(RECURSIVE_ASSIGNMENT)"
@echo
SIMPLE_ASSIGNMENT := $(shell gdate +%s.%N)
RECURSIVE_ASSIGNMENT = $(shell gdate +%s.%N)
输出:
❯ make
Running at: 1645056840.980488000
Simple assignment: 1645056840.949181000
Recursive assignment: 1645056840.958590000
sleep 1
Running at: 1645056842.008998000
Simple assignment: 1645056840.949181000
Recursive assignment: 1645056840.969616000
Running at: 1645056842.047367000
Simple assignment: 1645056840.949181000
Recursive assignment: 1645056842.027600000
sleep 1
Running at: 1645056843.076696000
Simple assignment: 1645056840.949181000
Recursive assignment: 1645056842.035901000