如何理解GNU make文档中的‘立即展开变量赋值’(:::=)?
GNU make中
:::=(完全立即展开赋值)的解释 :::=是GNU make 4.3版本才引入的新特性,是对传统:=/::=立即展开赋值的增强版,核心区别在于它会彻底清除所有变量引用,把赋值右侧的表达式完全展开成字面量,之后无论相关变量怎么修改,这个变量的值都不会再变化。
先结合你已经熟悉的赋值方式,对比看:::=的独特性:
已知赋值方式回顾
=:递归(延迟)展开,每次使用变量时才解析右侧表达式,会受后续变量修改影响,甚至可能出现递归展开问题。:=/::=:立即(简单)展开,定义变量时就解析右侧表达式,但如果右侧引用了递归展开型变量,它只会展开到变量引用的层级,不会彻底解析到字面量。
:::=的核心特性:彻底立即展开
用一个直观的例子就能看出差异:
# 定义递归展开变量(用=赋值) RECURSIVE_VAR = $(ANOTHER_VAR) ANOTHER_VAR = 初始值 # 用:=赋值 SIMPLE_VAR := $(RECURSIVE_VAR) # 用:::=赋值 FULL_SIMPLE_VAR :::= $(RECURSIVE_VAR) # 后续修改递归变量的值 ANOTHER_VAR = 修改后的值 all: @echo SIMPLE_VAR输出: $(SIMPLE_VAR) @echo FULL_SIMPLE_VAR输出: $(FULL_SIMPLE_VAR)
运行这个Makefile,输出结果为:
SIMPLE_VAR输出: 修改后的值 FULL_SIMPLE_VAR输出: 初始值
背后的逻辑:
SIMPLE_VAR := $(RECURSIVE_VAR)定义时,仅把$(RECURSIVE_VAR)展开为$(ANOTHER_VAR)(因为RECURSIVE_VAR是递归变量),所以后续ANOTHER_VAR修改后,执行echo时会再次解析$(ANOTHER_VAR)得到新值。FULL_SIMPLE_VAR :::= $(RECURSIVE_VAR)定义时,会逐层解析所有变量引用到最终字面量:先把$(RECURSIVE_VAR)解析为当时ANOTHER_VAR的具体值初始值,这个变量的值就此固定,后续ANOTHER_VAR的修改不会对它产生任何影响。
适用场景
当你需要某个变量的值完全固定在定义时刻,无论后续相关变量如何变动都不能影响它时,就适合用:::=。比如配置类固定参数、预计算的常量值,能避免后续变量修改带来的意外行为。
内容的提问来源于stack exchange,提问作者user23334898
相关产品推荐
相关产品推荐

