C语言的本质(37)——makefile之隐含规则和模式规则
大多数的C/C++编译器都支持一个“-M”的选项,即自动找寻源文件中包含的头文件,并生成一个依赖关系。你就不必再手动书写若干文件的依赖关系,而由编译器自动生成了。GNU的C/C++编译器,你得用“-MM”参数,不然,“-M”参数会把一些标准库的头文件也包含进来。GNU组织建议把编译器为每一个源文件的自动生成的依赖关系放到一个文件中,为每一个“name.c”的文件都生成一个“name.d”的Makefile文件,[.d]文件中就存放对应[.c]文件的依赖关系。
通常,make会把其要执行的命令行在命令执行前输出到屏幕上。当我们用“@”字符在命令行前,那么,这个命令将不被make显示出来。
“伪目标”并不是一个文件,只是一个标签,由于“伪目标”不是文件,所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显示地指明这个“目标”才能让其生效。使用一个特殊的标记“.PHONY”来显示地指明一个目标是“伪目标”,向make说明,不管是否有这个文件,这个目标就是“伪目标”。
我们可以在Makefile的命令行前加一个减号“-”(在Tab键之后),标记为不管命令出不出错都认为是成功的。
make的“模式”一般是至少含有一个“%”。一个目标的模式有一个有前缀或是后缀的"%",或是没有前后缀,直接就是一个"%"。因为"%"代表一个或多个字符,所以在定义好了的模式中,我们把"%"所匹配的内容叫做"茎"。在目标和依赖目标中同时有"%"时,依赖目标的"茎"会传给目标,当做目标中的"茎"。
ifeq、else和endif。ifeq的意思表示条件语句的开始,并指定一个条件表达式,表达式包含两个参数,以逗号分隔,表达式以圆括号括起。else表示条件表达式为假的情况。endif表示一个条件语句的结束,任何一个条件表达式都应该以endif结束。
函数调用,很像变量的使用,也是以“$”来标识的,其语法如下:$(<function> <arguments> )或是${<function> <arguments>}。<function>就是函数名,make支持的函数不多。<arguments>是函数的参数,参数间以逗号“,”分隔,而函数名和参数之间以“空格”分隔。函数调用以“$”开头,以圆括号或花括号把函数名和参数括起。
“$<”和“$@”是自动化变量。每个依赖文件“$<”。“$@”表示模式“%.d”文件。
模式规则:。至少在规则的目标定义中要包含"%",否则,就是一般的规则。
%.o : %.c ; <command ......>,其含义是,指出了怎么从所有的[.c]文件生成相应的[.o]文件的规则。如果要生成的目标是"a.o b.o",那么"%c"就是"a.c b.c"。
-c 只激活预处理,编译,和汇编,也就是他只把程序做成obj文件
-o 制定目标名称,缺省的时候,gcc 编译出来的文件是a.out,很难听
-Idir 制定了目录
-M 生成文件关联的信息,-MM 但是它将忽略由#include<file>造成的依赖关系,-MD 和-M相同,但是输出将导入到.d的文件里面,-MMD 和-MM相同,但是输出将导入到.d的文件里面。
-MT Target :在生成的依赖文件中,指定依赖规则中的目标。自动生成依赖关系时,需要添加文件路径,-MT"$(<:.cpp=.o) $@" 来指定.o 与.d。文件。完美,找了几天的问题。
-llibrary 制定编译的时候使用的库
-Wall 生成所有警告信息。-ansi 只支持 ANSI 标准的 C 语法。