我刚开始接触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路径。