函数调用的格式如下:
$(function arguments)
这里function’ 是函数名,
arguments’ 是该函数的参数。参数和函数名之间是用空格
或 Tab 隔开,如果有多个参数,它们之间用逗号隔开。这些空格和逗号不是参数值的一部分。
内核的 Makefile 中用到大量的函数,现在介绍一些常用的。
字符串替换和分析函数
- ( 1) $(subst from,to,text)
在文本text’中使用to’替换每一处from’。
比如: $(subst ee,EE,feet on the street)
结果为‘ fEEt on the street’。
- ( 2) $(patsubst pattern,replacement,text)
寻找ext中符合格式pattern的字,用replacement替换它们。 pattern和
replacement中可以使用通配符。
比如: $(patsubst %.c,%.o,x.c.c bar.c)
结果为:`x.c.o bar.o’ 。
- 3) $(strip string)
去掉前导和结尾空格,并将中间的多个空格压缩为单个空格。
比如: $(strip a b c )
结果为`a b c’ 。
- ( 4) $(findstring find,in)
在字符串n中搜寻find ,如果找到,则返回值是find ,否则返回值为空。
比如: $(findstring a,a b c)
$(findstring a,b c)
将分别产生值a 和`’ (空字符串)。
- ( 5) $(filter pattern…,text)
返 回 在 text’中 由 空 格 隔 开 且 匹 配 格 式 pattern…的 字 , 去 除 不 符 合 格 式
pattern…的字。 比如: $(filter %.c %.s,foo.c bar.c baz.s ugh.h)
结果为`foo.c bar.c baz.s’。
- ( 6) $(filter-out pattern…,text)
返 回 在 text中 由 空 格 隔 开 且 不 匹 配 格 式 pattern…的 字 , 去 除 符 合 格 式
pattern… 的字。 它是函数 filter 的反函数。
比如: $(filter %.c %.s,foo.c bar.c baz.s ugh.h)
结果为`ugh.h’ 。
- ( 7) $(sort list)
将‘ list’中的字按字母顺序排序,并去掉重复的字。输出由单个空格隔开的字的列表。
比如: $(sort foo bar lose)
返回值是‘ bar foo lose’
2. 文件名函数
- ( 1) $(dir names…)
抽取‘ names…’中每一个文件名的路径部分,文件名的路径部分包括从文件名的首字 符到最后一个斜杠(含斜杠)之前的一切字符。
比如:$(dir src/foo.c hacks)
结果为‘src/ ./’ 。
- ( 2) $(notdir names…)
抽取‘ names…’中每一个文件名中除路径部分外一切字符(真正的文件名)。
比如: $(notdir src/foo.c hacks)
结果为‘ foo.c hacks’ 。
- ( 3) $(suffix names…)
抽取‘ names…’中每一个文件名的后缀。
比如: $(suffix src/foo.c src-1.0/bar.c hacks)
结果为‘ .c .c’ 。
- ( 4) $(basename names…)
抽取‘ names…’中每一个文件名中除后缀外一切字符。
比如: $(basename src/foo.c src-1.0/bar hacks)
结果为‘ src/foo src-1.0/bar hacks’ 。
- ( 5) $(addsuffix suffix,names…)
参数‘ names…’ 是一系列的文件名,文件名之间用空格隔开; suffix 是一个后缀名。 将
suffix(后缀)的值附加在每一个独立文件名的后面,完成后将文件名串联起来,它们之间 用单个空格隔开。
比如: $(addsuffix .c,foo bar)
结果为‘ foo.c bar.c’
- ( 6) $(addprefix prefix,names…)
参数‘ names’ 是一系列的文件名,文件名之间用空格隔开; prefix 是一个前缀名。将
preffix(前缀)的值附加在每一个独立文件名的前面,完成后将文件名串联起来,它们之间用 单个空格隔开。
比如: $(addprefix src/,foo bar)
结果为‘ src/foo src/bar’ 。
- ( 7) $(wildcard pattern)
参数‘ pattern’是一个文件名格式,包含有通配符(通配符和 shell 中的用法一样)。函 数 wildcard
的结果是一列和格式匹配的且真实存在的文件的名称,文件名之间用一个空格隔 开。
比如若当前目录下有文件 1.c、 2.c、 1.h、2.h,
则: c_src := $(wildcard *.c) 结果为‘ 1.c 2.c’ 。
3. 其他函数
- ( 1) $(foreach var,list,text)
前两个参数,‘ var’和‘list’将首先扩展,注意最后一个参数‘ text’此时不扩展; 接着,‘ list’扩展所得的每个字,都赋给‘ var’变量;然后‘ text’引用该变量进行扩展, 因此‘ text’ 每次扩展都不相同。 函数的结果是由空格隔开的‘text’ 在‘ list’中多次扩展后,得到的新‘ list’ ,就 是说: ‘text’多次扩展的字串联起来,字与字之间由空格隔开,如此就产生了函数 foreach 的返回值。
下面是一个简单的例子,
将变量‘files’ 的值设置为 ‘dirs’ 中的所有目录下的所有 文件的列表:
dirs := a b c d files := ( f o r e a c h d i r , (foreach dir, (foreachdir,(dirs),$(wildcard $(dir)/*))这里 text是$(wildcard $$(dir)/*) ,它的扩展过程如下
① 第一个赋给变量 dir 的值是a’ 扩展结果为$(wildcard a/*)
② 第二个赋给变量 dir 的值是b, 扩展结果为$(wildcard b/*)
③ 第三个赋给变量 dir 的值是c,扩展结果为$(wildcard c/*)
④ 如此继续扩展。 这个例子和下面的例有共同的结果files :=$(wildcard a/* b/* c/* d/*)
- ( 2) $(if condition,then-part[,else-part])
首先把第一个参数‘ condition’ 的前导空格、结尾空格去掉,然后扩展。如果扩展为非 空字符串,则条件‘condition’为‘真’;如果扩展为空字符串,则条件‘ condition’为‘假’。 如果条件‘ condition’为‘真’,那么计算第二个参数‘ then-part’的值,并将该值作 为整个函数 if 的值。 如果条件‘ condition’为‘假’,并且第三个参数存在,则计算第三个参数‘ else-part’ 的值,并将该值作为整个函数 if 的值;如果第三个参数不存在,函数 if将什么也不计算, 返回空值。 注意: 仅能计算‘ then-part’和‘ else-part’二者之一,不能同时计算。这样有可能产生 副作用(例如函数 shell 的调用)。
- ( 3) $(origin variable)
变量‘ variable’是一个查询变量的名称,不是对该变量的引用。所以,不能采用‘ $’ 和圆括号的格式书写该变量,当然,如果需要使用非常量的文件名,可以在文件名中使用变 量引用。第 4 章 嵌入式编程 函数 origin的结果是一个字符串,该字符串变量是这样定义的: ‘ undefined’ :如果变量‘ variable’ 从没有定义; ‘ default’ :变量‘ variable’ 是缺省定义; ‘ environment’ :变量‘ variable’作为环境变量定义,选项‘ -e’ 没有打开; ‘ environment override’ :变量‘ variable’ 作为环境变量定义,选项‘ -e’ 已打开; ‘ file’ :变量‘ variable’ 在 Makefile 中定义; ‘ command line’ :变量‘ variable’ 在命令行中定义; ‘ override’ :变量‘ variable’ 在 Makefile 中用 override 指令定义; ‘ automatic’ :变量‘ variable’ 是自动变量
- ( 4) $(shell command arguments)
函数 shell 是 make 与外部环境的通讯工具。函数 shell 的执行结果和在控制台上执行 ‘ command arguments’的结果相似。不过如果‘ command arguments’的结果含有换行符(和 回车符),则在函数 shell 的返回结果中将把它们处理为单个空格,若返回结果最后是换行符 (和回车符)则被去掉。
比如当前目录下有文件 1.c、 2.c、 1.h、2.h,
则: c_src := $(shell ls *.c) 结果为‘ 1.c 2.c’ 。
例子:
Makefile
src := $(shell ls *.c)
objs := $(patsubst %.c, %.o, $(src))
test:$(objs)
gcc -o $@ $^
%.o:%.c
gcc -c -o $@ $<
上述 Makefile 中$@、 $^、 $<称为自动变量。 $@表示规则的目标文件名; $^表示所有依赖
的名字,名字之间用空格隔开; $<表示第一个依赖的文件名。‘ %’是通配符,它和一个字符
串中任意个数的字符相匹配。
a.c
#include<stdio.h>
extern int fun1(int i);
int main()
{
int ret = 0;
ret = fun1(3);
printf("main ret = %d\n", ret);
return ret;
}
b.c
#include<stdio.h>
extern int fun2(int i);
int fun1(int i)
{
printf("fun1 rx %d\n", i);
return fun2(i);
d.c
#include<stdio.h>
int fun2(int i)
{
printf("fun2 rx %d\n", i);
return i+3;
}
执行make
kayshi@ubuntu:~/code/makefile$ make
gcc -c -o a.o a.c
gcc -c -o b.o b.c
gcc -c -o d.o d.c
gcc -o test a.o b.o d.o
kayshi@ubuntu:~/code/makefile$ ls
a.c a.o b.c b.o d.c d.o Makefile test
kayshi@ubuntu:~/code/makefile$ ./test
fun1 rx 3
fun2 rx 3
main ret = 6