📙 作者简介 :RO-BERRY
📗 学习方向:致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识
📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持
目录
- 1.背景
- 2.依赖关系和依赖方法
- 3.简单使用
- 4.项目清理
- 5.三个时间
- 6.修改访问时间:
- 7.PHONY修饰目标文件
- 8.make实现原理
1.背景
- 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
- 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
- makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编
译,极大的提高了软件开发的效率。 - make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
- make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
2.依赖关系和依赖方法
make是一个命令,makefile是一个文件,makefile里面存储的是依赖关系和依赖方法
- 在makefile里写入如下这种信息:
mybin就是目标文件,mytest.c就是依赖文件
通过依赖方法将依赖文件生成目标文件
依赖关系:确定为什么要帮你。
依赖方法:确定怎么帮你。
3.简单使用
- Makefile文件编辑好后再输入make
- 即可自动完成文件的编译
- 形成的可执行程序叫做mybin
4.项目清理
我们在实现了make之后再次实现make会出现如下提示
💧提示说明该可执行程序是最新的,不能再编译了。只要可执行程序的最近修改时间比源文件的最近修改时间要来的新,那么该可执行程序就是最新的,此时make就会出现以上状况。
这个时候我们有两种办法解除提示
1.修改源文件内容
2.清理项目:
在Makefile文件添加如下指令
输入make clean
将项目及时清理,以便我们后续的编译
以上就是项目的自动化构建以及项目的自动化清理
这里我们引申一个概念:
1.Makefile和make形成目标文件的时候,默认是从上到下扫描makefile文件的,默认形成的是第一个目标文件
2.默认只形成一个
- 正常情况下:
输入make执行编译,输入make clean才会执行clean
- 将clean写在make前:
输入make执行清理,输入make mybin才会执行编译
在这里,make后再次make的时候会出现已更新到最新,那么make和makefile怎么知道可执行程序是最新的呢?
这个是通过对比时间比出来的,只要可执行程序的最近修改时间比所有源文件的最近修改时间新,说明他就是最新的
5.三个时间
我们来认识一下时间
使用指令
stat 文件
这里有三个时间
Access是访问时间,即查看该文件的内容的时间;
Modify是文件内容的修改时间;
Change是文件属性的改变时间。
文件=内容+属性
接下来我们来测试一下时间各自的对应操作:
-
1.我们修改文件的权限属性
change时间发生了改变其他的事件没有改动
-
2.修改文件内容
三个时间属性均改变
-
3.查看文件内容
三个时间均没有改变
我们可以看到当多次访问同一个文件的时候,不是每次访问(access)时间都会实时更新,而是过了一段时间后再次访问后才会进行更新。这是因为,时间也是文件的属性,我们要对文件属性进行修改就要到文件所在的磁盘底下对数据进行修改,而访问文件时修改文件,改动属性这三者当中占比最多的一个。如果我们每次访问文件都对文件的访问时间(access)进行实时更新的话,那也就是说在系统当中相当一大部分时间都只在对文件的属性进行更新,而且还是实时更新的,那个假设有多个文件同时访问呢?这务必会对系统的一些效率会产生一定的影响,所以设计者就规定,只有在访问后的一段时间,或者访问到一定的次数之后我们的访问时间才会进行更新。
6.修改访问时间:
我们原来想实现make功能只能更新源文件内容以及实现clean
我们如果每次都要这样是不是会很麻烦?
我们也可直接从修改时间下手,直接通过命令直接修改——修改时间(modify)就要用到我们之前学到的一个命令——touch
,touch除了可以创建一个文件外,还可以对一个已成创建的文件进行刷新修改时间(modify)
7.PHONY修饰目标文件
被".PHONY"修饰后的目标文件成为一个伪目标,修饰后的结果——总是可以被执行。
这个时候无论执行多少次make都可以了,因为这个时候目标文件被.PHONY修饰后成为伪目标,总是可以被执行。
但是我们一般并不希望把目标文件设置为伪目标,一把比较希望把clear设置为总是被执行的。
这里为什么没有被.PHONY修饰还是可以被执行呢,是因为由-f选项,强制删除。
至于为什么不希望把目标文件设置为伪目标呢?是因为当我们在一个项目里面,有很多个.c文件,当这些文件都生成.o文件之后,需要进行链接,而链接也是有效率的,而对于项目多多少少都可能会出现一些问题在给别的.c文件里面,这个时候需要对部分的.c文件进行debug,也就是对部分.c我文件进行修改,那么一旦我们的目标文件被.PHONY修饰为伪目标之后,在debug之后,所有的.o文件都将重新进行链接,个别两个效率可能还看不出来,如果时成百上千个呢?这个时候效率显现出来的,而如果没有被修饰成伪目标,make之后对修改了的我进行再次编译,链接的时候只需要把修改后的文件重新进行链接就行了,这样链接的整体效率就得到了提高。
8.make实现原理
在上面的依赖关系和依赖方法我们都是一步到位的,但是其实中间是有四个过程的
预处理,编译,汇编,和链接
构成的,所有它们的依赖关系和依赖方法应该也是有四个的。
上面的文件
mytext
依赖mytext.o
mytext.o
依赖mytext.s
mytext.s
依赖mytext.i
mytext.i
依赖mytext.c
make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,
- make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
- 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“mytest”这个文件,并把这个文件作为最终的目标文件。
- 如果mytest文件不存在,或是hello所依赖的后面的mytest.o文件的文件修改时间要比mytest这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成mytest这个文件。
- 如果hello所依赖的mytest.o文件不存在,那么make会在当前文件中找目标为hello.o文件的依赖性,如果找到则再根据那一个规则生成mytest.o文件。(这有点像一个堆栈的过程)
- 当然,你的C文件和H文件是存在的啦,于是make会生成 mytest.o 文件,然后再用 mytest.o 文件声明make的终极任务,也就是执行文件mytest了。
- 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
- 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
- make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。