Physical Address:
ChongQing,China.
WebSite:
作为一名Android开发工程师,源码编译乃是家常便饭的事。但每次在新的环境上进行配置,总会出现这样或者那样的问题。今天这篇文章将会根据自己在源码编译过程中遇到一些问题及经历,写一篇总结性的文章,方便以后出现问题时进行查阅。
一般我们可以通过虚拟机或者是直接使用Linux服务器来进行源码的编译。由于Android源码较大(200G以上),我们需要留足够的磁盘空间,这里推荐磁盘大小为350G以上。除此之外,官方推荐RAM为16G,CPU核心推荐8核。
Google官方给出的一些数据可能会对你的编译配置有一些帮助,在72核机器,RAM64G的情况下整编需要40分钟;在RAM相近的情况下6核心机器编译在3小时左右。系统的话,推荐Ubuntu18或者Ubuntu20.
在以上硬件基础满足的情况下,我们来进行软件环境的配置。
1)安装repo:由于AOSP源码数量庞大,拥有众多的Git仓库。为了方便地管理这些Git仓库,Google推出了repo这个工具。repo工具本身是一系列Python脚本的集合,利用Python脚本实现对git命令的封装,从而完成对git仓库的管理,这里我们开始安装repo(以Ubuntu为例):
sudo apt-get update
sudo apt-get install repo
如果你的发行版软件源中找不到repo的package,你也可以通过手动安装的方式进行下载(推荐使用手动安装):
#创建目录
mkdir -p ~/.bin
#设定环境变量
PATH="${HOME}/.bin:${PATH}"
#获取repo
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo
#赋予相关权限
chmod a+rx ~/.bin/repo
在安装完成后,我们通过repo version命令查看是否正常安装,如显示如下内容,则表明repo安装成功:
这里需要注意,repo依赖的Python版本为Python3,而后续我们编译AOSP源码时使用的是Python2,如果报Python相关的错误,请检查Python版本。
2)安装git:repo并不能取代git,所以我们还是需要安装git来实现对代码仓库的管理.这里我们安装git(以Ubuntu为例):
sudo apt-get install git
安装完成后我们通过git –version命令查看是否正常安装,正常安装后我们需要配置git,包括用户名与邮箱等,相关配置命令可以自行搜索。
在我们基本的软件安装之后,我们就可以开始准备拉取安卓源代码了。我们可以创建一个单独的目录用于存放AOSP的源码。接下来,我们初始化repo.通过如下命令进行初始化:
repo init -u 地址 -b 分支名
在这个命令中,-u参数代表url地址,这里的地址依照实际情况进行对应,-b参数待变branch分支。由于众所周知的原因,国内无法正常下载AOSP的源码,你可以通过一些第三方源进行下载(如清华源、中科大源等)。比如我们通过如下命令下载清华源的AOSP代码:
repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-11.0.0_r27
一般在项目上我们会有自己的服务器,那一般会有自己的内网地址进行下载。
在repo init成功后,会把远程仓库的manifest.xml同步到本地.这份manifest.xml会记录我们远程仓库的仓库地址与版本信息,以及数量众多的git仓库信息。我们可以进入.repo目录->manifests目录查看。
接下来我们使用repo sync命令拉取源码,这里我们可以通过一些参数设置来更快地进行拉去,比如我们使用-j参数来设定线程数,一般设定的线程数不要超过你机器的限制,否则会得不偿失。
整个拉取过程可能会比较漫长,中途也可能会有失败的情况,为了解决这个问题,我们可以写一份shell脚本使其在失败后重新进行同步,如下所示:
#!/bin/bash
repo sync -j12
while [ $? = 1 ]; do
echo "======sync failed, re-sync again======"
sleep 3
repo sync -j12
done
最终拉取完成之后,我们会看到repo sync has finished successfully.的提示,自此代码拉取已经完成。
这里附上一些repo的常用操作,也许可能会用到:
repo status:用于查看各个git仓库的状态
repo start:本地创建并切换到新的分支,是对git checkout -b的封装
repo checkout:切换分支,是对git checkout的封装
repo info:查看当前manifest分支,以及各仓库的分支信息
repo upload:上传内容
repo forall:针对所有git仓库的操作
Android源码的编译依赖于Soong,具体细节我们可以不必去细究。基于Soong,AOSP提供了非常方便的编译流程。
1)初始化编译环境:这一步将加载AOSP提供的编译脚本进行编译环境的设置,通过如下命令开启:
source build/envsetup.sh
在这个脚本内,将会执行以下三个function:
validate_current_shell
source_vendorsetup
addcompletions
这三个shell script function各自的作用如下:
validate_current_shell :用于检查当前的shell环境,必须是bash或者zsh环境,其余shell环境将无法正常执行。
source_vendorsetup:用于加载device/vendor/product三个目录下的vendorsetup.sh脚本
addcompletions :将会根据 validate_current_shell 中拿到的shell环境去进行命令的补全
在环境初始化以后,我们就可以使用一些新的命令了,通过hmm命令可以查看这些新的命令,如下图所示:
这里挑几个比较常用的命令:
lunch:选择编译的版本类型
mm:编译当前目录下的模块及其依赖
mmm:编译当前目录、子目录下的模块及其依赖
croot:回到Android源码环境的顶层目录
cgrep:用于在C/C++文件中进行grep操作
jgrep:用于在Java文件中进行grep操作
2)选择编译版本:AOSP提供了众多的版本选择,我们可以通过这一步来进行选择,不同的版本选择最终的产物是不一样的
lunch
这里我们可以直接lunch + 版本名称,也可以在执行lunch后再输入具体的版本编号
这里讲一下AOSP的产品命名规则:
phone:适用于手机的版本
auto:适用于汽车的版本
tv:适用于Android TV的版本
user版本:权限受限,适用于生产环境
userdebug版本:与user类似,但具有 root 权限和调试功能;是进行调试时的首选编译类型
eng:具有额外调试工具的开发配置
x86:适合于x86架构的版本
arm:适合于arm架构的版本
mips:适合于mips架构的版本
3)执行编译: 这里我们通过make命令开始编译
make -j8
其中-j参数用于设定线程数,8代表8个线程。
开始编译后,整个的编译过程是比较漫长的,编译完成后的产物在/out/target目录下。
比较重要的几个产物:
system.img:包含有Android系统的可执行程序、库、系统服务和app等。内核启动后,会运行第一个用户态进程init,其会依据init.rc文件中的规则启动Android系统组件,这些系统组件就在system分区中。将Android系统组件启动完成后,最后会启动系统app —— launcher桌面,至此完成Android系统启动。
vendor.img:包含有厂商私有的可执行程序、库、系统服务和app等。可以将此分区看做是system分区的补充,厂商定制ROM的一些功能都可以放在此分区。
userdata.img:用户存储空间。一般新买来的手机此分区几乎是空的,用户安装的app以及用户数据都是存放在此分区中。用户通过系统文件管理器访问到的手机存储(sdcard)即此分区的一部分,是通过fuse或sdcardfs这类用户态文件系统实现的一块特殊存储空间。
recovery.img:包含recovery系统的kernel和ramdisk。如果bootloader选择启动recovery模式,则会引导启动此分区的kernel并加载ramdisk,并启动其中的init继而启动recovery程序,至此可以操作recovery模式功能(主要包括OTA升级、双清等)。
在编译后我们一般还需要进行打包,进行打包的命令也相当简单:
make dist
以上,就是本篇博客的全部内容了~