天天看点

makefile变量

在声明变量时需要初始化。通过在变量名前加上 $ 符号引用变量,最好用上小括号 () 或

大括号 {} 把变量括起来。变量是大小写敏感的。

如果需要用 $ 字符,那么需要用 $$ 来表示。 变量可以使用在规则中的“目标”、“依赖”、“命令”中及新的变量中。如:

CC = gcc
OBJS = program.o foo.o utils.o
program : $(OBJS)
  $(CC) -o program $(OBJS)
$(OBJS) : defs.h      

注:强烈建议在引用变量时,加下小括号或大括号,这样可以更安全地引用变量。

变量会在引用它的地方展开,如:

foo = c
prog.o : prog.$(foo)
  $(foo)$(foo) -$(foo) prog.$(foo)      

展开后得到:

prog.o : prog.c
  cc -c prog.c      

上面这个例子的用法,在实际生产,强烈不建议这么使用。

在 Makefile 中有两种方式来在用变量定义变量的值:

  • 使用 = 号,右侧变量的值可以定义在文件的任何一处,即不需要定义在引用变量处之前,执行make时,会在引用的地方展开。
CC = gcc      
  • 使用 := 号
CC := gcc      

第一种=号方式,因为引用它时,不用先定义(即可先引用后定义,或者反过来),这将导致递归定义,如:

CFLAGS = $(include_dirs) -o
include_dirs = -Ifoo -Ibar
CFLAGS = $(CFLAGS) -o      

CFLAGS = $(CFLAGS) -o在命令中被展开时会形成递归定义,这会让 make 陷入无限的变量展开过程中去。虽然,make有能力检测出这样的定义,并会报错。如果在变量中使用函数的话,这种递归让make 运行得非常慢,甚至可能发生不可预知的错误。

使用:= 操作符可以解决这个问题。而且使用这个操作符的话,前面的变量不能使用后面的变量,只能使用前面已定义好了的变量。

如:

x := foo
y := $(x)      

等价于:

y := foo bar
x := later      

特别强调,如果是这样:

y := $(x)      

那么,y 的值是“bar”,而不是“foo bar”。

?=操作符

FOO ?= bar      

含义:如果 FOO 没有被定义过,那么将“bar”赋给它。如果 FOO 先前被定义过,那么这条语将什么也不做。上面这条语句等价于:

ifeq ($(origin FOO), undefined)      

变量高级用法

  • 第一种是变量值的替换

    可以替换变量中的公共部分,格式:$(var:a=b) 或 ${var:a=b} ,表示把变量“var”中所有以“a”结尾的“a”替换成“b”,如:

foo := a.o b.o c.o
bar := $(foo:.o=.c)      

这个例子中,定义了变量foo。$(foo:.o=.c)就是把 $(foo) 中所有以 .o结

尾的.o全部替换成 .c ,所以$(bar) 的值是“a.c b.c c.c”。

另外一种变量替换的技术是以“静态模式”定义的,如:

foo := a.o b.o c.o
bar := $(foo:%.o=%.c)      

这依赖于被替换字符串中的有相同的模式,%是一个通配符,而且静态模式中必须包含一个 % 字符,这个例子同样让 $(bar) 变量的值变为“a.c b.c c.c”。

- 第二种是“把变量的值再当成变量”

x = y
y = z
a := $($(x))      

在这个例子中,$(x) 的值是“y”,所以 $($(x)) 就是 $(y),于是 $(a) 的值就是“z”。还可以使用更多的层次,如:

x = y
y = z
z = u
a := $($($(x)))      

这里的 $(a) 的值是“u”。

+= 操作符给变量追加值

如:

objects = main.o foo.o bar.o utils.o
objects += another.o      

$(objects) 值变成:“main.o foo.o bar.o utils.o another.o”

使用 += 操作符也可以写成下面的样子:

objects = main.o foo.o bar.o utils.o
objects := $(objects) another.o      

如果变量之前没有定义过,那么,+= 会自动变成 = ,如果前面有变量定义,那么 += 会继承于前

次操作的赋值符。如果前一次的是 := ,那么 += 会以 := 作为其赋值符,如:

variable := value
variable +=      

等价于:

variable := value
variable := $(variable)      

但如果是:

variable = value
variable +=      

由于前次的赋值符是 = ,所以 += 也会以 = 来做为赋值,那么就会发生变量的递归定义,很不好,幸好 make 会自动解决这个问题。

define two-lines
echo foo
echo $(bar)