最近由于工作需要学习Android Framework部分的知识,就想着自己编译一下AOSP,方便debug阅读源码。但是我只有一台机器,平时用Windows方便一些,又不想搞两个系统,来回切换也不太方便,试过虚拟机我这老机器吃不消,就想着用WSL2试试,百度也确实搜到有不少这样的教程,但都不怎么全,在这里记录一下我的全部过程。
一、软硬件要求
由于我这里只有一台电脑,没有试过其他机器,就列举下我的配置吧,做个参考
- CPU:Intel i7-7700HQ 2.8GHz,最高睿频3.8GHz
- 内存:32GB(最初用的16GB的,关掉不需要的软件只保留终端,分给WSL 14GB,勉强能跑)
- 硬盘:2TB SATA SSD(最初用的机械硬盘,奇慢无比,忍无可忍)
- 系统:Win10 22H2(支持WSL2就行)
二、安装配置WSL2
编译AOSP需要使用Ubuntu,所以我们的WSL就直接安装Ubuntu,以下在管理员权限的Powershell下完成,也可参考设置 WSL 开发环境的最佳做法,不得不说微软的文档相当的详细,当然也可以去Microsoft Store安装。
# 设置默认使用WSL2
$ wsl --set-default-version 2
# 列出可用的 Linux 发行版
$ wsl --list --online
# 安装Ubuntu
$ wsl --install Ubuntu
安装完成后进入开始菜单,找到并打开Ubuntu,按指示设置用户名密码,然后即可进入WSL2的Ubuntu系统。此时就可以参照Google的文档搭建构建环境了。
编译AOSP必须在Linux的ext4文件系统下,直接用window的NTFS是不行的,这个坑就不用再踩了。这里要使用VHD虚拟硬盘创建一个ext4的文件系统,用来存放AOSP的源码。当然如果是台式机硬盘位比较多,也可以专门用一个盘做ext4分区,可以减少一些性能损耗,注意wsl只能挂载整个盘,如果一块硬盘有一个NTFS分区和一个ext4分区,挂载了ext4分区,NTFS就不可用了,这也是我必须创建虚拟硬盘的原因。
# 创建VHD,动态扩展,空间可以设置的大一点
$ New-VHD -Path d:\aosp.vhdx -Dynamic -SizeBytes 2TB
# 附加VHD到WSL
$ wsl --mount --vhd d:\aosp.vhdx
# 进入wsl
$ wsl
# 查看分区
$ sudo fdisk -l
# 一般目标是/dev/sdc,可以用lsblk -f确认,或者看容量
$ sudo fdisk /dev/sdc
# g: 创建一个空的GPT分区表
# n: 创建新分区
# w: 保存并退出
# 格式化为ext4,2TB格式化时间较长
$ sudo mkfs -t ext4 /dev/sdc
# 退出WSL
$ exit
# 分离VHD,并关闭WSL
$ wsl --unmount \\?\D:\aosp.vhdx
$ wsl --shutdown
至此ext4磁盘创建完成,后面再重新附加到wsl即可
下面是wsl配置文件,参考
[wsl2]
# 将VM内存限制为不超过24GB,可以使用GB或MB将其设置为整数
memory=24GB
# 将虚拟机设置为使用6个虚拟处理器
processors=6
三、下载编译AOSP代码
由于众所周知的原因,AOSP仓库不能直接访问,好在我们有清华镜像AOSP,用这个就可以了。以下命令都在WSL中执行
# 附加的虚拟磁盘默认挂载在/mnt/wsl/Daospvhdx下,默认owner和group是root,需要修改为普通用户
$ sudo chown [username] Daospvhdx
$ sudo chgrp [username] Daospvhdx
# 配置repo工具
$ mkdir ~/bin
$ cd ~/bin
$ curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o repo
$ chmod +x repo
$ echo '
# repo
export PATH=$PATH:$HOME/bin
export REPO_URL=https://mirrors.tuna.tsinghua.edu.cn/git/git-repo
' >> ~/.profile
$ source ~/.profile
# 创建源码目录
$ mkdir /mnt/wsl/Daospvhdx/aosp
$ cd /mnt/wsl/Daospvhdx/aosp
$ repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android12-release
$ repo sync -c
# 编译
$ source build/envsetup.sh
$ lunch sdk_car_x86_64-userdebug
# 开始编译,注意j值最好不要超过cpu核心数,否则系统可能卡死,慢就慢点吧
$ make -j4
好了,等待编译完成,我使用了8个小时,毕竟我的老机器有些弱了
四、编译虚拟机镜像
参照构建 AVD 映像,在build结束后执行以下命令,会再out\host\linux-x86\sdk\sdk_car_x86_64目录下生成sdk-repo-linux-system-images-eng.[username].zip和repo-sys-img.xml两个文件
$ make emu_img_zip # make -j4 sdk sdk_repo (<=12)
然后我们把这两个文件拷贝出来,例如放到D:\Android\avd_image\下,修改repo-sys-img.xml文件,以下是精简版,详细配置可以参考官方配置。这里将镜像文件重命名为sdk-repo-system-images-eng-android12.zip以便区分。然后将以下内容保存为local_build_avd_iamge.xml,在Android SDK设置页中SDK Update Sites中新增一项,URL填入file:/D:/Android/avd_image/local_build_avd_iamge.xml,切换到SDK Platforms即可看到我们的镜像了,勾选下载。然后关闭设置,打开Device Manager,Create device,选择我们镜像的类型如Automotive,New Hardware Profile,创建一个硬件设备。完成后选择刚刚创建的硬件设备,Next即可看到我们的镜像,跟随引导创建即可。
<?xml version="1.0" ?>
<sys-img:sdk-sys-img xmlns:sys-img="http://schemas.android.com/sdk/android/repo/sys-img2/03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- license定义,可以有多个,以供不同的remotePackage使用 -->
<license id="android-sdk-license" type="text">This is a License</license>
<channel id="channel-0">stable</channel>
<channel id="channel-1">beta</channel>
<channel id="channel-2">dev</channel>
<channel id="channel-3">canary</channel>
<!-- 可以添加多个remotePackage,对应一个镜像,path对应sdk下的system-images目录,即镜像解压目录,注意区分 -->
<remotePackage path="system-images;android-31;android-automotive-custom;x86_64">
<type-details xsi:type="sys-img:sysImgDetailsType">
<api-level>31</api-level> <!-- 镜像的api level -->
<base-extension>true</base-extension>
<tag> <!-- 镜像标签 -->
<!-- id有default,android-desktop,android-automotive,android-tv,android-wear等可选 -->
<id>android-automotive</id> <!-- id不可随便设置,否则创建虚拟机时找不到对应类型的镜像 -->
<display>Automotive Local Build</display>
</tag>
<vendor> <!-- 供应商信息 -->
<id>Custom</id>
<display>Custom Build</display>
</vendor>
<abi>x86_64</abi>
</type-details>
<revision>
<major>1</major> <!-- 在SDK下载对应api level下显示 -->
</revision>
<!-- display-name在SDK下载对应api level下显示,注意区分 -->
<display-name>Local Build Automotive x86_64 System Image ---> Custom</display-name>
<uses-license ref="android-sdk-license"/> <!-- 对应上文的定义,下载镜像时显示 -->
<dependencies>
<dependency path="emulator">
<min-revision> <!-- 依赖模拟器的最低版本 -->
<major>30</major>
<minor>3</minor>
<micro>1</micro>
</min-revision>
</dependency>
</dependencies>
<channelRef ref="channel-0"/> <!-- channel对应上文的定义 -->
<archives>
<archive>
<complete>
<!-- size和checksum可以从repo-sys-img.xml拷贝 -->
<size>829472586</size> <!-- 文件大小 -->
<checksum type="sha1">861e15a2c842e4b7d3c0055ce24531be91996692</checksum> <!-- 文件hash,类型sha1 -->
<url>file:/D:/Android/avd_image/sdk-repo-system-images-eng-android12.zip</url> <!-- 镜像文件下载地址 -->
</complete>
</archive>
</archives>
</remotePackage>
<!-- 定义更多remotePackage,注意需要区分的部分 -->
</sys-img:sdk-sys-img>
五、虚拟机debug
学习framework在debug,需要经常push我们自己编译的模块或lib库,但是Android Studio的模拟器默认不能remount,无法push文件到系统目录,这里我们需要直接使用sdk中emulator启动镜像
# 列出已创建的模拟器
$ .\emulator.exe -list-avds
Automotive_API_31
# 使用emulator冷启动可写system的模拟器
$ .\emulator.exe -avd Automotive_API_31 -writable-system -no-snapshot-load
# 等待启动完成,即可remount,push文件了
六、遇到的问题
wsl2和emulator不能同时开启
$ wsl --shutdown
$ bcdedit /set hypervisorlaunchtype auto
# 重启电脑即可
打完收工,希望对你有所帮助