在 Makefile: = 和 = 有什么区别?

对于 Make 中的变量赋值,我看到: = 和 = 操作符。它们之间的区别是什么?

76589 次浏览

来自 http://www.gnu.org/software/make/manual/make.html#Flavors:

=定义一个递归展开的变量。 :=定义一个简单展开的变量。

这在 GNU Make 文档中有描述,在标题为 < a href = “ http://www.GNU.org/software/Make/hand/html _ node/Flavors.html # Flavor”rel = “ noReferrer”> 6.2 The Two Flavor of Variables 的章节中有描述 .

简而言之,用 :=定义的变量可以展开一次,但是用 =定义的变量只要使用就可以展开。

简单的任务 :=

一个简单的赋值表达式只在第一次出现时求值一次。 例如,如果在第一次遭遇时 CC :=${GCC} ${FLAGS}被评估为 gcc -W,那么 每次 ${CC}发生它将被取代与 gcc -W

递归赋值 =

每次遇到变量时都计算递归赋值表达式 例如,像 CC = ${GCC} {FLAGS}这样的语句只有在 执行类似于 ${CC} file.c的操作 GCC=c++然后 ${CC}将被转换为 c++ -W后,重新分配。

条件赋值 ?=

条件赋值只有在变量没有值时才给它赋值

附录 +=

假设使用 CC = gcc,然后使用附加运算符,就像使用 CC += -w一样
那么 CC现在的值就是 gcc -W

想了解更多,请看这些 教程

对我来说,在实践中看到它的最佳方式是在这个 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进行评估,而在后一种文件中,即使没有使用,也会立即对 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