4. 开发环境搭建

GKI内核构建不是“下载一个内核源码、敲一条make”就能完成的事情。它依赖一整套与AOSP版本严格匹配的主机环境、源码树和工具链。本章把开发环境拆成五个可验证的环节:Ubuntu主机准备、编译依赖安装、repo工具与AOSP源码下载、Android内核源码获取、目录结构解析。每个环节都给出可执行的命令和判断标准,避免“装完却编不过”的常见困境。

一、核心原理:为什么环境必须“版本对齐”

Android内核构建的本质是“用AOSP提供的构建系统,把内核源码编译成boot.img中的kernel”。这里的依赖关系是双向的:内核源码的构建脚本(如build/build.sh、build_abi.sh)来自AOSP的kernel/build仓库;而AOSP的构建又依赖主机上的Python、JDK、GCC/Clang、libc等版本。任何一处版本漂移,都会在编译中途以“找不到符号”“ABI不匹配”“Python模块缺失”等形式爆发。

因此,环境搭建的目标不是“装上最新版”,而是“装上与目标Android版本匹配的版本”。例如Android 13的GKI内核通常要求Ubuntu 20.04/22.04、Python 3.8+、OpenJDK 11,并使用AOSP预置的Clang工具链,而不是系统自带的GCC。

关键原则:主机环境、AOSP分支、内核分支、工具链四者必须来自同一份版本说明(如Android 13的android13-5.15内核分支对应android-13.0.0_r*的AOSP标签)。

二、Ubuntu主机配置与编译依赖安装

推荐使用Ubuntu 20.04 LTS或22.04 LTS的物理机/虚拟机,磁盘至少400GB(AOSP+内核源码+编译产物),内存建议32GB以上,否则链接阶段极易OOM。首先安装基础依赖:

sudo apt update
sudo apt install -y git curl python3 python3-pip openjdk-11-jdk \
  build-essential zip unzip flex bison libssl-dev libelf-dev \
  bc rsync ccache libncurses5-dev libncursesw5-dev \
  gcc-multilib g++-multilib libc6-dev-i386 lib32z1-dev

接着配置git身份与repo工具。repo是Google用Python写的多仓库管理脚本,必须放在PATH中:

git config --global user.name "Your Name"
git config --global user.email "you@example.com"
mkdir -p ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH

验证依赖是否齐全,可用AOSP自带的检查脚本(下载源码后执行):source build/envsetup.sh后运行lunch,若提示缺少包,按提示补装即可。

三、AOSP源码下载与repo工作流

AOSP源码体积巨大,必须使用repo init指定分支和清单,再repo sync拉取。以Android 13为例:

mkdir ~/aosp && cd ~/aosp
repo init -u https://android.googlesource.com/platform/manifest \
  -b android-13.0.0_r3 --depth=1
repo sync -c -j8 --no-tags --no-clone-bundle

-c只拉当前分支,--depth=1浅克隆,能显著减少下载量。若网络不稳定,可配置国内镜像源,但需注意镜像的同步时间可能滞后。同步完成后,repo status应无报错,ls能看到build/、kernel/、device/等目录。

repo常用命令:repo sync -c增量同步;repo start <分支名> --all为所有仓库创建本地分支;repo forall -c "git reset --hard"批量重置。

四、Android内核源码获取与目录结构解析

GKI内核源码不在AOSP主manifest中,而是独立的kernel/common仓库。获取方式有两种:一是用repo初始化内核manifest,二是直接git clone。推荐前者,便于管理多个内核分支:

mkdir ~/kernel && cd ~/kernel
repo init -u https://android.googlesource.com/kernel/manifest \
  -b common-android13-5.15
repo sync -c -j8

同步后目录结构如下,理解它是后续配置和编译的基础:

目录/文件作用GKI适配关注点
common/内核主体源码(Linux 5.15)驱动、Kconfig、Makefile所在
common/arch/arm64/ARM64架构相关代码设备树、defconfig、boot协议
common/drivers/设备驱动厂商驱动常以模块形式加入
build/构建脚本与工具链配置build.sh、build_abi.sh
prebuilts/预编译Clang、GCC工具链必须使用此处的Clang
common/abi/ABI符号列表GKI ABI稳定性校验

其中build/build.sh是内核编译入口,build/build_abi.sh用于生成和校验ABI。GKI的核心约束是“内核镜像与厂商模块之间的ABI必须稳定”,因此common/abi/下的符号列表是适配时的红线,不能随意增删导出符号。

GKI开发环境搭建与源码获取流程 Ubuntu主机 20.04 / 22.04 LTS ≥400GB磁盘 · ≥32GB内存 OpenJDK 11 · Python 3.8+ 编译依赖 build-essential · flex · bison libssl-dev · libelf-dev · bc ccache · rsync · zip/unzip repo工具 ~/bin/repo 加入PATH repo init / repo sync 多仓库统一管理 版本对齐 AOSP标签 内核分支 Clang工具链 AOSP源码下载 repo init -u .../platform/manifest -b android-13.0.0_r3 --depth=1 repo sync -c -j8 --no-tags 产出:build/ kernel/ device/ Android内核源码获取 repo init -u .../kernel/manifest -b common-android13-5.15 repo sync -c -j8 产出:common/ build/ prebuilts/ 内核源码目录结构(GKI适配关注点) common/ 内核主体 arch/arm64/ 设备树与defconfig drivers/ 厂商驱动 build/ 构建脚本 prebuilts/ 预置Clang common/abi/ ABI符号列表

五、案例场景:从零到可编译的验证路径

假设目标设备是Pixel 6(Android 13,内核5.15)。完整验证路径如下:

  1. 在Ubuntu 22.04上安装依赖,配置repo并加入PATH。
  2. 下载AOSP android-13.0.0_r3,执行source build/envsetup.sh和lunch aosp_oriole-userdebug,确认无缺包报错。
  3. 下载内核common-android13-5.15,进入common/执行BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh。
  4. 编译成功后,在out/android13-5.15/dist/下应看到Image.lz4、System.map、vmlinux等产物。
  5. 用build/build_abi.sh --update检查ABI是否与common/abi/一致,若不一致需分析新增/删除的符号。
常见误区:直接用系统GCC编译内核。GKI必须使用prebuilts/clang/host/linux-x86/下的Clang,否则会出现“unknown register name”或ABI校验失败。另一个误区是忽略--depth=1导致下载数百GB历史数据,磁盘瞬间占满。

六、复盘与检查清单

环境搭建完成后,用以下清单逐项确认,可避免90%的编译失败:

  • Ubuntu版本是否为20.04/22.04,磁盘剩余是否大于200GB。
  • repo是否在PATH中,repo --version能否正常输出。
  • AOSP分支与内核分支是否来自同一Android版本说明。
  • build/build.sh是否使用prebuilts中的Clang。
  • common/abi/下的符号列表是否与当前内核分支匹配。
  • 编译产物是否包含Image.lz4和System.map。

完成以上步骤后,主机环境、AOSP源码、repo工具、编译依赖和内核源码树均已就绪,且目录结构清晰可查。后续的GKI内核配置、编译与ABI校验,都将在这个基础上展开。