Makefile学习笔记(四)

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

上一篇:变量Variable


下一篇:GGR376 Regression