6.变量
-
变量名是大小写敏感的。
-
推荐大写的变量名来控制隐含规则或者用户使用命令行时会覆盖的参数;小写变量名在Makefile内部使用。
变量引用基础¶
$(xxx)
与${xxx}
都是可以的。
在文件名或recipe中写入$
符号必须键入$$
。
变量的两种类型¶
- recursively expanded变量。使用
=
(单行)或define
(多行)定义变量。 缺点:CFLAGS = $(CFLAGS) -O
- 会引起自循环,make会检测到自循环并报告一个错误。
- 每次变量被扩展的时候任何在定义中的函数(see Functions for Transforming Text)引用都会执行。会引起wildcard和shell函数给出不可预知的结果。
- simply expanded变量,可以解决上述的缺点。使用
:=
或::=
来定义。只有::=
被POSIX标准支持。对于所有引用该变量的其它变量或者函数,它只会被扫描一次。 例:
x := foo
y := $(x) bar
x := later
结果:
y := foo bar
x := later
区别:make在执行定义recursively expanded variable时,不会扩展该变量中的引用变量,只有在引用该变量的时候引用变量才会被扩展;simply expanded variable则是在定义变量的时候就已经将引用变量扩展了。
还有另一种定义操作?=
,条件赋值变量,如果该变量没有被定义过,那么才会被赋值。¶
FOO ?= bar
等于
ifeq ($(origin FOO), undefined)
FOO = bar
endif
note:变量被赋予空值的话,它仍然是被定义了。所以?=
不会被设置变量。
引用变量的高级特性¶
替换引用¶
格式$(var:a=b)
(or ${var:a=b}
)会导致替换掉var的值中用b替换a。
可与patsubst
结合使用。
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
结果:bar = a.c b.c c.c
计算变量名¶
变量可能被引用在一个变量名中。这叫做computed variable name或nested variable reference。
这种方式的唯一缺点就是不能指定被调用的函数名。???
执行shell脚本¶
!=
可用于执行shell脚本并把输出设置为变量的值。
hash != printf '\043'
file_list != find . -name '*.c'
如果结果中含有$
,并且不想使其扩展为make变量,那么必须替换为$$
。你也可以使用shell函数(See The shell Function)。
hash := $(shell printf '\043')
var := $(shell find . -name "*.c")
向变量添加内容¶
向一个已经定义的变量中添加内容:
objects = main.o foo.o bar.o utils.o
objects += another.o
变量没有被定义时,+=
相当于=
。
如果定义了,取决于变量类型。
override指令¶
如果使用命令行参数设置了变量,那么在makefile中的设置将被忽略。override
可以打破这个规则。
override variable = value
比所有其它方式定义的变量的优先级都要高。
用来提示并添加用户指定的命令行参数:
override CFLAGS += -g
结合define使用:
override define foo =
bar
endef
定义多行变量¶
define two-lines =
echo foo
echo $(bar)
endef
当在recipe中使用此种变量时,相当于
two-lines = echo foo; echo $(bar)