Chinaunix首页 | 论坛 | 博客
  • 博客访问: 188184
  • 博文数量: 37
  • 博客积分: 1110
  • 博客等级: 少尉
  • 技术积分: 395
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-29 22:01
文章分类

全部博文(37)

文章存档

2013年(10)

2011年(2)

2010年(25)

我的朋友

分类: LINUX

2010-11-07 21:40:38

 
   

四  foreach   函数

 

函数“foreach”不同于其它函数。它是一个循环函数。类似于 Linux 的 shell 中的循环(for语句)。“foreach”函数的语法:

    $(foreach VAR,LIST,TEXT)

 

函数功能:这个函数的工作过程是这样的:如果必要(存在变量或者函数的引用),首先展开变量“VAR”和“LIST”;而表达式“TEXT”中的变量引用不被展开。执行时把“LIST”中使用空格分割的单词依次取出赋值给变量“VAR”,然后执行“TEXT”表达式。重复直到“LIST”的最后一个单词(为空时结束)。“TEXT”中的变量或者函数引用在执行时才被展开,因此如果在“TEXT”中存在对“VAR”的引用,那么“VAR”的值在每一次展开式将会到的不同的值。

返回值:空格分割的多次表达式“TEXT”的计算的结果。

我们来看一个例子,实现了将变量“files”赋值为目录“dirs”下所有文件列表:

dirs := a b c d

files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))

例子中,“ TEXT”的表达式为“$(wildcard $(dir)/*)”。表达式第一次执行时将展开为“$(wildcard a/*)”;第二次执行时将展开为“$(wildcard b/*)”;第三次展开为“$(wildcard c/*)”;….;以此类推。所以此函数所实现的功能就和一下语句等价:

 files := $(wildcard a/* b/* c/* d/*)

 函数的“TEXT”表达式过于复杂时,我们可以通过定义一个中间的变量来表示表达式的一部分。对于上边的例子我们也可以对各个部分分解来实现,如下:

 find_files = $(wildcard $(dir)/*)

 dirs := a b c d

files := $(foreach dir,$(dirs),$(find_files))

 在这里我们定义了一个变量(也可以称之为表达式),需要注意的是,在这里定义的是“递归展开”时的变量“find_files”。保证定义时变量值中的引用不被展开,而是在“find_files”才展开(如果这里使用直接展开式的定义将是无效的表达式)。

函数说明:函数中参数“VAR”是一个局部的临时变量,它在“foreach”函数的执行过程中有效,它在汉书中对它的定义不会影响其它部分定义的同名“VAR”变量的值。它在函数的执行过程中是一个“直接展开”式变量。

 

在使用函数“foreach”时,需要注意:变量“VAR”的名字。我们建议使用一个单词、最好能够表达其含义的名字,不要使用一个奇怪的字符串作为变量名。虽然在可能在执行时没有错误,但是可能会让人很费解。

没有人会喜欢这种方式,尽管可能它可以正常工作:

 

files := $(foreach Esta escrito en espanol!,b c ch,$(find_files))


 

五 if 函数

 

函数“if”提供了一个在函数上下文中实现条件判断的功能。就像make所支持的条件语句—ifeq一样。

  函数语法:

 

$(if CONDITION,THEN-PART[,ELSE-PART])

 

  函数功能:第一个参数“CONDITION”,在函数执行时忽略其前导和结尾空字符并展开。“CONDITION”的展开结果非空,则条件为真,就将第二个参数“THEN_PATR”作为函数的计算表达式,函数的返回值就是第二表达式的计算结果;“CONDITION”的展开结果为空,将第三个参数“ELSE-PART”作为函数的表达式,返回结果为第三个表达式的计算结果。

返回值:根据条件决定函数的返回值是第一个或者第二个参数表达式的计算结果。当不存在第三个参数“ELSE-PART”,且“CONDITION”展开为空,函数返回空。

 函数说明:函数的条件表达式“CONDITION”决定了,函数的返回值只能是“THEN-PART”或者“ELSE-PART”两个之一的计算结果。

  函数示例:

 

SUBDIR += $(if $(SRC_DIR) $(SRC_DIR),/home/src)

 

函数的结果是:如果“SRC_DIR”变量值不为空,变量“SRC_DIR”指定的目录作为一个子目录;否则将目录“/home/src”作为一个子目录。

 

 

六、call函数

 

“call”函数是唯一一个可以创建定制参数化的函数的引用函数。我们可以将一个变量定义为

一个复杂的表达式,用“call”函数根据不同的参数对它进行展开来获得不同的结果。

  函数语法:

 

$(call VARIABLE,PARAM,PARAM,...)

 

  函数功能:在执行时,将它的参数“PARAM”依次赋值给临时变量“$(1)”、“$(2)”(这些临时变量定义在“VARIABLE”的值中,参考下边的例子)…… call 函数对参数的数目没有限制,也可以没有参数值,没有参数值的“call”没有任何实际存在的意义。执行时变量“VARIABLE”被展开为在函数上下文有效的临时变量,变量定义中的“$(1)”作为第一个参数,并将函数参数值中的第一个参数赋值给它;变量中的“$(2)”一样被赋值为函数的第二个参数值;依此类推(变量$(0)代表变量“VARIABLE”本身)。之后对变量“VARIABLE”   表达式的计算值。

  返回值:参数值“PARAM”依次替换“$(1)”、“$(2)”…… 之后变量“VARIABLE”定义的表达式的计算值。

  函数说明:1. 函数中“VARIBLE”是一个变量名,而不是对变量的引用。因此,通常“call”函数中的“VARIABLE”中不包含“$”(当然,除了此变量名是一个计算的变量名)。2. 当变量“VARIBLE”是一个 make 内嵌的函数名时(如“if”、“foreach”、“strip”等),对“PARAM”参数的使用需要注意,因为不合适或者不正确的参数将会导致函数的返回值难以预料。3. 函数中多个“PARAM”之间使用逗号分割。4. 变量“VARIABLE”在定义时不能定义为直接展开式!只能定义为递归展开式。

  函数示例:

首先,来看一个简单的例子。

示例 1:

 

reverse =  $(2) $(1)

foo = $(call reverse,a,b)

 

变量“foo”的值为“ba”。这里变量“reverse”中的参数定义顺序可以根据需要来调整,

并不是需要按照“$(1)”、“$(2)”、“$(3)”……    这样的顺序来定义。看一个稍微复杂一些的例子。我们定义了一个宏“pathsearch”来在“PATH”路径中搜索第一个指定的程序。

示例 2:

  pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))

LS := $(call pathsearch,ls)

 

变量“LS”的结果为“/bin/sh”。执行过程:函数“subst”将环境变量“PATH”转换为空格分割的搜索路径列表;“addsuffix”构造出可能的可执行程序“$(1)”(这里是“ls”)带路径的完整文件名(如:“/bin/$(1)”),之后使用函数“wildcard”匹配,最后“firstword”函数取第一个文件名。

 

 函数“call”以可以套嵌使用。每一层“call”函数的调用都为它自己的局部变量“$(1)”等赋值,覆盖上一层函数为它所赋的值。

示例 3:

 map = $(foreach a,$(2),$(call $(1),$(a)))

o = $(call map,origin,o map MAKE)


 

那么变量“o”的值就为“file file default”。我们这里使用了“origin”函数。我们分析函数的执行过程:首先,“o=$(call map,origin, o map MAKE)”这个函数调用使用了变量“map”所定义的表达式;使用内嵌函数名“origin”作为它的第一个参数值,使用Makefile中的变量“o map MAKE”作为他的第二个参数值。当使用“call”函数每一的展开后等价于“$(foreach a,o map MAKE,$(origin $(a)))”。

 注意:和其它函数一样,“call”函数会保留出现在其参数值列表中的空字符。因此在使用参数值时对空格处理要格外小心。如果参数中存在多余的空格,函数可能会返回一个莫名奇妙的值。为了安全,在变量作为“call”函数参数值之前,应去掉其值中的多余空格(可以使用 “strip”函数  )。

 

 

七、value函数

 

函数“value”提供了一种在不对变量进行展开的情况下获取其值的方式。注意:并不是说函数会取消之前已经执行过的替换扩展。比如:我们定义了一个直接展开式的变量,此变量在定义过程中对其它变量的引用进行替换展开得到自身的值。我们在使用“value”函数取它的值时,得到的是不包含任何引用的实际值。而不是将定义过程中的替换展开动作取消后包含引用的定义值。就是说它不能取消此变量中已经发生了的替换展开动作。

函数语法:

$(value VARIABLE)

 

  函数功能:不对变量“VARIBLE”进行任何展开操作,直接返回变量“VARIBALE”代表的值。这里“VARIABLE”是一个变量名,一般不包含“$”(当然,除了计算的变量名),

  返回值:变量“VARIBALE”所定义文本值(不展开其中的变量或者函数应用)。

  函数说明:

示例:

# sample Makefile

FOO = $PATH

 

all:

@echo $(FOO)

@echo $(value FOO)

 

执行make时,我们可以看到的结果是:第一行为:“ATH”。这是因为变量“FOO”定义为“$PATH”,所以展开为“ATH”(“$P”为空,参考 5.1  变量的引用 一节)。第二行才是我们需要显示的系统环境变量“PATH”的值(value函数得到变量“FOO”的值为“$PATH”)。



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