一、概念
Makefile
是一个特殊的文件,用于指导 make
工具自动化软件的构建过程。它包含了一系
列的指令和规则,用于告诉 make
如何编译和链接程序。在Linux大型项目中,有不同类型的模
块,这些模块放在不同的目录下,不同的目录下又包含了较多的源代码,比如编译源代码的时候我
们总不能一个一个的用gcc编译器去编译吧,所以我们肯定希望的是写一个文件,这个文件告诉了
make工具我们要编译哪些目录下的源代码,以及编译的先后顺序是怎样的,所以到时候直接用
make指令就能编译源代码了。
二、makefile文件命名规则
2.1 文件命名
一般为makefile或者是Makefile2.2 Makefile规则
一个Makefile文件中可以有一个或者是多个规则。
目标...:依赖...
命令(shell命令)
.....
目标:最终生成的文件(伪目标除外),比如可知执行文件
依赖:生成目标所需要的文件或是目标,例如依赖是.c文件和依赖的动态库。
命令:通过执行命令对依赖依赖操作生成目标(命令前必须要Tab键缩进)这里的命令就是
gcc *.c -o app
2.2 案例展示
经过上述说明,相信还有不少人是不知道这个makefile文件到底是干啥的,下面通过例子说明
我的目录是这样的:
这个Makefile文件创建,使用如下指令即可: 对了这个vim编辑器如何使用建议上网艘一下,
就涉及到三种模式---->命令模式、插入模式、底线模式,注意的是插入模式不能直接与底线模式相
互转换,只能通过命令模式间接转换!
vim Makefile
我写的Makefile是这样的: 第一行的app就是生成的可执行文件,自己随便起名字,后面紧跟着的
是生成这个文件所需要的依赖,依赖必然是源代码和要链接的库文件;第二行是编译的命令,注意
这个命令写之前要用按一下tab键缩进,然后再写。
使用make指令编译Makefile文件可得到:
有的同学会有疑问,这直接用gcc编译指令不久好了嘛,为何还要写Makefile文件呢,这不是
多此一举吗?想一下,如果源代码修改了,按照你说的用gcc编译器源代码,指令如下:
gcc xx1.c xx2.c xx3.c xx4.c -o app
然而用写好的Makefile文件,指令只要用
make
哪个方便?你可以这样想,Makefile是一个编译的接口,而make指令调用这个接口,至于这
个接口里面是如何实现的,不用关心。
2.3 Makefile工作原理
(1)命令在执行之前,需要检查规则中的某些依赖是否存在,如果存在,执行命令,如果不
存在向下检查其他的规则,检查有没有一个规则是用来生成这个依赖的,如果找到了执行该规则中
的命令。
(2) 检查更新,在执行规则中的命令时,会比较目标和依赖文件的时间,如果依赖的时间比
目标时间晚,需要重新生成目标。如果依赖的时间比目标时间早,目标不需要更新,对应规则中的
命令不需要被执行。
赤裸裸地说上面两个原理,那是挺抽象的,下面进行实操讲解,先看第一条:
app这一行是第一条规则,后面所有的规则都是为他服务的,app是即将要生成的目标文件,后
面的main.o、my_print.o、print_hello.o文件是生成该目标文件的依赖项,首先,Makefile会检查第
一个main.o文件是否存在,如果不存在,往下找其他的规则,找到了main.o这一规则,所以他会执
行下面gcc -c main.c -o main.o这一指令,然后生成main.o这一文件,作为app后面的依赖项;然后
开始搜索my_print.o这个依赖项,发现没有,继续往下搜索遇到my_print.o这一规则,然后执行这
个规则,生成app的第二个依赖向,依次类推,只有当app后面所有的依赖向都存在的时候,才会
执行app下面的指令!!如下图:
再看第二条,app是生成的文件,执行make显示的是app已经是最新的,说明并未执行
第一条规则下的指令,这也就是说依赖项的时间比目标文件要早,目标不需要更新,也不需要执行
对应的命令,这个时间早晚是如何理解的呢?你这样想:依赖向是先生成的,目标文件是后生成的
所以,早晚时间不就有概念了么。
倘若此时我修改了main.c的程序,重新执行make指令,将会得到如下:
解释一下:由于我的main.c改变了,在main.o:main.c这个规则下,我的依赖项main.c要比
之前生成的main.o要晚,所以执行该规则下面的指令,同理可得,对于第一个规则app而言,app
是之前存在的,而main.o是刚生成的,依赖向比目标文件时间晚,执行第一条规则下面的命令!
所以Makefile有自动检测更新功能!