Makefile工具的使用( 五 )


3.3通配符
规则中的文件名可以包含统配符,如"*","?" 。
文件名前的字符"~"有特殊的含义 。单独使用,或跟随一个"/",代表用户的home目录,比如"~/bin"扩展为/home/you/bin";如果"~"跟随一个单词,表示单词指示的那个用户的home目录,如"~john/bin"扩展为"/home/john/bin" 。
通配符在目标,依赖关系,命令中自动扩展,其它情况下,统配符的扩展除非显式使用"wildcard"函数 。通配符的特殊意义可以使用""符号关闭 。
例子:
clean:
rm -f *.o

print: *.c
lpr -p $?
touch print
通配符在定义变量时并不扩展,例如:
objects = *.o
则objects的值是字符串"*.o";但是如果你将objects用于目标,依赖或命令中,扩展会进行 。要将objects设置成扩展过的内容,使用:
objects := $(wildcard *.o)
3.3.1通配符的缺陷
这是一个使用通配符的例子,但结果不是你所期望的 。假设可执行文件"foo"是从当前目录中的所有".o"文件生成的:
objects = *.ofoo : $(objects)
cc -o foo $(CFLAGS) $(objects)
objects变量的值是字符串"*.o" 。通配符扩展在规则"foo"中进行,于是所有存在的".o"文件成为"foo"的依赖而且在需要时重新编译 。
但如果删除了所有的".o"文件呢?当通配符不匹配任何文件时,一切都保持原样:则"foo"依赖于一个叫做"*.o"的文件;由于这个文件不大可能存在,"make"程序会报告一个无法生成"*.o"文件的错误,这不是期待的结果 。
实际上可以用通配符获得期望结果,但是需要复杂的技术,包括"wildcard"函数和字符串替换函数 。
3.3.2wildcard函数
通配符自动在规则中进行 。但是在变量赋值的和函数的参数中通配符不会扩展,如果在这些情况下需要通配符扩展,必须使用"wildcard"函数 。语法如下:
$(wildcard PATTERN...)
这个在makefile任何地方出现的字符串,会被匹配任何一个文件名格式的以空格隔开的现有文件列表替换 。如果没有任何文件匹配一个模式,这个模式从"wildcard"的输出中忽略,注意,这和上述的通配符的处理是不一样的 。
‘wildcard"函数的一个功能是找出目录中所有的".c"文件:
$(wildcard *.c)
可以通过替换后缀".c"为".o"从C文件列表得到目标文件的列表:
$(patsubst %.c,%.o,$(wildcard *.c))
这样,上节中的makefile改写为:
objects := $(patsubst %.c,%.o,$(wildcard *.c))foo : $(objects)
cc -o foo $(objects)
这个makefile利用了编译C程序的隐含规则,所以不需要对编译写出显式的规则 。(":="是"="的一个变体)
注意:"PATTERN"是大小写敏感的 。
3.4目录搜索
对于大的系统,通常将源文件和目标文件放在不同的目录中 。目录搜索功能可以让make自动在多个目录中搜寻依赖文件,当你将文件重新分布是,不需要改变规则,更改搜索路径即可 。
3.4.1‘VPATH"
make变量"VPATH"列出make应当搜索的目录列表 。很多情况下,当前目录不包含依赖文件,"VPATH"描述一个对所有文件的搜索列表,包含那些是规则的目标的文件 。
如果一个目标或者依赖文件在当前目录没找到的话,"make"在"VPATH"中列出的目录中查找同名的文件 。如果找到的话,那个文件成为依赖文件;规则可以象这些文件在当前目录中一样来使用他们 。
在"VPATH"变量中,目录名以冒号或空格隔开;目录列出的顺序决定make查找的顺序 。(注:在pSOSystem 2.5移植到Win32的GNU make目录名必须使用分号隔开,以下均简称Win32 GNU make) 。举例说明:VPATH = src:../headers 则规则
foo.o : foo.c
被解释为
foo.o : src/foo.c
假设"foo.c"在当前目录不存在,在"src"目录中可以找到 。
3.4.2选择性搜索
与"VPATH"变量相似但更具选择性的是"vpath"指令(注意是小写),可以指定对于符合特定模式文件的查找路径 。这样可以为不同类型的文件指定不同的搜索路径 。

推荐阅读