1.背景
- 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
- 一个工程中的源文件不计其数,其按类型,功能,模块分别放在若干目录中,makefile定义了一系列的规则来制定,那些文件需要先编译,那些文件需要后编译,那些文件需要重新编译,甚至于进行更复杂的功能操作
- makefile带来的好处就是—“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
- make是一个命令工具,是一个解释Makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令。
- make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建
2.实例代码
-
首先在Linux下创建两个文件,一个用来完成代码的编写,另一个是makefile(也可以是大写的Makefile)。 -
在mycode.c中简单的编写一个hello world的代码 -
在makefile编写依赖关系,和依赖方法 说明:makefile中的第一行表明依赖关系:mycode的可执行程序依赖mycode.c;第二行表明依赖方法:用gcc进行编译mycode.c生成mycode。后面三行是进行项目清理,下面会有介绍,现在可以忽略。 -
之后我们编译代码就再也不用用gcc mycode.c这样的指令,而是可以直接make,可执行程序mycode就会生成了。 -
当然我们也可以运行这个可执行程序 -
如果我们不想要mycode可执行程序,在命令行直接输入make clean即可。 注意: 通过make/Makefile管理的方式,就是Linux下的自动化构建工具。
3.三个时间
3.1 三个时间的引入
通过上述例子,细心的同志就会发现如果你连续make生成可执行程序,就会生成一个报错mycode is up to date(mycode 是最新生成的),那么Linux是如何判断mycode是不是最新的呢? 毫无疑问,通过比较两个时间,mycode和mycode.c时间,那怎么查看文件的时间呢?stat + 文件名 用来查看时间。 这里通过比较两个文件Modify时间(后文具体介绍三个时间),来判断是否需要生成最新的mycode可执行程序 这里发现mycode的Modefy时间比mycode.c的文件新,所以不需要生成最新的可执行程序mycode,所以报错mycode is up to date也不难理解了。
3.2 三个时间的具体介绍
3.2.1 Access访问时间
Access是最近访问文件的时间,但是由于用户访问文件的次数过多,而且用户对Access的时间需求不大。所以Linux系统优化了这Access的访问时间。可能是访问一定次数更改一次,也可能间隔一定的时间。如果需要准确了解,可能需要源码剖析,有兴趣的同志自行研究。
这里cat访问文件之后,Access的时间并没有进行修改。
3.2.2 Change文件属性修改时间
这个就很好理解了,当文件属性属性修改的时候,Change的时间也会修改。
3.2.3 Modify文件内容修改时间
举例:把mycode.c中的printf赋值三遍 比较两个Modify时间 毫无疑问,modify的时间变了,但这里其实还有一个问题: 问:为什么在Change的时间也更新的呢? 答:当文件的大小发生改变,那大小算不算文件属性的一部分呢?
4.makefile的推导规则
我们在Makefile中编写这样的依赖关系和依赖方法 makefile的推导规则类似于stack结构,先进后出。 mycode 依赖于mycode.o mycode.o 依赖于 mycode.s mycode.s 依赖于 mycode.i mycode.i 依赖于 mycode.c 所以先执行那个依赖方法就很明显了后进去的先执行
5.原理
那么make是如何工作的?
- make会在当前目录下找名字叫Makefile或者makefile的文件。
- 如果找到,它会找文件中的第一个目标文件(target),并把这个目标文件作为最终的文件。
- 如果mycode文件不存在,或者mycode所依赖的后面的mycode.o文件修改时间要比mycode要新。那么他会执行后面所定义的命令来生成这个mycode文件。
- 如果mycode依赖的文件mycode.o不存在,那么make会在当前文件夹找目标为mycode.o文件的依赖性,如果找到,再根据那个规则生成mycode.o文件。
- 这就是整个make的依赖性,make会一层一层去寻找文件的依赖关系,直到最终编译出第一个目标文件。当编译成功第一个目标文件后,make就不往下面进行编译了。
- 在寻找的过程中,如果发现错误,那么make会直接退出,并报错。而对于所定义的命令错误,或者编译不成功,make根本不理。
- make只管文件的依赖性。即,如果我找到依赖关系后,冒号后面的文件还是不在,那么make就直接罢工。
6.项目清理
- 还记的我们编写Makefile中的.PHONY:clean吗?它表明clean总是被执行。跳出时间比较,那如果我们进行.PHONY:mycode操作呢?
结果显而易见,我们可以一直make了,在也不用比较两个Modify时间了 - 像clean这种,没有被第一个目标文件直接或间接关联,那么他后面的所定义的命令不会被自动执行。所以如果我们需要执行它,需要显示执行,如make clean 来清除目标文件,以便重新编译。
- 但是一般我们这种clean目标文件,我们将它设置为伪目标。用.PHONY修饰。伪目标的特点:总是被执行。
|