Chinaunix首页 | 论坛 | 博客
  • 博客访问: 181022
  • 博文数量: 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)

 

函数功能:这个函数的工作过程是这样的:如果必要(存在变量或者函数的引用),首先展开变量VARLIST;而表达式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 内嵌的函数名时(如ifforeachstrip等),对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)。



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