Android 进阶——源码编译之产品配置和常用的Make脚本模板

Posted CrazyMo_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 进阶——源码编译之产品配置和常用的Make脚本模板相关的知识,希望对你有一定的参考价值。

文章大纲

引言

前面文章总结了MakeFile基础语法和对android.mk的进行了解读,这篇文章将从整体上概述下AOSP 编译时的产品配置相关知识。Android 的产品配置文件的作用是按照Build系统的要求,将生成产品的各种image文件所需要的对应信息(如版本号等各种参数)、资源(图片、字体、多媒体等)、二进制文件(apk、jar、so库等)有机组织起来,同时根据配置文件进行裁剪或增加模块,所谓系统支持在一定程度上其实就像将相应的资源添加到对应的文件中。

比如PRODUCT_APPT_CONFIG :=normal hdpi xhdpi xxhdpi xxxhdpi指定了系统中能够支持的屏幕密度类型(dip),在编译时就将相应的资源添加到framework_res.apk之中。

一、编译类型eng、user和userdebug

1、eng

默认的编译类型,该编译类型适用于开发阶段,执行makemake eng,编译时以下模块将安装进系统:

  • 在Android.mk里使用LOCAL_MODULE_TAGS变量定义了标签为 eng、debug、shell_$(TARGET_SHELL)、user和development的模块
  • 非APK模块且不带任何标签的模块
  • 所有产品配置文件中指定的APK模块

编译后adb是默认开启的,附带以下系统属性:

  • ro.secure=0
  • ro.debuggable=1
  • ro.kernel.android.checkjni=1

2、user

该编译类型适合用于最终发布阶段,编译时以下模块将安装进系统:

  • 在Android.mk里使用LOCAL_MODULE_TAGS变量定义了标签为 shell_$(TARGET_SHELL)和user的模块
  • 非APK模块且不带任何标签的模块
  • 所有产品配置文件中指定的APK模块,同时忽略其标签属性

编译后adb是默认不开启,需要自己手动打开,附带以下系统属性:

  • ro.secure=0
  • ro.debuggable=0

3、userdebug

该编译类型适合用于 debug 阶段,编译时以下模块将安装进系统:

  • 在Android.mk里使用LOCAL_MODULE_TAGS变量定义了标签为 `shell_$(TARGET_SHELL)、user和debug
  • 非APK不带任何标签的模块
  • 非APK模块且不带任何标签的模块
  • 所有产品配置文件中指定的APK模块,同时忽略其标签属性

编译后具有root权限,adb是默认不开启,需要自己手动打开,附带以下系统属性:

  • ro.secure=0
  • ro.debuggable=1

系统属性的前缀含义

前缀说明
ro.read only 只读属性,意境设置不可改变
persist.persistent 设置的值即使关机重启后依然生效,因为设置这个前缀的属性时会同时写入到/data/property下与属性同名的文件中,再次开机时会被init进程读出来使用
net.设置这个前缀的属性时将会被自动设置为最后修改的属性名
ctl.ctl.start、ctl.stop、ctl.restart 控制类属性,同于控制服务启动或者停止。

二、产物里的Image 文件

AOSP 编译成功后会默认生成几个Image 镜像文件:boot.img、system.img、recovery.img和userdata.img。

1、boot.img

boot.img一种Android 自定义的文件格(包含adbd和init.rc文件),包括了一个2*1024字节的文件头,接着是用gzip压缩过的linux kernel镜像,紧接着是一个ramdisk镜像,最后是BootLoader程序。

2、recovery.img

recovery.img 相当于是一个微型的文本界面Linux 系统,其作用就是恢复或升级系统,通常在sbin目录下会有一个recovery可执行程序,recovery也包含了adbd和init.rc文件,但与boot.img的不一样。

3、system.img

system.img就是设备系统目录system下的镜像,包含了Android主要的目录和文件。

目录名说明
app存放普通apk
bin存放Linux的一些工具,大部分是toolbox的链接
etc存放系统配置文件
fonts存放系统字体文件
framework存放系统所有的jar、art、oat包和资源文件包
lib存放系统的共享库so
media存放系统多媒体资源,主要是铃声
priv-app存放系统核心APK文件
tts存放系统语音合成文件
usr存放各种键盘布局、时间区域文件
vendor存放第三方厂商的配置文件、firmware及动态库
xbin存放系统管理工具,相当于是Linux下的sbin
build.prop文件系统属性的定义文件

4、userdata.img

userdata.img 是设备中data目录的镜像,初始化时一般不包含任何文件,是由Android系统初始化时在/data目录下创建一些子目录和文件的。

三、模块编译变量

Android.mk文件可以编译出不同的模块,本质上是通过include $(BUILD_) 指令把其他模块编译文件包含进来,常见的模块编译变量(以BUILD_为前缀)有:

编译变量说明
BUILD_HOST_STATIC_LIBRARY包含host_static_library.mk文件,生成编译平台的本地静态库
BUILD_HOST_SHARED_LIBRARY包含host_shared_library.mk文件,生成编译平台的本地共享库
BUILD_STATIC_LIBRARY包含static_library.mk文件,生成目标系统的本地静态库
BUILD_SHARED_LIBRARY包含shared_library.mk文件,生成目标系统的本地共享库
BUILD_HOST_EXECUTABLE包含host_executable.mk文件,生成编译平台的Linux可执行程序
BUILD_EXECUTABLE包含executable.mk文件,生成目标系统的Linux可执行程序
BUILD_PACKAGE包含package.mk文件,生成apk
BUILD_HOST_PREBUILT包含host_prebuilt.mk文件,生成编译平台的预编译模块
BUILD_PREBUILT包含prebuilt.mk文件,生成目标系统的预编译模块并将这个预编译模块引入系统
BUILD_MULTI_PREBUILT包含multi_prebuilt.mk文件,生成目标系统的多个预编译模块并将这些预编译模块引入系统
BUILD_JAVA_LIBRARY包含java_library.mk文件,生成Java 共享库
BUILD_STATIC_JAVA_LIBRARY包含java_static_library.mk文件,生成Java 静态库

动态链接库显示调用的方法:

  • Java层,使用System.loadLibrary(String libName)和System.load(String pathName),前者只需要支出动态链接库的名称,系统负责在预先设置的路径中去查找并加载正确的so库;后者允许将动态链接库存储到任何程序有权限访问的地方,由pathName给出完整的加载路径。这两个函数的实现主题在libjavacore.so库中,这个库是Runtime在启动过程中通过LoadNativeLibrary来加载的。

  • Native层,使用dlopen,dlsym等Linux标准的动态链接库接口。

四、常用模块的Makefile脚本模板

在不同的模块定义文件中个,使用个不同的编译变量。

1、编译一个APK

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_JAVA_LIBRARIES := #依赖的Java 共享库
LOCAL_SHARED_JAVA_LIBRARIES := #依赖的Java 静态库
# 使用系统函数自动搜索src 目录下的java文件形成的源码列表
LOCAL_SRC_FILES:= $(call all-java-files-under, src)

#LOCAL_C_INCLUDES :=
#LOCAL_STATIC_LIBRARIES :=
#LOCAL_SHARED_LIBRARIES :=
LOACAL_MODULE_TAGS:= #可选的模块标签
LOCAL_CERTIFICATE:= #APK 签名方式
LOCAL_PACKAGE_NAME:= #apk名称

include $(BUILD_PACKAGE)

2、编译一个Java 共享库和静态库

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_JAVA_LIBRARIES := #依赖的Java 共享库
LOCAL_SHARED_JAVA_LIBRARIES := #依赖的Java 静态库
# 使用系统函数自动搜索src 目录下的java文件形成的源码列表
LOCAL_SRC_FILES:= $(call all-java-files-under, src)

LOACAL_MODULE_TAGS:= #可选的模块标签
LOCAL_MODULE:= #java库名称

include $(BUILD_JAVA_LIBRARY) #编译共享库
# include $(BUILD_STATIC_JAVA_LIBRARY) 编译静态库

3、编译一个Native 共享库和静态库

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)


LOCAL_SRC_FILES:=helloworld.c #c源文件

LOCAL_MODULE:= libtest_static #库名称

LOCAL_C_INCLUDES := # 编译标志
LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES :=

include $(BUILD_SHARED_LIBRARY)
# include $(BUILD_STATIC_LIBRARY) 编译静态库

五、预编译模块

在实际系统开发中,并不会向Android一样将所有的源码一起编译,事实上有很多的APK、jar包都是需要预先编译好的,编译时通过PRODUCT_COPY_FILES 变量将这些二进制文件复制到生成的image文件中。但是针对一些APK或者jar包需要使用系统签名才能正常运行或者系统所需的依赖动态库文件,这种简单复制方式就不行了。于是Android 定义预编译模块来解决之,定义一个预编译模块和定义上面那种普通模块语法相似,区别在于预编译模块的LOCAL_SRC_FILES变量配置的是二进制文件的路径且需要配合LOCAL_MODULE_CLASS来设置模块类型,最后再通过include $(BUILD_PREBUILT)

1、定义一个预编译APK

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

# Module name should match apk name to be installed 系统唯一的名称
LOCAL_MODULE := LamyNetServer
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS #类别是APK
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := platform # 使用系统的platform级别签名
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_DEX_PREOPT := false
LOCAL_PRIVILEGED_MODULE := true

include $(BUILD_PREBUILT)

2、定义一个预编译的静态jar

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := xxxxx
LOCAL_SRC_FILES :=app/$(LOCAL_MODULE)
LOCAL_MODULE_CLASS := JAVA_LIBRARIES #类别是Java静态jar包
LOCAL_CERTIFICATE := platform # 使用系统的platform级别签名

include $(BUILD_PREBUILT)

3、定义一个预编译的动态库so

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := xxxxx
LOCAL_SRC_FILES :=app/$(LOCAL_MODULE)
LOCAL_MODULE_CLASS := SHARED_LIBRARIES  #类别是SHARED_LIBRARIES 

include $(BUILD_PREBUILT)

4、定义一个预编译的可执行文件

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := xxxxx
LOCAL_SRC_FILES :=
LOCAL_MODULE_CLASS := EXECUTABLES  #类别是EXECUTABLES

include $(BUILD_PREBUILT)

以上是关于Android 进阶——源码编译之产品配置和常用的Make脚本模板的主要内容,如果未能解决你的问题,请参考以下文章

Android 进阶——源码编译之产品配置和常用的Make脚本模板

Android 进阶——源码编译之产品配置和常用的Make脚本模板

iOS开发-Swift进阶之源码编译

iOS开发-Swift进阶之源码编译!

Android 进阶——Framework 核心之dumpsys命令浅析

Android 进阶——Framework 核心之dumpsys命令浅析