为什么要使用Makefile
- 会不会使用Makefile从一个侧面说明了是否具备完成大型工程的能力
- 一个工程中的文件不计其数,按类型,功能,模块分别放在若干个目录中,Makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件选哟重新编译,以及更加复杂的操作
- Makefile带来的好处就是——“自动化编译”,一旦写好就只需要一个make命令整个工程就可以完全自动编译,极大的提高了软件开发的效率
- make是一个命令工具,是一个解释Makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GUN的make。可见,Makefile已经成为了一种在工程方面的编译方法
- make是一条指令,makefile是一个为你教案,两个搭配使用完成项目的自动化构建
Makefile的理解
首先我们先来看一个示例代码
C++代码
1 | /*hello.c*/ |
Makefile文件
1 | hello:hello.o |
依赖关系
- 上边的文件中,hello依赖hello.o
- hello.o依赖hello.s
- hello.s依赖hello.i
- hello.i依赖hello.c
依赖方法
- g++ hello. -option hello.
看到上边的简单例子,很容易发现它主要分成了三个部分,冒号之前的hello(hello.o,hello.s,hello.i),我们称之为目标文件(target),被认为是这条语句所要生成的目标对象;冒号后面的部分hello.o(hello.s,hello.i,hello.c),我们称之为依赖关系表,也就是需要编译target文件所需要的文件,这些文件只要有一个发生了变化就会触发该语句的第三部分,我们称之为命令部分,相信你也可以看得出这是一条编译命令。
请注意!在gcc命令之前必须是一个tab缩进,而不能是空格
语法规定Make file中的命令之前必须要有一个tab缩进,否则make时会报错
原理
- 在我们输入make命令后,make会在当前目录下找名字叫做“makefile”或者”Makefile“的文件
- 如果找到,它会找文件中的第一个目标文件(target),在上边的例子中,它会找到”hello”这个文件,并把这个文件当作最终的目标文件
- 如果hello文件不存在,或是hello所依赖的后面的hello.o文件的文件修改时间要比hello这个文件新,那么它就会去执行后面所定义的命令去生成这个hello文件
- 如果hello所依赖的hello.o文件不存在,那么make会在当前文件中找hello.o文件的依赖性,如果找到则再根据那一个规则去生成hello.o文件
- 这就是make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件
- 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或者是编译不成功,make则不会理会
Makefile的简便使用
学会了上边的基础使用后,我们来看一看下边的代码
1 | cc = g++ |
如你所见,我们在上述代码中定义了 三个常量cc,prom,source。它们分别告诉了make我们所要使用的编译器,要编译的文件以及源文件。这样我们在需要修改这三者中的任何一项时只需要修改常量的定义即可,而不用去管后面的代码
在这里再介绍几个特殊的宏:
%.o:%.c
这是一个模式规则,表示所有的.o目标都依赖于与它同名的.c文件
$^
引用的是整个关系表
$<
代表的是依赖关系表中的第一项
$@
代表的是目标文件
Makefile中的伪目标
像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显式用make来执行,即命令——“make clean”,以此来清楚所有的目标文件,以便重新编译。
但是一般这种clean的目标文件,我们会将它设置为伪目标,用.PHONY修饰,伪目标的特性是——它是被执行的