Android.mk--编译Android的模块
2015-09-14 18:01
627 查看
Android中的各种模块,无论是APK应用、可执行程序还是jar包,都可以通过Build系统编译生成。在每一个模块的源码目录下,都有一个Android.mk文件,里面包含了模块代码的位置、模块的名称、需要链接的动态库等一系列的定义。
先看一个比较典型的文件:package/apps/Settings/Android.mk,如下:
在Android.mk文件的结尾一般都会有类似“include $(BUILD_PACKAGE)”的语句,这将包含进Build系统的模块编译文件,不同的模块需要包含不同的模块编译文件。
模块编译变量详解
单个模块编译文件规模都很小,主要是定义模块的目标和依赖关系。
1、编译一个APK文件。
3、编译一个java静态库
常用的方法是通过PRODUCT_COPY_FILES变量将这些文件直接复制到生成的image文件中。但是有些APK文件或jar包,需要使用系统的签名文件才能正常运行,这样用复制的方式就行不通了。另外,一些动态库文件可能是源码中某些模块所依赖的,用复制的方法也无法建立依赖关系,这将导致这些模块编译失败。Android可以通过定义预编译模块的方法来解决上面的问题。
定义一个预编译模块和一个普通的编译模块格式相似。不同的是LOCAL_SRC_FILES变量指定的不是源文件,而是二进制文件的路径,同时还要通过LOCAL_MODULE_CLASS来指定模块的类型,最后include的是BUILD_PREBUILD变量定义的编译文件。
下面看下几种常见模块的写法。
1、定义apk文件目标
4、定义可执行文件目标
编译变量说明
先看一个比较典型的文件: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定义了路径,则安装到该路径 |
相关文章推荐
- Android使用fragment底部菜单栏
- Android:使用AsyncTask实现天气预报功能
- com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process
- (转)android 如何获取手机信息总结
- 阅读《Android 从入门到精通》(7)——图片按钮
- android调试各种bug
- 利用Android的UncaughtExceptionHandler捕获崩溃异常
- Android Studio 加载so文件
- Android中Socket通信,模拟了一个简单的CS聊天室
- 开发者必备的十八大Android开发资源
- Android EditText与第三方输入法删除键(退格键)冲突问题解决方案
- Android 使用动态加载框架DL进行插件化开发
- Android studio如何使用SVN进行版本控制?
- Android 开源项目PhotoView源码分析
- Android 安装apk代码
- Android.mk集成第三方jar与so的方法
- android SlidingUpPanel (一)
- android tools使用方式
- Android之SD卡文件浏览器实现
- Android 实现简单的帧动画