什么是makefile?
makefile关系到整个工程的编译规则.会不会写makefile从一个侧面说明了一个人是否有具备完成大型工程的能力.
一个工程的源文件不计其数,其按类型,功能,模块分别放在若干个目录中.makefile定义了一系列规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译
自动化编译,只需要一个make命令,极大提高开发效率
程序的编译 链接
编译:首先要把源文件编译成中间代码文件,在windows下是.obj文件,unix下是.o文件
需要语法的正确,函数和变量的声明正确(函数和变量声明需要头文件)
链接:主要链接函数和全局变量
库文件:由于编译生成的中间文件太多,我们要给中间目标文件打个包,这个包叫做库文件
库文件分为静态库和动态库
静态库:是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接
windows 后缀.lib linux 后缀.o
动态库:动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入.
不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题.
也解决了静态库对程序的更新,部署和发布页会带来麻烦.用户只需要更新动态库即可,增量更新.
windows 后缀.dll linux 后缀.so
makefile规则,核心
target ... : prerequisites ... target 可以为.o ,可执行文件,或者标签 prerequisties为依赖文件
[tab] command -------command行必须以tab开头
prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行.这就是Makefile的规则,
示例
edit:main.o files.o
gcc -o edit main.o files.o
main.o:main.c main.h
gcc -c main.c
files.o:files.c files.h
gcc -c files.c
clean:
rm edit main.o files.o
makefile 工作步骤
1.make 会在当前目录找名字叫做makefile或者Makefile的文件
2.在文件中查找第一个target,在上面的例子中"edit",并将这个文件作为最终目标文件
3.若edit不存在,或者edit所依赖的后面的.o文件修改时间比edit文件新,他会执行后面定义的命令来生成edit这个文件
4.若edit所依赖的.o文件也不存在,那么make会在当前文件中找到目标为.o文件的依赖,然后按规则生成.o文件
5.用.o文件声明make的最终任务
make 一层一层找文件的依赖关系,直到编译出第一目标文件
Makefile主要包含了五个东西:显示规则,隐晦规则,变量定义,文件指示和注释
显示规则:明显指出要生成的文件,文件的依赖文件,生成的命令
隐晦规则:make有自动推导的功能,如果make找到一个[A.o]文件,它会自动把[A.c]文件加在依赖关系中
并且gcc -c A.c也会被推导出来
例如
edit:main.o files.o
cc -o edit main.o files.o
main.o:main.h
files.o:files.h
clean:
rm edit main.o files.o
变量定义:makefile允许定义一系列变量,只有当变量被执行的时候,才会扩展到相应的引用位置
例如
objects=main.o files.o
edit:$(objects) -----shell环境变量是用${}
cc -o edit $(objects)
main.o:main.h
file.o:files.h
clean:
rm edit $(objects)
文件指示:一个是makefile中引用另一个Makefile 类似C的include
根据情况指定makefile中有效部分 类似C的预编译
定义一个多行的命令
注释:只有行注释.注释使用#字符,如果要在makefile中使用,可以反斜框转义\#
引用其他makefile
make 命令开始时,会把找寻include所指出的其它Makefile,并把其内容安置在当前的位置.
就好像C/C++的#include指令一样。如果文件都没有指定绝对路径或是相对路径的话.
make会在当前目录下首先寻找,如果当前目录下没有找到.
那么,make还会在下面的几个目录下找:
1、如果make执行时,有“-I”或“--include-dir”参数,那么make就会在这个参数所指
定的目录下去寻找。
2、如果目录<prefix>/include(一般是:/usr/local/bin或/usr/include)存在的话,m
ake也会去找。
通配符
支持*,?
通符同样可以用在变量中,例如objects = *.o
objects的值就是*.o,不会展开
如果要让通配符中展开,可以这样objects:=$(wildcard *.o)
文件搜寻
当make需要去找寻文件的依赖关系时,你可以在文件前加上路径.但最好的方法是把一个路径告诉make,让make在自动去找.
Makefile文件中的特殊变量“VPATH”就是完成这个功能的
如果定义了这个变量,make就会在当当前目录找不到的情况下,到所指定的目录中去找寻文件了
VPATH = src:../headers
make会按照这个顺序进行搜索,目录由“冒号”分隔
另一个设置文件搜索路径的方法是使用make的“vpath”关键字(注意,它是全小写的)这是一个make的关键字
使用方法有三种
1 vpath <pattern> <directories>
为符合模式<pattern>的文件指定搜索目录<directories>
2 vpath <pattern>
清除符合模式<pattern>的文件的搜索目录
3 vpath
清除所有已被设置好了的文件搜索目录
我们可以连续地使用vpath语句,以指定不同搜索策略.make会按照vpath语句的先后顺序来执行搜索
vpath %.c foo
vpath % blish
vpath %.c bar
其表示“.c”结尾的文件,先在“foo”目录,然后是“blish”,最后是“bar”目录(%表示匹配零或若干字符)
伪目标
.PHONY:clean ------------用一个特殊的标记PHONY
clean:
rm edit *.o
只要有这个声明,不管是否有“clean”文件,要运行“clean”这个目标,只有make clean才会执行