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

Android编译详解之lunch命令

Android的优势就在于其开源,手机和平板生产商可以根据自己的硬件进行个性定制自己的手机产品, 如小米,LePhone,M9等,因此,在我们在对Android的源码进行定制的时候,很有必要...
  • zmnqazqaz
  • zmnqazqaz
  • 2014年07月08日 09:54
  • 16220

Android编译详解之lunch命令

Android的优势就在于其开源,手机和平板生产商可以根据自己的硬件进行个性定制自己的手机产品,如小米,LePhone,M9等,因此,在我们在对Android的源码进行定制的时候,很有必要了解下,An...
  • wang92453
  • wang92453
  • 2014年03月24日 15:59
  • 15085

Android编译系统详解(一)——build/envsetup.sh

http://www.cloudchou.com/android/post-134.html 准备好编译环境后,编译Rom的第一步是 source build/envsetup.sh...
  • thinkinwm
  • thinkinwm
  • 2014年05月04日 20:26
  • 4858

android系统源码 锁屏流程

谷歌对Android4.2的版本做了一些改动,突出的改动就是锁屏可以添加widget,即锁屏widget, 这个是谷歌的一个大的改动,先来说说android4.2做了哪些改动?    (1)Lock ...
  • index_jsf
  • index_jsf
  • 2013年09月16日 16:50
  • 1013

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

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

Android系统启动流程源码分析

Android系统启动流程源码分析 首先我们知道,Android是基于Linux的,当Linux内核加载完成时就会自动启动一个init的进程。 又因为我们每当我们启动一个App时,就会生成一个新的...
  • jwc2436
  • jwc2436
  • 2017年11月29日 18:45
  • 604

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

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

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

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

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

原文:http://blog.csdn.net/guoleimail/article/details/8738041  Android在经过几次更新后,在与卡相关的管理出现的重大的改...
  • YinYueRenZhangWenDa
  • YinYueRenZhangWenDa
  • 2016年02月29日 12:33
  • 1992

[Android]Android系统启动流程源码分析

Android系统启动流程源码分析 首先我们知道,Android是基于Linux的,当Linux内核加载完成时就会自动启动一个init的进程。 又因为我们每当我们启动一个App时,就会生成一个新的...
  • bfboys
  • bfboys
  • 2016年09月17日 19:20
  • 100
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android源码阅读与理解(二):Android系统Build流程详解
举报原因:
原因补充:

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