背景
·会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
·一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
·makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
·make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
·make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
实例代码
首先创立一个Makefile的文件
[yyh@ecs-86081 lesson2]$ touch Makefile [yyh@ecs-86081 lesson2]$ ll total 8 -rw-rw-r-- 1 yyh yyh 0 Jul 28 23:13 Makefile -rw-rw-r-- 1 yyh yyh 281 Jul 28 22:14 mytest.c -rw-rw-r-- 1 yyh yyh 90 Jul 27 23:04 mytest.cpp然后编写Makefile文件,用以表明依赖关系和依赖方法
也可以像这样编写Makefile:
[yyh@ecs-86081 lesson2]$ cat Makefile mytest:mytest.c gcc -o $@ $^其中$@表示的是目标生成文件,$^表示的是参与编译的源文件
直接使用make命令就可直接为我们生成可执行文件mytest
[yyh@ecs-86081 lesson2]$ make gcc mytest.c -o mytest -std=c99 [yyh@ecs-86081 lesson2]$ ll total 24 -rw-rw-r-- 1 yyh yyh 50 Jul 28 23:16 Makefile -rwxrwxr-x 1 yyh yyh 8392 Jul 28 23:16 mytest -rw-rw-r-- 1 yyh yyh 281 Jul 28 22:14 mytest.c -rw-rw-r-- 1 yyh yyh 90 Jul 27 23:04 mytest.cpp
Makefile实际就是表明依赖关系和依赖方法。比如举一个生活中非常形象的例子:到月底了,给家里人打电话“爸,我是你的儿子,月底了,没钱了,给我打一千块钱。”这句话里,首先表明了依赖关系,没钱了要钱表明了依赖方法。这就说明了,只有依赖关系和依赖方法共同作用才能达成某种目的。
依赖关系(文件和文件之间的相互依赖关系)
- 1 mytest:mytest.o
- 2 gcc -o mytest mytest.o
- 3 mycode.o:mytest.s
- 4 gcc -c mytest.s -o mytest.o
- 5 mycode.s:mytest.i
- 6 gcc -S mytest.i -o mytest.s
- 7 mycode.i:mytest.c
- 8 gcc -E mytest.c -o mytest.i
- 9 .PHONY:clean
- 10 clean:
- 11 rm -f mytest mytest.i mytest.s mytest.o
原理
·make是如何工作的?在默认的方式下,也就是我们只输入make命令即可运行成功。那么,
1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“mytest这个文件,并把这个文件作为最终的目标文件。
3. 如果mytest文件不存在,或是mytest所依赖的后面的mytest.o文件的文件修改时间要比mytest这个文件新,那么,他就会执行后面所定义的命令来生成mytest这个文件。
4. 如果mytest所依赖的mytest.o文件不存在,那么make会在当前文件中找目标为mytest.o文件的依赖性,如果找到则再根据那一个规则生成mytest.o文件。(这有点像一个堆栈的过程)
5. 当然,你的C文件和H文件是存在的啦,于是make会生成 mytest.o 文件,然后再用mytest.o 文件声明make的终极任务,也就是执行文件mytest了。
6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件
7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
项目清理
·工程是需要被清理的
·像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。
[yyh@ecs-86081 lesson2]$ ll total 24 -rw-rw-r-- 1 yyh yyh 50 Jul 28 23:18 Makefile -rwxrwxr-x 1 yyh yyh 8392 Jul 28 23:16 mytest -rw-rw-r-- 1 yyh yyh 281 Jul 28 22:14 mytest.c -rw-rw-r-- 1 yyh yyh 90 Jul 27 23:04 mytest.cpp [yyh@ecs-86081 lesson2]$ make clean rm -f mytest [yyh@ecs-86081 lesson2]$ ll total 12 -rw-rw-r-- 1 yyh yyh 83 Jul 28 23:20 Makefile -rw-rw-r-- 1 yyh yyh 281 Jul 28 22:14 mytest.c -rw-rw-r-- 1 yyh yyh 90 Jul 27 23:04 mytest.cpp执行上面的"make clean"命令过后可执行文件mytest就被清除了
·但是一般我们这种clean的目标文件,我们将它设置为伪目标用 .PHONY 修饰,伪目标的特性是,总是被执行的。