变量的基础
变量在声明时需要给初始值,在使用的时候要使用$(name)
的方式,这里可以使小括号()
也可以是{}
。如果我们要使用真实的$
,那么需要使用$$
表示。
objects = program.o foo.o utils.o
program : $(objects)
gcc -o $(objects)
$(objects):defs.h
变量会在使用它的地方,精确的展开,例如
foo = c
prog.o:prog.$(foo)
g$(foo)$(foo) -$(foo) prog.$(foo)
展开后得到:
prog.o:prog.c
gcc -c prog.c
变量中的变量
在定义变量的值是,我们可以使用其他变量来构造变量的值,在Makefile中有两种方式来用变量定义变量的值。
第一种:使用=
号,如
foo = $(bar)
bar = $(ugh)
ugh = Huh?
all:
echo $(foo)
当我们执行make all
时将会打出变量$foo
的值是Huh?
,因此,变量是可以通过后面的变量来定义的
优点:我么可以变量的真实值推到后面去定义
CFLAGS = $(include_dirs) -o
include_dirs = -lfoo -lbar
缺点:如果出现递归定义,则报错
第二种:使用:=
的操作符
x := foo
y := $(x) bar
x := later
#等价于
y := foo bar
x := later
这里我们前面的变量不能使用后面的变量,只能使用前面已经定义好的变量
y := $(x) bar
x := foo
那么y的值是bar
,而不是foo bar
.因为这里我们的x
还没有定义
这个例子可能比较简单,来看一个比较难的
这里包括了make的函数,条件表达式和一个系统变量MAKELEVEL
的使用
ifeq (0,${MAKELEVEL})
cur-dir := $(shell pwd)
whoami := $(shell whoami)
host-type := $(shell arch)
MAKE := ${MAKE} host-type=${host-type} whoami=${whoami}
endif
关于MAKELEVEL
的意思是如果我们的make有一个嵌套执行的动作,那么这个变量会记录了我们当前的Makefile的调用层数
这是关于定义空格变量的例子
nullstring :=
space := $(nullstring) # ending of the line
nullstring 是一个Empty变量,其中什么也没有,而我们的space的值是一个空格,因为在操作符的邮编是很难描述一个空格,这里采用的技术很管用,先用一个Empty变量来表明变量值的开始,而后面采用#
注释符来表示变量定义的终止,这样,我们可以定义出值是一个空格变量
变量的高级用法
变量值的替换
这里我们可以替换变量中,共有的部分,其格式是$(var:a=b)
或者${var:a=b}
,意思是,把变量var
中所有的a
字符串结尾的a
替换成b
字符串,这里结尾的意思是空格或者结束符
foo:=a.o b.o
bar := $(foo:.o=.c)
这里的意思是将a.o
和b.o
文件改成a.c
和b.c
文件
静态模式
foo := a.o b.o c.o
bar := $(bar:%.o=%.c)
这里依赖于被替换的字符串有相同的模式,模式中必须包含一个%
字符,同样是将所有的.o
文件转换成.c
文件
把变量的值在当做变量
x = y
y = z
a := $($(x))
所以a变量的值是z
使用函数
x := variable1
variable2 := hello
y = $(subst 1,2,$(x))
z := y
a := $($($(z)))
其中subst
函数的意思是将$(x)中的1
替换成2
,所以最终的结果是hello
同样我们可以采用拼接的方式实现较长标量名称
first_second = hello
a := fist
b := second
x := $($a_$b)
将两种方式组合在一起,内容就比较丰富了
a_object := a.o b.o c.o
b_object := 1.o 2.o 3.o
a1 :=a
source := $($(a1)_object:.o=.c)
这里a1的值是a,所以,最终的结果是将a.o
,b.o
,c.o
文件变成a.c
,b.c
,c.c
文件
和函数结合
ifdef do_sort
func := sort
else
func := strip
endif
bar : a d b g q c
foo := $($(func) $(bar))
这里如果定义了do_sort
函数,那么使用sort
函数,将bar
从新排序
这里需要注意,把变量的值在当做变量,同样可以在操作符的左边
dir := foo
$(dir)_sources := $(wildcard $(dir)/*.c)
define $(dir)_print
lpr $($(dir)_sources)
endef
这例子中定义了三个变量:dir
,foo_source
,foo_print
追加变量值
我们使用+=
来追加
objects := main.o foo.o bar.o util.o
objects += another.o
#等价于
objects := main.o foo.o bar.o util.o
objects := $(objects) another.o
override指示符
如果变量是通过make的命令行参数设置的,那么Makefile中对这个变量的赋值将会被忽略。如果想要设置这个参数的值,需要使用override指示符
override define foo
bar
endef