您的位置:首页 > 移动开发 > Android开发

Android.mk--编译Android的模块

2015-09-14 18:01 627 查看
Android中的各种模块,无论是APK应用、可执行程序还是jar包,都可以通过Build系统编译生成。在每一个模块的源码目录下,都有一个Android.mk文件,里面包含了模块代码的位置、模块的名称、需要链接的动态库等一系列的定义。

先看一个比较典型的文件:package/apps/Settings/Android.mk,如下:

#设置当前编译目录(包含此Android.mk的目录)
LOCAL_PATH:= $(call my-dir)
#清除LOCAL_XXX变量,LOCAL_PATH除外
include $(CLEAR_VARS)

#指定依赖的共享java类库
LOCAL_JAVA_LIBRARIES := bouncycastle conscrypt telephony-common ims-common
#指定依赖的静态java类库
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 android-support-v13 jsr305
#定义模块的标签为optional
LOCAL_MODULE_TAGS := optional

#定义源文件列表
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
src/com/android/settings/EventLogTags.logtags

#可选定义,推荐不定义。默认product package和device package相应的res路径和$(LOCAL_PATH)/res。
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res

#指定模块名称
LOCAL_PACKAGE_NAME := Settings
#指定模块签名使用platform签名
LOCAL_CERTIFICATE := platform
#为true表示此apk将安装到priv-app目录下
LOCAL_PRIVILEGED_MODULE := true

#指定混淆的标志
LOCAL_PROGUARD_FLAG_FILES := proguard.flags

#将下面指定的文件包含进来
include frameworks/opt/setupwizard/navigationbar/common.mk

#指定编译模块的类型为APK
include $(BUILD_PACKAGE)

# Use the following include to make our test apk.
ifeq (,$(ONE_SHOT_MAKEFILE))
#将源码目录下其余的Android.mk都包含进来
include $(call all-makefiles-under,$(LOCAL_PATH))
endif
对于一个模块定义文件Android.mk而言,有几行是必须的,其中最开始的两行是固定的写法:

#设置当前编译目录(包含此Android.mk的目录)
LOCAL_PATH:= $(call my-dir)
#清除LOCAL_XXX变量,LOCAL_PATH除外
include $(CLEAR_VARS)
第二行的作用是包含进clear_vars.mk文件,在这个文件里会将除了LOCAL_PATH变量以外,所有“LOCAL_”开头的变量都清除掉。

在Android.mk文件的结尾一般都会有类似“include $(BUILD_PACKAGE)”的语句,这将包含进Build系统的模块编译文件,不同的模块需要包含不同的模块编译文件。

模块编译变量简介

Android.mk文件能编译出不同的模块,是通过包含某个模块编译文件,如上面代码里面的“include $(BUILD_PACKAGE)”实现的。Android的Build系统定义了很多的模块编译变量,说明如下:

模块编译变量详解

模块编译变量说明
BUILD_STATIC_LIBRARY对应的文件是static_library.mk。用来产生目标系统使用的本地静态库。
BUILD_SHARED_LIBRARY对应的文件是shared_library.mk。用来产生编译平台使用的本地共享库。
BUILD_EXECUTABLE对应的文件是executable.mk。用来产生目标系统使用的Linux可执行程序。
BUILD_PACKAGE对应的文件是package.mk。用来产生apk文件。
BUILD_PREBUILT对应的文件是prebuilt.mk。用来定义编译平台下的预编译模块目标。
BUILD_JAVA_LIBRARY对应的文件是java_library.mk。用来产生java共享库。
BUILD_STATIC_JAVA_LIBRARY对应的文件是static_java_library.mk。用来产生java共享库。
单个模块编译文件规模都很小,主要是定义模块的目标和依赖关系。

常用模块定义实例

在不同的模块定义文件中,会使用不同的编译变量。下面我们对几个常见的模块给出一个例子。
1、编译一个APK文件。
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

#指定依赖的共享java类库
LOCAL_JAVA_LIBRARIES :=
# No static java libraries.
LOCAL_STATIC_JAVA_LIBRARIES :=

# All of the source files that we will compile.
LOCAL_SRC_FILES := $(call all-java-files-under, src)

#指定模块标签
LOCAL_MODULE_TAGS := optional
#指定模块的签名方式
LOCAL_CERTITICATE := shared
#指定模块名称
LOCAL_PACKAGE_NAME := testapk
include $(BUILD_PACKAGE)
2、编译一个java共享库
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

# All of the source files that we will compile.
LOCAL_SRC_FILES := $(call all-java-files-under, src)

#指定模块标签
LOCAL_MODULE_TAGS := optional
#指定模块名称
LOCAL_MODULE := javadynamiclib
include $(BUILD_JAVA_LIBRARY)

3、编译一个java静态库
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

# All of the source files that we will compile.
LOCAL_SRC_FILES := $(call all-java-files-under, src)

#指定模块名称
LOCAL_MODULE := testapk
include $(BUILD_STATIC_JAVA_LIBRARY)
4、编译一个native共享库
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

#指定模块标签
LOCAL_MODULE_TAGS := optional
#指定模块名称
LOCAL_MODULE := libnativedynamic

# 指定模块源文件
LOCAL_SRC_FILES := \
nativedynamic.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils

#指定模块依赖的静态库
LOCAL_STATIC_LIBRARIES := libnativestatic
#指定头文件的查询路径
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
$(LOCAL_PATH)/../include
#定义编译标志
LOCAL_CFLAGS += -O
include $(BUILD_JAVA_LIBRARY)
</pre>5、编译一个native静态库</div><div><pre name="code" class="java">LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

#指定模块标签
LOCAL_MODULE_TAGS := optional
#指定模块名称
LOCAL_MODULE := libnativestatic

# 指定模块源文件
LOCAL_SRC_FILES := \
nativedynamic.cpp

#指定头文件的查询路径
LOCAL_C_INCLUDES +=
#定义编译标志
LOCAL_CFLAGS += -O

include $(BUILD_STATIC_LIBRARY)

预编译模块的目标定义

在实际的系统开发中,并不会像Android一样将所有源码集中在一起编译,有很多APK文件,jar包等都是预先编译好的,编译系统时需要将这些二进制文件复制到生成的image文件中。
常用的方法是通过PRODUCT_COPY_FILES变量将这些文件直接复制到生成的image文件中。但是有些APK文件或jar包,需要使用系统的签名文件才能正常运行,这样用复制的方式就行不通了。另外,一些动态库文件可能是源码中某些模块所依赖的,用复制的方法也无法建立依赖关系,这将导致这些模块编译失败。Android可以通过定义预编译模块的方法来解决上面的问题。
定义一个预编译模块和一个普通的编译模块格式相似。不同的是LOCAL_SRC_FILES变量指定的不是源文件,而是二进制文件的路径,同时还要通过LOCAL_MODULE_CLASS来指定模块的类型,最后include的是BUILD_PREBUILD变量定义的编译文件。
下面看下几种常见模块的写法。
1、定义apk文件目标
include $(CLEAR_VARS)

#这里可以是任何字符串,但必须是系统唯一的目标
LOCAL_MODULE := FactoryPattern.apk
LOCAL_SRC_FILES := app/$(LOCAL_MODULE)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := APPS
LOCAL_CERTIFICATE := platform

include $(BUILD_PREBUILT)
2、定义静态jar包目标
include $(CLEAR_VARS)

LOCAL_MODULE := libfirewall.jar
LOCAL_SRC_FILES := app/$(LOCAL_MODULE)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_CERTIFICATE := platform

include $(BUILD_PREBUILT)
3、定义动态库文件目标
include $(CLEAR_VARS)

LOCAL_MODULE := libglobaltheme_jni.so<pre name="code" class="java">LOCAL_MODULE_OWNER :=
LOCAL_SRC_FILES := app/$(LOCAL_MODULE)LOCAL_MODULE_TAGS := optionalLOCAL_MODULE_CLASS := SHARED_LIBRARIESLOCAL_CERTIFICATE := platforminclude $(BUILD_PREBUILT)

4、定义可执行文件目标
include $(CLEAR_VARS)

LOCAL_MODULE := bootanimation
LOCAL_MODULE_OWNER :=
LOCAL_SRC_FILES := bin/bootanimation
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := EXECUTABLES
#还可以指定复制到的目标目录
LOCAL_MODULE_PATH := $(TARGET_OUT)/bin

include $(BUILD_PREBUILT)
5、定义xml文件目标
include $(CLEAR_VARS)

LOCAL_MODULE := apns-conf-cu.xml
LOCAL_MODULE_OWNER :=
LOCAL_SRC_FILES := etc/$(LOCAL_MODULE)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC #ETC表示文件将复制到/system/etc目录下

include $(BUILD_PREBUILT)

常见的“LOCAL_”变量

编写模块的编译文件,实际就是定义一系列以“LOCAL_”开头的编译变量。

编译变量说明

变量名说明
LOCAL_C_INCLUDES指定头文件的搜索路径
LOCAL_MODULE_TAGS定义模块标签,Build系统根据标签决定哪些模块将安装
LOCAL_JAVA_LIBRARIES指定模块依赖的java共享库
LOCAL_PACKAGE_NAME指定APP应用名称
LOCAL_PATH指定Android.mk文件所在的目录
LOCAL_PREBUILT_LIBS指定预编译C/C++动态和静态库列表。用于预编译模块定义中
LOCAL_PREBUILT_JAVA_LIBRARIES指定预编译java库列表。用于预编译模块定义中。
LOCAL_SHARED_LIBRARIES指定模块依赖的C/C++共享库列表
LOCAL_SRC_FILES指定源文件列表
LOCAL_MODULE除应用(apk)以LOCAL_PACKAGE_NAME指定模块名以外,其余的模块名都以LOCAL_MODULE指定
LOCAL_MODULE_PATH指定模块在目标系统的安装路径
LOCAL_BUILT_MODULE指定编译时存放中间文件的目录
LOCAL_MODULE_CLASS定义模块的分类。根据分类,生成的模块文件会安装到目标系统响应的目录下。例如,apps会安装到/system/app下;SHARED_LIBRARIES安装到/system/lib下;EXECUTABLES安装到/system/bin下,ETC安装到/system/etc下。但是如果同时用LOCAL_MODULE_PATH定义了路径,则安装到该路径
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: