一、模式规则
模规则用来定义相同处理规则的多个文件,不同于隐式规则,隐式规则仅仅能够用make默认的变量来进行操作,而模式规则还能引入用户自定义变量,为多个文件建立相同的规则,从而简化Makefile的编写。
比如:将任意一个.c文件转换为.o文件:
%.c:%.o
$(CC) $(CCFLAGS) $(CPPFLAGS) -c -o $@ $<码片
提示:模式规则的格式类似于普通规则,这个规则中的相关文件前必须用“%”标明
一个模式规则就好像一个一般的规则,只是在规则中,目标的定义需要有"%“字符。”%“的意思是表示一个或多个任意字符。在依赖目标中同样可以使用”%“,只是依赖目标中的”%“的取值,取决于其目标。
有一点需要注意的是,”%“的展开发生在变量和函数的展开之后,变量和函数的展开发生在make载入Makefile时,而模式规则中的”%“则发生在运行时。
模式规则中,至少在规则的目标定义中要包含”%“,否则,就是一般的规则。目标中的”%“定义表示对文件名的匹配,”%“表示长度任意的非空字符串。例如:”%.c"表示以".c"结尾的文件名(文件名的长度至少为3),而"s.%.c"则表示以"s.“开头,”.c"结尾的文件名(文件名的长度至少为5)。
如果"%“定义在目标中,那么,目标中的”%“的值决定了依赖目标中的”%“的值,也就是说,目标中的模式的”%“决定了依赖目标中”%"的样子。例如有一个模式规则如下:
%.o : %.c ; <command ......>;
其含义是,指出了怎么从所有的[.c]文件生成相应的[.o]文件的规则。如果要生成的目标是"a.o b.o",那么"%c"就是"a.c b.c"。
一旦依赖目标中的"%"模式被确定,那么,make会被要求去匹配当前目录下所有的文件名,一旦找到,make就会规则下的命令,所以,在模式规则中,目标可能会是多个的,如果有模式匹配出多个目标,make就会产生所有的模式目标,此时,make关心的是依赖的文件名和生成目标的命令这两件事。
二、自动化变量
在上述的模式规则中,目标和依赖文件都是一系例的文件,那么我们如何书写一个命令来完成从不同的依赖文件生成相应的目标?因为在每一次的对模式规则的解析时,都会是不同的目标和依赖文件。
自动化变量就是完成这个功能的。在前面,我们已经对自动化变量有所提涉,相信你看到这里已对它有一个感性认识了。所谓自动化变量,就是这种变量会把模式中所定义的一系列的文件自动地挨个取出,直至所有的符合模式的文件都取完了。这种自动化变量只应出现在规则的命令中。
下面是所有的自动化变量及其说明:
1.$@
表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,"$@"就是匹配于目标中模式定义的集合
2.$<
依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%“)定义的,那么”$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的。
3.$^
所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。
三、makefile的运行规则
如果依赖文件有一个以上的文件比目标文件要新的话,就要重新执行一次规则指令,生成新的目标文件(目标文件一定比依赖文件新,否则,编译时会重新执行相对应的规则命令,生成比依赖文件更新的目标文件)
四、变量的基础
变量在声明时需要给予初值,而在使用时,需要给在变量名前加上“$”符号,但最好用小括号“()”或是大括号”把变量给包括起来。如果你要使用真实的“$”字符那么你需用“$”来表示。变量会在使用它的地方精确地展开,就像C/C++中的宏一样。
在Makefile中的定义的变量,就像是C/C-+语言中的宏一样,他代表了一个文本字串,在Makefi1e中执行的时候其会自动原模原样地展开在所使用的地方。其与C/C+所不同的是,你可以在Makefile中改变其值。在akefi1e中,变量可以使用在“目标”,“依赖目标”,“命令”或是Makefi1e的其它部分中。
变量的命名字可以包含字符、数字,下划线(可以是数字研头),但不应该含有“:”
五、override指示符
通常在执行 make 时,如果通过命令行定义了一个变量,那么它将替代在 Makefile中出现的同名变量的定义。就是说,对于一个在 Makefile 中使用常规方式(使用“=”、“:=”或者“define”)定义的变量,我们可以在执行make 时通过命令行方式重新指定这个变量的值,命令行指定的值将替代出现在 Makefile 中此变量的值。如果不希望命令行指定的变量值替代在 Makefile 中的变量定义,那么我们需要在 Makefile 中使用指示符“override”来对这个变量进行声明。
六、多行变量
还有一种设置变量值的方法是使用define关键字。使用define关键字设置变量的值可
以有换行,这有利于定义一系列的命令(前面我们讲过“命令包”的技术就是利用这个关键字)。
define指示符后面跟的是变量的名字,而重起一行定义变量的值,定义是以endef关键字结束。其工作方式和“”操作符样。变量的值可以包含函数、命令、文字,或是其它变量.因为命令需要以[Tab]键开头,所以如果你用define定义的命令变量中没有以[Tab]键开头,那么make就不会把其认为是命令。
七、环境变量
make运行时的系统环境变量可以在make开始运行时被载入到Makefile文件中,但是如果Makefile中已定义了这个变量,或是这个变量由make命令行带入,那么系统的环境变量的值将被覆盖。(如果make指定了“-e”参数,那么,系统环境变量将覆盖Makefile中定义的变量)
因此,如果我们在环境变量中设置了“CFLAGS”环境变量,那么我们就可以在所有的Make1e中使用这个变量了。这对于我们使用统一的编译参数有比较大的好处。如果
Makefile中定义了CFLAG,那么则会使用Makefle中的这个变量,如果没有定义则使用系统环境变量的值,一个共性利个性的统,很像“全局变量”和“局部变量”的特性。
当nake嵌套调用时(参见前面的嵌套调用”章节),上层Makefile中定义的变量会以系统环境变量的方式传递到下层的Makefile中。当然,默认情况下,只有通过命令行设置的变量会被传递。而定义在文件中的夜量,如果要向下层Makfi1e传递,则需要使用export关键字来声明