Makefile中的:=和=有什么区别?

问题描述 投票:0回答:7

对于 Make 中的变量赋值,我看到 := 和 = 运算符。他们之间有什么区别?

makefile gnu-make colon-equals
7个回答
170
投票

简单作业
:=

简单的赋值表达式仅在第一次出现时计算一次。 例如,如果第一次遇到时的

CC :=${GCC} ${FLAGS}
被评估为
gcc -W
那么 每次
${CC}
出现时,都会被
gcc -W
替换。

递归赋值
=

每次遇到变量时都会计算递归赋值表达式 在代码中。例如,像

CC = ${GCC} {FLAGS}
这样的语句只有在以下情况下才会被评估: 执行类似
${CC} file.c
的操作。但是,如果变量
GCC
被重新分配,即
GCC=c++
那么重新分配后
${CC}
将转换为
c++ -W

有条件作业
?=

条件赋值仅在变量没有值时才为其赋值

追加
+=

假设

CC = gcc
那么附加运算符的使用方式类似于
CC += -w

那么
CC
现在的值为
gcc -W

有关更多信息,请查看这些教程


121
投票

这在 GNU Make 文档中标题为 6.2 变量的两种风格的部分中进行了描述 .

简而言之,用

:=
定义的变量会扩展一次,但用
=
定义的变量每次使用时都会扩展。


55
投票

对我来说,在实践中看到它的最好方法是在这个 Makefile 片段中:

简单的作业

XX := $(shell date) # date will be executed once
tt:
    @echo $(XX)
    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)
    sleep 2
    @echo $(XX)

跑步

make tt

将产生:

sex 22 jan 2021 14:56:08 -03
sex 22 jan 2021 14:56:10 -03

不同


12
投票

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

=
定义递归扩展变量。
:=
定义了一个简单扩展变量。


6
投票

这是一个老问题,但这个例子可以帮助我在我忘记的时候理解其中的区别。

使用以下 Makefile 运行

make
将立即退出:

a = $(shell sleep 3)

使用以下 Makefile 运行

make
将休眠 3 秒,然后退出:

a := $(shell sleep 3)

在前一个 Makefile 中,直到在 Makefile 中的其他地方使用

a
才会被评估,而在后者中
a
即使没有被使用也会立即评估。


1
投票

递归赋值

=
每次使用时都会进行评估,但不是按照在配方命令中遇到它的顺序,而是在之前运行任何配方命令。

基于以下示例:

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

0
投票

=
称为递归扩展变量或惰性扩展变量。在下面的例子中,当 make 读取这一行时

VAR1 = $(VAR1) + 100

将右侧 VAR1 中刚刚存储的值放入左侧 VAR1 中,而不进行扩展。当 make 尝试读取左侧定义的 $(VAR1) 时。这是不断重复并导致无限循环

VAR1 = 10
VAR2 = 20
VAR3 = 30

# Lazy initialization
VAR1 = $(VAR1) + 100

default:
    echo $(VAR1)

Makefile结果:

% make
Makefile:6: *** Recursive variable `VAR1' references itself (eventually).  Stop.

:=
称为扩展变量或即时

当 make 读取这一行时,右侧的变量将被扩展并将结果值保存到左侧。请参阅下面的程序输出

VAR1 = 10
VAR2 = 20
VAR3 = 30

# instant initialization
VAR1 := $(VAR1) + 100

default:
    echo $(VAR1)

% make
echo 10 + 100
10 + 100

Makefile结果:

% make
echo 10 + 100
10 + 100

编辑: 已经有很好的答案了。我在 Udemy 的 make 培训课程上遇到了这个概念,并提供了很好的例子。

© www.soinside.com 2019 - 2024. All rights reserved.