makefile是什么
makefile: makefile是linux下对源文件的自动编译工具,一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中, makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,makefile 就像一个 Shell 脚本一样,其中也可以执行操作系统的命令
make:make 是一个命令工具,是一个解释 makefile中指令的命令工具,makefile 带来的好处就是——“自动化编译”,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率
makefile文件
make命令执行时,需要一个makefile文件,以告诉make命令需要怎么样的去编译和链接程序,该文件名称必须为"Makefile"或"makefile"或"GNUmakefile",如果使用了其他名称,则需要使用make命令-f或–file参数去指定,如"make -f MakeLinux"
大多数make都支持"makefile"和"Makefile"这两者默认文件名,因而最好使用其作为文件名
makefile文件书写规则:
target:prerequisites
command
target是要生成的目标文件(Object File),也可以是执行文件或一个标签
prerequisites就是要生成target所必须的先决文件
commnd就是由prerequisites生成target所需要的命令(Shell命令)
注意:commnd前要用Tab缩进
这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中
makefile文件中,规则的书写顺序是很重要的,makefile中应该有一个最终目标,其他的目标都是被这个目标所连带出来的,要让make知道你的最终目标。makefile中第一条规则中的目标将被确立为最终的目标。如果第一条规则中的目标有很多个,那么,第一个目标会成为最终的目标。make所完成的也就是这个目标
例如下图:(main是最终目标)
使用变量
变量是计算机系统用于保存可变值的数据类型,我们可以直接通过变量名称来提取到对应的变量值。就是以一组文字或符号等,来替换一些设置或一串保留的数据
变量使用方式:
- 定义:用=进行定义
- 使用:$(变量名)
例如:上例中有5个.o文件,可以如下定义
file=my_add.o my_sub.o my_mux.o\
my_div.o main.o
反斜杠\是换行符的意思,以后用到这5个.o文件,使用$(file)即可
变量与环境变量的其他介绍请参考我的上一篇博客:Linux:Shell、BASH以及Shell Script简介
文件搜寻
在一些大的工程中,有大量的源文件,我们通常的做法是把这许多的源文件分类,并存放在不同的目录中。所以,当make需要去找寻文件的依赖关系时,你可以在文件前加上路径,但最好的方法是把一个路径告诉make,让make自动去找
makefile中的特殊变量VPATH就是实现该功能的,如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么,make就会在当前目录找不到的情况下,到所指定的目录中去找寻文件了
VPATH使用规则:
VPATH=path1:path2
上面指定了两个路径,路径之间用冒号:分隔
还可以使用make的关键字vpath设置文件搜索路径,vapth是全小写,不同于VPATH,vapth是关键字,VPATH是变量
vpath使用规则:
vpath <pattern> <directories> #为符合模式<pattern>的文件指定搜索路径<directories>
vpath<pattern> #清除符合模式<pattern>的文件的搜索目录
vpath #清除所有已被设置好了的文件搜索目录
例:vpath %.c path1表示指定.c文件的搜寻目录为path1,%表示匹配零或若干字符
隐晦规则
GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个.o文件后都写上类似的命令,因为,我们的make会自动识别,并自己推导命令
只要make看到一个.o文件,它就会自动的把 .c文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c就会是whatever.o的依赖文件。并且 gcc -c whatever.c 也会被推导出来,这就是make的隐晦规则
根据隐晦规则与变量,刚开始的例子可以进行简化,如下图:
引用其他的makefile
在maikefile文件中使用include关键字可以把别的makefile包含进来,被包含的文件会原模原样的放在当前文件的包含位置
include语法:
include file1 file2 file3
file可以是当前操作系统Shell的文件格式,可以包含路径和通配符,也可是使用变量
伪目标
makefile书写规则中的target也可以是一个伪目标,例如清除命令
clean:
rm *.o
执行完rm *.o命令并不会生成一个clean文件,clean只是一个标签,形象地称其为伪目标
可以使用.PHONY来显示地指明一个目标是伪目标
.PHONY:clean
clean:
rm *.o
注意:每个makefile中都应该写一个清空目标文件(.o和执行文件)的命令,以便于重编译和保持文件的清洁,不成文的规矩是——“clean从来都是放在文件的最后”,make会把makefile里出现的第一个target当作缺省target。其他的除非是生成缺省target需要,否则不会执行,因此该clean在make时并不会执行,要执行该clean命令,手动使用make clean命令来清除掉*.o文件
make工作执行流程
GNU的make工作时执行步骤如下:
- 读入所有的makefile文件
- 读入被include的其他的makefile
- 初始化文件中的变量
- 推导隐晦规则,并分析所有规则
- 为所有的目标文件创建关系依赖链
- 根据依赖关系,决定哪些目标要重新生成
- 执行生成命令