Android编译 Makefile入门学习

1 Makefile的基本规则

在讲述这个 makefile 之前,还是让我们先来粗略地看一看 makefile 的规则。

target ... : prerequisites ...
command
...
...
  • target

可以是一个 object file(目标文件),也可以是一个执行文件,还可以是一个标签(label)。对于
标签这种特性,在后续的“伪目标”章节中会有叙述。

  • prerequisites

生成该 target 所依赖的文件和/或 target

  • command

该 target 要执行的命令(任意的 shell 命令)
这是一个文件的依赖关系,也就是说,target 这一个或多个的目标文件依赖于 prerequisites 中的文
件,其生成规则定义在 command 中。说白一点就是说: 3
, 发布 1.0
prerequisites 中如果有一个以上的文件比 target 文件要新的话,command 所定义的命令就会被执行。

例子

  1. 创建文件
touch Makefile main.o main.cpp
MakeFileTest : main.o
	@echo "make MakeFileTest"

main.o : main.cpp
	@echo "make main.o-------"
  1. 执行make结果
ubuntu@ubuntu:~/work/shell/MakeFile2$ make
make main.o-------
make MakeFileTest
  1. 修改main.o
    根据上面说法,如果main.o的文件时间比main.cpp新的话,证明是main.0没有变化,不需要编译main.o的,也就不会执行make main.0
ubuntu@ubuntu:~/work/shell/MakeFile2$ make
make MakeFileTest

MakeFile的执行顺序时,遍历执行Makefile文件里面所有的mk命令,然后执行第一个target目标

2. make执行步骤

在默认的方式下,也就是我们只输入 make 命令。那么,

  1. make 会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文
    件,并把这个文件作为最终的目标文件。
  3. 如果 edit 文件不存在,或是 edit 所依赖的后面的 .o 文件的文件修改时间要比 edit 这个文件新,
    那么,他就会执行后面所定义的命令来生成 edit 这个文件。
  4. 如果 edit 所依赖的 .o 文件也不存在,那么 make 会在当前文件中找目标为 .o 文件的依赖性,如
    果找到则再根据那一个规则生成 .o 文件。(这有点像一个堆栈的过程)
  5. 当然,你的 C 文件和 H 文件是存在的啦,于是 make 会生成 .o 文件,然后再用 .o 文件生成 make
    的终极任务,也就是执行文件 edit 了。
    这就是整个 make 的依赖性,make 会一层又一层地去找文件的依赖关系,直到最终编译出第一个目
    标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么 make 就会直接退出,并
    报错,而对于所定义的命令的错误,或是编译不成功,make 根本不理。make 只管文件的依赖性,即,如
    果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。

3. 变量赋值

结果看都是忽略掉=右边的空格,后面的空格不会过滤
添加“”和变量赋值,不会忽略掉空格

OBJECT :=  wangdong test ffille    ssddf #最后都有一个空格
OBJECT1 :=  " wangdong test ffille    ssddf "
OBJECT2 = $(OBJECT1)

MakeFileTest : main.o
	@echo "make MakeFileTest"
	@echo "OBJECT : --$(OBJECT)--"
	@echo "OBJECT1 : --$(OBJECT1)--"
	@echo "OBJECT2 : --$(OBJECT2)--"

结果:
make MakeFileTest
OBJECT : --wangdong test ffille    ssddf --
OBJECT1 : -- wangdong test ffille ssddf --
OBJECT2 : -- wangdong test ffille ssddf --

4. make clean和伪目标文件

.PHONY : clean

clean :
	-rm xxx.txt  //-会跳过错误,不影响后面执行
	@echo "clean rm-------"
	cp xx.txt xxxxx.txt  //没有xx.txt会退出,不会执行后面
	@echo "clean cp-------"

@make clean结果:
rm xxx.txt
rm: 无法删除'xxx.txt': 没有那个文件或目录
makefile:20: recipe for target 'clean' failed
make: [clean] Error 1 (ignored)
clean rm-------
cp xx.txt xxxxx.txt
cp: 无法获取'xx.txt' 的文件状态(stat): 没有那个文件或目录
makefile:20: recipe for target 'clean' failed
make: *** [clean] Error 1

前面说过,.PHONY 表示 clean 是一个“伪目标”。而在 rm 命令前面加了一个小减号的意思就是,也
许某些文件出现问题,但不要管,继续做后面的事。当然,clean 的规则不要放在文件的开头,不然,这
就会变成 make 的默认目标,相信谁也不愿意这样。不成文的规矩是——“clean 从来都是放在文件的最
后”。

5. Makefile 里有什么?

Makefile 里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释

  1. 显式规则。显式规则说明了如何生成一个或多个目标文件。这是由 Makefile 的书写者明显指出要
    生成的文件、文件的依赖文件和生成的命令。
  2. 隐晦规则。由于我们的 make 有自动推导的功能,所以隐晦的规则可以让我们比较简略地书写 Makefile,这是由 make 所支持的。
  3. 变量的定义。在 Makefile 中我们要定义一系列的变量,变量一般都是字符串,这个有点像你 C 语
    言中的宏,当 Makefile 被执行时,其中的变量都会被扩展到相应的引用位置上。
  4. 文件指示。其包括了三个部分,一个是在一个 Makefile 中引用另一个 Makefile,就像 C 语言中的
    include 一样;另一个是指根据某些情况指定 Makefile 中的有效部分,就像 C 语言中的预编译 #if
    一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。
    8 Chapter 2. makefile 介绍
    , 发布 1.0
  5. 注释。Makefile 中只有行注释,和 UNIX 的 Shell 脚本一样,其注释是用 # 字符,这个就像 C/C++
    中的 // 一样。如果你要在你的 Makefile 中使用 # 字符,可以用反斜杠进行转义,如:# 。
    最后,还值得一提的是,在 Makefile 中的命令,必须要以 Tab 键开始。

6. 引用其他Makefile文件

使用include来引用其他mk文件,其表示,无论 include 过程中出现什么错误,都不要报错继续执行

include vendor/chinatsp/scripts/Chinatsp.mk

# -表示chinatsp.mk报错不会影响执行
-include vendor/chinatsp/scripts/Chinatsp.mk

//这里找不到Chinatspxx.mk就不会退出,如果没有-,那么就会退出MakeFile

-include Chinatspxx.mk

MakeFileTest : main.o
	@echo "make MakeFileTest"

7. 伪目标

“伪目标”并不是一个文件,只是一个标签,由于“伪目标”
不是文件,所以 make 无法生成它的依赖关系和决定它是否要执行。我们只有通过显式地指明这个“目
标”才能让其生效。当然,“伪目标”的取名不能和文件名重名,不然其就失去了“伪目标”的意义了。

当然,为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显式地指明
一个目标是“伪目标”,向 make 说明,不管是否有这个文件,这个目标就是“伪目标”。

make执行all,all是一个伪目标不会生成,就会去遍历prog1,2,3

all : prog1 prog2 prog3
.PHONY : all
prog1 : prog1.o utils.o
cc -o prog1 prog1.o utils.o
prog2 : prog2.o
cc -o prog2 prog2.o
prog3 : prog3.o sort.o utils.o
cc -o prog3 prog3.o sort.o utils.o

8. 多目标$@

bigoutput littleoutput : text.g
generate text.g -$(subst output,,$@) > $@

上述规则等价于:
bigoutput : text.g
generate text.g -big > bigoutput
littleoutput : text.g
generate text.g -little > littleoutput

9. 显示命令@

通常,make 会把其要执行的命令行在命令执行前输出到屏幕上。当我们用 @ 字符在命令行前,那么,
这个命令将不被 make 显示出来,最具代表性的例子是,我们用这个功能来向屏幕显示一些信息

不加@会首先打印命令 echo “make MakeFileTest”,然后在执行命令
机上@,不会打印命令内容,直接执行shell命令

@Makefile
OBJECT :=  wangdong test ffille    ssddf 
OBJECT1 :=  " wangdong test ffille    ssddf "
MakeFileTest : main.o
	echo "make MakeFileTest"
	echo "OBJECT : --$(OBJECT)--"
	@echo "OBJECT1 : --$(OBJECT1)--"

结果:
echo "make MakeFileTest"
make MakeFileTest
echo "OBJECT : --wangdong test ffille    ssddf --"
OBJECT : --wangdong test ffille    ssddf --
OBJECT1 : -- wangdong test ffille ssddf --

10. 命令执行

两次pwd内容不一样,可见每一个shell命令都是在独立的进程

MakeFileTest : main.o
	echo "make MakeFileTest"
	cd ~
	pwd
	cd ~;pwd


cd ~
pwd
/home/wangdong/work/shell/MakeFile2
cd ~;pwd
/home/wangdong

11. 命令出错 -

命令出错
每当命令运行完后,make 会检测每个命令的返回码,如果命令返回成功,那么 make 会执行下一条
命令,当规则中所有的命令成功返回后,这个规则就算是成功完成了。如果一个规则中的某个命令出错
了(命令退出码非零),那么 make 就会终止执行当前规则,这将有可能终止所有规则的执行。

有些时候,命令的出错并不表示就是错误的。例如 mkdir 命令,我们一定需要建立一个目录,如果
目录不存在,那么 mkdir 就成功执行,万事大吉,如果目录存在,那么就出错了。我们之所以使用 mkdir
的意思就是一定要有这样的一个目录,于是我们就不希望 mkdir 出错而终止规则的运行。

为了做到这一点,忽略命令的出错,我们可以在 Makefile 的命令行前加一个减号 - (在 Tab 键之
后),标记为不管命令出不出错都认为是成功的。如:

clean:
-rm -f *.o

还有一个全局的办法是,给 make 加上 -i 或是 --ignore-errors 参数,那么,Makefile 中所有命
令都会忽略错误。而如果一个规则是以 .IGNORE 作为目标的,那么这个规则中的所有命令将会忽略错误。
这些是不同级别的防止命令出错的方法,你可以根据你的不同喜欢设置。
还有一个要提一下的 make 的参数的是 -k 或是 --keep-going ,这个参数的意思是,如果某规则中
的命令出错了,那么就终止该规则的执行,但继续执行其它规则。

12. 自动化变量 $@ @< $$@

在上述的模式规则中,目标和依赖文件都是一系例的文件,那么我们如何书写一个命令来完成从不
同的依赖文件生成相应的目标?因为在每一次的对模式规则的解析时,都会是不同的目标和依赖文件。

自动化变量就是完成这个功能的。在前面,我们已经对自动化变量有所提涉,相信你看到这里已对
它有一个感性认识了。所谓自动化变量,就是这种变量会把模式中所定义的一系列的文件自动地挨个取
出,直至所有的符合模式的文件都取完了。这种自动化变量只应出现在规则的命令中。

下面是所有的自动化变量及其说明:

@ : 表 示 规 则 中 的 目 标 文 件 集 。 在 模 式 规 则 中 , 如 果 有 多 个 目 标 , 那 么 , @ : 表示规则中的目标文件集。在模式规则中,如果有多个目标,那么, @:@ 就是匹配于目标中模
式定义的集合。

, 那 么 , % : 仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是 foo.a(bar.o) ,那么, % 就是 bar.o ,$@ 就是 foo.a 。如果目标不是函数库文件(Unix 下是 .a ,Windows
下是 .lib ),那么,其值为空。

• $< : 依赖目标中的第一个目标名字。如果依赖目标是以模式(即 % )定义的,那么 $< 将是符合模
式的一系列的文件集。注意,其是一个一个取出来的。

• $? : 所有比目标新的依赖目标的集合。以空格分隔。

• $^ : 所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除
重复的依赖目标,只保留一份。

• $+ : 这个变量很像 $^ ,也是所有依赖目标的集合。只是它不去除重复的依赖目标。

∗ : 这 个 变 量 表 示 目 标 模 式 中 a . * : 这个变量表示目标模式中 % 及其之前的部分。如果目标是 dir/a.foo.b ,并且目标的模式是 a.%.b ,那么, :a.* 的值就是 dir/a.foo 。这个变量对于构造有关联的文件名是比较有较。如果目
标中没有模式的定义,那么 $* 也就不能被推导出,但是,如果目标文件的后缀是 make 所识别的,
那么 ∗ 就 是 除 了 后 缀 的 那 一 部 分 。 例 如 : 如 果 目 标 是 f o o . c , 因 为 . c 是 m a k e 所 能 识 别 的 后 缀 名 , 所 以 , * 就是除了后缀的那一部分。例如:如果目标是 foo.c ,因为 .c 是 make 所能识别的后缀 名,所以, foo.c.cmake* 的值就是 foo 。这个特性是 GNU make 的,很有可能不兼容于其它版本的 make,所
以,你应该尽量避免使用 $* ,除非是在隐含规则或是静态模式中。如果目标中的后缀是 make 所
不能识别的,那么 $* 就是空值。

• ’ $ '符号的使用
美元符号$,主要扩展打开makefile中定义的变量

• ’ ′ 符 号 的 使 用 '符号的使用 使 符号主要扩展打开makefile中定义的shell变量

示例:

@build/core/definitions.mk

define copy-file-to-target
@mkdir -p $(dir $@)
$(hide) rm -f $@
echo "cp $< $@"
echo " 1: $@   --2: $<   --3:  $$@ "
endef

# Define a rule to copy a file.  For use via $(eval).
# $(1): source file
# $(2): destination file
define copy-one-file
$(warning 2: $(2)  1: $(1))
$(2): $(1)
	echo "  1: $@   --2: $<   --3:  $$@ "
	echo "Copy: $$@"
	@echo "---------------------------------------------"
	$$(copy-file-to-target)
endef

#$(eval $(call copy-one-file, app.apk, sys.apk) )
$(eval $(call  copy-one-file, app.apk one.apk ,  two.apk sys.apk) )

结果:

$(2): $(1) 是使用eval call之后传入的参数,这里是一个拷贝,代表src文件和dst文件

直接使用$@ $<是空的, $$@是dst参数的第一个文件

$$(copy-file-to-target)是展开copy-file-to-target里面的shell命令

得到的$@ 是目标target(dst)第一个值 < 依 赖 的 t a r g e t ( < 依赖的target( <target((1))的第一个值
$$@得到的是是dst参数的第一个文件

在android 10 java.mk编译static jar时候,有调用copy-one-file来完成编译jar

makefile:28: 2:   two.apk sys.apk  1:  app.apk one.apk 
echo "  1:    --2:    --3:  two.apk "
  1:    --2:    --3:  two.apk 
echo "Copy: two.apk"
Copy: two.apk
---------------------------------------------
rm -f two.apk
echo "cp app.apk two.apk"
cp app.apk two.apk
echo " 1: two.apk   --2: app.apk   --3:  $@ " 
 1: two.apk   --2: app.apk   --3:
define copy-file-to-target
@mkdir -p $(dir $@)
$(hide) rm -f $@
$(hide) cp "$<" "$@"
endef

define copy-one-file
$(2): $(1)
	@echo "Copy: $$@"
	$$(copy-file-to-target)
endef

$(eval $(call copy-one-file, /home/wangdong/work/shell/MakeFile2/main.cpp, /home/wangdong/work/shell/MakeFile2/my.cpp))
$(eval $(call copy-one-file, /home/wangdong/work/shell/MakeFile2/Chinatsp.mk, /home/wangdong/work/shell/MakeFile2/Chinatsp.mk.cpp))

Chinatsp :
	@echo "==========="

$(eval $(call copy-one-file, /home/wangdong/work/shell/MakeFile2/Chinatsp.mk, /home/wangdong/work/shell/MakeFile2/Chinatsp3.mk.cpp))

结果log,编译后,第二,三个copy one file根本不执行,chinatsp也不会执行,因为makefile默认会执行第一个遇到的target,其他的就执行不到了,因此编译里面自己直接添加这个,可能执行不到哦

$ make
Copy: /home/wangdong/work/shell/MakeFile2/my.cpp
rm -f /home/wangdong/work/shell/MakeFile2/my.cpp
cp "/home/wangdong/work/shell/MakeFile2/main.cpp" "/home/wangdong/work/shell/MakeFile2/my.cpp"

13. 字符串函数

13.1 subst 字符串替换函数

$(subst ,, )

• 名称:字符串替换函数
• 功能:把字串 中的 字符串替换成
• 返回:函数返回被替换过后的字符串。
• 示例:
$(subst ee,EE,feet on the street)

把 feet on the street 中的 ee 替换成 EE ,返回结果是 fEEt on the strEEt 。

返回字符串去掉了.xml,意思是把.xml替换为null

$(warning $(subst .xml,,vendor/qcom/adb.xml test.xml))

makefile:41: vendor/qcom/adb  test
13.2 patsubst 模式字符串替换函数

$(patsubst ,, )

• 名称:模式字符串替换函数。

• 功能:查找 中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式
,如果匹配的话,则以 替换。这里, 可以包括通配符 % ,
表示任意长度的字串。如果 中也包含 % ,那么, 中的这个 % 将是
中的那个 % 所代表的字串。(可以用 \ 来转义,以 % 来表示真实含义的 % 字符)

• 返回:函数返回被替换过后的字符串。

可以看到subst和patsubst区别,subst只要是.c都会替换为.o,patsubst而是符合%.c替换为%.o, 这里%相当于x.c

$(warning subst: $(subst .xml,,vendor/qcom/adb.xml  test.xml))
$(warning patsubst: $(patsubst %.c,%.o,x.c.c bar.c))
$(warning patsubst: $(subst .c,.o,x.c.c bar.c))

makefile:41: subst: vendor/qcom/adb  test
makefile:42: patsubst: x.c.o bar.o
makefile:43: patsubst: x.o.o bar.o
13.3 strip 去空格

$(strip )

• 名称:去空格函数。

• 功能:去掉 字串中开头和结尾的空字符。

• 返回:返回被去掉空格的字符串值。

把string中的字符串按空格隔开,全部去除空格,中间多个空格只有一个空格

$(warning strip: --$(strip  bar.c      -     xxx  )--)

makefile:45: strip: --bar.c - xxx--
13.4 findstring 查找字符串函数

$(findstring ,)

• 名称:查找字符串函数

• 功能:在字串 中查找 字串。

• 返回:如果找到,那么返回 ,否则返回空字符串。

• 示例:

$(findstring a,a b c)
$(findstring a,b c)

第一个函数返回 a 字符串,第二个返回空字符串

证明字符串查找函数没有问题,以前加空格,只是因为后面多加了空格

STRING_I := aabb bb cdrd
FIND := cdrd

$(warning findstring: --$(findstring abb,aabb bb cc)-- )
$(warning findstring: --$(findstring cc,aabb bb cc)-- )
//证明字符串查找函数没有问题
$(warning findstring: --$(findstring ab,aabb bb cdrd)-- )
$(warning findstring: --$(findstring $(FIND),$(STRING_I))-- )
#FIND后面多了个空格,相当于查找的是card ,而不是card,因此找不到为null
$(warning findstring: --$(findstring $(FIND) ,$(STRING_I))-- )

makefile:49: findstring: --abb-- 
makefile:50: findstring: --cc-- 
makefile:51: findstring: --ab-- 
makefile:52: findstring: --cdrd-- 
makefile:53: findstring: ---- 

13.5 filter过滤函数

$(filter <pattern…>, )

• 名称:过滤函数

• 功能:以 模式过滤 字符串中的单词,保留符合模式 的单词。可以有多个模式。

• 返回:返回符合模式 的字串。

返回符合要求*.cpp的字符串

$(warning filter: --$(filter %.cpp,babcdedfb.cpp adbc.cpp xxx)-- )

makefile:52: filter: --babcdedfb.cpp adbc.cpp--
13.6 filter-out 反过滤函数

$(filter-out <pattern…>, )

• 名称:反过滤函数

• 功能:以 模式过滤 字符串中的单词,去除符合模式 的单词。可以有多个模式。

• 返回:返回不符合模式 的字串。

返回和filter相反的字符串

$(warning filter-out: --$(filter-out %.cpp,babcdedfb.cpp adbc.cpp xxx)-- )

makefile:52: filter-out: --xxx--
13.7 sort 排序,去重函数

$(sort )

• 名称:排序函数

• 功能:给字符串 中的单词排序(升序)。

• 返回:返回排序后的字符串。

• 示例:$(sort foo bar lose) 返回 bar foo lose 。 • 备注:sort 函数会去掉 中相同的单词。


13.8 words单词个数统计函数

$(words )

• 名称:单词个数统计函数

• 功能:统计 中字符串中的单词个数。

• 返回:返回 中的单词数。

• 示例: ( w o r d s , f o o b a r b a z ) 返 回 值 是 3 。 • 备 注 : 如 果 我 们 要 取 < t e x t > 中 最 后 的 一 个 单 词 , 我 们 可 以 这 样 : (words, foo bar baz) 返回值是 3 。 • 备注:如果我们要取 <text> 中最后的一个单词,我们可以这样: (words,foobarbaz)3<text>(word $(words ), ) 。

$(warning words: --$(words abc  a  b  cd)-- )

makefile:52: words: --4--
13.9 wordlist取单词串函数

$(wordlist ,, )

• 名称:取单词串函数

• 功能:从字符串 中取从 开始到 的单词串。 和 是一个数字。

• 返回:返回字符串 中从 到 的单词字串。如果 比 中的单词数要大,那么返回空字符串。如果 大于 的单词数,那么返回从 开始,到 结束的单词串。

• 示例:$(wordlist 2, 3, foo bar baz) 返回值是 bar baz 。

2,4必须是数字,列出第2到第4的字符串

$(warning wordlist: --$(wordlist 2,4,abc  a  b  cd)-- )

makefile:52: wordlist: --a  b  cd--
13.10 word取单词函数

**$(word , ) **

• 名称:取单词函数

• 功能:取字符串 中第 个单词。(从一开始)

• 返回:返回字符串 中第 个单词。如果 比 中的单词数要大,那么返回空字符串。

• 示例:$(word 2, foo bar baz) 返回值是 bar 。

13.11 firstword取第一个单词

$(firstword )

• 名称:首单词函数——firstword。 • 功能:取字符串 中的第一个单词。

• 返回:返回字符串 的第一个单词。

• 示例: ( f i r s t w o r d f o o b a r ) 返 回 值 是 f o o 。 • 备 注 : 这 个 函 数 可 以 用 w o r d 函 数 来 实 现 : (firstword foo bar) 返回值是 foo。 • 备注:这个函数可以用 word 函数来实现: (firstwordfoobar)fooword(word 1, ) 。

$(warning firstword: --$(firstword abc  a  b  cd)-- )

makefile:52: firstword: --abc--

14. 文件名操作函数

14.1 dir取目录函数

$(dir <names…>)

• 名称:取目录函数——dir。

• 功能:从文件名序列 中取出目录部分。目录部分是指最后一个反斜杠(/ )之前的部分。如果没有反斜杠,那么返回 ./ 。

• 返回:返回文件名序列 的目录部分。

• 示例:$(dir src/foo.c hacks) 返回值是 src/ ./ 。

$(warning dir: --$(dir vendor/Android.mk  a  b  cd)-- )

makefile:52: dir: --vendor/ ./ ./ ./--
14.2 文件名操作函数

$(notdir <names…>)

• 名称:取文件函数——notdir。

• 功能:从文件名序列 中取出非目录部分。非目录部分是指最後一个反斜杠(/ )之后的部分。

• 返回:返回文件名序列 的非目录部分。

• 示例: $(notdir src/foo.c hacks) 返回值是 foo.c hacks 。

//和dir相反,取/右边的字符串
makefile:52: notdir: --Android.mk a b cd--

$(warning notdir: --$(notdir vendor/Android.mk  a  b  cd)-- )
14.3 suffix取后缀函数

$(suffix <names…>)

• 名称:取後缀函数——suffix。

• 功能:从文件名序列 中取出各个文件名的后缀。

• 返回:返回文件名序列 的后缀序列,如果文件没有后缀,则返回空字串。

• 示例:$(suffix src/foo.c src-1.0/bar.c hacks) 返回值是 .c .c。

//去字符串最后一个点右边的字符串
$(warning suffix: --$(suffix vendor/Android.mk  a  b  cd)-- )

makefile:52: suffix: --.mk--
14.4 basename取前缀函数

$(basename <names…>)

• 名称:取前缀函数——basename。

• 功能:从文件名序列 中取出各个文件名的前缀部分。

• 返回:返回文件名序列 的前缀序列,如果文件没有前缀,则返回空字串。

• 示例:$(basename src/foo.c src-1.0/bar.c hacks) 返回值是 src/foo src-1.0/bar hacks 。

//和suffix取后缀相反,取最后一个.前面的字符串
$(warning basename: --$(basename vendor/Android.mk  a  b  cdc.dd.d)-- )
makefile:52: basename: --vendor/Android a b cdc.dd--
14.5 addsuffix加后缀函数

$(addsuffix ,<names…>)

• 名称:加后缀函数——addsuffix。

• 功能:把后缀 加到 中的每个单词后面。

• 返回:返回加过后缀的文件名序列。

• 示例:$(addsuffix .c,foo bar) 返回值是 foo.c bar.c 。

//注意新得到的字符串最后的空格没有了

$(warning addsuffix: --$(addsuffix _suffix,  a  b  cdc.dd.d  )-- )
$(warning addprefix: --$(addprefix prefix_,  a  b  cdc.dd.d  )-- )

makefile:52: addsuffix: --a_suffix b_suffix cdc.dd.d_suffix-- 
makefile:53: addprefix: --prefix_a prefix_b prefix_cdc.dd.d--
14.6 addprefix加前缀函数

$(addprefix ,<names…>)

• 名称:加前缀函数——addprefix。

• 功能:把前缀 加到 中的每个单词后面。

• 返回:返回加过前缀的文件名序列。

• 示例:$(addprefix src/,foo bar) 返回值是 src/foo src/bar 。

$(warning addsuffix: --$(addsuffix _suffix,  a  b  cdc.dd.d  )-- )
$(warning addprefix: --$(addprefix prefix_,  a  b  cdc.dd.d  )-- )

makefile:52: addsuffix: --a_suffix b_suffix cdc.dd.d_suffix-- 
makefile:53: addprefix: --prefix_a prefix_b prefix_cdc.dd.d--
14.7 join

$(join ,)

• 名称:连接函数——join。

• 功能:把 中的单词对应地加到 的单词后面。如果 的单词个数要比 的多,那么, 中的多出来的单词将保持原样。如果 的单词个数要比 多,那么, 多出来的单词将被复制到 中。

• 返回:返回连接过后的字符串。

• 示例:$(join aaa bbb , 111 222 333) 返回值是 aaa111 bbb222 333 。

把list2里面的字符串依次加到1的后面

$(warning join: --$(join  list1 list2 list3 list4  list5,  a  b  xcb  )-- )
$(warning join: --$(join  list1 list2 ,  a  b  xcb  xxxx)-- )

makefile:52: join: --list1a list2b list3xcb list4 list5-- 
makefile:53: join: --list1a list2b xcb xxxx-- 
14.8 wildcard 查询文件

表示查询,当前目录下的so文件,可以查询多个目录,在android mk中需要使用的路径如LOCAL_PATH
dirnotdir=$(notdir $(wildcard ./*.so) )

使用:SRC = $(wildcard *.c ./foo/*.c) 
搜索当前目录及./foo/下所有以.c结尾的文件,生成一个以空格间隔的文件名列表,并赋值给SRC.当前目录文件只有文件名,子目录下的文件名包含路径信息,比如./foor/bar.c。

15. shell命令

使用$(shell xxx)

16. ifeq条件判断

ifeq ($(origin FOO), undefined)
FOO = bar
endif

17. foreach循环

//命令中途断开,需要使用
表示javalib是传入第一个参数里的对象,循环执行后面的warning语句

$(foreach javalib, $(1), \
    $(warning $(ONE_JARALIB_MOUDLE_NAME)  $(TSP_PREBUILT_MODULE_NAME))

18. call函数

call 函数是唯一一个可以用来创建新的参数化的函数。你可以写一个非常复杂的表达式,这个表达式中,你可以定义许多参数,然后你可以 call 函数来向这个表达式传递参数。其语法是:

$(call <expression>,<parm1>,<parm2>,...,<parmn>)

19. eval

eval表示展开表达式,使用时可以现场调试

$(eval ONE_JARALIB_MOUDLE_NAME := $(javalib)) \

20. log

warning和info用来打印log,error会直接停止

$(warning warning---- )
$(info info---- )
$(error error---- )

makefile:52: warning---- 
info---- 
makefile:54: *** error---- 。 停止。

参照link

跟我一起写Makefile

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值