一、前言
二、理解
1.使用
makefile就是创建一个文件叫做 makefile 。
我们vim打开makefile。
我们敲出上图代码。正常情况下,我们要编译 test.c 文件,我们直接 gcc test.c ,加上 -o [文件名]可以指定编译出来的可执行程序名字。
其中 test:test.c 冒号左边是生成的程序名,冒号右边的是程序生成依赖的文件,这一行是依赖关系。而下面一行则是依赖方法,记住,下面一行开头必须是 tab 键。
clean没有依赖的文件,所以后面不接文件名,下面同样是依赖方法。而 .PHONY: 则是将clean修饰成伪目标。
做好上述的的准备之后,我们输入 make
就会发现,系统会自动帮我们输入依赖关系。当操作的文件非常多的时候,这是极其方便的。
我们再次 make 就会发现系统提示我们 test 文件已经是最新的了,不能再编译。
我们想要删除输入:make clean ,可是我们却发现 make clean 是可以一直清理的。这就是因为我们用 .PHONY 将它设置成了伪目标,伪目标的特性是:总是被执行。
那么 make 是如何识别文件是不是最新的呢?
2.文件三个时间
当我们用 stat 命令查看文件属性的时候,我们可以看到有:access、modify、change 三个时间。
access:是进入文件的时间,但是当一个系统运行起来的时候,同时会进入非常多的文件,如果每进入一次,就修改大量文件的时间,那么也太浪费性能了,所以就规定了一段时间进入了一定次数后才修改时间。
modifiy:是修改文件内容的时间,当修改一个文件的内容的时候,access的时间一定改变。
change:是修改文件属性的时间。
当可执行文件生成的时候会得到这三个时间,如果我们源文件修改了,时间也会刷新,当源文件的内容修改时间要比可执行文件的时间晚的时候,那么这时候我们输入 make 才会重新编译。
三、原理
- make会在当前目录下找名字叫“Makefifile”或“makefifile”的文件。
- 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“test”这个文件,并把这个文件作为最终的目标文件。
- 如果hello文件不存在,或是hello所依赖的后面的hello.o文件的文件修改时间要比test这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成test这个文件。
- 如果test所依赖的test.o文件不存在,那么make会在当前文件中找目标为test.o文件的依赖性,如果找到则再根据那一个规则生成test.o文件。(这有点像一个堆栈的过程)
- 当然,你的C文件和H文件是存在的啦,于是make会生成test.o 文件,然后再用test.o 文件声明make的终极任务,也就是执行文件test了。
- 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
- 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
- make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
例如:
mycode 是依赖 mycode.o的,而 mycode.o 是依赖 mycode.s 的,mycode.s 是依赖 mycode.i的,mycode.i 是依赖 mycode.c 的,没有依赖文件就会向下去找,逐层递归,最终倒着生成。mycode.i依赖 mycode.c 生成,然后mycode.s 依赖 mycode.i 生成……,最终生成了mycode,但是我们实际上写的时候是没必要这样写的, 我们直接mycode依赖mycode.c就行了,其他的编译器会自动处理的。