第2章:AOSP源码环境搭建

好,咱们正式开始动手了。这一章我带你搭好AOSP的编译环境。说实话,这一步看着简单,但坑是真不少。我当年第一次搞的时候,光环境就折腾了两天——嗯,后来发现是JDK版本没选对。

2.1 Ubuntu环境配置

我个人习惯用Ubuntu 20.04 LTS,64位系统。为什么?因为Google官方推荐的就是这个版本,兼容性最好。你非要用22.04也行,但有些依赖包得自己额外处理。

硬件要求

  • CPU:至少4核,8核以上更佳(我编译AOSP时,8核大概40分钟,4核要1.5小时)
  • 内存:16GB起步,32GB是舒适区
  • 硬盘:至少250GB空闲空间(完整编译一次AOSP,大概占用150GB)
  • 文件系统:建议ext4,NTFS会有权限问题

装好系统后,第一件事就是安装必要的依赖包。别偷懒,少一个包编译就会报错。我曾经因为漏了libssl-dev,卡了整整一个下午。

sudo apt-get update
sudo apt-get install -y git-core gnupg flex bison build-essential \
  zip curl 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 unzip fontconfig

小技巧:如果你用的是Ubuntu 22.04,记得把libncurses5换成libncurses5-dev,否则会报找不到头文件。

2.2 Repo工具使用

Repo是Google专门为AOSP开发的代码管理工具。说白了,它就是Git的管家——帮你同时管理几百个Git仓库。

安装Repo很简单:

mkdir -p ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH

这里有个坑:Repo的版本很重要。我建议用最新的稳定版,别用太老的。有一次我用了个两年前的版本,结果同步代码时一直报SSL错误——折腾半天才发现是Repo版本太旧,不支持新的TLS协议。

Repo的常用命令,我列个表:

命令 作用 我的经验
repo init 初始化Repo仓库 记得加-u参数指定manifest地址
repo sync 同步所有仓库代码 第一次同步建议加-j4,别贪多
repo start 创建本地分支 每个功能模块单独建分支,方便管理
repo status 查看所有仓库状态 比git status好用,一目了然

2.3 AOSP源码下载与同步

源码下载是重头戏。你想想看,AOSP源码有多大?完整版大概60GB左右。所以网络一定要稳定,最好用有线连接。

先初始化:

mkdir aosp
cd aosp
repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r30

这里-b参数指定分支。我建议新手从android-13.0.0_r30开始,这个版本比较稳定,文档也全。别一上来就搞最新的android-14,有些驱动还没适配好。

然后开始同步:

repo sync -j4 -c

注意:-j4表示4个线程并行下载。别设太大,比如-j32,你的路由器可能会崩溃。我试过-j16,结果路由器过热重启了...嗯,从那以后我就老实了。

同步过程中如果中断了,别慌。重新执行repo sync就行,它会断点续传。不过要注意,如果网络特别差,建议加个--fail-fast参数,这样某个仓库失败时不会卡住整个流程。

2.4 编译环境初始化

代码下好了,接下来就是配置编译环境。这一步很关键,直接决定你能不能编译成功。

首先,安装JDK。AOSP 13需要OpenJDK 11:

sudo apt-get install openjdk-11-jdk

然后设置环境变量。我个人习惯把下面这段加到~/.bashrc里:

export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
export ANDROID_JAVA_HOME=$JAVA_HOME

接着,进入源码目录,执行初始化脚本:

source build/envsetup.sh

这个脚本会加载一堆编译相关的函数。你执行完后,会看到类似这样的输出:

including device/asus/fugu/vendorsetup.sh
including device/generic/car/emulator/vendorsetup.sh
including device/generic/goldfish/vendorsetup.sh
...

然后选择编译目标:

lunch aosp_arm64-eng

这里aosp_arm64-eng的意思是:

  • aosp_arm64:目标设备是64位ARM模拟器
  • eng:工程版本,带调试工具

建议:第一次编译选eng版本。user版本会去掉很多调试功能,出了问题不好排查。我刚开始就选了user,结果有个驱动加载失败,日志里啥信息都没有——白折腾了两天。

最后,开始编译:

make -j$(nproc)

nproc会返回你的CPU核心数。比如8核机器,就相当于make -j8。编译时间取决于你的硬件配置,一般30分钟到2小时不等。

编译过程中如果报错,别急着重来。先看错误日志,大部分问题都是依赖缺失或环境变量没配好。我遇到过最奇葩的一次,是Python版本不对——AOSP 13要求Python 3.8以上,而我系统里默认的还是3.6。

编译成功标志:看到类似下面的输出,就说明你成功了:

#### build completed successfully (00:45:32) ####

生成的镜像文件在out/target/product/generic_arm64/目录下。

好了,环境搭好了,代码也编译通过了。下一章咱们就开始研究OTA升级的核心机制——说实话,这部分才是真正有意思的地方。