Android 源代码上手指南 - Makefile语法

JerryXia 发表于 , 阅读 (18)

Android 源代码上手指南 - Makefile语法

上一篇我们将到android build system, 讲了envsetup.sh和lunch, 在继续研究build过程之前有必要先讲讲Makefile的语法. android使用GNUMake 3.81(不支持其他版本!), 因此有许多GNU的特定语法, 和一般的Makefile长得很不一样. (为了叙述方便, 本文中凡是提到Makefile的地方, 均指GNU Makefile.) Makefile的基本语法是这样的:

TARGET: <DEPENDS><TAB>   instructions

运行make TARGET命令时, 根据TARGET对应的DEPENDS来确定依赖关系, 根据修改时间来判断某个TARGET是否需要rebuild.如果需要, 则执行TARGET对应的instructions. 这就是Makefile的基本原理.

.PHONY targets

在Makefile中, 有时会遇到标明为.PHONY的target, 它表示这个target只是一个名字, 不是一个文件. 例如:

clean:		rm *.o temp

这个名为clean的target指示makefile去做一些删除临时文件的指令, 但如果你的目录下刚好有个名为clean的文件, 又因为clean没有任何的dependencies, make会认为clean这个文件是最新的, 不需要执行. 这时我们就要告诉make, clean这个target只是一个名称而已, 并不是一个文件:

.PHONY: clean

multiple targets

当一行写有个多个target时, 相当于把这些target分开写, 并使用一样的commands. 例如:

foo bar:		echo $@    			

等价于:

foo:		echo $@bar:		echo $@

其中$@会被替换为target名称.

GNUMake中, 有一些特定的语法在android中广泛使用, 下面一一介绍一下:

define

Makefile中, 定义一个变量可以用=或者:=.其中=:=的区别在于, =recusively expanded variable, 它在每次被用到的时候都会被求值; 而:=simply expanded variable, 它在定义的时候就被展开. 例如:

x = foo var1 = $(x)var2 := $(x)x = bar target:        echo var1: $(var1)        echo var2: $(var2)

执行make会显示:

echo var1: barvar1: barecho var2: foovar2: foo

除了=:=, 还有一个?=, 它只在变量没有被定义时起作用, 常用于设置默认值.

define 也可以用来定义一个变量, 但define更强的一点在于可以定义多行变量. 例如:

define command@echo foo@echo barendeftarget:			$(command)

输出:

foo bar

其中@放在一个命令前, 表示不输出这一行执行的命令.不过, 在Makefile中有一个call函数, 它可以”调用”一个变量, 因此变量可以用来实现类似于宏展开的功能. 例如:

define concat$1,$2endeftarget:			@echo $(call concat,foo,bar)