22、makefile常用讲解(2)
4)变量的引入
变量的引入和应用:
CC=gcc
HD=-I headers
SC=-c $<
OBJ=-o $@
bin/st_work : obj/main.o obj/st_work.o obj/fun.o
gcc $^ -o $@ (命令一定要用以Tab开头)
obj/st_work.o : sources/st_work.c
$(CC) $(HD) $(SC) $(OBJ)
obj/main.o : sources/main.c
$(CC) $(HD) $(SC) $(OBJ)
obj/fun.o : sources/fun.c
$(CC) $(HD) $(SC) $(OBJ)
clean:
rm -f bin/st_work file_o/*.o
可以看到,依赖关系由上到下。
More:
(1)如此定义变量后,
objects = main.o,
foo = $(bar)
使用$(object)来代替变量的值,用“$$”来表示$。
(2)变量替换
其格式是“$(var:a=b)”或是“${var:a=b}”,其意思是,把变量“var”中所有以“a”字串“结尾”的“a”替换成“b”字串。这里的“结尾”意思是“空格”或是“结束符”。
foo := a.o b.o c.o
bar := $(foo:.o=.c)
(3)变量可以嵌套
$($(x))
(4)可以使用“+=”操作符给变量追加值。
(5)当make嵌套调用时,上层Makefile中定义的变量会以系统环境变量的方式传递到下层的Makefile中。这里的系统环境变量与本makefile中定义的变量的关系有点类似于全局变量与局部变量的关系。默认情况下,只有通过命令行设置的变量会被传递。而定义在文件中的变量,如果要向下层Makefile传递,则需要使用exprot关键字来声明。
5)信息显示
在执行make时,会把所有这些信息都输出来。
在命令前面加个@,就不会把相关信息输出屏幕了。
6)函数的使用
函数调用后,函数的返回值可以当做变量来使用。
调用格式如下所示: $(<function> <arguments>;)
函数调用以“$”开头,以圆括号或花括号把函数名和参数括起。参数间以逗号“,”分隔,而函数名和参数之间以“空格”分隔。参数可以使用变量。
bar:= $(subst $(space),$(comma),$(foo))
上面的函数subst是把第三个参数中包含第一个参数中的字串替换成第二个参数中的字串。
7)语句的使用
$(if <condition>;,<then-part>;)
$(if <condition>;,<then-part>;,<else-part>;)
make支持三各通配符:“*”,“?”和“[...]”。波浪号“~”字符在文件名中也有比较特殊的用途。如果是“~/test”,这就表示当前用户的$HOME目录下的test目录。而“~hchen/test”则表示用户hchen的宿主目录下的test目录
5、其他注意点
1)在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,通常要给中间目标文件打个包,在Windows 下这种包叫“库文件”(Library File),也就是 .lib 文件,在UNIX 下,是Archive File,也就是 .a 文件。
编译阶段,主要解决语法问题,如函数,变量等声明是否正确,而链接阶段,因为要生成可执行文件了,要明确具体的地址关系,及寻找真实的定义等。
2)将长行用 “\” 分开便于阅读。
3)和目标没有依赖关系的规则不会被处理,除非指定make 处理(如make clean)。
4)将源文件分门别类地放置时,编译时要进行寻找。通过VPATH实现。
如果没有指明这个变量,make 只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么,make就会在当当前目录找不到的情况下,到所指定的目录中去找寻文件了。
VPATH = src:../headers
多个目录使用:分开。
另外一个vpath,不是变量,使用方法如下:
它可以指定不同的文件在不同的搜索目录中。使用方法有三种:
(1)vpath <pattern> <directories>。为符合模式<pattern>的文件指定搜索目录<directories>。
(2)vpath <pattern>。清除符合模式<pattern>的文件的搜索目录。
(3)vpath。清除所有已被设置好了的文件搜索目录。
<pattern>需要包含“%”字符。“%”的意思是匹配零或若干字符,例如,“%.h”表示所有以“.h”结尾的文件。<pattern>指定了要搜索的文件集,而<directories>则指定了<pattern>的文件集的搜索的目录。例如:
vpath %.h ../headers
该语句表示,要求make 在“../headers”目录下搜索所有以“.h”结尾的文件。
5)有些情况下,则规则失效,没有依赖文件,文件clean命令永远不会执行;为避免这个问题,可使用".PHONY"指明该目标。如:
.PHONY : clean
这样,在make clean是会无视clean是否存在,直接执行其命令。
与上面等效的另外一个表达:
clean: FORCE
rm $(objects)
FORCE:
6)此外,还有很少使用的双冒号规则。
7)使用include关键字可以把别的Makefile包含进来。