我刚开始接触Android系统时,接触了Android的编译命令及Android.mk,因为以前没用过,觉得比较陌生。不过有对Makefile的基本了解的话,还是很好理解的。

1、Android编译命令

- m:       Makes from the top of the tree.
- mm:      Builds all of the modules in the current directory, but not their dependencies.
- mmm:     Builds all of the modules in the supplied directories, but not their dependencies.
- mma:     Builds all of the modules in the current directory, and their dependencies.
- mmma:    Builds all of the modules in the supplied directories, and their dependencies.

 

2、Android.mk例子来分析

 说明下每一句的作用

 

LOCAL_PATH := $(call my-dir)				//指定路径当前文件夹

include $(CLEAR_VARS)					//清除原本设定的变量,就是LOCAL_XXX, 除了LOCAL_PATH

LOCAL_SRC_FILES:=       \				//指定要编译的source文件
    jni/XXXUtils.cpp \
    jni/XXXService.cpp \

LOCAL_SHARED_LIBRARIES := \			//指定需要连接的动态库,即.so文件
	libutils \
	libbinder \
	libandroid_runtime \
	libcutils \
	libmedia \
	libmediaplayerservice \
	

LOCAL_C_INCLUDES :=  \				//头文件目录,这里指的是JNI的头文件和源码framework下指定的include目录
	$(JNI_H_INCLUDE) \
	$(TOP)\frameworks\av\include \

LOCAL_MODULE_TAGS := optional			//指明该模块在所有的版本都编译(user版本,eng版本,test版本)
LOCAL_PROGUARD_ENABLED := disabled	//这是代码混淆标识,disable就是不需要混淆
LOCAL_PRELINK_MODULE := false			//这个是动态库需要预先加载与否的标识,系统默认是需要的
LOCAL_MODULE:= libXXXUtils			//编译的库的名字
ALL_DEFAULT_INSTALLED_MODULES += $(LOCAL_MODULE)	//就是说把这个模块打包到系统镜像中

include $(BUILD_SHARED_LIBRARY)		//模块编译为动态库,即libXXXUtils.so

include $(CLEAR_VARS)					//上面已经说了作用,看到这个标识,就知道到此结束一个模块,开始新的一个模块了

LOCAL_MODULE_TAGS := optional			//已经说了

LOCAL_STATIC_JAVA_LIBRARIES := android-common commons-codec-1.6  android-support-v4 commons-logging-1.1.3 fluent-hc-4.3.3 httpclient-4.3.3 httpclient-cache-4.3.3 httpcore-4.3.2 httpmime-4.3.3					//使用到的java静态库,就是jar包
LOCAL_JAVA_LIBRARIES := XXX			//也是说要用到这个jar
LOCAL_SRC_FILES := \					//已经说了,然后这里使用(call 	all-subdir-java-files)获取所有子文件夹下的java文件
         $(call all-subdir-java-files) \
		 src/com/XXX/aidl/ICallBack.aidl \
		 src/com/XXX/aidl/XXX.aidl \

LOCAL_PACKAGE_NAME := XXX	//生成的package的名字,也就是APK名字

#LOCAL_CERTIFICATE := shared			//使用的签名,这里是share
LOCAL_CERTIFICATE := platform			//使用系统的签名

LOCAL_OVERRIDES_PACKAGES := Home		//改标志是说Home.apk不变编译到系统中
LOCAL_PROGUARD_ENABLED := obfuscation	//使混淆
LOCAL_PROGUARD_FLAG_FILES := proguard.cfg	//指定混淆的机制文件

include $(BUILD_PACKAGE)				//模块编译为XXX.apk

include $(CLEAR_VARS) 					//上面已经说了
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \	//指定上面使用的第三方就jar包的路径
	commons-codec-1.6:libs/commons-codec-1.6.jar \
	commons-logging-1.1.3:libs/commons-logging-1.1.3.jar \
	fluent-hc-4.3.3:libs/fluent-hc-4.3.3.jar \
	httpclient-4.3.3:libs/httpclient-4.3.3.jar \
	httpclient-cache-4.3.3:libs/httpclient-cache-4.3.3.jar \
	httpcore-4.3.2:libs/httpcore-4.3.2.jar \
	httpmime-4.3.3:libs/httpmime-4.3.3.jar 

include $(BUILD_MULTI_PREBUILT) 			//引入第三方so和jar需要用此编译

 

 

3、Android.mk语法:

 

 

从上面的例子也可以看出来,其实这个Android.mk就是由两种东西组成:变量+宏

 

变量:像LOCAL_PATH这种被称为变量,这些是Android编译系统中已经赋值的变量,我们自己也可以定一些变量,通常来说,变量名字都是大写。

变量用于向编译系统描述你的模块。应该定义在'include $(CLEAR_VARS)'和'include $(BUILD_XXXXX)'之间定义。

1、正如上述例子,$(CLEAR_VARS)是一个脚本,清除所有这些变量。

2、include $(BUILD_SHARED_LIBRARY)

$(BUILD_SHARED_LIBRARY)也是一个脚本(应该就是在build/core目录下的shared_library.mk),负责收集自从上次调用'include $(CLEAR_VARS)'以来,定义在LOCAL_XXX变量中的所有信息,并且决定编译什么,如何正确地去做。并根据其规则生成静态库。同理对于其他的BUILD_XXXXX。

 

基本的变量的功能,在前面已经说了,基本上我用到的也就这些。

 

宏:像my-dir这种被称为宏,下面是一些宏,必须通过使用'$(call <function>)'来求值,他们返回文本化的信息。

1、my-dir

返回当前Android.mk所在的目录路径,在Android.mk文件的开头一般如此定义:

LOCAL_PATH := $(call my-dir)

 

2、all-subdir-makefiles

返回一个位于当前'my-dir'路径的子目录列表。例如,看下面的目录层次:

sources/foo/Android.mk

sources/foo/lib1/Android.mk

sources/foo/lib2/Android.mk

如果sources/foo/Android.mk包含一行:

include $(call all-subdir-makefiles)

那么它就会自动包含sources/foo/lib1/Android.mk 和sources/foo/lib2/Android.mk

这项功能用于向编译系统提供深层次嵌套的代码目录层次。在默认情况下,只搜索在sources/*/Android.mk。

3、this-makefile

返回当前Makefile的路径(即这个宏的地方)

4、parent-makefile 

返回调用树中父Makefile路径。