首页 > 代码库 > Makefile中的隐式规则
Makefile中的隐式规则
Makefile中的隐式规则
1、隐式规则中的变量
隐式规则中使用的变量分成两种:一种是命令相关的,如“CC”;一种是参数相关的,如“CFLAGS”。
与命令相关的变量
变量 | 含义 |
AR | 函数库打开包程序。默认命令是“ar” |
AS | 汇编语言编译程序。默认命令是“as” |
CC | C语言编译程序。默认命令是“cc” |
CXX | C++语言编译程序。默认命令是“g++” |
CO | 从RCS文件中扩展文件程序。默认命令是“co” |
CPP | C程序的预处理器(输出是标准输出设备)。默认命令是“$(CC)-E” |
FC | Fortran和Ratfor的编译器和预处理程序。默认命令是”f77” |
GET | 从SCCS文件扩展文件的程序。默认命令是“get” |
LEX | Lex方法分析器程序(针对于C或Ratfor)。默认命令是”lex” |
PC | Pascal语言编译程序。默认命令是”pc” |
YACC | Yacc文法分析器(针对C程序)。默认命令是“yacc” |
YACCR | Yacc文法分析器(针对Ratfor程序)。默认命令是“yacc -r” |
MAKEINFO | 转换Texinfo源文件(.texi)到info文件程序。默认命令是“makeinfo” |
TEX | 从TeX源文件创建TeX DVI文件的程序。默认命令是“tex” |
WEAVE | 转化Web到TeX的程序。默认命令是“weave” |
TEXI2DVI | 从Texinfo源文件创建TeX DVI文件的程序。默认命令是“texi2dvi” |
CWEAVE | 转化C Web到TeX的程序。默认命令是“cweave” |
TANGLE | 转换Web到Pascal语言的程序,默认命令是”tangle“ |
CTANGLE | 转换C Web到C。默认命令是”ctangle“ |
RM | 删除文件命令。默认命令是”rm-f“ |
与参数相关的变量
变量 | 含义 |
ARFLAGS | 函数库打包程序AR命令的参数。默认值是“rv” |
ASFLAGS | 汇编语言编译参数(当明显地调用”.s”或”.S”文件时) |
CFLAGS | C语言编译器参数 |
CXXFLAGS | C++语言编译器参数 |
COFLAGS | RCS命令参数 |
CPPFLAGS | C预处理器参数(C和Fortran编译器也会用到) |
FFLAGS | Fortran语言编译器参数 |
GFLAGS | SCCS ”get“程序参数 |
LDFLAGS | 连接器参数(如“ld”) |
LFLAGS | Lex文法分析器参数 |
PFLAGS | Pascal语法编译器参数 |
RFLAGS | Ratfor程序的Fortran编译器参数 |
YFLAGS | Yacc文法分析器参数 |
2、使用模式规则
可以使用模式规则定义一个隐式规则。和一般规则类似,只是在模式规则中,目标的定义需要有“%”字符。“%”定义对文件名的匹配,表示任意长度的非空字符串。在依赖目标中同样可以使用“%”,只是依赖目标中“%”的取值,取决于其目标。
模式规则中“%”的展开和变量与函数的展开是有区别的,“%”的展开发生在变量和函数的展开之后。变量和函数的展开发生在make载入Makefile时,而“%”的展开则发生在运行时。 |
1),模式规则举例
模式规则中,至少在规则的目标中要包含“%”符号。
%.o : %.c ; <command......>
其含义是,字指出了从所有的.c文件生成相应的.o文件的规则。如果要生成的目标是”a.o b.o”,那么
“%.c”就是”a.c b.c”。
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS)$< -o $@
表示把所有的.c文件都编译成.o文件。
其中,“$@”表示所有目标的集合,”$<”表示所有依赖目标的集合(在模式定义规则的情形下)。
2),自动化变量
自动化变量只应出现在规则的命令中。
Makefile的自动化变量
变量 | 含义 |
$@ | 表示规则中的所有目标文件的集合。在模式规则中如果有多个目标,“$@”就是匹配于目标中模式定义的集合 |
$% | 仅当目标是函数库文件时,表示规则中的目标成员名,如果目标不是函数库文件(UNIX下是 .a,Windows是.lib),其值为空。 |
$< | 依赖目标中的第一个目标名字,如果依赖目标是以模式(即”%“)定义的,则”$<”是符合模式的一系列的文件集 注意,其是一个一个取出来的 |
$? | 所有比目标新的依赖目标的集合,以空格分隔 |
$^ | 所有依赖目标的集合,以空格分隔。如如果在依赖目标中有多个重复的,则自动去除重复的依赖目标,只保留一份 |
$+ | 同”$^”,也是所有依赖目标的集合,只是它不去除重复的依赖目标。 |
$* | 目标模式中“%”及其之前的部分 |
$(@D) | “$@”的目录部分(不以斜杠作为结尾),如果”$@”中没有包含斜杠,其值为“.”(当前目录) |
$(@F) | “$@”的文件部分,相当于函数”$(notdir $@)” |
$(*D) | 同”$(@D)”,取文件的目录部分 |
$(*F) | 同”$(@F)”,取文件部分,但不取后缀名 |
$(%D) | 函数包文件成员的目录部分 |
$(%F) | 函数包文件成员的文件名部分 |
$(<D) | 依赖目标中的第一个目标的目录部分 |
$(<F) | 依赖目标中的第一个目标的文件名部分 |
$(^D) | 所有依赖目标文件中目录部分(无相同的) |
$(^F) | 所有依赖目标文件中文件名部分(无相同的) |
$(+D) | 所有依赖目标文件中的目录部分(可以有相同的) |
$(+F) | 所有依赖目标文件中的文件名部分(可以有相同的) |
$(?D) | 所有被更新文件的目录部分 |
$(?F) | 所有被更新文件的文件名部分 |
3、老式风格的"后缀规则"
后缀规则是一个比较老式的定义隐含规则的方法。后缀规则会被模式规则逐步地取代。因为模式规则更强更清晰。为了和老版本的Makefile兼容,GNU make同样兼容于这些东西。后缀规则有两种方式:"双后缀"和"单后缀"。
双后缀规则定义了一对后缀:目标文件的后缀和依赖目标(源文件)的后缀。如".c.o"相当于"%o : %c"。单后缀规则只定义一个后缀,也就是源文件的后缀。如".c"相当于"% : %.c"。
后缀规则中所定义的后缀应该是make所认识 的,如果一个后缀是make所认识的,那么这个规则就是单后缀规则,而如果两个连在一起的后缀都被make所认识,那就是双后缀规则。例如:".c" 和".o"都是make所知道。因而,如果你定义了一个规则是".c.o"那么其就是双后缀规则,意义就是".c"是源文件的后缀,".o"是目标文件的 后缀。如下示例:
.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
后缀规则不允许任何的依赖文件,如果有依赖文件的话,那就不是后缀规则,那些后缀统统被认为是文件名,如:
.c.o: foo.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
这个例子,就是说,文件".c.o"依赖于文件"foo.h",而不是我们想要的这样:
%.o: %.c foo.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
后缀规则中,如果没有命令,那是毫无意义的。因为他也不会移去内建的隐含规则。
而要让make知道一些特定的后缀,我们可以使用伪目标".SUFFIXES"来定义或是删除,如:
.SUFFIXES: .hack .win
把后缀.hack和.win加入后缀列表中的末尾。
.SUFFIXES: # 删除默认的后缀
.SUFFIXES: .c .o .h # 定义自己的后缀
先清楚默认后缀,后定义自己的后缀列表。
make的参数"-r"或"-no-builtin-rules"也会使用得默认的后缀列表为空。而变量"SUFFIXE"被用来定义默认的后缀列表,你可以用".SUFFIXES"来改变后缀列表,但请不要改变变量"SUFFIXE"的值。
--by 吴尚奇 Devil_box