转:http://blog.csdn.net/haoel/article/details/2890html
首先看GCC编译四个阶段: http://www.cnblogs.com/chris-cp/p/3865035.htmlspa
转:http://www.cnblogs.com/luchen927/archive/2012/02/05/2339002.html.net
Makefile的规则:htm
目标 : 须要的条件 (注意冒号两边都留有空格)blog
命令 (注意前面用tab键开头)字符串
解释一下:
1 目标能够是一个或多个,能够是Object File,也能够是执行文件,甚至能够是一个标签。
2 须要的条件就是生成目标所须要的文件或目标
3 命令就是生成目标所须要执行的脚本get
总结一下,就是说一条makefile规则规定了编译的依赖关系,也就是目标文件依赖于条件,生成规则用命令来描述。it
在编译时,若是须要的条件的文件比目标更新的话,就会执行生成命令来更新目标。
下面举个简单的例子说明。若是一个工程有3个头文件,和8个C文件,咱们为了完成前面所述的那三个规则,咱们的Makefile应该是下面的这个样子的。
edit : main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
将上面的内容写入到Makefile文件中,而后执行make就能够进行编译,执行make clean就能够删除全部目标文件。解释一下,也就是说生成最终的目标文件edit,依赖于一系列的.o目标文件,而这些.o文件又是须要用源文件来编译生成的。
须要注意的是,clean后面没有条件,而clean自己也不是文件,它只不过是一个动做名字,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。
make是如何工做的
在默认的方式下,也就是咱们只输入make命令。那么,
一、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
二、若是找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件做为最终的目标文件。
三、若是edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。
四、若是edit所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,若是找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
五、固然,你的C文件和H文件是存在的啦,因而make会生成 .o 文件,而后再用 .o 文件生命make的终极任务,也就是执行文件edit了。编译
makefile中使用变量
前面的知识已经足以让你本身完成一个简单的makefile了,不过makefile的精妙之处远不止如此,下面来看看如何在makefile中使用变量吧。
在上面的例子中,先让咱们看看edit的规则:
edit : main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
咱们能够看到[.o]文件的字符串被重复了两次,若是咱们的工程须要加入一个新的[.o]文 件,那么咱们须要在两个地方加(应该是三个地方,还有一个地方在clean中)。固然,咱们的makefile并不复杂,因此在两个地方加也不累,但若是 makefile变得复杂,那么咱们就有可能会忘掉一个须要加入的地方,而致使编译失败。因此,为了makefile的易维护,在makefile中咱们 可使用变量。makefile的变量也就是一个字符串,理解成C语言中的宏可能会更好。
因而,咱们使用变量objects
objects = main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
这样一来,原来的makefile变成以下的样子:
objects = main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit $(objects)
这样看起来方便多了吧,也更加省事了。若是有新的.o文件怎么办?固然是在objects里面添加了,这样只须要一处改变,很方便吧。
让make自动推导
GNU的make很强大,它能够自动推导文件以及文件依赖关系后面的命令,因而咱们就不必去在每个[.o]文件后都写上相似的命令,由于,咱们的make会自动识别,并本身推导命令。
只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,若是make找到一 个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。而且 cc -c whatever.c 也会被推导出来,因而,咱们的makefile不再用写得这么复杂。咱们的是新的makefile又出炉了。
objects = main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h
clean :
rm edit $(objects)
固然,若是你以为那么多[.o]和[.h]的依赖有点不爽的话,好吧,没有问题,这个对于make来讲很容易,谁叫它提供了自动推导命令和文件的功能呢?来看看最新风格的makefile吧。
objects = main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h
clean :
rm edit $(objects)
变量