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. Python3 的异常处理

    Python3 的异常处理,在官方文档的 tutorial 中有说明. 这里把常用的异常处理方法都列出来,方便平时查找. 捕获异常基类 Python3 要求我们的异常必须继承 Exception 类. ...

  2. 二进制<1>

    Matrix67:位运算简介及实用技巧(一) 基础篇 什么是位运算?    程序中的所有数在计算机内存中都是以二进制的形式储存的.位运算说穿了,就是直接对整数在内存中的二进制位进行操作.比如,and运 ...

  3. BZOJ1499 [NOI2005]瑰丽华尔兹 【单调队列优化dp】

    题目 你跳过华尔兹吗?当音乐响起,当你随着旋律滑动舞步,是不是有一种漫步仙境的惬意?众所周知,跳华尔兹时,最重要的是有好的音乐.但是很少有几个人知道,世界上最伟大的钢琴家一生都漂泊在大海上,他的名字叫 ...

  4. 20140323组队赛 2012福建省第三届ACM省赛题目

    A - Solve equation Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u ...

  5. Pebbles(hdu 2167)

    题意:给定一个N*N的方格,让你在里面取出一些数使其和最大,要求每一个数不能与其相邻的8个数同时取出. /* 和hdu1565差不多,只不过在更新的时候考虑斜上方的格子对该格子的影响. */ #inc ...

  6. FOJ Problem 2260 Card Game

                                                                                            Problem 2260 ...

  7. 【NOIP2016游记】

    day-5:上午看了火箭打马刺 火箭差点翻盘但老大爷们还是稳 下午一场五校 T1T2原题做过 T3分块 day-4:上午五校1小时写3道暴力 2个半小时优化 然而还不知道拿了多少 %%%CC T2树链 ...

  8. Linux 之 FTP服务器搭建

    FTP服务器搭建 参考教程:[千峰教育] 1.关闭防火墙: service iptables stop 2.关闭Selinux setenforce 0 3.安装所需要依赖及编译工具 yum inst ...

  9. Yii中的数据库事务的使用方法小结

    在项目中遇到批量删除的地方一般会使用到事务,下面列举一个用法实例与大家分享. 查看代码   打印 01 <?php 02 $array=array( 03     0=>array('us ...

  10. socket的accept: Invalid argument问题

    void local_sdk_server::wait_remote_client_connect_and_comm() { /*服务器服务启动,等待客户端的链接的到来*/ //sockaddr_in ...