Makefile 中的 := 和 = 有啥区别?

Posted

技术标签:

【中文标题】Makefile 中的 := 和 = 有啥区别?【英文标题】:What's the difference between := and = in Makefile?Makefile 中的 := 和 = 有什么区别? 【发布时间】:2011-06-20 06:12:07 【问题描述】:

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

【问题讨论】:

Makefile variable assignment 的可能重复项 What is the difference between the GNU Makefile variable assignments =, ?=, := and +=?的可能重复 【参考方案1】:

对我来说,在实践中查看它的最佳方式是在这个 Makefile sn-p 期间:

简单赋值

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

不同的

【讨论】:

【参考方案2】:

这是一个老问题,但这个例子可以帮助我在忘记时理解差异。

使用以下 Makefile 运行 make 将立即退出:

a = $(shell sleep 3)

使用以下 Makefile 运行 make 会休眠 3 秒,然后退出:

a := $(shell sleep 3)

在前一个 Makefile 中,a 直到它在 Makefile 的其他地方使用才被评估,而在后者中,a 即使没有被使用也会立即被评估。

【讨论】:

【参考方案3】:

简单赋值:=

一个简单的赋值表达式只计算一次,在第一次出现时。 例如,如果在第一次相遇期间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

更多信息请查看tutorials

【讨论】:

“一个简单的赋值表达式在第一次出现时只计算一次”:明确地说,扩展/计算是在定义变量时完成的,而不是第一次使用它。 【参考方案4】:

这在 GNU Make 文档的标题为 6.2 The Two Flavors of Variables 的部分中有描述。

简而言之,用:= 定义的变量会展开一次,而用= 定义的变量会在每次使用时展开。

【讨论】:

那么说 := 更有效对吗?或者效率不是 Makefile 的真正因素? @Ungeheuer 这不是问题,因为进程调用(make 的主要工作)比这种内部变量解析的开销要大得多。【参考方案5】:

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

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

【讨论】:

以上是关于Makefile 中的 := 和 = 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

Makefile 中的括号 $() 和大括号 $ 语法有啥区别?

Makefile 中的 $(objs): %.o : %.cpp 和 $(objs): $(objs:.o=.cpp) 有啥区别

makefile 和 sh 文件有啥区别

GNU Makefile 变量赋值 =、?=、:= 和 += 有啥区别?

android.mk makefile 有啥区别

-m32、-m64 和 gcc 选项中的任何内容有啥区别?