写点什么

一个视频带你编译自己的 Android 系统!

用户头像
刘望舒
关注
发布于: 2021 年 03 月 28 日
一个视频带你编译自己的Android系统!

本文首发于微信公众号「刘望舒」


这是 BATcoder 的第五篇,BATcoder 是 Android 进阶三部曲的番外篇,会对 Android 进阶三部曲的内容进行拓展和升级,会以视频的形式分享给大家。至于为啥叫 BATcoder,这是因为我希望大家看了我的技术视频能进入自己中意的大厂。


视频版本

更多细节和内容见视频:


B 站地址: https://www.bilibili.com/video/BV1VU4y1s7xF


独立博客地址: http://liuwangshu.cn/batcoder/aosp/3-compiling-aosp.html


前言

我们顺利的将 AOSP 下载了下来后,很多时候我们不仅仅需要去查看源码,还有以下的几个需求:


  • 1.定制 Android 系统

  • 2.将最新版本的 Android 系统刷入到自己的 Android 设备中

  • 3.将整个系统源码导入到 Android Studio 中

  • 4.动态调试 Android 系统源码

为了实现这些需求,就需要我们去编译系统源码。其中第三条和第四条也可以不用编译源码来实现,第三条只要有对应 Android 源码版本的 android.iml 和 android.ipr 两个文件就可以将源码导入到 Android Studio 中,第四条动态调试系统源码不一定非要导入整个系统源码进行调试。关于第三条和第四条的具体内容,我会在以后的内容中进行讲解。


1.编译系统概述

了解以下一些概念,会对 Android 编译系统有大概的了解。


Makefile


Android 平台的编译系统,其实就是用 Makefile 写出来的一个独立项目。它定义了编译的规则,实现了“自动化编译”,不仅把分散在数百个 Git 库中的代码整合起来、统一编译, 而且还把产物分门别类地输出到一个目录,打包成手机 ROM,还可以生成应用开发时所使用的 SDK、NDK 等。 因此,采用 Makefile 编写的编译系统,也可以称为 Makefile 编译系统。


Android.mk Makefile 编译系统的一部分,Android.mk 是 android 编译环境下的一种特殊的“makefile”文件, 它是经过了 android 编译系统处理的。Android.mk 中定义了一个模块的必要参数,使模块随着平台编译。通俗来讲就是告诉编译系统,以什么样的规则编译你的源代码,并生成对应的目标文件。


Ninja


Ninja 是一个致力于速度的小型编译系统,如果把其他的编译系统看作高级语言,那么 Ninja 目标就是汇编。使用 Ninja 主要目的就是因为其编译速度快。


Soong


Soong 是谷歌用来替代此前的 Makefile 编译系统的替代品,负责解析 Android.bp 文件,并将之转换为 Ninja 文件


Blueprint


Blueprint 用来解析 Android.bp 文件翻译成 Ninja 语法文件。


kati


kati 是谷歌专门为了 Android 而开发的一个小项目,基于 Golang 和 C++。 目的是把 Android 中的 Makefile,转换成 Ninja 文件。


Android.bp


Android.bp,是用来替换 Android.mk 的配置文件。


Android.mk、Ninja、Soong、Blueprint、kati、Android.bp 的概念之间的联系为:



Blueprint 负责解析 Android.bp 文件内容,Blueprint 类似一个处理相关语法的库文件,Soong 则是定义具体如何处理相应的语法以及命令实现。通俗来讲就是 Soong 借助于 Blueprint 定义的 Android.bp 语法,完成 Android.bp 的解析,最终转换成 Ninja 文件。 Makefile 文件会通过 kati 转换为 Ninja 文件。 随着 Android 工程越来越大,采用 Makefile 的编译系统花费的时间也越来越长,因此谷歌在 Android 7.0 开始引入了 Ninja 来编译系统,相对于 Makefile 来说 Ninja 在大的项目管理中速度和并行方面有突出的优势。 Makefile 默认文件名为 Makefile 或 makefile,也常用.make 或.mk 作为文件后缀。 Ninja 的默认文件名是 build.ninja,其它文件以.ninja 为后缀。Makefile 与 Ninja 的区别在于, Makefile 是设计来给开发编写的,而 Ninja 设计出来是给其它程序生成的。如果 Makefile 是 Java 语言,那么 Ninja 就是汇编语言。


2.编译源码的方式

Androd 系统源码编译有很多种方式,主要有以下几种:


  • 在 Linux 中直接进行系统源码编译(Android 官方支持)

  • 在 Mac OS 中直接进行系统源码编译(Android 官方支持)

  • 使用Docker编译,支持 Mac OS 和 Windows

其中需要注意的是,Docker 的最低支持版本为 Windows7,建议用 Windows10 环境下使用 Docker,因为在 Windows7 中还需要借助 Docker Toolbox 和 VirtualBox 中的容器进行通信,效率相对低些。 考虑到大多数人的设备和上手难易程度,本为讲解在 Linux 中直接进行系统源码编译。


3.准备编译环境

1.设置处理器数量


在没有运行 Ubuntu 的时候,在 VirtualBox 里选择设置-->系统-->处理器选项,设置处理器数量,建议设置比较大一些,这里设置的是 6。 如果不能够设置,请检查是否开启虚拟化技术。不同的电脑开启的方式也不同,比如我此前惠普暗影精灵 4 的台式机,在开机时连续按 F10 就会进入 BIOS,在安全->系统安全性->虚拟化技术选项设置启用即可。 现在的暗影精灵 6 台式机,则是在 BIOS 的配置选项里开启虚拟化技术选项。


2.安装 jdk8


sudo apt-get updatesudo apt-get install openjdk-8-jdk
复制代码

3.使用 ubuntu 14+,需要安装以下依赖包:


sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip
复制代码

4.源码整编

整编就是编译整个 Android 源码,整编主要有三个步骤,下面分别就行介绍。


1.初始化环境


在 AOSP 的根目录,输入如下的命令:


source build/envsetup.shmake clobber
复制代码

使用 build 目录中的 envsetup.sh 脚本初始化环境,这个脚本会引入其他的执行脚本。make clobber 用于清除缓存。


2. 选择编译目标


输入命令:


lunch
复制代码

lunch 命令是 envsetup.sh 里定义的一个命令,用来让用户选择编译目标。 会有以下信息输出:


You're building on Linux
Lunch menu... pick a combo: 1. aosp_arm-eng 2. aosp_arm64-eng 3. aosp_mips-eng 4. aosp_mips64-eng 5. aosp_x86-eng 6. aosp_x86_64-eng 7. aosp_car_arm-userdebug 8. aosp_car_arm64-userdebug 9. aosp_car_x86-userdebug 10. aosp_car_x86_64-userdebug 11. mini_emulator_arm64-userdebug 12. m_e_arm-userdebug 13. m_e_mips64-eng 14. m_e_mips-userdebug 15. mini_emulator_x86_64-userdebug 16. mini_emulator_x86-userdebug 17. uml-userdebug 18. aosp_cf_x86_auto-userdebug 19. aosp_cf_x86_phone-userdebug 20. aosp_cf_x86_tablet-userdebug 21. aosp_cf_x86_tablet_3g-userdebug 22. aosp_cf_x86_tv-userdebug 23. aosp_cf_x86_wear-userdebug 24. aosp_cf_x86_64_auto-userdebug 25. aosp_cf_x86_64_phone-userdebug 26. aosp_cf_x86_64_tablet-userdebug 27. aosp_cf_x86_64_tablet_3g-userdebug 28. aosp_cf_x86_64_tv-userdebug 29. aosp_cf_x86_64_wear-userdebug 30. cf_x86_auto-userdebug 31. cf_x86_phone-userdebug 32. cf_x86_tablet-userdebug 33. cf_x86_tablet_3g-userdebug 34. cf_x86_tv-userdebug 35. cf_x86_wear-userdebug 36. cf_x86_64_auto-userdebug 37. cf_x86_64_phone-userdebug 38. cf_x86_64_tablet-userdebug 39. cf_x86_64_tablet_3g-userdebug 40. cf_x86_64_tv-userdebug 41. cf_x86_64_wear-userdebug 42. aosp_marlin-userdebug 43. aosp_marlin_svelte-userdebug 44. aosp_sailfish-userdebug 45. aosp_walleye-userdebug 46. aosp_walleye_test-userdebug 47. aosp_taimen-userdebug 48. hikey-userdebug 49. hikey64_only-userdebug 50. hikey960-userdebug
Which would you like? [aosp_arm-eng]
复制代码

意思就是要你选择编译目标的格式,编译目标的格式组成为 BUILD-BUILDTYPE,比如aosp_arm-eng的 BUILD 为 aosp_arm,BUILDTYPE 为 eng。


其中 BUILD 表示编译出的镜像可以运行在什么环境,aosp 代表 Android 开源项目,arm 表示系统是运行在 arm 架构的处理器上。 更多参考官方文档。 BUILDTYPE 指的是编译类型,有以下三种:


  • user:用来正式发布到市场的版本,权限受限,如没有 root 权限,不能 dedug,adb 默认处于停用状态。

  • userdebug:在 user 版本的基础上开放了 root 权限和 debug 权限,adb 默认处于启用状态。一般用于调试真机。

  • eng:开发工程师的版本,拥有最大的权限(root 等),具有额外调试工具的开发配置。一般用于模拟器。

如果你没有 Nexus /ˈneksəs/ 设备,只想编译完后运行在模拟器查看,那么 BUILD 可以选择aosp_x86,BUILDTYPE 选择 eng,Which would you like? [aosp_arm-eng]后面直接输入对应序号 5 就可以。


也可以直接指定编译的目标:


lunch aosp_x86-eng
复制代码

或者(不同的系统版本,序号的对应会有差别,建议不要直接用序号)


lunch 5
复制代码

3. 开始编译


通过-jN 参数来设置编译的并行任务数,以提高编译速度,在此前我的 CPU 核心数为 6,这里 N 值最好选在 6 到 12 之间,这里我们设置 6 个并行任务进行编译:


make -j6
复制代码

整编成功后会打印类似如下内容: 


由于采用的是虚拟机整编,编译速度会慢一些,这里花费了 2 小时 46 分钟. 最终会在 out/target/product/generic_x86/目录生成了三个重要的镜像文件: system.img、userdata.img、ramdisk.img。大概介绍着三个镜像文件: system.img:系统镜像,里面包含了 Android 系统主要的目录和文件,通过 init.c 进行解析并 mount 挂载到/system 目录下。 userdata.img:用户镜像,是 Android 系统中存放用户数据的,通过 init.c 进行解析并 mount 挂载到/data 目录下。 ramdisk.img:根文件系统镜像,包含一些启动 Android 系统的重要文件,比如 init.rc。


运行模拟器


在编译完成之后,就可以通过以下命令运行 Android 虚拟机了,命令如下:


source build/envsetup.shlunch aosp_x86-engemulator
复制代码

如果是在编译完后运行虚拟机,由于之前已经执行过 source 和 lunch 命令了,可以直接运行:


emulator
复制代码

如果不出意外就会启动模拟器,如果出现报错,网上也有很多的解决方案。


5.源码单编

比如我们要编译系统的 Settings 应用模块, 在 AOSP 根目录执行:


source build/envsetup.shlunch aosp_x86-eng
复制代码

进入 Settings 的目录:


cd packages/apps/Settings
复制代码

mm 编译当前目录下的模块,不编译依赖模块。


mm
复制代码

编译成功后会有提示生成文件的存放路径。



除了 Settings.odex 文件,还会在 out/target/product/generic_x86/system/priv-app/Settings 目录下生成 Settings.apk。


此外还有以下命令可以进行单编:


  • mmm:编译指定目录下的模块,不编译它所依赖的其它模块。

  • mma:编译当前目录下的模块及其依赖项。

  • mmma:编译指定路径下所有模块,并且包含依赖。

如果你修改了源码,想查看生成的 APK 文件,有两种方式:


  1. 通过 adb push 或者 adb install 来安装 APK。

  2. 使用 make snod 命令,重新生成 system.img,运行模拟器查看。

更多细节和内容见视频:


B 站地址: https://www.bilibili.com/video/BV1VU4y1s7xF


独立博客地址: http://liuwangshu.cn/batcoder/aosp/3-compiling-aosp.html


作者简介:刘望舒,腾讯云最具价值专家,著有畅销书《Android 进阶之光》《Android 进阶解密》《Android 进阶指北》,蝉联四届电子工业出版社年度优秀作者,前华为面试官,现大厂技术负责人,谷歌开发者社区特邀讲师。


也欢迎大家关注我的公号「刘望舒」,会分享大前端、Java 相关的技术。


发布于: 2021 年 03 月 28 日阅读数: 29
用户头像

刘望舒

关注

腾讯云TVP,公众号「刘望舒」主理人 2018.05.02 加入

腾讯云TVP,著有畅销书《Android进阶之光》《Android进阶解密》《Android进阶指北》,蝉联四届电子工业出版社年度优秀作者,前华为面试官,现大厂技术负责人,谷歌开发者社区特邀讲师。

评论

发布
暂无评论
一个视频带你编译自己的Android系统!