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
会把从命令行定义的变量也覆盖了,而我们只想重新定义环境传来的,而不是重新定义命令行传来的。