make是一个命令工具,是一个解释makefile中指令的命令工具。
一般来说每一个源文件都会对应一个中间目标文件。
编译(compile)生成中间目标文件,连接(link)生成可执行文件,连接主要是连接函数和变量。链接器不管源文件,只管中间目标文件。函数如果未被声明可以生成中间目标文件,但是连接时候会报错。
make命令执行时候需要一个makefile文件,以告诉make命令需要怎么样去编译和连接程序。我们需要一个makefile来告诉make命令如何编译个连接。规则是:
1)如果这个工程没有被编译过,那么我们所有的c文件都要被编译并且被连接
2)如果这个工程中间的几个c文件被修改,那么我们只需要编译被修改的c文件,并且连接目标程序
3)如果这个工程的头文件被修改,那么需要编译引用这个头文件的c文件。并且连接目标文件。
makefile的规则:
targe...: prerequisites...
command
...
...
;target就是一个目标文件,可以是一个obj文件,也可以是可执行文件,还可以是一个标签(label)。
;prerequisites就是要生成那个target所需要的文件或者是目标。
;command也就是make要执行的命令。(任意的shell命令)
依赖关系实质上说明了目标文件是由哪些文件生成的,换言之,目标文件是由哪些文件更新的。在定义好依赖关系以后,后续的那一行定义了如何生成目标文件的操作系统命令,一定要一个tab键开头。
在默认的方式下,我们只是输入了make命令,那么make是如何工作的呢?
1)make会在当前目录下寻找名字叫“Makefile”或者“makefile”的文件
2)如果找到,它就会找文件中的第一个目标文件(target)。就是makefile文件中的第一个target。并且把这个文件作为最终的目标文件。
3)如果目标文件不存在,或者是目标所依赖后面的.o文件的修改时间要比target文件新,那么就会执行后面所定义的命令来生成目标文件
4)如果目标文件所依赖的.o文件也不存在,那么make就会在当前文件中间寻找.o文件的依赖型。生成.0文件
5)当然,c文件和h文件都是存在的啦。于是make会生成.o文件,然后再用.o文件生成make的终极任务,也就是最终的目标文件。
make的依赖型:make会一层一层的寻找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中如果出现错误,比如最后被依赖的文件没 有找到,那么make会直接推出,并且报错。对于所定义的命令的错误,或者是编译不成功,make根本不理睬。make只管文件的依赖型。
声明一个变量,叫objects,OBJECTS,objs,OBJS,obj,OBJ.在makefile中以“$(objects)”的方式来使用这个变量。
每一个makefile中都应该写一个清空目标文件(.o和执行文件)的规则。这不仅便于重新编译,而且有利于保持文件的清洁。clean从来就是放在文件的最后。
makefile里面有什么?主要包括五个东西:显式规则,隐晦规则,变量定义,文件指示和注释。
1)显式规则:要生成的文件,文件的依赖文件和生成的命令。
2)隐晦规则:make有自动推导的功能,能够推导出依赖关系。
3)变量的定义:makefile中要定义一系列的变量,变量一般都是字符串。
4)文件指示:包括三部分:
A)一个makefile引用另一个makefile,类似于c中的“include”。使用include关键字将别的makefile包含进来。语法:include<filename>
B)根据某些情况指定makefile中的有效部分,类似于c中的“#if”
C)多行命令
5)注释:行注释“#”,用“\#”进行转义。
make一次寻找“GNUmakefile”,“makefile”,“Makefile”。
伪目标并不是一个文件,只是一个标签,由于“伪目标”不是文件,所以make无法生成他的依赖关系和决定它是否要执行。为了避免伪目标和文件重名,使用特殊的标记“.PHONY”来显式的表示是“伪目标”。