介绍
新的三天,祝您工作愉快。
本文来自面哥师傅(麻辣牛肉面)。 对Android7.0系统源码下载和编译进行了一些总结。 之前开发组一直有人问7.0源码编译的问题,希望勉老师的这篇文章能够对大家有所帮助
麻辣牛肉面博客地址:
文本
最近打算研究一下Android 7.0的系统源码,之前一直没有做记录。 这次只是把学习的内容记录下来,方便以后的准备和巩固。
既然我们想要学习我们的系统源代码,那么我们需要做的第一步就是下载源代码并编译它。
硬件环境要求 1、编译环境
根据官方的说法,编译Android 2.3.x及以上版本的系统源码需要64位系统运行环境支持,而编译2.3.x以下版本则需要32位系统运行环境。
2、硬盘空间
官方建议预留100G的C盘空间用于下载源码,150G的C盘空间用于编译源码。 如果使用ccache(一种高速编译缓存工具,可以大幅提高gcc的编译速度),那么就需要更大的空间来支持。
所以尽量保证你的C盘空间足够大。 之前由于C盘预留空间不足,导致源码编译过程中空间不足,把自己坑得很惨。
3、内存空间
如果你在虚拟机上运行Linux,官方建议至少需要16G显存空间。 我的机器只有8G显存空间来运行虚拟机。 运行起来问题不大,但是编译源码的过程很长。 我不知道。 和内存大小有关系吗?
软件环境要求 1、操作系统
Android系统源码编译同时支持Linux和Mac OS操作系统。 一般Android系统的源码都是在Linux Ubuntu系统上进行开发和测试的,所以如果你打算使用Linux系统进行源码编译,那么通常建议安装Ubuntu版本的Linux。
下面列出了各个Android版本与编译系统版本的对应关系
Linux:
Android版本GNU/Linux
Android 6.0(棉花糖)- Android 的最新版本
Ubuntu 14.04(可信)
Android 2.3.x(姜饼)- Android 5.x(棒棒糖)
Ubuntu 12.04(精确)
Android 1.5(纸杯蛋糕)- Android 2.2.x(Froyo)
Ubuntu 10.04(清醒)
苹果系统
安卓版Mac OS (Intel/x86)
Android 6.0(棉花糖)- Android 的最新版本
Mac OS v10.10 (Yosemite) 或更高版本,带有 Xcode 4.5.2 和命令行工具
安卓 5.x(棒棒糖)
Mac OS v10.8 (Mountain Lion),带有 Xcode 4.5.2 和命令行工具
Android 4.1.x-4.3.x(果冻豆)- Android 4.4.x(奇巧)
Mac OS v10.6 (Snow Leopard) 或 Mac OS X v10.7 (Lion) 和 Xcode 4.2(Apple 开发人员工具)
Android 1.5(纸杯蛋糕)- Android 4.0.x(冰淇淋三明治)
Mac OS v10.5 (Leopard) 或 Mac OS X v10.6 (Snow Leopard) 和 Mac OS X v10.5 SDK
2.JDK版本要求
不同Android版本的编译也需要相应的JDK环境。 这是版本之间的对应关系列表
Android 版本 JDK 版本 (Ubuntu) JDK 版本 (Mac OS)
安卓最新版本
OpenJDK 8
jdk 8u45 或更新版本
Android 5.x(棒棒糖)- Android 6.0(棉花糖)
OpenJDK 7
jdk-7u71-macosx-x64.dmg
Android 2.3.x(姜饼)- Android 4.4.x(奇巧)
Java JDK 6
Java JDK 6
Android 1.5(纸杯蛋糕)- Android 2.2.x(Froyo)
Java JDK 5
搭建编译环境根据里面列出的软硬件要求,我们可以根据自己要编译的Android版本和自己的设备来选择合适的系统和JDK。 接下来我们就来说说如何搭建编译环境。
这里我们主要配置Android 7.0所需编译环境的Linux和Mac OS:
搭建Linux系统编译环境 1.安装JDK
Android 7.0目前需要openJDK 8的JDK环境
乌班图 15.04+
如果您的系统是Ubuntu 15.04及以上版本,可以直接运行以下命令安装:
乌班图14.04
如果您使用的是Ubuntu 14.04版本,没有专门针对14.0.4的开放jdk8包,
但是Ubuntu 15.04 OpenJDK 8的包可以在14.0.4上成功运行,所以我们下载Ubuntu 15.04 OpenJDK 8的安装包来自动安装:
从 archive.ubuntu.com 按顺序下载下面列出的 64 位开放式 JDK 8 .deb 安装包
openjdk-8-jre-headless_8u45-b14-1_amd64.deb
openjdk-8-jre_8u45-b14-1_amd64.deb
openjdk-8-jdk_8u45-b14-1_amd64.deb
安装.deb包
首先运行apt-get命令更新软件列表
sudo apt-get update
然后运行以下命令依次安装之前下载的三个deb文件:
sudo dpkg -i 下载的文件地址
最后运行apt-get -f命令来打补丁并安装依赖包
sudo apt-get -f install
更新系统默认使用的JDK版本
如果你的系统安装了多个版本的JDK,可以通过以下命令进行切换,会弹出可选的JDK版本,根据需要选择对应的版本即可:
2.安装所需工具包Ubuntu 14.04
我们在编译过程中会用到以下依赖包,执行如下指令统一安装:
3.设置源码编译输出路径
默认情况下,编译后的系统源码会放在源码所在目录的out文件夹中。
如果要调整输出目录的路径,可以执行以下命令指定输出目录:
4.设置USB接口访问设备
在Linux下,默认情况下普通用户是不允许通过USB接口直接访问设备的。
推荐的方法是以 root 用户身份在 /etc/udev/rules.d/51-android.rules 路径中创建文件。
我们可以通过以下命令来实现此目的(将命令中的用户名替换为您的系统用户名):
设置Mac OS系统编译环境
Mac OS 的文件系统默认情况下保留大小写,但实际上不区分大小写。
目前的Git命令很难支持这样的文件系统,这会导致一些莫名其妙的错误。 因此,要在Mac OS上编译Android系统源代码,首先要创建区分大小写的C盘镜像。
创建区分大小写的磁盘映像
这里我们直接通过命令行创建:
该命令会在系统根目录下生成一个 android.dmg 或 android.dmg.sparseimage 文件。 安装后,它将用作驱动程序映像分区,支持Android开发所需的格式。
如果以后需要更多空间,可以使用以下命令调整空间:
您还可以在 ~/.bash_profile 中添加用于挂载和卸载的辅助函数:
之后,我们可以通过执行mountAndroid命令挂载镜像,并使用umountAndroid命令卸载镜像。
安装JDK安装工具依赖包1.安装xcode命令行工具
$ xcode-select --install
对于老版本的Mac OS系统(10.8或10.8之前),我们需要去Apple开发者网站下载并安装。
如果您还没有注册成为苹果开发者,则需要注册苹果账户才能下载。
2. 前往macports.org,下载Mac OS版本对应的macports(类似于Linux下的apt-get,用于帮助您安装其他应用程序)
注意:确保 /opt/local/bin 位于路径 /usr/bin 之前,如果不是,请将其添加到 ~/.bash_profile 文件中
export PATH=/opt/local/bin:$PATH
注意:如果根目录下没有.bash_profile文件,则会自动创建
3.通过macports安装make、git和GPG
$ POSIXLY_CORRECT=1 sudo port install gmake libsdl git gnupg
如果您使用的是Mac OS X v10.4系统,还需要安装bison:
$ POSIXLY_CORRECT=1 sudo port install bison
注意:如果编译的是Android 4.0.x及以下系统,gmake 3.8.2有bug,需要恢复到gmake 3.8.1
优化编译环境(可选)设置ccache
我们可以自由选择是否启用ccache编译工具。
ccache 是一个高速编译缓存工具,它通过将头文件缓存到源文件中来提高构建性能,从而通过减少编译每一步添加头文件所需的时间来提高 CC++ 的构建速度。
从整个编译过程来看,如果不使用ccache,同一个头文件在编译过程中会被解析多次,浪费处理器周期,更重要的是浪费开发者的时间,因为他们要等待至此完成该过程。 在一个团队中,这种影响可能更加显着,因为团队成员可能会重复编译和解析同一个头文件。
因此,这个功能一般对于专门编译系统的服务器或者大容量的生产环境比较有用,可以加快重新编译的速度。
注意:如果您只是个人开发者,不是专用的编译服务器,并且不需要增量构建,那么使用 ccache 可能会因为缺少缓存而提高您的构建速率。
打开ccache
要启用 ccachewindow编译android源码,请在源树的根路径中执行以下命令:
缓存的大小通常设置为50G-100G
然后在.bashrc(或etc/profile)中添加以下指令
export USE_CCACHE=1
默认情况下,缓存会存放在主根目录的~/.ccache中,但是如果你使用的是NFS或者其他非本地文件系统,那么你还需要在.bashrc中指定缓存目录地址
在 Mac OS 上,您需要将 linux-x86 替换为 darwin-x86:
prebuilts/misc/darwin-x86/ccache/ccache -M 50G
当编译的Android系统为4.0.x或更旧版本时,ccache的缓存路径会不同
prebuilt/linux-x86/ccache/ccache -M 50G
此设置仍将存储在 CCACHE_DIR 中。
在 Linux 上,您可以使用以下命令启用对 ccache 的窃听:
$ watch -n1 -d prebuilts/misc/linux-x86/ccache/ccache -s
下载源代码
编译环境配置完成后,我们就可以开始下载我们的源码了
安装仓库
Repo是Google用Python编写的脚本工具。 Android使用git作为代码管理工具。 一个Android系统由N多个git库组成。 如果自动一一下载的话,是一件特别痛苦的事情,而repo就是用来维护、管理和下载这个git库的。
通过Repo工具,我们可以轻松完成Android系统源码的下载。
1、在系统home根路径下创建bin目录,并将其添加到path路径中:
2.下载repo工具并设置为可执行
初始化Repo客户端 1.创建一个空目录来存放我们的Android系统源码,名称可选
2.初始化repo仓库
从trunk master下载源码,最新版本
如果需要下载特定版本系统的分支,可以在上述命令后添加 -b 版本分支号,这里我指定Android 7.0的版本分支
具体版本分支号可以在这个地址查看(需要翻墙):
Android系统版本分支号
3.同步源码到本地
此时执行sync命令手动下载源码到本地
使用国外镜像下载源码
由于国外网络问题,以上操作的源码下载需要翻墙下载,速度会受到很大影响。 上周可能需要下载几十GB的系统源代码。
因此,我们可以选择国外镜像进行源码下载:
清华大学镜像站
参考页面上的说明,对之前的说明进行一些调整。 网站上写的比较详细,这里就不重复了。
根据网络速度,下载通常可以在一天内完成。
对于下载的源代码,我们无法直接将其烧录到目标设备或使用模拟器来运行它。 我们必须编译源代码来生成相应的图像二进制图像文件。
当然,您也可以直接从官网下载系统版本对应的镜像文件:
这里我们还是自己编译源码,熟悉一下整个编译过程。
源码编译
首先,我们通过命令行进入源代码目录。 这里的目录名称是aosp
cd aosp
清空输出目录
为了保证我们编译生成的文件不受之前构建创建的文件影响,我们在源码目录下执行以下命令,会清除out输出目录下的所有文件
$ make clobber
设置编译环境
首先我们通过源码build目录下的envsetup.sh脚本文件初始化我们的编译环境,执行
$ source build/envsetup.sh
或者
$ . build/envsetup.sh
这两个命令的效果是一样的,并且会初始化一些有用的命令工具
我们之前执行的一些指令必须在 envsetup 初始化之后执行
选择编译目标
然后我们使用lunch命令选择我们需要编译的目标
执行午餐命令
$ lunch
将弹出一个可选的目标项:
所有构建目标均由 BUILD-BUILDTYPE 组成:
BUILD对应代号
这是官方的对比表:
这是官方的对比表:
设备代码名称构建配置
像素XL
马林鱼
aosp_marlin-userdebug
像素
旗鱼
aosp_sailfish-userdebug
海基
远足
hikey-用户调试
Nexus 6P
钓鱼者
aosp_angler-userdebug
Nexus 5X
牛头
aosp_bullhead-userdebug
Nexus 6
沙木
aosp_shamu-userdebug
Nexus 播放器
河豚
aosp_fugu-userdebug
Nexus 9
比目鱼(比目鱼)
aosp_flounder-userdebug
Nexus 5(GSM/LTE)
锤头鲨
aosp_hammerhead-userdebug
Nexus 7(无线网络)
剃须刀(弗洛)
aosp_flo-userdebug
Nexus 7(移动)
拉佐格 (deb)
aosp_deb-userdebug
Nexus 10
曼塔雷(蝠鲼)
full_manta-userdebug
Nexus 4
奥卡姆 (mako)
full_mako-userdebug
Nexus 7(无线网络)
纳卡西(石斑鱼)
full_grouper-userdebug
Nexus 7(移动)
纳卡西格(罗非鱼)
full_tilapia-用户调试
Galaxy Nexus (GSM/HSPA+)
药酒(金枪鱼)
full_maguro-userdebug
Galaxy Nexus(威瑞森)
米西德(托罗)
aosp_toro-userdebug
Galaxy Nexus(实验性)
mysidspr (toroplus)
aosp_toroplus-userdebug
摩托罗拉 Xoom(美国 Wi-Fi)
翼鳐
full_wingray-用户调试
Nexus S
烧酒(克雷斯波)
full_crespo-用户调试
Nexus S 4G
烧酒 (crespo4g)
full_crespo4g-userdebug
BUILD_TYPE对照表:
构建类型目的
用户
访问权限有限,主要用于发布即将发布的产品,无root和调试权限
用户调试
与用户类型类似,但具有root和debug权限
英语
具有各种调试工具的开发版本设置,并具有root和debug权限
如果是作为开发使用,那么我们通常选择-eng,
这里我打算在模拟器上运行编译好的镜像,而我笔记本的cpu是intel x86,所以选择了6.aosp_x86-eng
我们可以根据自己的需求选择对应的cpu类型。
注意:我们知道官方的Android模拟器非常慢,
Intel特意提供了一种名为HAXM的虚拟硬件加速技术,全称是:Intel Hardware Accelerated Execution Manager。
只要你的CPU是Intel产品并且支持VT(虚拟化技术),你就可以使用HAXM技术将你的模拟器的速度提升到真机的水平。
目前Intel只提供Windows版本和MAC版本,Linux系统只能通过安装KVM才能达到这种效果。
安装KVM
首先我们测量一下我们的cpu是否支持硬件虚拟化(硬件虚拟化)
egrep -c '(vmx|svm)' /proc/cpuinfo
如果输出值小于0,说明你的cpu支持
如果你使用的是vmware虚拟机上安装的linux,注意设置虚拟机的cpu支持硬件虚拟化,先关闭虚拟机,然后右键点击虚拟机=》设置,选择cpu,然后检查虚拟化Intel VT项,这样就可以支持KVM了。
对于Ubuntu 10.0.4以上版本,我们可以通过以下指令安装KVM
sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils
如果您在安装KVM的过程中有任何疑问window编译android源码,可以访问以下网址进行排查:
这样,编译完目标intel cpu的镜像文件后,我们运行模拟器的时候就会手动加速。
编译源代码
好了,一切准备就绪,我们可以开始编译我们的源代码了,
我们在源代码路径下使用make -jN命令编译源代码,其中N通常建议设置为CPU核心线程数的1-2倍。
$ make -j4
通常情况下,我们只是等待源代码编译完成,但是从Android 7.0 N开始,make命令会默认打开Jack编译工具链来编译Java代码,这个过程中可能会出现一些问题。
什么是Jack编译工具链(The Jack toolchain)?
我们知道,平时编译Android代码时,我们会先将Java代码编译成.class文件,最后转换成.dex文件,如图:
Jack编译工具链跳过编译成.class文件的过程,直接将Java代码编译成.dex文件
其优点:
如果你想了解更多关于Jack的知识,可以访问Compiling with Jack(翻墙),这里就不做过多解释了。
据官方说法,Jack可以提升编译率
但在实际编译过程中,Jack会占用我设备大量显存,拖慢编译速度,并报错,而且官方文档中写的配置方法对Jack来说不起作用。
Jack编译过程年报编译过程中遇到的问题Out of memory错误和中断编译
执行make命令后,第一次编译Java代码时,Jack将被启用。 这个时候经常会卡住,过一段时间就会报Out of memory的错误。
根据官方的说法,Jack在并行编译时,占用资源过大,导致显存溢出。
您可以通过减少 $HOME/.jack 文件中 SERVER_NB_COMPILE 的值来减少并行编译的数量。 SERVER_NB_COMPILE 的值默认为 4
但实际情况是Jack并没有在根路径生成.jack文件,自动创建并设置SERVER_NB_COMPILE后重启Jack服务也没有效果。
经过测试发现,make编译过程中第一次启用Jack时,会在home根路径下生成.jack-server目录
您可以通过以下方式更改此目录中的 config.properties 文件
.jack.server.max-service 值设置并发线程数。
同时也可以设置减少Jack的内存容量来解决这个问题,命令如下
export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096m"
然后单步进入输出路径的bin目录:
cd /home/cjpx00008/aosp/out/host/linux-x86/bin
执行以下命令重启Jack服务
./jack-admin stop-server./jack-admin start-server
我改变了服务大小,同时减少了显存,编译过程中没有出现其他问题。
有没有办法关闭Jack编译?
既然Jack有问题,我们可以关闭Jack编译吗?
目前我还没有找到编译Android 7.0时如何关闭Jack的方法。 如果有人知道请留言告诉我。 非常感谢! !
运行编译好的镜像image
经过漫长的等待,我们的源码终于编译完成了,接下来就是运行编译好的镜像image了。
这时我们只需要在源码目录下执行emulator命令即可运行模拟器
$ emulator
第一次启动可能需要较长时间,耐心等待即可
手术成功了,是不是有点兴奋!
注意:如果您的命令行窗口关闭并重新打开,模拟器命令可能会提示找不到该命令。 我们可以在源码根目录环境下通过envsetup.sh重新初始化命令,运行lunch命令选择编译目标。 这样再次运行模拟器时就不会提示找不到命令了(每次关闭命令行窗口都需要重新运行以下命令来执行模拟器)
也可以通过配置环境变量来设置模拟器命令,不过我没有成功,哈哈
$ source build/envsetup.sh$ lunch$ emulator
好了,到此为止,我们的源码就已经编译完成了。 下一篇我们会讲如何使用Android Studio导出Android系统源码,并通过AS调试Java源码,以及使用GDB调试系统Native CC++源码。
最初是面哥师傅(麻辣牛肉面)的贡献,如果想了解更多,请参考面哥的博客。
麻辣牛肉面博客地址: