Makefile学习笔记
使用变量
变量的名字可以包含字符、数字、下划线(可以是数字开头,在C中只允许字母和下划线开头),但不应该含有“:”、“#”、“=”或者空字符,比如回车,空格。
变量区分大小写。
一、变量基础
变量在初始化时需要给予初值,而在使用时需要在变量名前加上“$$”符号
但最好用小括号“()”或者大括号“{} ”把变量名给包括起来。如果想使用" " 这 个 字 符 的 话 , 那 么 你 需 要 用 “ "这个字符的话,那么你需要用“ "这个字符的话,那么你需要用“$$”来表示
变量可以用在许多地方,如规则中的“ 目标 ”,“ 依赖 ”,“ 命令 ”以及新的变量中。
例:
objects = program.o foo.o utils.o
program : $(objects)
cc -o program $(objects)
$(objects) : defs.h
另外,给变量加上括号也是为了调用是起到安全可靠的作用,不会出现意外的错误,这也是和c语言里面的宏类似,加上括号编译器会把它看成一个整体,不加括号,它就是零散的,很有可能在调用时出现因为优先级的运算顺序导致最终结果错误
二、变量中的变量
在makefile中有两种方式来定义变量的值
第一种方式就是利用“=”来进行定义,“=”的左侧是变量,右侧是变量的值。
例:
foo = $(bar)
bar = $(ugh)
ugh = Huh?
all:
echo $(foo)
当执行make all时,将输出“Huh?”
第二种方式是“ := ”操作符
例:
x := foo
y := $(x) bar
x := later
其等价于:
y := foo bar
x := later
注意:前面的变量不能使用后面的变量,只能使用前面定义好的变量。
比如:
y := $(x) bar
x := foo
那么最终y的值是“bar”,而不是“foo bar”
举个栗子:
nullstring :=
space := $(nullstring) # end of the line
nullstring是一个空变量Empty,但是space其实是赋值为一个空格
最后一个比较特殊的定义操作符“?=”,举例:
abc ?= abcd
这句的意思是如果abc之前没有被定义过,那么现在将会被赋值为abcd,但是如果之前被定义过了,那么现在就什么也不做。等价于:
ifeq ($(origin abc) , undefine)
abc = abcd
endif
三、变量的高级用法
第一种:
可以替换变量中的共有部分,其格式是“$(abc:a=b)”或是“ ${abc:a=b}”,其意思是,把变量“abc”中所有以“a”字符结尾的“a”替换成“b”,这里的结尾意思是空格或者结束符。
举例:
efg := a.o b.o c.o
abc := $(efg:.o=.c)
这段代码的意思就是把以.o文件后缀的文件全部改为.c后缀的文件
另外一种 替换方法 :
以 “静态模式”
efg := a.o b.o c.o
abc := $(efg:%.o=%.c)
这依赖于被替换字符串中有相同的模式,功能和第一种是一样的。
第二种:
x = y
y = z
a := $($(x))
在这个例子中,$(x)的值是“y”,所以$($(x))就是$(y)
于是$(a)的值就是“z”。(注意,是“x=y”,而不是“x=$(y)”)
四、追加变量值
“+=”就是追加变量值的操作符
举例:
objects = main.o foo.o bar.o utils.o
objects += another.o
所以,$(objects)的值就变成了 main.o foo.o bar.o utils.o another.o
五、override指示符
如果有变量是使用make命令行参数设置的,那么makefile中就会忽略对这个变量的赋值。但是如果想在makefile中设置这类参数的值,那么就可以使用override这个操作符来设置。语法规则:
override < variable > = < value >
override < variable > = < value >
它也可以追加:
override < variable> += < more text>
对于多行的变量定义,可以使用定义命令包。
举例:
override define foo
bar
endef
六、多行变量
举例:
define two-lines
echo foo
echo $(bar)
endef
从define到endef前面都不要有[Tab]键,不然make就会认为这是一个命令
七、目标变量
“自动化变量”属于“规则型变量”,这种变量的值依赖于规则的目标和依赖目标的定义。
也可以为某个目标设置局部变量,这种变量被称为“target-specific Variable”,它允许和全局变量(之前讲的变量)同名。
局部变量的语法规则:
<target …> : < variable-assignment>
<target …> : overide < variable-assignment>
< variable-assignment>可以是前面讲过的各种赋值表达式,如“=”、“:=”、“+=”或是“?=”
第二个语法是针对于make命令行带入的变量,或是系统环境变量。(overide)
举例:
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目标中,以及这个目标所引发的规则中$(CFLAGS )的值都是“-g”,
这就是局部变量
八、模式变量
通过上面的目标变量,可以清楚变量可以定义在某个目标上。模式变量的好处就是我们可以给定一种模式,然后把变量定义在符合这种模式的基础上的变量,比如:%.o : CFLAGS = -o
同样,模式变量的语法和“目标变量”一样。
<target …> : < variable-assignment>
<target …> : overide < variable-assignment>
参考资料:
https://blog.csdn.net/haoel/article/details/2892