编译 AOSP 总流程
记录为 Pixel 3(blueline)搭建 AOSP 编译环境的全过程,运行环境为 Debian 13,已写步骤均经实机验证。
配置 SSH 免密登录
后续步骤均在该主机上执行,先配置免密登录。
| 项目 | 值 |
|---|---|
| 系统 | Debian 13 |
| IP | 192.168.2.13 |
| 用户 | kpa |
Windows 机器上生成密钥对(默认路径、空口令):
powershellssh-keygen -t rsaWindows 机器上查看公钥:
ps1PS C:\Users\Kpa\.ssh> cat .\id_rsa.pub登录主机,将公钥写入
authorized_keys并设置权限:shssh kpa@192.168.2.13 cd ~ mkdir -p .ssh && echo "上面公钥内容" > .ssh/authorized_keys chmod 700 .ssh && chmod 600 .ssh/authorized_keysWindows 侧配置连接信息,在
C:\Users\Kpa\.ssh\config中加入:Host 192.168.2.13 HostName 192.168.2.13 User kpa IdentityFile C:\Users\Kpa\.ssh\id_rsa
查看手机信息
编译前确认设备信息,源码分支与内核版本均以此为准。
| 信息类型 | 命令 | 示例输出 |
|---|---|---|
| 设备型号 | adb shell getprop ro.product.model | Pixel 3 |
| 设备品牌 | adb shell getprop ro.product.brand | |
| 设备制造商 | adb shell getprop ro.product.manufacturer | |
| 操作系统版本 | adb shell getprop ro.build.version.release | 11 |
| 硬件信息 | adb shell getprop ro.hardware | blueline |
| 产品名称 | adb shell getprop ro.product.name | blueline |
| Build ID | adb shell getprop ro.build.id | RQ3A.211001.001 |
| 构建版本号 | adb shell getprop ro.build.version.incremental | 7641976 |
| 构建描述 | adb shell getprop ro.build.description | blueline-user 11 RQ3A.211001.001 7641976 release-keys |
| 构建日期 | adb shell getprop ro.build.date | Sat Aug 14 01:17:42 UTC 2021 |
| 内核版本 | uname -a | Linux localhost 4.9.248-gc4689af91bc5-ab7425221 #0 SMP PREEMPT Fri Jun 4 06:01:28 UTC 2021 aarch64 |
获取源码
源码分支由 AOSP tag 唯一确定,tag 可由设备的 ro.build.id 在官网反查。
根据
ro.build.id(RQ3A.211001.001)查询对应的 AOSP tag:https://source.android.com/docs/setup/about/build-numbers?hl=zh-cn查询结果:
Build Id 标记 版本 支持的设备 安全补丁级别 RQ3A.211001.001 android-11.0.0_r46 Android11 Pixel 3、Pixel 3 XL、Pixel 3a、Pixel 3a XL、Pixel 4、Pixel 4 XL、Pixel 4a、Pixel 4a (5G)、Pixel 5 2021-10-01 即 tag 为
android-11.0.0_r46,后续按该 tag 拉取源码。根据 build id 查询对应的驱动文件:https://developers.google.cn/android/drivers?hl=zh-cn
适用于 Android 11.0.0(RQ3A.211001.001)的 Pixel 3 二进制文件:
硬件组件 公司 下载 SHA-256 校验和 供应商图片 Google 下载 845382bc012a70ae69b03be70a16532d1f92e759bc5c65e85ad1a3417c80f485GPS、音频、相机、手势、图形、DRM、视频、传感器 Qualcomm 下载 b12a986161e912e3afd71e57d31d2b4e5c682a8f70c31b37c064fe4bc08de5ad根据 build id 查询对应的原厂刷机包:https://developers.google.cn/android/images?hl=zh-cn
- 版本:11.0.0(RQ3A.211001.001,2021 年 10 月)
- 在线刷机:Flash
- 刷机包下载:blueline-rq3a.211001.001-factory-2cca4239.zip
- SHA-256:
2cca42397f29cc3b032dbd2b627e65049ffd894be4801a39c292e663d01cbc71
确认 Pixel 3 对应的内核版本代号:https://source.android.com/docs/setup/build/building-pixel-kernels?hl=zh-cn#legacy-kernel-branches
设备 AOSP 树中的二进制文件路径 仓库分支 Pixel 3 (blueline)、Pixel 3 XL (crosshatch) device/google/crosshatch-kernel android-msm-crosshatch-4.9-android12
环境准备
Debian 13 下安装 LXD 作为容器管理工具。
# 安装 LXD(Debian 13 软件源中包名为 incus)
sudo apt update
sudo apt install -y incus
# 将当前用户加入 incus-admin 组,之后操作容器无需每次都加 sudo
sudo adduser $USER incus-admin
# 当前终端激活分组(不用重新登录),之后所有 incus 命令都不需要 sudo
newgrp incus-admin
# 初始化向导会依次询问网络与存储配置;日常本地开发一路回车(全部默认值)即可
incus admin init
# 验证服务可用
incus list配置 Git
在宿主机上配置 git 提交身份与镜像重定向:
git config --global user.email "473926009@qq.com"
git config --global user.name "kpa"
# 将 android.googlesource.com 重定向到科大镜像,后续 repo 拉取自动走镜像
git config --global url."https://mirrors.ustc.edu.cn/aosp/".insteadOf "https://android.googlesource.com/"下载 Repo 工具
在宿主机上执行:
sudo apt install repo -y
# 安装好后执行 repo -h 检查再通过科大代理获取官方脚本,并将 repo 自我更新源持久指向国内镜像:
mkdir -p ~/bin
PATH=~/bin:$PATH
# 下载 repo 脚本(清华镜像,连接更稳)
curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > ~/bin/repo
chmod a+x ~/bin/repo
# 关键:指定 repo 自我更新的国内镜像源
export REPO_URL='https://gerrit-googlesource.proxy.ustclug.org/git-repo'
# 建议把上面两项永久写入 ~/.bashrc
echo 'export PATH=~/bin:$PATH' >> ~/.bashrc
echo "export REPO_URL='https://gerrit-googlesource.proxy.ustclug.org/git-repo'" >> ~/.bashrc拉取 AOSP 源码
在宿主机上按 tag android-11.0.0_r46 初始化仓库,--depth=1 浅克隆:
mkdir aosp && cd aosp
repo init -u https://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-11.0.0_r46 --depth=1
# 同步代码
repo sync -c -j4创建 aosp11 容器
容器系统镜像按手机目标系统选择:目标为 Android 11,编译容器使用 Ubuntu 18.04。官方远程镜像 images:ubuntu/18.04 已因过期下架,无法再用 incus launch 直接拉取,改为手动下载官方归档并导入为本地镜像。
# 1. 下载官方归档(amd64 为例)
wget https://cloud-images.ubuntu.com/releases/bionic/release/ubuntu-18.04-server-cloudimg-amd64-lxd.tar.xz
wget https://cloud-images.ubuntu.com/releases/bionic/release/ubuntu-18.04-server-cloudimg-amd64.squashfs
# 2. 导入为本地镜像
incus image import ubuntu-18.04-server-cloudimg-amd64-lxd.tar.xz ubuntu-18.04-server-cloudimg-amd64.squashfs --alias ubuntu-18.04
# 3. 启动并进入容器
incus launch ubuntu-18.04 aosp11
incus exec aosp11 -- bash常用容器操作(容器名 aosp11):
| 操作 | 命令 | 说明 |
|---|---|---|
| 查看状态 | incus list | 查看所有容器的运行状态、IP、资源占用 |
| 进入容器 | incus exec aosp11 -- bash | 相当于 SSH 登录进容器终端 |
| 退出终端 | exit | 退出终端回到宿主机(容器仍会继续运行) |
| 停止容器 | incus stop aosp11 | 类似于关机,下班不用时可以关掉 |
| 启动容器 | incus start aosp11 | 启动已经存在的容器(不用再 launch 了) |
| 重启容器 | incus restart aosp11 | 重启容器 |
| 彻底删除 | incus delete -f aosp11 | 强制删除容器(-f 表示即使在运行也强行删除) |
| 主机/容器拷文件 | incus file push 本地文件 aosp11/root/ | 将宿主机文件拷贝进容器 |
| 容器/主机拷文件 | incus file pull aosp11/root/文件 本地路径 | 将容器里的文件拷回宿主机 |
挂载源码到容器
容器只用于编译,源码放在宿主机,以 disk 设备挂载进容器:
# shift=true 利用内核 idmap 机制,让容器内的 root 读写该目录时自动映射为宿主机的 kpa 权限
incus config device add aosp11 aosp_share disk source=/home/kpa/aosp path=/root/aosp shift=true容器内源码目录即 /root/aosp,后续编译在该目录进行。
安装 AOSP 编译环境
在 aosp11 容器内执行:
sudo apt update
sudo apt install flex bison build-essential zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc fontconfig -y
sudo apt install make git-core gnupg zip unzip curl python3 openjdk-11-jdk -y
sudo apt clean && sudo apt autoremove -y配置内存交换空间
本机器 64G 内存,无需配置交换空间;内存低于 32G 时再开启(32G 内存编译到一半进程会被 kill):
sudo swapoff /swapfile
sudo rm /swapfile
sudo fallocate -l 32G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 配置永久交换
# /etc/fstab
# 最后一行插入,进入后按 i 进入编辑模式,修改好按 ESC :wq
sudo apt-get install vim
sudo vim /etc/fstab
/swapfile swap swap defaults 0 0
# 配置交换规则
# /etc/sysctl.conf
sudo vim /etc/sysctl.conf
vm.min_free_kbytes=1500000 # 大致 1.5G,启用交换
# 重启生效下载驱动文件
- 下载驱动和官方刷机包:https://developers.google.cn/android/drivers
- 机型和代号关联:https://source.android.google.cn/docs/setup/build/running?hl=zh-cn#selecting-device-build
用 build id RQ3A.211001.001 搜索,得到对应 Pixel 3 二进制文件:
| 硬件组件 | 公司 | 下载 | SHA-256 校验和 |
|---|---|---|---|
| 供应商图片 | 下载 | 845382bc012a70ae69b03be70a16532d1f92e759bc5c65e85ad1a3417c80f485 | |
| GPS、音频、相机、手势、图形、DRM、视频、传感器 | Qualcomm | 下载 | b12a986161e912e3afd71e57d31d2b4e5c682a8f70c31b37c064fe4bc08de5ad |
在宿主机上执行:
export ALL_PROXY="http://192.168.2.12:7890"
cd ~/aosp_driver
wget https://googledownloads.cn/dl/android/aosp/google_devices-blueline-rq3a.211001.001-4c450e6d.tgz
wget https://googledownloads.cn/dl/android/aosp/qcom-blueline-rq3a.211001.001-cec8e6a7.tgz
tar xf google_devices-blueline-rq3a.211001.001-4c450e6d.tgz
tar xf qcom-blueline-rq3a.211001.001-cec8e6a7.tgz
cp extract-google_devices-blueline.sh ../aosp
cp extract-qcom-blueline.sh ../aosp
cd ~/aosp
# 按D翻页 输入 I ACCEPT 同意协议
./extract-google_devices-blueline.sh
./extract-qcom-blueline.sh编译
在 aosp11 容器内执行,repo 命令用法参考:https://source.android.com/docs/setup/reference/repo?hl=zh-cn
cd ~/aosp
# 加载 shell 环境变量,只有加载了变量后,对应的命令才可以使用
source ./build/envsetup.sh
# 选择编译哪种版本,lunch 命令输出菜单,列出当前 Android 源码支持的所有设备代号和编译类型,输入相应数字选择
lunch
# lunch 给出的列表选项都是 debug 版本,如果想要纯粹的 user 版本,直接指定运行
lunch aosp_blueline-user
# 设置编译线程,12 代表 12 个线程同时编译
make -j12
# 遇到错误后清理再重新编译
make clean不要删除
aosp/.repo目录,否则相当于重新下载。
编译类型说明:
- user:限制所有权限,用于发布给用户使用的最终版本
- userdebug:开放部分权限,允许 root
- eng:工程师模式,开放所有权限并且有额外的调试工具
启动模拟器
运行模拟器需要硬件加速(KVM),先安装并验证:
# 安装 kvm
sudo apt-get install cpu-checker
sudo chmod 777 -R /dev/kvm
# 测试 kvm
egrep -c '(vmx|svm)' /proc/cpuinfo
kvm-ok
cd ~/aosp
source ./build/envsetup.sh
lunch aosp_x86_64-eng
emulator刷机
编译好之后开始刷机,以 Pixel 3 为例,依次执行:
adb reboot fastboot
# 等待手机进入 fastboot 界面之后
fastboot flashall -w
# 刷机完成之后,执行 fastboot reboot 进入系统
fastboot reboot
fastboot flashall -w在工程外面执行时,要配置$ANDROID_PRODUCT_OUT目录环境
单独编译
在 aosp11 容器内、~/aosp 目录下:
# 设置环境
source ./build/envsetup.sh
lunch aosp_x86_64-eng
# 单独编译 framework
make framework-minus-apex
# 使用 make snod 命令重新生成 system.img,运行模拟器查看
make snod
# 清数据启动
emulator -wipe-data其他相关编译命令
部分编译
# 编译指定目录且不编译依赖
mmm frameworks/base
# 编译当前路径下的模块且不编译依赖
mm
# 编译指定目录且编译依赖
mmma frameworks/base
# 修改隐藏 API:@hide,必须先执行以下命令
make update-api
# 将部分编译后的模块打包进 img
make snodrepo 分支操作
# 创建分支
repo start YOURBRANCH --all
# 遍历并执行 git 命令
repo forall -c git xxx
# 切换分支
repo forall -c git checkout default
# 丢弃分支
repo forall -c git git reset --hard HEAD
# 查看每个目录下的分支并打印目录路径(-p 参数在遍历到每个仓库时先打印当前路径再执行 git 命令)
repo forall -p -c git branch
# 查看分支
repo branch单独编译framework.jar
source ./build/envsetup.sh
lunch aosp_blueline-user
make framework-minus-apex