参考原文http://blog.csdn.net/liang13664759/article/details/1771246/shell
Makefile中变量如C\C++中宏同样执行时候自动原模原样展开在使用的地方,与C/C++不一样得失,Makefile中能够改变其值。Makefile中变量可使用在“目标”,“依赖目标”,“命令”或其余部分。ide
变量名能够包含字符数字下划线(能够数字开头),可是不该该含有“:”、“#”、“=”或是空字符,区分大小写。函数
声明时须要给予初始值,使用时加上“$”符号,最好用“()”或者“{}”把变量包括起来。而使用真是的“$”须要“$$”表示。spa
变量能够用在许多地方,如规则中的目标、依赖、命令以及新的变量。.net
①使用“=”,左侧是变量,右侧是变量的值,右侧变量的值能够定义在文件的任何一处,也就是说右侧变量不必定是一已定义好的值,也可使用后面定义的值。命令行
例如:blog
foo = $(bar)递归
bar = $(ugh)ip
ugh = huh?ci
all:
echo $(foo)
执行make all会打印出变量$(foo)的值“Huh?”。因此,变量是能够用后面的变量来定义的。
注:这样可能会产生递归定义:
A= $(B)
B=$(A)
这会让make陷入无限的变量展开过程当中去,固然,make有检测这样的能力,并会报错。
若是变量中使用函数,这也会让make运行时很是慢。他会使用make的“wildcard”和“shell”发生不可预知的错误。
②“:=”,前面的变量不能使用后面的变量,只能使用已定义好的变量。
x:=foo
y:=$(x) bar
x:=later
等价于
y := foo bar
x := later
而
y := $(x) bar
x := foo
那么y的值是“bar”,而不是“foo, bar”
系统变量“MAKELEVEL”表示,若是make有一个嵌套执行的动做,则该变量会记录当前的Makefile调用层数.
(如下的我也还没懂,先标记)
nullstring :=
space := $(nullstring) # end of the line
nullstring是一个Empty变量,其中什么也没有,而咱们的space的值是一个空格。由于在操做符的右边是很难描述一个空格的,这里采用的技术很管用,先用一个Empty变量来标明变量的值开始了,然后面采用“#”注释符来表示变量定义的终止,这样,咱们能够定义出其值是一个空格的变量。请注意这里关于“#”的使用,注释符“#”的这种特性值得咱们注意,若是咱们这样定义一个变量:
dir := /foo/bar # directory to put the frobs in
dir这个变量的值是“/foo/bar”,后面还跟了4个空格,若是咱们这样使用这样变量来指定别的目录——“$(dir)/file”那么就完蛋了。
③、另外的赋值法,“?=”表示若是没有被定义过,则赋值。若是定义过,则什么也不作。
FOO ?= bar
等价于:
ifeq ($(origin FOO), undefined)
FOO = bar
endif
①变量值的替换
替换变量中的共有部分,格式“$(var:a=b)”或是“${var:a=b}”,表示吧变量var中的全部以“a”结尾的“a”替换成“b”
例如:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
把“$(foo)”中的全部“.o”结尾所有替换为“.c”,因此“$(bar)”的值就是“a.c b.c c.c”。
另一种前面记录过得静态模式,
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
②、“把变量的值在当成变量”
x = y
y = z
a:=$($(x))
例子中,$(x)=y, 因此$($(x))就是$(y),因而$(a)的值就是z
“函数”于“条件语句”一同使用的例子:
ifdef do_set
func := sort
else
func := strip
endif
bar := a b d g q c
foo := $($(func) $(bar))
示例中若是定义了"do_sort",foo:=$(sort a d b g q c),因而$(foo)就是“a b c d g q”。若是没有定义“do_sort”,则foo:=$(strip a d b g q c),调用strip函数。
“把变量的值当成变量”一样能够用在操做符的左边:
dir = foo
$(dir)_sources := $(wildcard $(dir)/*.c)
define $(die)_print
lpr $($(dir)_sources)#该命令表示把文件发送给打印机
endef
使用“+=”给变量追加值,如:
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.p foo.o bar.o utils.o
objects := $(objects) another.o
但“+=”更为简洁,且若是前面没有定义过该变量。“+=”自动变成“=”,若是 有定义过,“+=”聚集成前次操做的赋值符。若是前一次的是“:=”,那么“+=”会以“:=”为其赋值符,如:
variable := value
variable += more
等价于:
variable := value
variable := $(variable) more
可是“=”状况却不同,例如:
variable = value
variable += more
因为前次的赋值符是“=”,因此“+=”也会以“=”做为赋值,那么岂不会发生变量的递补归定义,这是很很差的,因此make会自动为咱们解决这个问题,咱们没必要担忧这个问题。(没懂)
若是有变量是一般的make命令行参数设置,那么Makefile中对这个变量的赋值会被忽略。若是想在Makefile中设置这类参数的值,可以使用“override”指示符。
override <variable>=<value>
override <variable>:=<value>
还能够追加
override <variable>+=<more text>
对于多行的变量定义,可使用define指示符,而define指示符前,也一样可使用override,如:
override define foo
bar
endef
定义变量foo bar
使用define关键字设置变量的值能够有换行,有利于一系列的命令。(命令包就是利用该关键字)
define指示符后面跟变量的名字,重起一行定义变量的值,定义以关键字endef结束。工做方式和“=”操做符同样。变量的值能够包含函数、命令、文字或是其余变量。define定义的命令变量中一样要以【Tab】键开头
define two-lines
echo foo
echo $(bar)
endef
make运行时的系统环境变量能够在make开始运行时被载入到Makefile文件中,可是若是Makefile中定义了这个变量,或是这个变量由make命令行带入,那么系统的环境变量的值将被覆盖(若是make指定了“-e”参数,那么系统环境变量将覆盖Makefile中定义的变量,-e, --environment-overrides环境变量覆盖Makefile文件)
所以,若是咱们在环境变量中设置了“CFLAGS”环境变量,那么咱们就能够在全部的Makefile中使用这个变量。这对于使用统一的编译参数很方便。若是Makefile中定义了CFLAGS,那么会使用Makefile中的这个变量,若是没有定义则使用系统的环境变量。
当make嵌套调用时,上层Makefile中定义的变量会以系统环境变量的方式传递到下层的Makefile中。默认状况下,只有经过命令行设置的变量会被传递。定义在文件中的变量传递须要export。
不推荐许多的变量定义在系统环境中,这样执行不用的Makefile拥有同一套系统变量,可能会有麻烦。
前面所述的Makefile中定义的变量都是“全局变量”,整个文件中均可以访问这些变量。固然“自动化变量”除外("$<"、“$@”、“$^”)属于“规则型变量”,这种变量的值依赖于规则的目标和依赖目标的定义。
固然,也能够为某个目标设置局部变量,成为“Target-specific Variable”,它能够和“全局变量”同名,由于他的做用范围只在这条规则以及连带规则中,其值也只在做用范围内有效,不会影响规则链之外的全局变量的值。以下:
<target...>:<variable-assignment>
<target...>:overide<vatiable-assignment>
<vatiable-assignment>能够是前面的各类赋值表达式。“=”、“:=”、“+=”、“?=”。第二条是make命令行带入的变量或是系统环境变量。
示例:
prog:CFLAGS=-g
prog:prog.o foo.o bar.o
$(CC) $(CFLAGS) prog.o foo.o bar.o
prog.o:prog.c
$(CC) $(CFLAGS) prog.c
foo.o:foo.c
$(CC) $(CFLAGS) foo.c
bar.o:bar.c
$(CC) $(CFLAGS) bar.c
实例中,无论全局的$(CFLAGS)的值是什么,在prog以及所引起的全部规则中(prog.o foo.o bar.o),$(CFLAGS)的值都是“-g”
9、模式变量
在GNU的make中,还支持模式变量(Pattern-speific Variable),经过前面,变量能够定义在某个目标上,模式变量的好处就是能够给定一种“模式”,能够把变量定义在符合这种模式的全部目标上。
示例:%.o:CFLAGS=-o
<pattern...>:<variable-assignment>
<pattern...>:override<variable-assignment>
make命令行指定变量override针对系统环境传入变量。