Makefile学习2 - 函数

一. 前言

        Makefile的函数提供了处理文件名,变量,文本和命令的方法。使用函数可以使Makefile的书写更加的灵活。函数的机制也是在调用函数的地方,将函数的处理结果替换原来的函数,简单举例如下:

objects = $(patsubst .c,.o,$(wildcard *.c))

        以上就是将patsubst函数的运行结果(将当前工作目录的所有包含".c"文件的文件名的文本替换为".o"文件名),赋值给objects。函数的输出结果替换了patsubst函数。

二. 调用函数的语法

1.格式:

$(FUNCTION ARGUMENT)
或者
${FUNCTION ARGUMENTS}

2.说明:

        1. 语法中"FUNCTION"是需要调用的函数名,应该是make内嵌的函数名。对于用户自定义的函数名需要通过make的"call"函数来间接调用。

        2. "ARGUMENTS"是函数的参数,参数和函数之间建议使用空格分开,如果存在多个参数,参数之间使用逗号","分开。

        3. 以"$"开头,使用成对的圆括号或花括号把函数名和参数括起来。

        4. 函数处理参数时,参数如果存在对其他变量或函数的引用,首先对这些引用进行展开得到参数的实际内容,而后对它们进行处理。函数的展开顺序按照参数的先后顺序来进行。

        5. 书写时,函数的参数不能出现逗号","和空格。这是因为逗号被用于多个参数的分隔符,而空格会被忽略。当实际书写Makefile时,当有逗号或者空格作为函数的参数时,需要把它们赋值给一个变量,在函数的参数中引用这个变量。示例如下:

[root@localhost makefile]# vim test1.mk
comma:=,
empty:=
space:=$(empty) $(empty)
foo:=a b c
bar:=$(subst $(space),$(comma),$(foo))

$(warning $(bar))

all:
        @echo hello

结果:
[root@localhost makefile]# make -f test1.mk  all
test1.mk:8: a,b,c
hello

三. 文本处理函数

1. $(subst FROM,TO,TEXT)

        字符串替换函数。将字符串"TEXT"中的"FROM"字符替换为"TO",返回替换后的新字符串。示例如下:

target=$(subst ee,EE,feet on the street)

结果:
target=fEEt on the street

2. $(patsubst PATTERN,REPLACEMENT,TEXT)

        模式替换函数。搜索"TEXT"中以空格分开的字符串,将符合模式"PATTERN"的字符串替换为"REPLACEMENT"的字符串。参数"PATTERN"中可以使用模式通配符"%"来代表一个字符串的若干字符。如果参数"REPLACEMENT"中也包含一个"%",那么"REPLACEMENT"中的"%"将是"PATTERN"中的那个"%"所代表的字符串。示例如下:

src:=a.c b.c c.c
objects=$(patsubst %.c,%.o,$(src))

结果:
objects=a.o b.o c.o

变量替换引用"patsubst"函数的简化版:

2.1. $(VAR:PATTERN=REPLACEMENT) = $(patsubst PATTERN,REPLACEMENT,$(VAR))

举例如下:

objects:=a.o b.o c.o
src:=$(objects:.o=.c)

结果:
src=a.c b.c c.c

2.2. $(VAR:SUFFIX=REPLACEMENT) = $(patsubst %SUFFIX,%REPLACEMENT,$(VAR))

举例如下:

objects:=a.o b.o c.o
src:=$(objects:%.o:%.c)

结果:
src=a.c b.c c.c

3. $(strip STRING)

        去空格的函数。去掉字符串"STRING"开头和结尾的空字符(空格或tab字符),并将字符串"STRING"内部的多个空格合并为一个空字符。示例如下:

empty:=
multi_space:=$(empty)   $(empty)
src:=$(multi_space) a.c   b.c c.c
result:=$(strip $(src))

结果:
src=    a.c   b.c c.c
result=a.c b.c c.c

4. $(findstring FIND,IN)

        查找字符串函数。在字符串"IN"中查找"FIND"字符串,如果字符串"IN"中存在字符串"FIND",则返回"FIND",否则为空。示例如下:

result:=$(findstring a,a b c)

结果:
result=a

5. $(filter PATTERN...,TEXT)

        过滤函数。过滤掉字符串"TEXT"中所有不符合模式"PATTERN"的字符串,保留符合"PATTERN"的字符串,可以有多个"PATTERN"。"PATTERN"字符串中一般需要包含模式字符"%",存在多个模式时,模式表达式之间使用空格分隔。示例如下:

src:=a.c b.c c.s d.h
result:=$(filter %.c %.s,$(src))

结果:
result=a.c b.c c.s

6. $(filter-out PATTERN...,TEXT)

        反过滤函数。和"filter"函数实现的功能相反,过滤掉字符串"TEXT"中所有符合"PATTERN"的字符串。保留所有不符合此模式的字符串。可以有多个模式,存在多个模式时,模式表达式之间使用空格分隔。返回"TEXT"字符串中不符合"PATTERN"的字符串。示例如下:

src:=a.c b.c c.s d.h
result:=$(filter-out %.c %.s,$(src))

结果:
result=d.h

7. $(word N,TEXT)

        取单词函数。取出多个字符串"TEXT"中第"N"个单词(N的值从1开始)。函数返回"TEXT"中第N个单词。示例如下:

result:=$(word 2,aaa bbb ccc ddd)

结果:
result=bbb

8. $(wordlist S,E,TEXT)

        取字符串函数。从多个字符串"TEXT"中取出从"S"开始到"E"的字符串。函数返回多个字符串"TEXT"中从"S"到"E"的单词字符串。示例如下:

result=$(wordlist 2,3,aaa bbb ccc ddd eee)

结果:
result=bbb ccc

9. $(words TEXT)

        统计字符串数目函数。函数返回"TEXT"中字符串数目。示例如下:

result=$(words aaa bbb ccc ddd eee)

结果:
result=5

10. $(firstword NAMES...)

        取首个字符串函数。函数返回"NAMES"第一个字符串。firstword函数的功能等效于$(word 1,NAMES...)。示例如下:

result=$(firstword aaa bbb ccc ddd)

结果:
result=aaa

四. 文件名处理函数

1. $(dir NAMES...)

        取目录函数。从文件名序列"NAMES..."中取出各个文件名的目录部分。文件名的目录部分就是包含在文件名中的最后一个斜线("/")之前的部分。函数返回文件序列"NAMES..."中每一个文件的目录部分,如果文件名中没有斜线,认为此文件为当前目录("./")下的文件。示例如下:

result=$(dir src/foo.c a/b/x.c aaa bbb)

结果:
result=src/ a/b/ ./ ./

2. $(notdir NAMES...)

        取文件名函数。从文件名序列"NAMES"中取出非目录部分。目录部分是指最后一个斜线("/")之前的部分。删除所有文件名中的目录部分,只保留非目录部分。函数返回文件名序列"NAMES"中每一个文件的非目录部分。函数的一个缺陷是文件名不能包含空格,否则会有问题。举例如下:

result:=$(notdir src/a.c include/a.h aaa bbb ccc)

结果:
result=a.c a.h aaa bbb ccc

3. $(suffix NMAES...)

        取后缀函数。从文件名序列"NAMES"中取出各个文件名的后缀(文件名中最后一个以点"."开始的部分),如果文件名中不包含点号,则为空。函数返回以空格分隔的"NAMES..."中每一个文件的后缀序列。如果"NAMES..."是多个文件名时,返回值是多个以空格分隔开的字符串序列,如果文件名没有后缀部分,则返回空。示例如下:

result=$(suffix src/a.c include/a.h b.c d)

结果:
result=.c .h .c

4. $(basename NAMES...)

        取前缀函数。从文件名序列"NAMES..."中取出各个文件名的前缀部分(点号之前的部分)。函数返回空格分隔的文件名序列"NAMES..."中各个文件的前缀序列,如果文件名没有前缀,则返回为空。如果"NAMES..."中包含没有后缀的文件名,此文件名不改变,如果一个文件名中存在多个点号,则返回文件名中最后一个点号之前的文件名部分。示例如下:

result=$(basename src/a.c include/b.h /home/god/x.a.c jacks)

结果:
result=src/a include/b /home/god/x.a jacks

5. $(addsuffix SUFFIX,NAMES...)

        加后缀函数。为"NAMES..."中的每一个文件名添加后缀"SUFFIX"。参数"NAME..."为空格分隔开的文件名序列,将"SUFFIX"追加到此序列的每一个文件名的末尾。函数返回添加了后缀"SUFFIX"的文件名序列。示例如下:

result:=$(addsuffix .c,aaa bbb ccc)

结果:
result=aaa.c bbb.c ccc.c

6. $(addprefix PREFIX,NAMES...)

        加前缀函数。为"NAMES"中的每一个文件名添加前缀"PREFIX"。参数"NAMES..."是空格分隔开的文件名序列,将"PREFIX"添加到此序列的每一个文件名之前。函数返回以单空格分隔的添加了前缀"PREFIX"的文件名序列。示例如下:

result=$(addprefix src/,a.c b.c c.c d.c)

结果:
result=src/a.c src/b.c src/c.c src/d.c

7. $(join LIST1,LIST2)

        单词连接函数。将字符串序列"LIST1"和字符串"LIST2"的各个字符串对应连接,将"LIST2"中的第一个字符串追加到"LIST1"的第一个字符串后合并为一个单词,将"LIST2"中的第二个字符串追加到"LIST1"的第二个字符串后合并为一个单词,等等,以此类推。函数返回单空格分隔的合并后的字符串序列。示例如下:

result=$(join a b c,.c .h)

结果:
result=a.c b.h c

8. $(wildcard PATTERN)

        获取匹配模式文件名函数。函数的作用是列出当前目录下所有符合模式"PATTERN"格式的文件名。函数返回以空格分隔的,存在当前目录下的所有符合模式"PATTERN"的文件名。"PATTERN"使用shell可以识别的通配符,包括"?","*"等。

五. 总结

        本文主要介绍了make的函数的用法,其中主要介绍了文本处理函数和文件名处理函数。文本处理函数有subst,patsubst,strip,findstring,filter,filter-out,sort,word,wordlist,words和firstword。文件名处理函数有dir,notdir,suffix,basename,addsuffix,addprefix,join和wildcard。

猜你喜欢

转载自blog.csdn.net/to_be_better_wen/article/details/130024342