makefile(四)使用变量

原创
2016/10/31 15:13
阅读数 5.1K

makefile可以使用变量,使用变量可以使makefile变的更加紧凑,但是makefile中的变量和通常意义上的变量有所不同。makefile文件中的变量代表了一个字符串。

一、使用普通变量

用户可以在makefile中定义变量,makefile文件中的变量代表了一个字符串。因此这些变量更像是C语言中的宏,在makefile文件执行过程中会展开在所使用的地方。makefile变量的命名可以包含字符、数字、下划线(可以是数字开头),并且大小写敏感。传统的makefile的变量名是全大写的命名方式。

makefile变量在声明的时候需要对其进行赋值,而在使用该变量时需要在变量名前加上$符号,例如$(VARNAME)。如果用户需要在makefile文件中使用$字符,则用$$来表示,这种应用多出现在对shell变量的使用上。

下面演示在makefile中使用变量:

objects =  main.o kdb.o command.o display.o \
	insert.o serach.o files.o utils.o
edit : $(objects)
	gcc -o edit $(objects)

main.o: main.c defs.h                       #生成 main.o
	gcc -c main.c
kdb.o: kdb.c defs.h command.h               #生成 kdb.o
	gcc -c kdb.c
command.o: command.c defs.h command.h       #生成 command.o
	gcc -c command.c
display.o: display.c defs.h buffer.h        #生成 display.o
	gcc -c display.c
insert.o: insert.c defs.h buffer.h          #生成 insert.o
	gcc -c insert.c
serach.o: serach.c defs.h buffer.h          #生成 serach.o
	gcc -c serach.c
files.o: files.c defs.h buffer.h command.h  #生成 files.o
	gcc -c files.c
utils.o: utils.c defs.h                     #生成 utils.o
	gcc -c utils.c

clean:
    rm edit $(objects)
.PHONY : clean

在很多情况下,用户应将编译器及编译器选项定义为变量,这样可以增强makefile文件的灵活性。下面演示了使用这中方法的编译器工程的makefile文件,该makefile文件中的编译器和变异选项都是可以替换的。

CC = gcc
FLAGS = -c
objects =  main.o kdb.o command.o display.o \
	insert.o serach.o files.o utils.o
edit : $(objects)
	$(CC) -o edit $(objects)

main.o: main.c defs.h                       #生成 main.o
	$(CC) $(FLAGS) main.c
kdb.o: kdb.c defs.h command.h               #生成 kdb.o
	$(CC) $(FLAGS) kdb.c
command.o: command.c defs.h command.h       #生成 command.o
	$(CC) $(FLAGS) command.c
display.o: display.c defs.h buffer.h        #生成 display.o
	$(CC) $(FLAGS) display.c
insert.o: insert.c defs.h buffer.h          #生成 insert.o
	$(CC) $(FLAGS) insert.c
serach.o: serach.c defs.h buffer.h          #生成 serach.o
	$(CC) $(FLAGS) serach.c
files.o: files.c defs.h buffer.h command.h  #生成 files.o
	$(CC) $(FLAGS) files.c
utils.o: utils.c defs.h                     #生成 utils.o
	$(CC) $(FLAGS) utils.c

clean:
    rm edit $(objects)
.PHONY : clean

当需要使用新的编译器对其进行编译时,只需要更改变量CC和变量FLAGS即可。

 

二、变量中的变量

在makefile文件中定义变量的值时,用户可以使用其他变量来构造变量的值。在makefile中使用变量定义变量值的方式有三种。

1.使用“=”操作符

该方式非常简单,=左侧是变量,右侧是变量的值,右侧变量的值可以定义在文件的任何一处。也就是说,右侧的变量不一定是已定义好的值,其也可以使用其后面定义的值。下面演示=的使用:

foo = $(bar)
bar = $(ugh)
ugh = hello?
all :
	echo $(foo)

执行结果为:

由上可知,makefile中的变量是可以使用后面的变量来定义的。这种定义变量值的方法有一个潜在的危险就是递归定义。例如:

a = $(b)
b = $(a)

make会检测出这种错误。

2.使用“:=”操作符

使用“:=”操作符定义变量的值可以避免前述递归定义的危险。使用其定义变量时,前面的变量不能使用后面的变量,只能使用前面已定义好的变量。如果使用前面未定义变量,则该变量为空。下面演示这样的定义:

y := $(x) bar
x := $(foo)
all :
	echo $(y)
.PHONY : all

执行结果为:

输出的值是变量y的值,由于在定义y值时x的变量未定义,所以其值为空。

3.使用“?=”操作符

该操作符的含义是,如果变量之前没有被定义过,那么变量的值就被定义。如果变量的值之前已被定义过,则赋值语句什么也不做。下面实例演示了使用“?=”定义一个变量:

a := hello
b ?= world
a ?= HELLO
all :
	echo $(a)
	echo $(b)
.PHONY : all

执行结果如下:

由于变量a在a ?= HELLO之前已经被定义,所以a变量的值没有被改变。b变量在“b ?= world”之前没有定义,所以变量b的值被定义为world。

 

三、追加变量的值

makefile文件允许给一个变量追加一个值,其操作符为“+=”。由于makefile文件的变量本身是一个字符串,所以追加操作实际上是一个字符串链接操作,如下:

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

上面的代码等价于:

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

如果变量之前没有定义过,“+=”操作符会自动变成“=”操作符,如果前一次变量定义时使用“:=”操作符,“+=”会以“:=”作为其操作符,如下:

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

等价于:

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

 

四、自动化变量

makefile中允许使用自动化变量,这些变量的名称是由make工具已经定义好的。makefile中一共有7个自动化变量,如下:

makefile中的自动化变量
自动化变量 表示的意义
$@ 表示规则中的目标文件集
$% 仅当目标是函数库文件时,表示规则中的目标成员名。例如,一个目标是foo.a(bar.o),那么,$%就是bar.o,$@就是foo.a。如果目标文件不是函数库文件,其值为空
$< 依赖列表中的第一个依赖的名字
$? 所有比目标新的依赖的合集,以空格分隔
$^ 所有依赖的集合,以空格分隔。如果依赖中有多个重复的,只保留一份
$+ 这个变量很像$^,也是所有依赖的集合,但是它不去除重复的依赖
$* 这个变量表示目标模式中“%”及之前的部分

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部