本篇记录在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 addgit 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刷机时需要adbfastboot等命令行工具。需要下载工具,并添加到系统环境变量里。下载地址: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. 参考资料