本篇记录在Windows WSL2环境下编译安卓源码(Android Open Source Project,AOSP)的过程。
1. 环境介绍
- 宿主机:Windows 10操作系统,内存32GB。wsl虚拟磁盘文件所在的磁盘分区,留出了200GB以上的空间。
- wsl虚拟机:Ubuntu 22.04.1 LTS操作系统,内存16GB,交换分区(swap)4GB。
- aosp版本分支:android-10.0.0_r2
- 手机设备:Pixel 3a XL
- 网络:能正常访问外网。
2. 安装环境依赖
- Git
sudo apt-get update
sudo apt install git
- 各种工具
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 libgl1-mesa-dev libxml2-utils xsltproc unzip
- JDK
sudo apt-get install openjdk-8-jdk
- libncurses5。编译源码时才发现缺了这个库。
sudo apt-get install libncurses5 libtinfo5
- python2。在解决libncurses5缺失的同时,听AI的建议,准备好python2的环境,并把python环境通过软链接的形式指向python2。我编译的版本是Android 10。新的Android版本源码,可能不需要python2。
sudo apt-get install python2
sudo ln -s /usr/bin/python2 /usr/bin/python
3. 下载源码
3.1 下载repo工具
安卓源码由多个项目构成,repo是管理安卓多个项目的工具。
这里把repo文件保存在~/bin目录下,把~/bin目录添加到环境变量PATH中(临时修改,只在当前终端窗口生效),并为repo文件添加可执行的权限。
mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
添加git的用户名和邮箱,内容随意(毕竟不准备提交到远程仓库)。
git config --global user.name "XXX"
git config --global user.email "[email protected]"
创建代码目录。这里以aosp命名,其它名字也可以。
mkdir aosp
cd aosp
repo初始化,指定aosp代码分支。build号、代码分支、设备的对应关系,可以在代码分支链接里查找。
因为不需要这个分支以往的提交历史,我设置了--depth=1参数。
repo init -u https://android.googlesource.com/platform/manifest -b android-10.0.0_r2 --depth=1
3.2 下载源码
使用repo工具下载aosp源码,-j8参数指定8线程并行。
repo sync -j8
下载完成后我查看了一下,文件夹大小大概是64GB。如果在repo初始化时没有指定--depth=1参数,项目还会更大。
3.3 下载驱动
下载驱动源码。aosp里不包含驱动,如果需要得自行下载。驱动下载链接。
驱动对应编译出来后的vendor分区镜像。第一次编译我没有下载这两个驱动的源码,编译出的镜像少了vendor分区。
下载到压缩包后,解压缩,把解压后的脚本保存在aosp目录(~/bin/aosp/)下。使用chmod 777 <filename>命令赋予脚本执行的权限。使用./<filename>命令执行脚本。执行脚本后需要阅读条款,按下方向键↓直到条款末尾。按要求输入同意。
3.4 修改源码
如果不需要进行自定义的源码修改,可以跳过这一部分。
这部分介绍repo、git的操作。借助repo和git,可以追踪修改的地方,方便随时复原项目。官方文档链接:源代码控制工作流程,Repo 命令参考资料。
# 创建新的分支
repo start branch-name [project-list]
branch-name是分支名称,自己本地修改代码的话,分支名称任意填写。[project-list]可以写入一或多个,可以是项目名称,也可以是本地代码目录的路径。
在需要修改代码的目录下,执行命令repo start XX-name .,就可以创建XX-name分支,并把当前目录下的修改添加到分支里。需要注意的是,这个命令无法在aosp总目录下执行,会报错。因为aosp由多个项目组成,整个aosp目录无法被识别为某个项目。需要进入二级、三级目录下执行命令。
修改代码。修改后用git add、git commit命令提交修改结果。这样修改的记录就保存在创建的分支里,可以随时撤销修改、回滚到原始的aosp代码版本。
4. 编译代码
关联代码:
source build/envsetup.sh
指定编译配置:
lunch aosp_bonito-userdebug
其中bonito是Pixel 3a XL设备的代号,其它设备的代号可以查看设备代号查询链接。userdebug是构建类型,可选的构建类型有user、userdebug、eng三种,具体区别不在这里解释。
编译代码:
make -j8
其中-j8参数指定8线程编译。线程数越多,编译越快;但是内存开销更大,可能会因为内存不足而编译失败。
最后编译成功。8线程编译耗时3.5小时,编译成功后磁盘占用多了77GB。
编译后的镜像保存在./out/target/product/bonito路径下,其中的bonito是编译时指定的代号。下面罗列了.img类型的文件:
$ ls ~/bin/aosp/out/target/product/bonito | grep img
boot-debug.img
boot.img
dtb.img
dtbo.img
persist.img
product.img
ramdisk-debug.img
ramdisk-recovery.img
ramdisk.img
super_empty.img
system.img
system_other.img
vbmeta.img
vendor.img
5. 刷机
wsl原生环境不支持通过USB连接设备,在wsl里识别不到连接的手机。所以刷机需要回到Windows环境下操作。
5.1 拷贝刷机文件
刷机需要的文件有:android-info.txt、各种.img类型的文件。这两种文件都存放在上述的~/bin/aosp/out/target/product/bonito路径下。
编译aosp后产生的文件还在wsl里,需要拷贝到Windows目录。以Windows D盘下的目录android-file为例,把文件拷贝到这个文件夹下,并在这个文件夹里刷机。在wsl里执行:
# 创建Windows下的D盘文件夹
mkdir /mnt/d/android-file
# 拷贝文件
cd ~/bin/aosp/out/target/product/bonito
cp android-info.txt /mnt/d/android-file/
cp ./*.img /mnt/d/android-file
5.2 环境依赖
在Windows下刷机,需要安装驱动,否则pixel手机不能被识别出来。下载地址:Google USB 驱动。教程:安装USB驱动。
安装驱动前需要连接手机、在设备管理器里找到手机。
在我电脑上,手机在“通用串行总线设备”栏目下。供参考定位。
在Windows刷机时需要adb、fastboot等命令行工具。需要下载工具,并添加到系统环境变量里。下载地址:Android SDK Platform-Tools。
在pixel手机里,打开开发者模式。在开发者选项里,打开“OEM解锁”,打开“USB调试”。打开USB调试后,pixel手机首次连接电脑,需要在手机上点击信任电脑。
电脑连接手机后,在命令行里输入adb devices,验证环境依赖是否搞定。如果能正常识别到手机,说明环境依赖已经解决。
5.3 刷机
手机保持开机。接下来让手机解锁bootloader。
电脑连接手机后,在命令行输入adb reboot bootloader,让手机进入fastboot模式。在命令行输入fastboot flashing unlock ,让手机解锁bootloader。到这一步,手机的bootloader已经解锁。
注意:解锁bootloader会清空手机数据。
接下来开始刷机。以Windows CMD环境为例。
:: 进入刷机文件所在的路径
cd /d D:\android-file
:: 指定镜像路径
set ANDROID_PRODUCT_OUT=.
:: 刷机
fastboot flashall -w
不出意外的话,刷机到这里顺利完成。
6. 相关问题
6.1 编译时环境缺失
编译时遇到了libncurses.so.5缺失的问题。报错日志如下:
prebuilts/clang/host/linux-x86/clang-3289846/bin/clang.real: error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory
Ubuntu 22.04自带的是libncurses6。但是Android源码编译需要的是libncurses5,需要额外安装:
sudo apt-get update
sudo apt-get install libncurses5 libtinfo5
6.2 编译时内存不足
遇到过内存不足的问题。
我的wsl配置是:内存16GB,交换分区(swap)4GB。尝试过16线程编译,编译失败,报错如下:
Killed
-e
******************************
You have tried to change the API from what has been previously released in
an SDK. Please fix the errors listed above.
******************************
(省略若干)
ninja: build stopped: subcommand failed.
15:05:42 ninja failed with: exit status 1
原因是wsl内存不足,编译进程被杀死。可以执行命令dmesg -T | grep -i oom,确认是不是内存不足的原因。
换成8线程后,成功编译。
6.3 刷机时报错
我刷机时遇到了下面的报错:
FAILED (remote: ‘Not enough space to resize partition’)
解决方案:先删除分区,再重新刷入。在cmd下执行:
:: 删除分区
fastboot delete-logical-partition system_a
:: 重新刷入
fastboot flashall -w
7. 参考资料
- Android源码开发(一)-简书。这一篇给我提供了很多帮助,我基本按照它的步骤完成编译。
- wsl编译AOSP-cnblogs。
- 刷机报错:Not enough space to resize partition-贴吧