mmo*_*ris 740 makefile gnu-make
任何人都可以清楚地解释变量赋值在Makefile中是如何工作的.
有什么区别:
VARIABLE = value
VARIABLE ?= value
VARIABLE := value
VARIABLE += value
Run Code Online (Sandbox Code Playgroud)
我已经阅读了GNU Make手册中的部分,但它对我来说仍然没有意义.
Aln*_*tak 978
VARIABLE = value
Run Code Online (Sandbox Code Playgroud)
变量的正常设置 - 当使用变量时,不会在声明变量时递归地扩展变量中的值
VARIABLE := value
Run Code Online (Sandbox Code Playgroud)
通过简单扩展内部值来设置变量 - 其中的值在声明时间扩展.
VARIABLE ?= value
Run Code Online (Sandbox Code Playgroud)
仅在变量没有值时设置变量
VARIABLE += value
Run Code Online (Sandbox Code Playgroud)
将提供的值附加到现有值(如果变量不存在,则设置为该值)
str*_*ger 253
使用=会导致为变量赋值.如果变量已有值,则替换它.使用时,该值将被扩展.例如:
HELLO = world
HELLO_WORLD = $(HELLO) world!
# This echoes "world world!"
echo $(HELLO_WORLD)
HELLO = hello
# This echoes "hello world!"
echo $(HELLO_WORLD)
Run Code Online (Sandbox Code Playgroud)
使用:=类似于使用=.但是,在使用它时,不是在扩展值时,而是在赋值期间扩展它.例如:
HELLO = world
HELLO_WORLD := $(HELLO) world!
# This echoes "world world!"
echo $(HELLO_WORLD)
HELLO = hello
# Still echoes "world world!"
echo $(HELLO_WORLD)
HELLO_WORLD := $(HELLO) world!
# This echoes "hello world!"
echo $(HELLO_WORLD)
Run Code Online (Sandbox Code Playgroud)
使用?=分配一个值的变量当且仅当变量没有被先前分配.如果先前为变量分配了一个空值(VAR=),我认为它仍然被认为是集合.否则,功能完全一样=.
使用+=就像使用一样=,但不是替换值,而是将值附加到当前值,中间有一个空格.如果变量先前已设置:=,我认为它会扩展.我认为,当使用它时,结果值会扩展.例如:
HELLO_WORLD = hello
HELLO_WORLD += world!
# This echoes "hello world!"
echo $(HELLO_WORLD)
Run Code Online (Sandbox Code Playgroud)
如果使用类似的东西HELLO_WORLD = $(HELLO_WORLD) world!,将导致递归,这很可能会结束Makefile的执行.如果A := $(A) $(B)使用了,结果将与使用完全相同,+=因为B扩展了,:=而+=不会导致B扩展.
小智 57
我建议你用"make"做一些实验.下面是一个简单的演示,展示之间的差异=和:=.
/* Filename: Makefile*/
x := foo
y := $(x) bar
x := later
a = foo
b = $(a) bar
a = later
test:
@echo x - $(x)
@echo y - $(y)
@echo a - $(a)
@echo b - $(b)
Run Code Online (Sandbox Code Playgroud)
make test 打印:
x - later
y - foo bar
a - later
b - later bar
Run Code Online (Sandbox Code Playgroud)
mip*_*adi 31
当您使用时VARIABLE = value,if value实际上是对另一个变量的引用,那么该值仅在VARIABLE使用时确定.最好用一个例子来说明:
VAL = foo
VARIABLE = $(VAL)
VAL = bar
# VARIABLE and VAL will both evaluate to "bar"
Run Code Online (Sandbox Code Playgroud)
使用时VARIABLE := value,您可以获得value 现在的值.例如:
VAL = foo
VARIABLE := $(VAL)
VAL = bar
# VAL will evaluate to "bar", but VARIABLE will evaluate to "foo"
Run Code Online (Sandbox Code Playgroud)
使用VARIABLE ?= val意味着您只设置了VARIABLE if 的值VARIABLE.如果它尚未设置,则将使用该值的设置直到VARIABLE使用(如示例1中所示).
VARIABLE += value只是追加value到VARIABLE.实际值value是根据最初设置时的确定,使用=或者:=.
在上面的答案中,重要的是要理解 "在声明/使用时间扩展价值"的含义.给予价值*.c不会带来任何扩张.只有当命令使用此字符串时,它才会触发某些通配.类似地,一个值喜欢$(wildcard *.c)或$(shell ls *.c)不需要任何扩展,并且即使我们:=在变量定义中使用,也会在定义时完全评估.
在您有一些C文件的目录中尝试以下Makefile:
VAR1 = *.c
VAR2 := *.c
VAR3 = $(wildcard *.c)
VAR4 := $(wildcard *.c)
VAR5 = $(shell ls *.c)
VAR6 := $(shell ls *.c)
all :
touch foo.c
@echo "now VAR1 = \"$(VAR1)\"" ; ls $(VAR1)
@echo "now VAR2 = \"$(VAR2)\"" ; ls $(VAR2)
@echo "now VAR3 = \"$(VAR3)\"" ; ls $(VAR3)
@echo "now VAR4 = \"$(VAR4)\"" ; ls $(VAR4)
@echo "now VAR5 = \"$(VAR5)\"" ; ls $(VAR5)
@echo "now VAR6 = \"$(VAR6)\"" ; ls $(VAR6)
rm -v foo.c
Run Code Online (Sandbox Code Playgroud)
运行make将触发一个规则,该规则创建一个额外的(空)C文件,调用foo.c但6个变量中没有一个具有foo.c其值.
最高票的答案可以改进。
让我参考 GNU Make 手册“设置变量”和“风味”,并添加一些注释。
您指定的值是逐字安装的;如果它包含对其他变量的引用,则只要替换此变量(在扩展某个其他字符串的过程中),就会扩展这些引用。当这种情况发生时,它被称为递归扩展。
foo = $(bar)
Run Code Online (Sandbox Code Playgroud)
catch :foo将扩展为$(bar) 每次 foo评估的值,可能导致不同的值。你当然不能称之为“懒惰”!如果在午夜执行,这会让您感到惊讶:
# This variable is haunted!
WHEN = $(shell date -I)
something:
touch $(WHEN).flag
# If this is executed on 00:00:00:000, $(WHEN) will have a different value!
something-else-later: something
test -f $(WHEN).flag || echo "Boo!"
Run Code Online (Sandbox Code Playgroud)
VARIABLE := value
VARIABLE ::= value
Run Code Online (Sandbox Code Playgroud)
用 ':=' 或 '::=' 定义的变量只是扩展变量。
简单的扩展变量由使用 ':=' 或 '::=' [...] 的行定义。这两种形式在 GNU make 中是等价的;然而,POSIX 标准 [...] 2012 仅描述了 '::=' 形式。
简单扩展变量的值将被一劳永逸地扫描,在定义变量时扩展对其他变量和函数的任何引用。
要补充的不多。它立即被评估,包括递归扩展,以及递归扩展的变量。
捕获:如果VARIABLE指的是ANOTHER_VARIABLE:
VARIABLE := $(ANOTHER_VARIABLE)-yohoho
Run Code Online (Sandbox Code Playgroud)
并且ANOTHER_VARIABLE在此赋值之前未定义,ANOTHER_VARIABLE将扩展为空值。
FOO ?= bar
Run Code Online (Sandbox Code Playgroud)
相当于
ifeq ($(origin FOO), undefined)
FOO = bar
endif
Run Code Online (Sandbox Code Playgroud)
其中,$(origin FOO)等于undefined只有当变量是根本没有设置。
catch:如果FOO被设置为空字符串,无论是在 makefiles、shell 环境还是命令行覆盖中,都不会被分配bar。
VAR += bar
Run Code Online (Sandbox Code Playgroud)
附加:
当所讨论的变量之前没有定义过时,'+=' 的作用就像普通的 '=':它定义了一个递归扩展的变量。但是,当有先前的定义时, '+=' 的确切作用取决于您最初定义的变量的风格。
所以,这将打印foo bar:
VAR = foo
# ... a mile of code
VAR += $(BAR)
BAR = bar
$(info $(VAR))
Run Code Online (Sandbox Code Playgroud)
但这会打印foo:
VAR := foo
# ... a mile of code
VAR += $(BAR)
BAR = bar
$(info $(VAR))
Run Code Online (Sandbox Code Playgroud)
问题在于,+=根据VAR之前分配的变量类型,其行为会有所不同。
define VAR_NAME :=
line
line
endef
Run Code Online (Sandbox Code Playgroud)
或者
define VAR_NAME =
line
line
endef
Run Code Online (Sandbox Code Playgroud)
可以省略赋值运算符,然后它会创建一个递归扩展的变量。
define VAR_NAME
line
line
endef
Run Code Online (Sandbox Code Playgroud)
endef删除之前的最后一个换行符。
HASH != printf '\043'
Run Code Online (Sandbox Code Playgroud)
是相同的
HASH := $(shell printf '\043')
Run Code Online (Sandbox Code Playgroud)
不要使用它。$(shell)call 更具可读性,并且非常不鼓励在 makefile 中同时使用两者。至少,$(shell)遵循 Joel 的建议,让错误的代码看起来明显是错误的。
| 归档时间: |
|
| 查看次数: |
204388 次 |
| 最近记录: |