Makefile之变量
Makefile变量使用
Makefile变量赋值符
Makefile变量赋值符类似于编程语言中对变量进行赋值的符号,常见的有 = 号,makefile中我目前所知道的有四种赋值符号,分别如下:
- =:这是最普通的赋值符号,赋值完成后使用变量会变成替换=之后的内容
- := :这种方式定义的变量,前面定义的变量不可以使用后边定义的变量,其实可以防止递归定义变量带来的缺陷,下文会有解释。
- ?= :这种方式定义的变量,如果前面已经定义过,那么此条定义语句就没有任何作用,也就是只有首次定义才会有效
- += :追加定义变量
接下来详细解释下每种定义变量的区别
1.最普通的= 定义变量,可以在任何位置定义变量,也就是说不一定要先定义,下面请看一个例子1
2
3foo=$(bar)
bar=$(ugh)
ugh=Huh?
那么最后foo的值就是Huh? ,这也就是=定义变量之前先引用之后定义的变量。
缺点:这种方式定义变量有明显的缺陷,就是递归定义,请看如下例子:1
CFLAGS=$(CFLAGS) -O
1 | A=$(B) |
这样子就会使得make陷入无限的变量展开过程中去,当然make具备检测这种情况的能力,会报错,为了避免上述情况发生,我们就可以使用”:=”符号定义变量
2.上面对”:=”已经有了初步介绍,下边请看详细的例子解释:1
2
3x :=foo
y :=$(x) bar
x := later
最后的结果就是 y的值是”foo bar” ,x是”later”1
2y :=$(x) bar
x :=later
最后的结果就是 y的值是”bar” ,x是”later”
3.接下来说一下追加定义变量符号 “+=”1
2obj=a.o b.o
obj+=c.o
最终obj结果就是”a.o b.o c.o”,其等价于1
2obj=a.o b.o
obj :=$(obj) c.o
如果变量之前没有定义过,那么,“+=”会自动变成“=”,如果前面有变量定义,那么“+=”会继承于前次操作的赋值符。如果前一次的是“:=”,那么“+=”会以“:=”作为其赋值符,如:1
2variable := value
variable += more
等价于1
2variable := value
variable := $(variable) more
但如果是这种情况:1
2variable = value
variable += more
由于前次的赋值符是“=”,所以“+=”也会以“=”来做为赋值,那么岂不会发生变量的递补归定义,这是很不好的,所以make会自动为我们解决这个问题,我们不必担心这个问题。
变量的高级用法
变量值的替换
我们可以替换变量中的共有的部分,其格式是“$(var:a=b)”或是“${var:a=b}”,其意思是,把变量“var”中所有以“a”字串“结尾”的“a”替换成“b”字串。这里的“结尾”意思是“空格”或是“结束符”。
例子:1
2foo := a.o b.o c.o
bar := $(foo:.o=.c)
这个示例中,我们先定义了一个“$(foo)”变量,而第二行的意思是把“$(foo)”中所有以“.o”字串“结尾”全部替换成“.c”,所以我们的“$(bar)”的值就是“a.c b.c c.c”。
把变量的值再当成变量
请看如下例子:1
2
3
4x=y
y=Hello
var=$($(x))
这样子其实就是个嵌套取变量内容,最终var=Hello,这一点有点类似于C语言中的取地址符号&,当然这也可以使用更多层次
override 指示符
使用override指示符定义的变量,可以忽略make命令通过命令行参数传入的变量的值,覆盖命令行参数传值的作用。
示例:1
2
3
4
5
6
7
8
9
10VAR=Hello override
target:
echo $(VAR)
```
使用make VAR=Ignore命令,也就是传值给VAR变量,结果显示如下:
```Makefile
echo Ignore
Ignore
也就是说命令行参数传递变量方式会覆盖我们内部定义的变量。
那么我们使用override关键字定义的变量呢?
1 | override VAR=Hello override |
同样使用上边的make命令,结果如下:
1 | echo Hello override |
定义多行变量
定义多行变量一般都是用在多行命令中来,使用define关键字可以定义一个变量的值为多行命令
示例:1
2
3
4
5
6
7define two_echo
echo "Hello define!"
echo "Hello end!"
endef
target:
$(two_echo)
结果如下:1
2
3
4echo "Hello define!"
Hello define!
echo "Hello end!"
Hello end!
目标变量
见名思意,目标变量是仅仅只针对于某个目标而定义的变量,特点是不会被全局变量所覆盖
示例:1
2
3
4
5
6
7
8
9target1:var=i am target1
var=Hello Target varible
target1:
echo $(var)
target2:
echo $(var)
如果使用make target1命令,结果显示:1
2echo i am target1
i am target1
如果是make target2命令,结果显示:1
2echo Hello Target varible
Hello Target varible
也就是说目标变量针对于某个目标下面的命令有效
模式变量
其实这个和目标变量很类似,目标变量是针对某种目标,模式变量是针对某种模式,比如make支持的%模式,%.o就是所有以.o结尾的文件1
%.o:var=hello
那么接下来所有以.o结尾的目标使用的变量var都是hello