查阅、下载与构建 AOSP 源码:环境与资源准备
环境与源码准备:查阅、下载、构建与运行 AOSP
很多人想读 AOSP,第一反应是先凑一台服务器。这个念头本身没有错,问题是它常常在还没想清楚要做什么之前就发生了。读一条调用链和编一个系统镜像,需要的机器差了好几个数量级。所以这篇先不讲命令,先把目标拆开。
先按目标选择投入
下面四种想法,最容易让人白白花钱或者白白等待:
| 常见误解 | 更准确的理解 |
|---|---|
| 看 AOSP 源码必须有一台 400GB 磁盘、64GB 内存的机器 | 官方的 400GB / 64GB 口径针对的是全量构建 main 分支,只查阅或只同步源码的投入小得多 |
下载 AOSP 就是 git clone | AOSP 由上千个 Git 仓库组成,官方用 repo 按 manifest 批量管理 |
| 编译产物必须放在源码目录里 | 输出默认在 out/,可以通过 OUT_DIR 放到另一块盘,编译本身不会污染源码 |
| 源码编译完就能直接跑模拟器 | 模拟器需要匹配的产品目标和 KVM 加速;真机还要解锁引导加载器,并准备厂商闭源库 |
先确定自己属于哪一种场景,再决定投入多少:
- 只想查代码、读调用链:浏览器加 Android Code Search 就够了,不需要下载源码。
- 想本地搜索、看 Git 历史、用编辑器跳转:同步源码即可,16GB 内存加 250GB 磁盘是起点。
- 想编译出系统镜像并在模拟器或真机上运行:按官方全量构建的要求准备 64GB 内存、400GB 磁盘和 Linux。
- 想定制 ROM 或做系统开发:在第 3 项的基础上,还需要一台受支持的目标设备,或者稳定的模拟器环境。
核心结论
- 查阅优先用 Android Code Search:免费、可搜索、可跨引用,还能切换分支。
- 下载用
repo:先repo init -u <manifest> -b <tag>,再repo sync -c -j8;国内网络可以配合清华或中科大的镜像。 - 编译分五步:导入环境、选择目标、构建、启动模拟器。对应命令是
source build/envsetup.sh → lunch → m → emulator;main分支自带预构建的 JDK、Make 和 Python 3。 - 环境按场景分级:查阅没有硬件要求,同步大约需要 250GB 磁盘,全量构建按官方要求是 64 位 Linux、400GB 磁盘和 64GB 内存。
- 真机运行比模拟器多两道门槛:解锁引导加载器,以及下载与源码 tag 匹配的厂商闭源二进制。
从查阅到运行的完整路径
下图把本章的主线串了起来:先确定目标,再准备环境,然后同步、构建、运行,最后回到排障闭环。失败时可以回到对应的环节,不必整体推倒重来。

一、查阅源码:最快的起步方式
大多数阅读场景其实不需要本地源码,直接用 Android Code Search 就行。
它是官方的代码搜索服务,覆盖 AOSP 全仓库,支持:
- 按项目、目录浏览源码,例如直接打开
frameworks/base/services/core/java/com/android/server/wm/; - 全局搜索类名、方法名或字符串,并跳转到定义和调用处;
- 点击符号查看跨文件引用,适合追调用链;
- 在页面右上角切换分支或 tag,例如从
main切到android-14.0.0_r75。
其他常用的查阅入口如下:
| 入口 | 特点 | 适合 |
|---|---|---|
| cs.android.com | 官方、可搜索、可跨引用、可切分支 | 日常查代码、追调用链 |
| github.com/aosp-mirror | 非官方 GitHub 镜像,单个仓库好浏览 | 快速打开某个仓库,不做全局搜索 |
本地源码树 + rg | 速度最快,支持正则和 Git 历史 | 需要深入检索、修改代码或对比版本 |
本地源码树里最常用的是两条命令:
rg -n "addWindow" frameworks/base/services
git log --oneline -5 -- frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.javarg 回答“这段逻辑在哪里”,git log 和 git blame 回答“这段逻辑是什么时候变成现在这样的”。两者配合着用,定位效率会高很多。阅读方法本身可以接着看 Android Framework 到底是什么 中“从 AOSP 根目录找到 Framework”一节。
二、设备要求:按场景给硬件预算
先选场景,再买设备。一开始就按全量构建的标准配机器,通常是浪费。
| 场景 | CPU | 内存 | 磁盘 | 说明 |
|---|---|---|---|---|
| 只在线查阅 | 任意 | 任意 | 任意 | 浏览器即可 |
| 只同步源码并本地阅读 | 双核以上 | 16GB 起 | 约 250GB 可用 | .repo 与工作区都占用磁盘 |
全量构建 main 分支 | 核数越多越好 | 64GB 起 | 400GB 以上 | 官方最低要求 |
| 构建后跑模拟器 | 支持虚拟化的 x86_64 | 32GB 以上 | 上述磁盘之外再加镜像空间 | 需要 /dev/kvm |
| 构建后刷真机 | 同全量构建 | 64GB 起 | 400GB 以上 | 另需一台受支持的目标设备 |
以下是官方“针对 AOSP 开发进行设置”页面(2025 年更新)给出的口径:
- 开发工作站需要 64 位 x86 Linux,glibc 2.17 及以上。
- 检出和构建代码至少需要 400GB 可用磁盘,其中 250GB 用于检出,150GB 用于构建。
- 至少 64GB 内存。Google 的参考机器是 72 核加 64GB 内存,全量构建约 40 分钟;同样 64GB 内存换成 6 核,全量构建约 6 小时。
- 构建 Android 11 及以上版本,需要 Ubuntu 18.04 或更高版本。
这里有两个容易忽略的地方。第一,64GB 是全量构建的口径,只编译个别模块(m <模块名>),或者更老的版本,可以放宽要求,但不要为此去挑战全量构建。第二,内存不足时系统会用到 swap,构建时间会成倍增长,所以磁盘再大也替代不了内存。
三、设备环境要求:操作系统、磁盘与目标设备
操作系统
官方完整支持的只有 64 位 Linux。AOSP main 分支自带预构建的 OpenJDK、Make 和 Python 3,不需要额外安装。在 Ubuntu 或 Debian 上,系统依赖包只需安装一次:
sudo apt-get install git-core gnupg flex bison build-essential zip curl \
zlib1g-dev libc6-dev-i386 x11proto-core-dev libx11-dev lib32z1-dev \
libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfigWindows 和 macOS 不在官方支持范围内。WSL2、虚拟机或容器属于自行折腾的方案,可以拿来学习,但要把“不受官方保证”当作前提。遇到诡异的构建错误时,优先回到 Linux 上验证。
磁盘与文件系统
源码和构建产物要放在区分大小写的 Linux 文件系统上,例如 ext4。FAT、NTFS、exFAT 不支持符号链接和大小写语义,会导致 repo sync 失败或构建异常。
构建期间 out/ 会迅速膨胀,磁盘要预留独立的空间。开始前先运行 df -h 确认余量。如果想把输出放到另一块盘,可以设置 export OUT_DIR=/path/to/other/disk,但要注意两块盘的读写速度差异会直接影响构建时间。
模拟器与虚拟化
Linux 上运行 Android 模拟器需要 KVM 加速。构建机如果跑在云服务器上,常常没有嵌套虚拟化,模拟器会极慢,甚至直接起不来。启动前可以先检查:
ls -l /dev/kvm
egrep -c '(vmx|svm)' /proc/cpuinfo/dev/kvm 存在,并且 CPU 标志计数大于 0,才说明硬件虚拟化可用。
真机要求
官方支持刷 AOSP 的设备主要是 Nexus 和 Pixel 系列。刷机之前需要满足三个条件:
- 引导加载器已解锁(unlocked bootloader);
- 下载并解压与源码 tag 匹配的厂商闭源二进制(proprietary binaries)。自解压脚本会把文件放进
vendor/,之后需要重新构建; - 有可用的
adb和fastboot,并确认设备连接正常。
没有合适的真机,可以用 Cuttlefish 虚拟设备直接运行 main 分支。它不需要厂商闭源库,是云端和 CI 中常用的方案。
四、耗材与资源预算
这里说的“耗材”,是指这次投入会被实际消耗掉的资源:磁盘、内存、CPU、网络带宽和时间。预算算清楚,同步到一半卡死的情况会少很多。
| 耗材 | 量级与说明 | 建议 |
|---|---|---|
| 磁盘 | 检出约 250GB,构建再占约 150GB;多分支或多产品还要再加 | 按 400GB 可用起步,用 df -h 盯住余量 |
| 网络带宽 | 首次同步的下载量很大,是否带全量历史影响很大 | 用 --partial-clone,国内优先走镜像源 |
| 内存 | 全量构建官方要求 64GB;不足会触发 swap,拖慢构建 | 不要用 swap 代替内存 |
| CPU | 核数几乎线性决定全量构建时间:6 核约 6 小时,72 核约 40 分钟 | 预算有限时优先核数,其次内存 |
| 时间 | 首次同步加首次构建,留出半天到一天 | 中途断网或断电后重跑即可,不必放弃 |
| 电量与运行成本 | 长时间满负荷构建,笔记本或云主机会持续吃资源 | 云主机按小时计费,先算清楚再开始 |
repo sync 中断后直接重跑就能续传。repo sync <某个项目> 可以只重试失败的项目。网络很差时,把并发降下来:repo sync -c -j1。
五、下载源码:repo 初始化与同步
安装 repo
最省事的方式是用系统包:
sudo apt-get update
sudo apt-get install repo
repo version官方也提供手动安装:从 https://storage.googleapis.com/git-repo-downloads/repo 下载启动器,用公钥 8BB9AD793E8E6153AF0F9A4416530D5E920F5C65 校验后放到 ~/bin/repo。repo version 输出应不低于 2.4。
国内网络拉不动默认源时,先把启动器指向清华镜像:
export REPO_URL=https://mirrors.tuna.tsinghua.edu.cn/git/git-repo选择分支或 tag
学习阶段用稳定的 tag,想追新功能就用 main。
官方示例初始化的是 main 分支:
mkdir aosp-main
cd aosp-main
repo init --partial-clone -b main \
-u https://android.googlesource.com/platform/manifest本知识库的例子锁定在 Android 14 r75:
repo init --partial-clone -b android-14.0.0_r75 \
-u https://android.googlesource.com/platform/manifest-b 指定分支或 tag,-u 指定 manifest 仓库,两者缺一不可。完整的 tag 与 build number 对照表见官方“源代码标记和 build”页面。另外要注意,android-14.0.0_r75 是源码 tag,不是手机“设置 → 关于手机”里看到的系统版本号,两者不要混用。
同步
repo sync -c -j8-c 表示只取当前分支,减少历史数据的下载;-j8 是并发数。官方口径是在正常网络下大约需要一个多小时,实际时间取决于带宽、镜像,以及是否带全量历史。
国内镜像
常用镜像做法是把 manifest 地址整体替换,启动器地址单独配置:
# 清华镜像
export REPO_URL=https://mirrors.tuna.tsinghua.edu.cn/git/git-repo
repo init --partial-clone -b android-14.0.0_r75 \
-u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest
# 中科大镜像
repo init --partial-clone -b android-14.0.0_r75 \
-u git://mirrors.ustc.edu.cn/aosp/platform/manifest如果已经用官方源初始化过,重新执行一次带镜像地址的 repo init 即可切换后续的同步地址,源码无需删除。同步时遇到 http 403 或 500,优先换镜像或降低并发,不要反复硬试。
六、构建与运行
标准五步
在源码树根目录执行:
source build/envsetup.sh
lunch aosp_x86_64-eng
m -j$(nproc)
emulator逐步说明如下:
source build/envsetup.sh导入lunch、m、emulator等命令。lunch选择产品目标。不带参数会列出可选目标;官方 AVD 示例用sdk_phone_x86_64,main分支的云端示例用aosp_cf_x86_64_phone-trunk_staging-userdebug。学习时用aosp_x86_64-eng最省时间。m从源码树顶部开始构建,-j$(nproc)指定并行任务数;不传-j时构建系统会自行决定。只想验证构建配置,可以运行m nothing。emulator启动当前构建的产物。运行前先确认/dev/kvm可用,否则会非常慢。
目标名由三段组成:产品、发布配置和构建变体。构建变体有三种:
| 变体 | 用途 |
|---|---|
user | 生产环境,限制最多 |
userdebug | 面向开发,比 user 多了调试能力,真机调试常用 |
eng | 构建最快,适合日常开发和学习 |
查看当前目标:echo "$TARGET_PRODUCT-$TARGET_BUILD_VARIANT"。
构建产物在哪里
镜像输出在 out/target/product/<产品名>/,例如 system.img、vendor.img、boot.img。源码没有改动时,增量构建只需要几分钟到几十分钟。切换产品目标或 tag 之后,输出目录会重建,所以要为 out/ 预留足够的磁盘。
模拟器与 Cuttlefish
传统模拟器(AVD)适合本机有图形环境的场景,Cuttlefish 则适合云端和无头环境。两者使用的产品目标不同:AVD 常用 sdk_phone_x86_64 或 aosp_x86_64-eng,Cuttlefish 使用 aosp_cf_x86_64_phone-* 系列。学习阶段选一个就够,不要两套一起折腾。
真机刷机
刷真机比模拟器多两步:
- 到官方二进制下载页下载与源码 tag 匹配的专有二进制,在源码根目录运行自解压脚本,把文件解压到
vendor/,然后重新构建。 - 解锁引导加载器后,用
fastboot devices确认设备,再执行fastboot flashall刷入镜像。
刷机前先确认三件事:设备在官方支持列表里,blobs 版本与源码 tag 匹配,引导加载器已经解锁。任何一项不匹配,设备都可能无法开机,刷之前先保留原厂镜像,便于回退。
七、验证与排障
开始前先确认环境:Linux 终端可用,网络能访问镜像或官方源,磁盘已经预留出空间。
df -h # 磁盘余量
repo version # repo 版本
ls -l /dev/kvm # 模拟器加速
echo "$TARGET_PRODUCT-$TARGET_BUILD_VARIANT" # 当前 lunch 目标
adb devices # 真机连接状态出现问题时,可以先对照下表:
| 现象 | 优先检查 | 常见原因 |
|---|---|---|
repo sync 报 http 403 或 500 | 换镜像;repo sync -j1 | 官方源不稳定,或被网络环境限制 |
repo init 卡在下载启动器 | REPO_URL 是否指向 git-repo 镜像 | 默认的 Google 源拉取失败 |
| 构建被 kill 或极慢 | 内存、swap、-j 并发数 | 内存不足,swap 拖垮构建 |
| 磁盘写满 | df -h,清理 out/ | 构建前没有预留足够空间 |
emulator 起不来或黑屏 | /dev/kvm、CPU 虚拟化标志 | 没有 KVM,或者不支持嵌套虚拟化 |
| 真机刷完不开机 | blobs 版本、引导加载器状态 | 版本不匹配,或者引导加载器未解锁 |
常见误区
- 只想看源码,却按全量构建的标准配机器。先用 Android Code Search,几乎零成本。
- 把
repo当成 Git 的替代品。repo是管理多仓库的封装,底层操作仍然是 Git。 - 用手机的系统版本号代替源码 tag。
android-14.0.0_r75是源码快照的标识,build number 是产物的标识。 - 以为所有 Android 手机都能刷 AOSP。只有官方支持的设备,在解锁引导加载器并配上匹配的 blobs 之后,才能跑起来。
- 认为 Windows 下“应该也能编译”。官方只支持 glibc 的 Linux,WSL2 属于自担风险的方案。
- 用大 swap 代替内存。构建会慢到无法使用,内存是硬指标。
- 把不同 tag 的结论混在一起用。阅读和排障时锁定一个 tag,结论才能复现。
延伸问题
- manifest 文件里的
project和revision分别是什么意思?企业内部如何维护定制的 manifest? --partial-clone缺少了哪些历史?需要完整的git log时怎么补?ccache或sccache如何加速重复构建?- Cuttlefish 与传统 AVD 在镜像格式、启动参数和云端适配上有哪些差异?
out/target/product/<产品名>/下的system.img、vendor.img、boot.img分别对应哪些分区?
源码入口
| 文件或目录 | 作用 |
|---|---|
build/envsetup.sh | 提供 lunch、m、emulator 等命令 |
.repo/manifest.xml | 记录各 Git 项目的位置与 revision |
build/make/core/ | 主构建系统与产品规则 |
device/generic/goldfish/ | 传统模拟器的产品定义 |
device/google/cuttlefish/ | Cuttlefish 虚拟设备 |
out/target/product/<产品名>/ | 构建镜像的输出目录 |