背景
会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了,一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建
原理
make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,
1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件(文件名一定是“Makefile”或者“makefile”否则make找不到)。
2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“hello”这个文件,并把这个文件作为最终的目标文件。
3. 如果hello文件不存在,或是hello所依赖的后面的hello.o文件的文件修改时间要比hello这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成hello这个文件。
4. 如果hello所依赖的hello.o文件不存在,那么make会在当前文件中找目标为hello.o文件的依赖性,如果找到则再根据那一个规则生成hello.o文件。(这有点像一个堆栈的过程)
5. 当然,你的C文件和H文件是存在的啦,于是make会生成 hello.o 文件,然后再用 hello.o 文件声明make的终极任务,也就是执行文件hello了。
6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
make 和 makefile 形成目标文件的时候,默认是从上到下扫描makefile文件的,默认形成的是第一个目标文件。默认之形成一个。
下面我们写一个makefile文件:
通俗的可以解释为mybin 的形成依赖 mytest.c 第二行是解释通过什么方法形成的。
这一段通过make clean 调用。clean的形成并没有依赖的对象,后面也可以不写。
如果将clean 这段代码放到 mybin前面 ,那么make一下所执行的就是clean ,make mybin 才是生成可执行程序。
通过以上的程序我们不难发现多次make之后 make命令便不再会执行了,这是为什么呢?这时我们要引入一个文件时间的概念。
通过stat mybin 这个命令
我们可以发现文件有access modify change 三个时间,分别问文件访问时间,文件更改时间,文件属性变化的时间。
其中modify 的改变会影响 change 。反之则不会。
通过向文件写入内容发现modify 和其他的两个都改变。
文件属性改变,只影响change 并不影响其他。
那么make 命令是对比那个时间来判断是否执行呢?当然是modify 通过对比它和 .obj 文件生成的时间来判断是都要重新执行make,也就是说只有modify的时间比 .obj 文件时间晚,那么就要生成文件了。
补充语法 .PHONY:clean .PHONY修饰clean,成为一个伪代码,使clean总是被执行,使得clean的执行不考虑 文件的时间问题!!!!