第八章 Make的内嵌函数
1 函数的调用语法
GNU make 函数的调用格式类似于变量的引用,以“ $ ”开始表示一个引用。语法格式如下:
$(FUNCTION ARGUMENTS)
或者:
${FUNCTION ARGUMENTS}
1. 调用语法格式中“ FUNCTION ”是需要调用的函数名,它应该是 make 内嵌的函数名。对于用户自己的函数需要通过 make 的“ call ”函数来间接调用。
2. “ ARGUMENTS ”是函数的参数,参数和函数名之间使用若干个空格或者 [tab] 字符分割(建议使用一个空格 );如果存在多个参数时,参数之间使用逗号“ , ”分开。
2 文本处理函数
1)$(subst FROM,TO,TEXT) -- 字符串替换函数
$(subst ee,EE,feet on the street)
替换“ feet on the street ”中的“ ee ”为“ EE ”,结果得到字符串“ fEEt on the strEEt ”。
2)$(patsubst PATTERN,REPLACEMENT,TEXT) -- 模式替换函数
$(patsubst %.c,%.o,x.c.c bar.c)
把字串“ x.c.c bar.c ”中以 .c 结尾的单词替换成以 .o 结尾的字符。函数的返回结果是“ x.c.o bar.o ”
$(VAR:PATTERN=REPLACEMENT)同上
3)$(strip STRINT) -- 去空格函数( 去掉字串 开头和结尾的空字符, 并将其中多个连续空字符合并为一个空字符)
STR = a b c
LOSTR = $(strip $(STR))
结果是“ a b c ”。
4)$(findstring FIND,IN) -- 查找字符串函数
$(findstring a,a b c)
$(findstring a,b c)
第一个函数结果是字“ a ”;第二个值为空字符。
5)$(filter PATTERN…,TEXT) -- 过滤函数
sources := foo.c bar.c baz.s ugh.h
foo: $(sources)
cc $(filter %.c %.s,$(sources)) -o foo
使用“ $(filter %.c %.s,$(sources)) ”的返回值给 cc 来编译生成目标“ foo ”,函数返回值为“ foo.c bar.c baz.s ”。
6)$(filter-out PATTERN...,TEXT) -- 反过滤函数
和filter函数相反
7) $(sort LIST) -- 排序函数
$(sort foo bar lose foo)
返回值为:“ bar foo lose ” 。
8)$(word N,TEXT) -- 取单词函数
$(word 2, foo bar baz)
返回值为“ bar ”。
9)$(wordlist S,E,TEXT) -- 取字串函数
$(wordlist 2, 3, foo bar baz)
返回值为:“ bar baz ”。
10)$(words TEXT) -- 统计单词数目函数
$(words, foo bar)
返回值是“ 2 ”
11)$(firstword NAMES…) -- 取首单词函数
$(firstword foo bar)
返回值为“ foo ”。
3 文件名处理函数
1)$(dir NAMES…) -- 取目录函数
$(dir src/foo.c hacks)
返回值为“ src/ ./ ”。
2)$(notdir NAMES…) -- 取文件名函数
$(notdir src/foo.c hacks)
返回值为:“ foo.c hacks ”。
3)$(suffix NAMES…) -- 取后缀函数
$(suffix src/foo.c src-1.0/bar.c hacks)
返回值为“ .c .c ”。
4)$(basename NAMES…) -- 取前缀函数
$(basename src/foo.c src-1.0/bar.c /home/jack/.font.cache-1 hacks)
返回值为:“ src/foo src-1.0/bar /home/jack/.font hacks ”。
5)$(addsuffix SUFFIX,NAMES…) -- 加后缀函数
$(addsuffix .c,foo bar)
返回值为“ foo.c bar.c ”。
6)$(addprefix PREFIX,NAMES…) -- 加前缀函数
$(addprefix src/,foo bar)
返回值为“ src/foo src/bar ”
7) $(join LIST1,LIST2) -- 单词连接函数
示例 1 :
$(join a b , .c .o)
返回值为:“ a.c b.o ”。
示例 2 :
$(join a b c , .c .o)
返回值为:“ a.c b.o c ”。
8)$(wildcard PATTERN) -- 获取匹配模式文件名函数
$(wildcard *.c)
返回值为当前目录下所有 .c 源文件列表。
4 foreach 函数
Ø “ foreach ”函数的语法 :
$(foreach VAR,LIST,TEXT)
Ø 函数功能: 这个函数的工作过程是这样的:如果需要(存在变量或者函数的引用),首先展开变量“ VAR ”和“ LIST ”的引用;而表达式“ TEXT ”中的变量引用不展开。执行时把“ LIST ”中使用空格分割的单词依次取出赋值给变量“ VAR ”,然后执行“ TEXT ”表达式。重复直到“ LIST ”的最后一个单词(为空时结束)。“ TEXT ”中的变量或者函数引用在执行时才被展开,因此如果在“ TEXT ”中存在对“ VAR ”的引用,那么“ VAR ”的值在每一次展开式将会到的不同的值。
Ø 返回值: 空格分割的多次表达式“ TEXT ”的计算的结果。
dirs := a b c d
files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))
5 if 函数
$(if CONDITION,THEN-PART[,ELSE-PART])
SUBDIR += $(if $(SRC_DIR) $(SRC_DIR),/home/src)
函数的结果是:如果“ SRC_DIR ”变量值不为空,则将变量“ SRC_DIR ”指定的目录作为一个子目录;否则将目录“ /home/src ”作为一个子目录。
6 call 函数
“ call ”函数是唯一一个可以创建定制化参数函数的引用函数。
$(call VARIABLE,PARAM,PARAM,...)
reverse = $(2) $(1)
foo = $(call reverse,a,b)
变量“ foo ”的值为“ ba ”。
7 value 函数
函数“ value ”提供了一种在不对变量进行展开的情况下获取变量值的方法。
$(value VARIABLE)
# sample Makefile
FOO = $PATH
all:
@echo $(FOO)
@echo $(value FOO)
执行 make ,可以看到的结果是:第一行为:“ ATH ”。这是因为变量“ FOO ”定义为“ $PATH ”,所以展开为“ ATH ”(“ $P ”为空)。
第二行才是我们需要显示的系统环境变量“ PATH ”的值( value 函数得到变量“ FOO ”的值为“ $PATH ”)。
8 eval 函数
函数“ eval ”是一个比较特殊的函数。使用它可以在 Makefile 中构造一个可变的规则结构关系(依赖关系链),其中可以使用其它变量和函数。
“ eval ”函数执行时会对它的参数进行两次展开。第一次展开过程发是由函数本身完成的,第二次是函数展开后的结果被作为 Makefile 内容时由 make 解析时展开的。 明确这一过程对于使用“ eval ”函数非常重要。理解了函数“ eval ”二次展开的过程后。实际使用时,如果在函数的展开结果中存在引用(格式为: $(x) ),那么在函数的参数中应该使用“ $$ ”来代替“ $ ”。因为这一点,所以通常它的参数中会使用 函数“ value” 来取一个变量的文本值。
# sample Makefile
PROGRAMS = server client
server_OBJS = server.o server_priv.o server_access.o
server_LIBS = priv protocol
client_OBJS = client.o client_api.o client_mem.o
client_LIBS = protocol
# Everything after this is generic
.PHONY: all
all: $(PROGRAMS)
define PROGRAM_template
$(1): $$($(1)_OBJ) $$($(1)_LIBS:%=-l%)
ALL_OBJS += $$($(1)_OBJS)
endef
$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
$(PROGRAMS):
$(LINK.o) $^ $(LDLIBS) -o $@
clean:
rm -f $(ALL_OBJS) $(PROGRAMS)
9 origin 函数
$(origin VARIABLE)
函数的返回情况有以下几种:
1. undefined
变量“ VARIABLE ”没有被定义。
2. default
变量“ VARIABLE ”是一个默认定义(内嵌变量)。如“ CC ”、“ MAKE ”、“ RM ”等变量。如果在 Makefile 中重新定义这些变量,函数返回值将相应发生变化。
3. environment
变量“ VARIABLE ”是一个系统环境变量,并且 make 没有使用命令行选项“ -e ”( Makefile 中不存在同名的变量定义,此变量没有被替代)。
4. environment override
变量“ VARIABLE ”是一个系统环境变量,并且 make 使用了命令行选项“ -e ”。 Makefile 中存在一个同名的变量定义,使用“ make -e ”时环境变量值替代了文件中的变量定义。
5. file
变量“ VARIABLE ”在某一个 makefile 文件中定义。
6. command line
变量“ VARIABLE ”在命令行中定义。
7. override
变量“ VARIABLE ”在 makefile 文件中定义并使用“ override ”指示符声明。
8. automatic
变量“ VARIABLE ”是自动化变量。
ifdef bletch
ifeq "$(origin bletch)" "environment"
bletch = barf, gag, etc.
endif
endif
10 shell 函数
函数“ shell ”所实现的功能和 shell 中的引用( `` )相同。
contents := $(shell cat foo)
将变量“ contents ”赋值为文件“ foo ”的内容,文件中的换行符在变量中使用空格代替。
11 make 的控制函数
1) $(error TEXT…) -- 产生致命错误
ifdef ERROR1
$(error error is $(ERROR1))
endif