Chinaunix首页 | 论坛 | 博客
  • 博客访问: 564792
  • 博文数量: 112
  • 博客积分: 5090
  • 博客等级: 大校
  • 技术积分: 1158
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-19 22:21
文章分类

全部博文(112)

文章存档

2016年(1)

2015年(1)

2012年(1)

2011年(5)

2010年(7)

2009年(6)

2008年(18)

2007年(28)

2006年(16)

2005年(29)

我的朋友

分类: LINUX

2005-08-20 12:56:37

8-17章和附录

[@more@]

8 文本转换函数

函数允许您在makefile文件中处理文本、计算文件、操作使用命令等。在函数调用时您必须指定函数名以及函数操作使用的参数。函数处理的结果将返回到makefile文件中的调用点,其方式和变量替换一样。

8.1函数调用语法

函数调用和变量引用类似,它的格式如下:

$(function arguments)

或这样:

${function arguments}

这里‘function’是函数名,是make内建函数列表中的一个。当然您也可以使用创建函数call创建的您自己的函数。‘arguments’是该函数的参数。参数和函数名之间是用空格或Tab隔开,如果有多个参数,它们之间用逗号隔开。这些空格和逗号不是参数值的一部分。包围函数调用的定界符,无论圆括号或大括号,可以在参数中成对出现,在一个函数调用中只能有一种定界符。如果在参数中包含变量引用或其它的函数调用,最好使用同一种定界符,如写为‘$(subst a,b,$(x))', 而不是 `$(subst a,b,${x})'。这是因为这种方式不但比较清楚,而且也有在一个函数调用中只能有一种定界符的规定。

为每一个参数写的文本经过变量替换或函数调用处理,最终得到参数的值,这些值是函数执行必须依靠的文本。另外,变量替换是按照变量在参数中出现的次序进行处理的。

逗号和不成对出现的圆括号、大括号不能作为文本出现在参数中,前导空格也不能出现在第一个参数中。这些字符不能被变量替换处理为参数的值。如果需要使用这些字符,首先定义变量commaspace,它们的值是单独的逗号和空格字符,然后在需要的地方因用它们,如下例:

comma:= ,

empty:=

space:= $(empty) $(empty)

foo:= a b c

bar:= $(subst $(space),$(comma),$(foo))

# bar is now `a,b,c'.

这里函数subst的功能是将变量foo中的空格用逗号替换,然后返回结果。

8.2字符串替换和分析函数

这里有一些用于操作字符串的函数:

$(subst from,to,text)

在文本‘text’中使用‘to’替换每一处‘from’。例如:

$(subst ee,EE,feet on the street)

结果为‘fEEt on the street’。

$(patsubst pattern,replacement,text)

寻找‘text’中符合格式‘pattern’的字,用‘replacement’替换它们。这里‘pattern’中包含通配符‘%’,它和一个字中任意个数的字符相匹配。如果‘replacement’中也含有通配符‘%’,则这个‘%’被和‘pattern’中通配符‘%’匹配的文本代替。在函数patsubst中的‘%’可以用反斜杠(\)引用。引用字符‘%’的反斜杠可以被更多反斜杠引用。引用字符‘%’和其它反斜杠的反斜杠在比较文件名或有一个stem(径)代替它之前从格式中移出。使用反斜杠引用字符‘%’不会带来其它麻烦。例如,格式the\%weird\\%pattern\\'the%weird\' 加上通配符‘%'然后和字符串‘pattern\\'连接。最后的两个反斜杠由于不能影响任何统配符‘%’所以保持不变。在字之间的空格间被压缩为单个空格,前导以及结尾空格被丢弃。例如:

$(patsubst %.c,%.o,x.c.c bar.c)

的结果为:‘x.c.o bar.o'。替换引用是实现函数patsubst功能一个简单方法:

$(var:pattern=replacement)

等同于:

$(patsubst pattern,replacement,$(var))

另一个通常使用的函数patsubst的简单方法是:替换文件名的后缀。

$(var:suffix=replacement)

等同于:

$(patsubst %suffix,%replacement,$(var))

例如您可能有一个OBJ文件的列表:

objects = foo.o bar.o baz.o

要得到这些文件的源文件,您可以简单的写为:

$(objects:.o=.c)

代替规范的格式:

$(patsubst %.o,%.c,$(objects))

$(strip string)

去掉前导和结尾空格,并将中间的多个空格压缩为单个空格。这样,‘$(strip a b c )'结果为‘a b c’。函数strip和条件语句连用非常有用。当使用ifeqifneq把一些值和空字符串‘’比较时,您通常要将一些仅由空格组成的字符串认为是空字符串(参阅makefile中的条件语句)。如此下面的例子在实现预期结果时可能失败:

.PHONY: all

ifneq   "$(needs_made)" ""

all: $(needs_made)

else

all:;@echo 'Nothing to make!'

endif

在条件指令ifneq中用函数调用‘$(strip $(needs_made))'代替变量引用‘$(needs_made)'将不再出现问题。

$(findstring find,in)

在字符串‘in’中搜寻‘find’,如果找到,则返回值是‘find’,否则返回值为空。您可以在一个条件中使用该函数测试给定的字符串中是否含有特定的子字符串。这样,下面两个例子:

$(findstring a,a b c)

$(findstring a,b c)

将分别产生值‘a’和‘’。对于函数findstring的特定用法参阅测试标志的条件语句

$(filter pattern...,text)

返回在‘text’中由空格隔开且匹配格式‘pattern...’的字,对于不符合格式‘pattern...’的字移出。格式用‘%’写出,和前面论述过的函数patsubst的格式相同。函数filter可以用来变量分离类型不同的字符串。例如:

sources := foo.c bar.c baz.s ugh.h

foo: $(sources)

        cc $(filter %.c %.s,$(sources)) -o foo

表明foo' 依靠foo.c',bar.c',baz.s' ugh.h'但仅有foo.c',bar.c' baz.s' 指明用命令编译。

$(filter-out pattern...,text)

返回在‘text’中由空格隔开且不匹配格式‘pattern...’的字,对于符合格式‘pattern...’的字移出。只是函数filter的反函数。例如:

objects=main1.o foo.o main2.o bar.o

mains=main1.o main2.o

下面产生不包含在变量‘mains’中的OBJ文件的文件列表:

$(filter-out $(mains),$(objects))

$(sort list)

将‘list’中的字按字母顺序排序,并取掉重复的字。输出是由单个空格隔开的字的列表。

$(sort foo bar lose)

返回值是‘bar foo lose’。顺便提及,由于函数sort可以取掉重复的字,您就是不关心排序也可以使用它的这个特点。

这里有一个实际使用函数substpatsubst的例子。假设一个makefile文件使用变量VPATH指定make搜寻依赖文件的一系列路径(参阅VPATH:依赖搜寻路径)。这个例子表明怎样告诉C编译器在相同路径列表中搜寻头文件。

变量VPATH的值是一列用冒号隔开的路径名,如‘src:../headers'。首先,函数subst将冒号变为空格:

$(subst :, ,$(VPATH))

这产生值‘src ../headers'。然后,函数patsubst为每一个路径名加入‘-|’标志,这样这些路径可以加到变量CFLAGS中,就可以自动传递给C编译器:

override CFLAGS += $(patsubst %,-I%,$(subst :, ,$(VPATH)))

结果是在以前给定的变量CFLAGS的值后追加文本‘-Isrc -I../headers’。Override指令的作用是即使以前使用命令参数指定变量CFLAGS的值,新值也能起作用。参阅override指令

8.3文件名函数

其中几个内建的扩展函数和拆分文件名以及列举文件名相关联。下面列举的函数都能执行对文件名的特定转换。函数的参数是一系列的文件名,文件名之间用空格隔开(前导和结尾空格被忽略)。列表中的每一个文件名都采用相同的方式转换,而且结果用单个空格串联在一起。

$(dir names...)

抽取‘names’中每一个文件名的路径部分,文件名的路径部分包括从文件名的开始到最后一个斜杠(含斜杠)之前的一切字符。如果文件名中没有斜杠,路径部分是‘./’。如:

$(dir src/foo.c hacks)

产生的结果为 ‘src/ ./’。

$(notdir names...)

抽取‘names’中每一个文件名中除路径部分外一切字符(真正的文件名)。如果文件名中没有斜杠,则该文件名保持不变,否则,将路径部分移走。一个文件名如果仅包含路径部分(以斜杠结束的文件名)将变为空字符串。这是非常不幸的,因为这意味着在结果中如果有这种文件名存在,两文件名之间的空格将不是由相同多的空格隔开。但现在我们并不能看到其它任何有效的代替品。例如:

$(notdir src/foo.c hacks)

产生的结果为‘foo.c hacks’。

$(suffix names...)

抽取‘names’中每一个文件名的后缀。如果文件名中(或含有斜杠,且在最后一个斜杠后)含有句点,则后缀是最后那个句点以后的所有字符,否则,后缀是空字符串。如果结果为空意味着‘names’没有带后缀文件名,如果文件中含有多个文件名,则结果列出的后缀数很可能比原文件名数目少。例如:

$(suffix src/foo.c src-1.0/bar.c hacks)

产生的结果是‘.c .c’。

$(basename names...)

抽取‘names’中每一个文件名中除后缀外一切字符。如果文件名中(或含有斜杠,且在最后一个斜杠后)含有句点,则基本名字是从开始到最后一个句点(不包含)间的所有字符。如果没有句点,基本名字是整个文件名。例如:

$(basename src/foo.c src-1.0/bar hacks)

产生的结果为‘src/foo src-1.0/bar hacks’。

$(addsuffix suffix,names...)

参数‘names’作为一系列的文件名,文件名之间用空格隔开;suffix作为一个单位。将Suffix(后缀)的值附加在每一个独立文件名的后面,完成后将文件名串联起来,它们之间用单个空格隔开。例如:

$(addsuffix .c,foo bar)

结果为‘foo.c bar.c’。

$(addprefix prefix,names...)

参数‘names’作为一系列的文件名,文件名之间用空格隔开;prefix作为一个单位。将preffix(前缀)的值附加在每一个独立文件名的前面,完成后将文件名串联起来,它们之间用单个空格隔开。例如:

$(addprefix src/,foo bar)

结果为‘src/foo src/bar’。

$(join list1,list2)

将两个参数串联起来:两个参数的第一个字串联起来形成结果的第一个字,两个参数的第二个字串联起来形成结果的第二个字,以此类推。如果一个参数比另一个参数的字多,则多余的字原封不动的拷贝到结果上。例如,‘$(join a b,.c .o)'产生‘a.c b.o'。字之间多余的空格不再保留,它们由单个空格代替。该函数可将函数dirnotdir的结果合并,产生原始给定的文件列表。

$(word n,text)

返回‘text’中的第n个字。N的合法值从1开始。如果n比‘text’中的字的数目大,则返回空值。例如:

$(word 2, foo bar baz)

返回 ‘bar’。

$(wordlist s,e,text)

管理员在2009年8月13日编辑了该文章文章。

-->
阅读(1370) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~