Android源码阅读与理解(二):Android系统Build流程详解

原创 2015年11月17日 22:29:53

个人认为,成为一个靠谱的Android系统工程师,必须具备以下技能:

  • 翻墙
  • 会使用Linux系统
  • 阅读英文资料

翻墙技能就不用说了,因为不翻墙,Android源码难以获取,更不用谈体验墙外精彩的世界了。关于第二点,最好的Android系统开发环境就是Linux(推荐ubuntu),如果能够熟练使用Linux系统可以节省不少折腾环境的时间。最后英文阅读能力也很关键,因为碰到问题Google, StackOverflow非常有用,上面的回答有不少是用英文写的。

在这里略过下载Android源码,最好的方法是参考官方文档。简单说一下我的环境:

  • Ubuntu 14.04 LTS 64位
  • Android 5.1.1源码
  • Sublime Text 2
  • Intel(R) Core(TM) i7-2630QM CPU @ 2.00GHz, 8G RAM, 1TB hd

配备一台Nexus 4/5也是极好的,这个上淘宝,几百元就能搞定,可以省下不少时间(用模拟器也可以,但是比较慢,对主机要求也比较高)。Nexus系列作为google的亲儿子,通常都会得到最新的更新,最适合折腾系统了。

源码下载后,执行如下命令即可编译Android系统(后面的文章将使用$ANDROID_SRC指代Android源码所在目录,如非特别指明,假设命令行在Android源码目录下执行):

  1. source build/envsetup.sh
  2. lunch
  3. make -j4

下面就解析以上三个步骤分别做了什么事情。

设置环境变量

打开$ANDROID_SRC/build/envsetup.sh文件,我们可以看到文件中定义了一些shell函数,其作用是初始化编译环境,并引入一些辅助的Shell函数,这其中就包括第二步使用lunch函数。这些shell函数可以看做shell命令,方便我们进行一些build任务,比如常用的mm。下面就列出一些常用的函数:

表 1. build/envsetup.sh 中定义的常用函数


名称 说明
lunch 选择产品,格式为lunch BUILDID-BUILDTYPE,如果不指定,会弹出一个列表选择
tapas build未打包到image的app,命令行后可以跟一个或者多个app的名称。用法为: tapas [ …] [arm
croot 切换到源码树的根目录
m 在源码树的根目录执行 make
mm Build 当前目录下的模块
mmm Build 指定目录下的模块
mma Build 当前目录下的模块及所有依赖的模块
mmma Build 指定目录下的模块及所有依赖的模块
cgrep 在所有 C/C++ 文件上执行 grep
ggrep 在所有 Gradle 文件上执行 grep
jgrep 在所有 Java 文件上执行 grep
resgrep 在所有 res/*.xml 文件上执行 grep
sgrep 在所有源码上执行grep
godir 转到包含某个文件的目录路径
printconfig 显示当前 Build 的配置信息
add_lunch_combo 在 lunch 函数的菜单中添加一个条目

除了定义辅助Shell函数,在脚本的结尾处,还会遍历device和vendor目录下的vendorsetup.sh文件,vendorsetup.sh文件定义与设备相关的环境变量,比如/device/lge/hammerhead/vendorsetup.sh就定义了如下:

add_lunch_combo aosp_hammerhead-userdebug

这会在lunch菜单中增加一个选项:aosp_hammerhead-userdebug

lunch函数详解

Android支持不同的硬件,比如不同的CPU架构(ARM、MIPS,X86),不同厂商的外设(如蓝牙、wifi、基带等),另外可能还需要分Debug版本和Release版本,这都是在lunch中进行选择的。lunch命令的格式为lunch BUILDID-BUILDTYPE,其中BUILDTYPE取值如下:

表 2. BUILDTYPE说明


BUILDTYPE 说明
user 相当于Release版本,无root权限,不打包调试工具,适合最后的产品发布
userdebug 和user类似,但多了root权限,可以调试,适合于产品调试
eng 开发阶段的配置,另外还打包了许多调试工具,适合于产品初期阶段

BUILDID则是一组特性集合的代码,这个通常与具体的平台相关。除了Android源码预置的选项外,还可以通过add_lunch_combo命令添加自定义的组合。当我们要开发一款新的Android产品时,首先就需要在Build系统中添加对于该产品的定义。

产品定义文件通常位于device目录下,vendor目录已经不建议使用(nexus系列的产品定义就是放在vendor目录)。device目录下通常根据公司名及产品名分为二级目录,比如lge的目录结构如下:

 device
   |-- lge
         |-- hammerhead
         |-- hammerhead-kernel
         |-- mako
         |-- mako-kernel

其中mako和hammerhead分别为nexus4和nexus5的产品代号。通常一个产品定义至少包含4个文件:AndroidProducts.mk, BoardConfig.mk, vendorsetup.sh及版本定义文件(文件名不固定)。关于如何添加产品定义,请参考<<理解 Android Build 系统>>一文的添加新的产品一节。

build Android系统

最后一步执行make -j4才开始真正的进行编译操作,j后面的数字代表同时编译的job数,这个数字可根据CPU核心线程数而定,通常可指定为CPU核心线程的1~2倍,数字越大,代表同时进行编译的任务越多,整个编译过程也会越快,但需要注意过犹不及。如果不指定目标,默认就会使用“droid”目标,build出完整的Android系统镜像。

Android build系统使用了GNU make,这点很让人意外,因为GNU Makefile实在太难编写了,也不易阅读。不过Google的天才工程师进行了模块化、写了很多实用函数,修改/添加起来还算容易。

Build输出目录结构

所有的编译产物都将位于 out 目录下,该目录下主要有以下几个子目录:

  • out/host/:该目录下包含了host端的工具和库,例如:emulator,adb,aapt等。
  • out/target/common/:该目录下包含了针对设备的共用的编译产物,主要是 Java 应用代码和 Java 库。
  • out/target/product/product_name/:包含了针对特定设备的编译结果以及平台相关的 C/C++ 库和二进制文件。其中,product_name是具体目标设备的名称。

Build生成的镜像文件

Build 的产物中最重要的是三个镜像文件,它们都位于 out/target/product/product_name/ 目录下。这三个文件是:

  • system.img:包含了 Android OS 的系统文件,库,可执行文件以及预置的应用程序,将被挂载为根分区。
  • ramdisk.img:在启动时将被 Linux 内核挂载为只读分区,它包含了 /init 文件和一些配置文件。它用来挂载其他系统镜像并启动 init 进程。
  • userdata.img:将被挂载为 /data,包含了应用程序相关的数据以及和用户相关的数据。

另外还有cache.img,启动模拟器时可使用-cache参数来挂载该文件,指定/cache内容。一般来说我们不直接使用userdata.img,而是使用userdata_qemu.data,用来存放用户数据,可读写,android启动后mount到 /data。只有使用-wipe-data参数启动模拟器是时候才会用到userdata.img,它会使用userdata.img的内容覆盖userdata-qemu.img。

参考文档

  1. Android官方文档
  2. 理解 Android Build 系统
  3. Android编译系统详解(一)——build/envsetup.sh
  4. Android模拟器镜像文件介绍
版权声明:本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接http://blog.csdn.net/mogoweb

相关文章推荐

Android7.0 编译系统流程分析

本文按照Android编译三部曲(source,lunch和make)的步骤来分析查看每个环节的主要流程,由于编译系统太过庞大,这里只是从关键的主干流程上做一个分析,不可能做到每个细节都剖析清楚,由于...

android Apk打包过程概述_android是如何打包apk的

最近看了老罗关于android应用资源编译和打包过程的分析,过程比较复杂,这里结合其他资料,简要描述下打包过程,从整体上了解这个流程,感兴趣的再去详细研究过程。流程概述:1、打包资源文件,生成R.ja...

Android系统的启动流程分析及如何看源码

Android系统的启动流程分析最近在听到很多面试官问Android工程师的关于启动的问题,我最近研究了一番,大概理了一理,过程如下,文章末尾有看源码攻略。 ##当用户按下物理按键对Android...

结合源码探讨Android系统的启动流程

结合源码探讨Android系统的启动流程 由于本人能力有限,所考虑或者疏忽错漏的地方或多或少应该存在。同时,Android从启动过程开始,实际上就涉及多个技术难点和多种通信机...

【源码分析】Android系统启动流程.

Android的启动过程是从init开始的,它是所有后续进程的祖进程。系统启动的过程可以大致分为以下几个步骤1,init.c的启动 挂载目录 初始化 解析配置文件 2,init.rc 3,在i...

Android系统源码学习-SIM卡(三) Android 4.2中与SIM/USIM 管理流程

原文:http://blog.csdn.net/guoleimail/article/details/8738041  Android在经过几次更新后,在与卡相关的管理出现的重大的改...

Android系统源码阅读(14):Zygote和System进程的启动

Android系统源码阅读(14):Zygote和System进程的启动 再不学习我们就老了 0. Zygote有什么卵用?Zygote是进程孵化器,Android系统中其他服务进程都是拷贝于它。...

查看Android系统的源码 在线和离线方式 及阅读工具

前言     不管是做Android底层(Framework-Linux-驱动)开发,还是做APP开发,对于Android的某一个功能,某一个机制,或者某一个API,它到底是如何实现的,需要 R...

Android系统源码阅读(12):InputChannel的注册过程

Android系统源码阅读(12):InputChannel的注册过程 请对照AOSP版本:6.0.1_r50。 InputManager可以获得输入事件并分发,Activity需要处理这些输入...

Android系统源码阅读(6):广播机制

Android系统源码阅读(6):广播机制 该系列只记录阅读代码时遇到的问题和心得体会,具体代码讲解可以参考老罗的《Android系统源代码情景分析》,我就不班门弄斧了。我编译的AOSP版本:6....
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android源码阅读与理解(二):Android系统Build流程详解
举报原因:
原因补充:

(最多只允许输入30个字)