1、foreach 函数
foreach 函数定义如下:
$(foreach <var>,<list>,<text>)
函数的功能是:把参数 <list> 中的单词逐一取出放到参数 <var> 所指定的变量中,然后再执行 <text> 所包含的表达式。
每一次 <text> 会返回一个字符串,循环过程中,<text> 的返所返回的每个字符串会以空格分割,最后当整个循环结束的时候,<text> 所返回的每个字符串所组成的整个字符串(以空格分隔)将会是 foreach 函数的返回值。
所以 <var> 最好是一个变量名,<list> 可以是一个表达式,而 <text> 中一般会只用 <var> 这个参数来一次枚举 <list> 中的单词。
示例:
filename = 11 22 33 44
files = $(foreach n, $(filename), $(n).cpp)
all:
echo $(files)
执行 make 结果
wohu@ubuntu:~/cpp/func$ make
echo 11.cpp 22.cpp 33.cpp 44.cpp
11.cpp 22.cpp 33.cpp 44.cpp
wohu@ubuntu:~/cpp/func$
foreach 中的 <var> 参数是一个临时的局部变量,foreach 函数执行完后,参数 <var> 的变量将不再作用,其作用域只在 foreach 函数当中。
2、if 条件选择函数
定义如下:
$(if <condition>,<then-part>)
或
$(if<condition>,<then-part>,<else-part>)
if 函数可以包含 else 部分,或者是不包含,即 if 函数的参数可以是两个,也可以是三个。
condition 参数是 if 表达式,如果其返回的是非空的字符串,那么这个表达式就相当于返回真,于是,then-part 就会被计算,否则 else-part 会被计算。
而 if 函数的返回值是:
如果 condition 为真(非空字符串),那么 then-part 会是整个函数的返回值。
如果 condition 为假(空字符串),那么 else-part 将会是这个函数的返回值。此时如果 else-part 没有被定义,那么整个函数返回空字串符。所以,then-part 和 else-part 只会有一个被计算。
示例 1:
file = aa
OBJ = $(if $(file), $(file), main.c)
all:
echo $(OBJ)
执行 make 结果
wohu@ubuntu:~/cpp/func$ make
echo aa
aa
wohu@ubuntu:~/cpp/func$
示例 2:
OBJ = $(if $(name), $(name), main.c)
other:
echo $(OBJ)
执行 make 结果
wohu@ubuntu:~/cpp/func$ make
echo main.c
main.c
wohu@ubuntu:~/cpp/func$
3、call 函数
函数定义如下:
$(call <expression>,<parm1>,<parm2>,<parm3>,...)
call 函数是唯一一个可以用来创建新的参数化的函数。我们可以用来写一个非常复杂的表达式,这个表达式中,我们可以定义很多的参数,然后你可以用 call 函数来向这个表达式传递参数。
当 make 执行这个函数的时候,expression 参数中的变量 $(1)、$(2)、$(3)等,会被参数 parm1,parm2,parm3 依次取代。而 expression 的返回值就是 call 函数的返回值。
reverse = $(2) $(1)
foo = $(call reverse, aa, bb)
all:
echo $(foo)
执行结果:
wohu@ubuntu:~/cpp/func$ make
echo bb aa
bb aa
wohu@ubuntu:~/cpp/func$
4、origin 函数
定义如下:
$(origin <variable>)
origin 函数不像其他的函数,它并不操作变量的值,它只是告诉你这个变量是哪里来的。
注意: variable 是变量的名字,不应该是引用,所以最好不要在 variable 中使用 $ 字符。
下面是 origin 函数返回值:
- undefined:如果 <variable> 从来没有定义过,函数将返回这个值。
- default:如果 <variable> 是一个默认的定义,比如说CC这个变量。
- environment:如果 <variable> 是一个环境变量并且当 Makefile 被执行的时候,-e参数没有被打开。
- file:如果 <variable> 这个变量被定义在 Makefile 中,将会返回这个值。
- command line:如果 <variable> 这个变量是被命令执行的,将会被返回。
- override:如果 <variable> 是被 override 指示符重新定义的。
- automatic:如果 <variable> 是一个命令运行中的自动化变量。
这些信息对于我们编写 Makefile 是非常有用的,例如假设我们有一个 Makefile ,其包含了一个定义文件 Make.def ,在 Make.def 中定义了一个变量 bletch ,而我们的环境变量中也有一个环境变量 bletch,我们想去判断一下这个变量是不是环境变量,如果是我们就把它重定义了。如果是非环境变量,那么我们就不重新定义它。于是,我们在 Makefile 中,可以这样写:
ifdef bletch
ifeq "$(origin bletch)" "environment"
bletch = barf,gag,etc
endif
endif
当然,使用 override 关键字不就可以重新定义环境中的变量了吗,为什么需要使用这样的步骤?
是的,我们用 override 是可以达到这样的效果的,可是 override 会把从命令行定义的变量也覆盖了,而我们只想重新定义环境传来的,而不是重新定义命令行传来的。