http://www.groad.net/bbs/simple/?f104.html

if  函数

if 函数的语法有两种形式:

() $(if <condition>, <then-something>)
() $(if <condition>, <then-something>, <else-something>)

也就是说,如果 <condition> 为真,那么就采用 <then-something>,否则就采用 <else-something>;如果<condition>为假且为第一种形式,那么啥都不做。

示例代码:

VERSION =
SUBLEVEL =
PATCHLEVEL =
OBJTREE := $(if $(VERSION),$(SUBLEVEL),$(PATCHLEVEL)) all:
@echo "$(OBJTREE)"

输出:

$ make
    

如果改变上面的代码,不赋值给 VERSION,那么 make 后输出结果则为 6 。

findstring -- 查找字符串函数

findstring 函数可以用来查找字符串,它的格式是:

$(findstring FIND,IN)

findstring 从 IN 中查找 FIND 的字符串。如果 IN 中有 FIND,那么返回 FIND,否则返回空。其中,IN 中可以包含空格以及制表符(TAB)。此外,搜索需要严格的文本匹配。

测试代码:

all:
@echo "$(findstring world, hello Makefile world)"

运行输出:

$ make
world

subst 函数 -- 字符串替换

语法:

$(subst <from>,<to>,<text>)

说明:

将 <text> 中的 <from> 字符串替换为 <to> 。

示例代码:

text := "i have a dream"

all:
@echo "$(subst i,you,$(text))"

运行输出:

$ make
you have a dream

word -- 取单词

语法:

$(word <n>, <string>)

说明:

该函数通过 n 参数来取出字符串 string 中的单词。n 是一个整数,表示要取出字符串中第几个单词。

示例:

string = are you ok

all:
@echo $(word ,$(string))
@echo $(word ,$(string))
@echo $(word ,$(string))

输出:

# make
are
you
ok

另外,如果指定的 n 超出 string 所包含的单词数,那么返回空字符串。

firstword -- 取出第一个单词

firstword 取出一个字符串中的第一个单词,比如一个 Makefile 内容为:

all:
@echo $(firstword hello Makefile world)

运行输出:

$ make
hello

words 函数-- 统计字符串中的单词个数

语法:

$(words <string>)

说明:

统计 string 中的单词个数

示例代码:

string = are you ok

all:
@echo $(words $(string))

输出:

# make
    

wildcard

wildcard 用来明确表示通配符。因为在 Makefile 里,变量实质上就是 C/C++ 中的宏,也就是说,如果一个表达式如 objs = *.o ,则 objs 的值就是 *.o ,而不是表示所有的 .o 文件。若果要使用通配符,那么就要使用 wildcard 来声明 * 这个符号,使 * 符号具有通配符的功能。如下举例:
在当前目录下随意建立两个 *.c 文件,如 hello.c 和 world.c ,现在编写一个 Makefile 如下:

src = $(wildcard *.c /usr/src/linux-2.6./drivers/char/ip2/*.c)
all:
@echo $(src)

运行输出:

# make
hello.c world.c /usr/src/linux-2.6./drivers/char/ip2/i2cmd.c /usr/src/linux-2.6./drivers/char/ip2/i2ellis.c /usr/src/linux-2.6./drivers/char/ip2/i2lib.c /usr/src/linux-2.6./drivers/char/ip2/ip2.mod.c /usr/src/linux-2.6./drivers/char/ip2/ip2base.c /usr/src/linux-2.6./drivers/char/ip2/ip2main.c /usr/src/linux-2.6./drivers/char/ip2/ip2main.mod.c

上面输出了当前目录下的两个 .c 文件以及/usr/src/linux-2.6.24/drivers/char/ip2/ 目录下所有的 .c 文件。

wildcard 也可以用来匹配变量。
比较以下几个代码(假设和 Makefile 文件同目录下已经有 include/config.mk 文件):
情况一:

OBJTREE = /root/Makefile
src = $(wildcard $(OBJTREE)/include/config.mk) all:
@echo $(src)

输出:

# make
/root/Makefile/include/config.mk

情况二:

OBJTREE = .
src = $(wildcard $(OBJTREE)/include/config.mk) all:
@echo $(src)

输出:

# make
./include/config.mk

情况三:

OBJTREE = hello
src = $(wildcard $(OBJTREE)/include/config.mk) all:
@echo $(src)

输出:

# make
/*输出内容为空*/

对比上面 3 种情况可以看到,wildcard 也可以用来匹配变量,即这个变量可以是任意的情况。只是注意,wildcard 的核心是“匹配存在的文件”!像上面,将 OBJTREE 变量设为 hello ,当然是不可能找到 hello/include/config.mk 这个不存在的文件的,所以它的输出为空;而将正确的路径赋给 OBJTREE 时,它最后就能够正常的输出。

sort -- 排序函数

使用方法:

$(sort <list>)

说明:

该函数的作用是对 <list> 中的字符串进行排序,按照升序排序。另外,如果字<list> 中含有相同的字符串,在返回的排序结果中只会包含一个。用法如:

objs = hello.c world.c are.c you.c ok.c

all:
@echo $(sort $(objs))

运行输出:

# make
are.c hello.c ok.c world.c you.c

addprefix 函数 -- 增加前缀

语法:

$(addprefix <prefix>, <name->, <name->...<name-n>)

说明:

该函数将前缀 <prefix> 加到各个 <name> 的前面去。

示例代码:

obj += s3c
prj += OBJS := $(addprefix $(obj),$(prj)) all:
@echo $(OBJS)

输出:

# make
s3c2440

strip 去空格函数

strip 函数可以用来去掉字符串中的空格(包括 [TAB] 等不可显示字符),这些空格的位置可以位于字符串中字符单词的前面,中间以及后面。去掉的结果是用一个空格代替多个原来的多个空格。

下面是示例:

string := "   are   you   ok"
nospace := $(strip $(string)) all:
@echo $(string)
@echo $(nospace)

输出:

[beyes@SLinux temp3]$ make
are you ok
are you ok

注意,上面输出第 2 行中的 are 的前面是有 1 个空格的。如果 are 原本没有空格,自然不用替换。

strip 函数经常用在条件判断表达式中,可以确保表达式比较的可靠性和健壮性。

foreach 函数

foreach 函数用来进行一些循环处理,其语法为:

$(foreach VAR, LIST, TEXT)

在 foreach 函数中,LIST 是一个值的列表,这些值用空格隔开,类似与一个数组。当函数执行时,会遍历这个列表,从头到尾依次将 LIST 中的值赋给 VAR,然后执行后面的 TEXT 表达式,而在 TEXT 中同样存在对 VAR 的一个引用。

需要注意的是,VAR 是一个局部的临时变量,它只在 foreach 函数的执行过程中有效,即使在 Makefile 中其它地方存在与之同名的变量也不会受其影响,因为它们不是同一个变量。

示例代码:

array :=
list := $(foreach num, $(array), $(addsuffix .c, $(num))) all:
@echo "$(list)"

运行输出:

$ make
.c .c .c .c .c .c

call 函数 -- 传递参数到变量

通过 call 函数可以将一个变量定义为一个复杂的表达式,它的语法格式为:

$(call VAR, 参数1, 参数2,...)

call 函数可以将 "参数1“ ,”参数2“ 传递到 VAR 中,然后 VAR 根据传递进来的参数进行展开成一个完整的表达式。

在函数执行时,参数1,参数2, 参数3, ... 等等会依次赋值到临时变量 $(1), $(2), $(3) ... 上,而这些临时变量则是定义在 VAR 中的。看下面例子演示:

reverse = $()$()
foo = $(call reverse, a, b) all:
@echo "foo = $(foo)"

运行输出:

$ make
foo = b a

参数 a 传递到 $(1) 中,参数 b 传递到 $(2) 中;而在变量 reverse 中并不要求 $(1) ,$(2) 这些变量有一定的顺序。也可以说,$(1), $(2) 这些是形参,而 a, b 这种是实参。

下面再演示一个复杂的例子:

lsfirstpath = $(subst /ls, ,$(wildcard $(addsuffix /$(),$(subst :, ,$(PATH)))))
lsPath := $(call lsfirstpath,ls) all:
@echo "command 'ls' is in \"$(call lsfirstpath,ls)\""

运行输出:

[beyes@beyes exp2]$ make
command 'ls' is in "/bin "

在上面的 Makefile 代码中,$(PATH) 是共有的环境变量,它存放各种路径名,这些路径名用冒号隔开。

$(subst :, ,$(PATH)) 这句用来去掉 $(PATH) 中的冒号。

$(addsuffix /$(1),$(subst :, ,$(PATH))) 这句为每个路径名后面添加上 "/$(1)",因为这里的 $(1) 其实就是 $(call lsfirstpath,ls) 中传递过去的 ls,所以此举执行之后会变成:

/usr/lib/ccache/ls /usr/local/bin/ls /usr/binls ... ...

等等。

$(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))) 这句中的 wildcard 函数是用来匹配文件是否存在,如果存在则保留下来,不存在就去掉。

$(subst /ls, ,$(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH))))) 最后当我们找到了 ls 所在的路径后,去掉 ”/ls“ 后就得出了它所在的目录。

另外,还有 $(0) 这个变量,它代表的是 VAR 本身。

call 函数还可以嵌套的调用。在嵌套调用时,每一层都有自己特定的局部变量($(1), $(2)...等),这些局部变量不会传递到下一层去,如:

k = $()$()
map = $(foreach a,$(),$(call $(),$(a),good-))
o = $(call map,k,are you ok) all:
@echo "$(o)"

运行输出:

[beyes@beyes exp3]$ make
good-are good-you good-ok

在上面的 Makefile 文件中,第 1 层 call 是 $(call map,k,are you ok) ,在这里 $(1) 和 $(2) 分别为 k 和 are you ok ,所以对已经定义的表达式 map 进行展开后得:

$(foreach a,are you ok,$(call k,$(a),good-))

第二层 call 为 $(call k,$(a),good-),在这里,它有自己的 $(1) 和 $(2);$(1) 就是 $(a) -- 就是 foreach 函数捡取的值(依次为 are you ok),$(2) 为 good- 。

要非常小心的是,在对 call 和 foreach 这些函数应用时,一定要注意空格,如果不小心多了空格,看到的结果基本上不是你所期望的。

shell 函数 -- 执行命令行命令

在 Makefile 中,可以调用 shell 函数来执行 shell 命令,这样就便于 Makefile 和外部进行通信,它和 shell 脚本中的 `command` 的功能相同。在执行 shell 命令返回结果时,可能会包含换行('\n' 或 "\n\r"),但 make 可以将它们去除。一般情况下,make 在读取 Makefile 文件时,函数 shell 就会被扩展,也就是说会执行 shell 函数后面的参数命令并返回结果。

示例代码:

cfile := $(shell ls /home/beyes/C/*.c)

all:
@echo "$(cfile)"

运行输出:

$ make
/home/beyes/C/percpu.c /home/beyes/C/wchar.c

notdir -- 取文件名

notdir 函数用来获取文件名,其语法格式是:

$(notdir NAMES...)

“NAMES..." 表示一系列的文件名,其中可以包含目录(以 '/' 符号结尾)名,但在函数返回时,会过滤掉目录部分,而只留下纯文件名部分。需要注意的是,被过滤掉的目录名在返回时用一个空格代替。

测试代码:

all:
@echo "$(notdir file1.c file2.txt /home/beyes/ test.h /root/)"

运行输出:

$ make
file1.c file2.txt test.h

dir -- 取目录名

dir 函数和 notdir 函数的作用相反,它用来取列表中的目录名。如果列表中含有普通文件名(没有以 '/' 符号结尾),那么在函数返回时普通文件名用 './' 来代替。
测试代码:

all:
@echo "$(dir file1.c file2.txt /home/beyes/ test.h /root/)"

运行输出:

$ make
./ ./ /home/beyes/ ./ /root/

内核顶层Makefile相关2的更多相关文章

  1. 内核顶层Makefile相关3

    http://www.groad.net/bbs/simple/?f104.html 伪目标 .PHONY是一个特殊工作目标(special target),它用来指定一个假想的工作目标,也就是说它后 ...

  2. 内核顶层Makefile相关4

    http://www.groad.net/bbs/simple/?f104.html make 的递归执行与 MAKEFLAGS 变量 make 的递归调用是指:在 Makefile 中使用 make ...

  3. 内核顶层Makefile相关1

    http://www.groad.net/bbs/simple/?f104.htm $(Q) 变量 内核 Makefile 文件 238 行到 259 行的注释中知道,$(Q) 变量的作用是决定是否在 ...

  4. Linux 内核的 Makefile

    Linux内核的配置系统的基本结构 Linux内核的配置系统由三个部分组成,分别是: 1.Makefile:分布在 Linux 内核源代码根目录及各层目录中,定义 Linux 内核的编译规则: 2.配 ...

  5. 浅谈内核的Makefile、Kconfig和.config文件

    Linux内核源码文件繁多,搞不清Makefile.Kconfig..config间的关系,不了解内核编译体系,编译修改内核有问题无从下手,自己写的驱动不知道怎么编进内核,不知道怎么配置内核,这些问题 ...

  6. Linux中mod相关的命令 内核模块化 mod相关命令都是用来动态加载内核模块/驱动程序模块

    Linux中mod相关的命令 内核模块化   mod相关命令都是用来动态加载内核模块/驱动程序模块 http://baike.baidu.com/link?url=lxiKxFvYm-UfJIxMjz ...

  7. uboot 顶层makefile细节分析

    uboot的源文件众多,学习庞然大物首先找到脊椎--顶层的makfile,逐一破解.但是,uboot的makefile同样是一个庞然大物,所以也要找到它的主线.倘若过分专注部分细节,很难做到把握全局, ...

  8. (笔记)Linux内核中内存相关的操作函数

    linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) ...

  9. 【总结】嵌入式linux内核中Makefile、Kconfig、.config的关系及增加开机Hello World【转】

    本文转载自:http://blog.csdn.net/fengyuwuzu0519/article/details/73772109 为了弄清内核的组织结构,我们先来实现下面这个简单的例子. 一.增加 ...

随机推荐

  1. eclipse中添加svn插件

    在eclipse中使用svn查看能非常方便的对代码进行查看和更新提交操作,能及时知道代码的更新状态. 在eclipse中如果要使用svn,只能使用svn插件的方式进行. 插件地址:http://sub ...

  2. Codeforces Round #345 (Div. 2)——B. Beautiful Paintings(贪心求上升序列个数)

    B. Beautiful Paintings time limit per test 1 second memory limit per test 256 megabytes input standa ...

  3. 【CCF】商路

    [60分] #include<iostream> #include<cstdio> #include<cstring> #include<string> ...

  4. java面试题之什么是线程ThreadLocal?作用是什么?

    定义:线程局部变量是局限于线程内的变量,属于线程自身所有,不在多个线程间共享.java提供ThreadLocal类来支持线程局部变量,是一个实现线程安全的方式. 任何线程局部变量一旦在工作完成后没有释 ...

  5. Wmap5 测试80端口 Your port 80 is actually used by :Server: Microsoft-HTTPAPI/2.0

    问题:win7系统! 在wamp5的apache启动不了: 目录下点击[测试80端口]的时候提示:Your port 80 is actually used by : Server: Microsof ...

  6. Python实现删除文件夹内规定时间内的文件

    需求:  在测试程序的时候,程序会大批量的上传文件到规定目录,然后文件根据日期DAY新建文件夹存放,比如28号上传的文件放到  .../28/* 内,29号上传的文件放到 .../29/*内,因为需要 ...

  7. maven打包加入依赖包以及加入本地依赖包的方法

    Maven引入本地Jar包并打包进War包中 1.概述 在平时的开发中,有一些Jar包因为种种原因,在Maven的中央仓库中没有收录,所以就要使用本地引入的方式加入进来. 2. 拷贝至项目根目录 项目 ...

  8. 用promise做图片的预加载

    var url='jsonp-master/0.jpg' var url1='jsonp-master/1.jpg' var url2='jsonp-master/2.jpg' var img=doc ...

  9. 《Linux命令行与shell脚本编程大全 第3版》

    第一部分 Linux 命令行 第1章  初识Linux she1.1   什么是Linux 21.1.1 深入探究Linux 内核 31.1.2 GNU 工具 61.1.3 Linux 桌面环境 81 ...

  10. Codeforces Gym101606 A.Alien Sunset (2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017))

    2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017) 寒假第一次组队训练赛,和学长一起训练,题目难度是3颗星,我和猪队友写 ...