首页 > 代码库 > Makefile中的隐式规则

Makefile中的隐式规则

Makefile中的隐式规则

1、隐式规则中的变量

隐式规则中使用的变量分成两种:一种是命令相关的,如“CC”;一种是参数相关的,如“CFLAGS”

与命令相关的变量

变量

含义

AR

函数库打开包程序。默认命令是“ar”

AS

汇编语言编译程序。默认命令是“as”

CC

C语言编译程序。默认命令是“cc”

CXX

C++语言编译程序。默认命令是“g++”

CO

RCS文件中扩展文件程序。默认命令是“co”

CPP

C程序的预处理器(输出是标准输出设备)。默认命令是“$(CC)-E”

FC

FortranRatfor的编译器和预处理程序。默认命令是”f77”

GET

SCCS文件扩展文件的程序。默认命令是“get”

LEX

Lex方法分析器程序(针对于CRatfor)。默认命令是”lex”

PC

Pascal语言编译程序。默认命令是”pc”

YACC

Yacc文法分析器(针对C程序)。默认命令是“yacc”

YACCR

Yacc文法分析器(针对Ratfor程序)。默认命令是“yacc -r”

MAKEINFO

转换Texinfo源文件(.texi)info文件程序。默认命令是“makeinfo”

TEX

TeX源文件创建TeX DVI文件的程序。默认命令是“tex”

WEAVE

转化WebTeX的程序。默认命令是“weave”

TEXI2DVI

Texinfo源文件创建TeX DVI文件的程序。默认命令是“texi2dvi”

CWEAVE

转化C WebTeX的程序。默认命令是“cweave”

TANGLE

转换WebPascal语言的程序,默认命令是”tangle“

CTANGLE

转换C WebC。默认命令是”ctangle“

RM

删除文件命令。默认命令是”rm-f“

与参数相关的变量

变量

含义

ARFLAGS

函数库打包程序AR命令的参数。默认值是“rv”

ASFLAGS

汇编语言编译参数(当明显地调用”.s”或”.S”文件时)

CFLAGS

C语言编译器参数

CXXFLAGS

C++语言编译器参数

COFLAGS

RCS命令参数

CPPFLAGS

C预处理器参数(CFortran编译器也会用到)

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下是

.aWindows.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