本页详细介绍了为 Android 设备构建自定义内核的流程。以下说明会逐步指导您如何选择正确的源代码,构建内核,以及将结果嵌入到根据 Android 开源项目 (AOSP) 构建的系统映像中。
您可以使用 Repo 获取最新的内核源代码;通过在源代码检出的根目录下运行 build/build.sh
可构建这些内核源代码,而无需更多配置。
下载源代码和构建工具
对于最新的内核,可以使用 repo
下载源代码、工具链和构建脚本。一些内核(例如 Pixel 3 内核)需要从多个 git 仓库获取源代码,而其他内核(如通用内核)只需要一份源代码。使用 repo
方法可确保源目录设置正确。
下载相应分支的源代码:
mkdir android-kernel && cd android-kernel
repo init -u https://android.googlesource.com/kernel/manifest -b BRANCH
repo sync
下表列出了可通过此方法获取的内核的 BRANCH 名称。
设备 | AOSP 树中的二进制文件路径 | Repo 分支 |
---|---|---|
Pixel 7 (panther) Pixel 7 Pro (cheetah) |
device/google/pantah-kernel | android-gs-pantah-5.10-android13-qpr2 |
Pixel 6a (bluejay) | device/google/bluejay-kernel | android-gs-bluejay-5.10-android13-qpr2 |
Pixel 6 (oriole) Pixel 6 Pro (raven) |
device/google/raviole-kernel | android-gs-raviole-5.10-android13-qpr2 |
Pixel 5a (barbet) Pixel 5 (redfin) Pixel 4a (5G) (bramble) |
device/google/redbull-kernel | android-msm-redbull-4.19-android13-qpr2 |
Pixel 4a (sunfish) | device/google/sunfish-kernel | android-msm-sunfish-4.14-android13-qpr2 |
Pixel 4 (flame) Pixel 4 XL (coral) |
device/google/coral-kernel | android-msm-coral-4.14-android13 |
Pixel 3a (sargo) Pixel 3a XL (bonito) |
device/google/bonito-kernel | android-msm-bonito-4.9-android12L |
Pixel 3 (blueline) Pixel 3 XL (crosshatch) |
device/google/crosshatch-kernel | android-msm-crosshatch-4.9-android12 |
Pixel 2 (walleye) Pixel 2 XL (taimen) |
device/google/wahoo-kernel | android-msm-wahoo-4.4-android10-qpr3 |
Pixel (sailfish) Pixel XL (marlin) |
device/google/marlin-kernel | android-msm-marlin-3.18-pie-qpr2 |
Hikey960 | device/linaro/hikey-kernel | hikey-linaro-android-4.14 hikey-linaro-android-4.19 common-android12-5.4 common-android13-5.10 |
Beagle x15 | device/ti/beagle_x15-kernel | omap-beagle-x15-android-4.14 omap-beagle-x15-android-4.19 |
Android 通用内核 | N/A | common-android-4.4 common-android-4.9 common-android-4.14 common-android-4.19 common-android-4.19-stable common-android11-5.4 common-android12-5.4 common-android12-5.10 common-android13-5.10 common-android13-5.15 common-android14-5.15 common-android14-6.1 common-android-mainline |
构建内核
然后使用以下内容构建内核:
build/build.sh
内核二进制文件、模块和相应的映像位于 out/BRANCH/dist
目录下。
使用 Bazel 构建 (Kleaf)
Android 13 引入了使用 Bazel 构建内核的功能,以取代 build/build.sh
。
如需为 aarch64 架构构建 GKI 内核,请查看不低于 Android 13 的 Android 通用内核分支,然后运行以下命令:
tools/bazel build //common:kernel_aarch64_dist
如需创建分发版本,请运行以下命令:
tools/bazel run //common:kernel_aarch64_dist -- --dist_dir=$DIST_DIR
之后,内核二进制文件、模块和相应的映像会置于 $DIST_DIR
目录中。如果未指定 --dist_dir
,请参阅该命令的输出以了解工件的位置。如需了解详情,请参阅 AOSP 文档。
为虚拟设备构建供应商模块
Android 11 引入了 GKI,用于将内核拆分为由 Google 维护的内核映像和由供应商维护的模块,二者分别单独构建。
以下示例展示了内核映像配置:
BUILD_CONFIG=common/build.config.gki.x86_64 build/build.sh
以下示例展示了模块配置(Cuttlefish 和模拟器):
BUILD_CONFIG=common-modules/virtual-device/build.config.cuttlefish.x86_64 build/build.sh
在 Android 12 中,Cuttlefish 和 Goldfish 融合,因此它们共享同一个内核:virtual_device
。如需构建该内核的模块,请使用以下 build 配置:
BUILD_CONFIG=common-modules/virtual-device/build.config.virtual_device.x86_64 build/build.sh
Android 13 引入了使用 Bazel (Kleaf) 构建内核的功能,以取代 build.sh
。
如需构建 virtual_device
的模块,请运行以下命令:
tools/bazel build //common-modules/virtual-device:virtual_device_x86_64_dist
如需创建分发版本,请运行以下命令:
tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist -- --dist_dir=$DIST_DIR
如需详细了解如何使用 Bazel 构建 Android 内核,请参阅:Kleaf - 使用 Bazel 构建 Android 内核。
如需详细了解对各个架构的 Kleaf 支持,请参阅对设备和内核的 Kleaf 支持。
对设备和内核的 Kleaf 支持
下表列出了对各个设备内核的 Kleaf 支持。对于未列出的设备,请与设备制造商联系。
设备 | Repo 分支 | Kleaf 支持 | build/build.sh 支持 |
---|---|---|---|
Android 通用内核 db845c 虚拟设备(x86_64、arm64) 虚拟设备(i686、arm) Rockpi4 |
common-android-4.4 common-android-4.9 common-android-4.14 common-android-4.19 common-android-4.19-stable common-android11-5.4 common-android12-5.4 common-android12-5.10 |
❌ | ✅ |
Android 通用内核 | common-android13-5.10 common-android13-5.15 |
✅ | ✅(官方)1 |
Android 通用内核 | common-android14-5.15 common-android14-6.1 common-android-mainline |
✅ | ❌ |
db845c | common-android13-5.10 | ❌ | ✅ |
db845c | common-android13-5.15 | ✅ | ✅(官方)1 |
db845c | common-android14-5.15 common-android14-6.1 common-android-mainline |
✅ | ❌ |
虚拟设备(x86_64、arm64) | common-android13-5.10 common-android13-5.15 |
✅(官方)1 | ⚠️(未维护)2 |
虚拟设备(x86_64、arm64) | common-android14-5.15 common-android14-6.1 common-android-mainline |
✅ | ❌ |
虚拟设备(i686、arm) | common-android13-5.10 common-android13-5.15 |
❌ | ✅ |
虚拟设备(i686、arm) | common-android14-5.15 common-android14-6.1 common-android-mainline |
✅ | ❌ |
Rockpi4 | common-android13-5.10 common-android13-5.15 |
❌ | ✅ |
Rockpi4 | common-android14-5.15 common-android14-6.1 common-android-mainline |
✅ | ❌ |
Hikey960 | hikey-linaro-android-4.14 hikey-linaro-android-4.19 common-android12-5.4 common-android13-5.10 |
❌ | ✅ |
fips140 模块 | common-android12-5.10 common-android13-5.10 common-android13-5.15 |
❌ | ✅ |
fips140 模块 | common-android14-5.15 | ✅ | ❌ |
1“官方”表示此为官方的内核构建方式,即使也有可能采用其他方式构建内核。 2“未维护”表示使用此方法应该可以构建内核,但此构建方法未持续测试。未来,此方法可能会停止构建。请改用“官方”方法进行构建。 |
运行内核
您可以通过多种方式运行以自定义方式构建的内核。下面介绍了几种适合各种开发场景的已知方法。
嵌入到 Android 映像构建中
将 Image.lz4-dtb
复制到 AOSP 树中相应的内核二进制文件位置,然后重新构建启动映像。
或者,您也可以在使用 make bootimage
(或用于构建启动映像的任何其他 make
命令行)时定义 TARGET_PREBUILT_KERNEL
变量。所有设备均支持该变量,因为它是通过 device/common/populate-new-device.sh
进行设置的。例如:
export TARGET_PREBUILT_KERNEL=DIST_DIR/Image.lz4-dtb
使用 fastboot 刷新和启动内核
最新的设备具有引导加载程序扩展,可以简化生成和启动启动映像的过程。
要启动内核而不刷新,请运行以下命令:
adb reboot bootloader
fastboot boot Image.lz4-dtb
使用此方法时,内核实际上并未刷新,因此不会在重新启动时保留。
自定义内核 build
如需为 Kleaf build 自定义内核 build,请参阅 Kleaf 文档。
对于 build/build.sh
,构建流程和结果可能会受环境变量的影响。它们中的大多数是可选的,并且每个内核分支都应该具有适当的默认配置。此处列出了最常用的变量。如需完整(且最新)的列表,请参阅 build/build.sh
。
环境变量 | 说明 | 示例 |
---|---|---|
BUILD_CONFIG |
用于初始化构建环境的 build 配置文件。必须相对于 Repo 根目录定义其具体位置。默认为 build.config 。必须为通用内核指定此变量。 |
BUILD_CONFIG=common/build.config.gki.aarch64 |
CC |
替换要使用的编译器。回退至 build.config 定义的默认编译器。 |
CC=clang |
DIST_DIR |
内核分发版本的基本输出目录。 | DIST_DIR=/path/to/my/dist |
OUT_DIR |
内核 build 的基本输出目录。 | OUT_DIR=/path/to/my/out |
SKIP_DEFCONFIG |
跳过 make defconfig |
SKIP_DEFCONFIG=1 |
SKIP_MRPROPER |
跳过 make mrproper |
SKIP_MRPROPER=1 |
本地构建的自定义内核配置
如果您需要定期切换内核配置选项(例如在开发某项功能时),或者需要设置一个用于开发的选项,可以通过维护 build 配置的本地修改或副本来实现这种灵活性。
将 POST_DEFCONFIG_CMDS 变量设为一个在常规 make defconfig
步骤完成后立即接受评估的语句。由于 build.config
文件源于构建环境,因此 build.config
中定义的函数可以作为 post-defconfig 命令的一部分进行调用。
一个常见示例是在开发期间针对 crosshatch 内核停用链接时优化 (LTO)。虽然 LTO 对已发布的内核有益,但构建时产生的开销可能巨大。添加到本地 build.config
的以下代码段将在使用 build/build.sh
时永久停用 LTO。
POST_DEFCONFIG_CMDS="check_defconfig && update_debug_config"
function update_debug_config() {
${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \
-d LTO \
-d LTO_CLANG \
-d CFI \
-d CFI_PERMISSIVE \
-d CFI_CLANG
(cd ${OUT_DIR} && \
make O=${OUT_DIR} $archsubarch CC=${CC} CROSS_COMPILE=${CROSS_COMPILE} olddefconfig)
}
确定内核版本
您可以通过以下两个来源确定要构建的正确版本:AOSP 树和系统映像。
AOSP 树中的内核版本
AOSP 树包含预构建的内核版本。git 日志会在提交消息中显示正确的版本:
cd $AOSP/device/VENDOR/NAME
git log --max-count=1
如果内核版本未在 git 日志中列出,请从系统映像中获取,如下所述。
系统映像中的内核版本
如需确定系统映像中使用的内核版本,请对内核文件运行以下命令:
file kernel
对于 Image.lz4-dtb
文件,请运行以下命令:
grep -a 'Linux version' Image.lz4-dtb
构建启动映像
可以使用内核构建环境构建启动映像。
使用 init_boot
为设备构建启动映像
对于具有 init_boot
分区的设备,启动映像会与内核一起构建。initramfs
映像未嵌入到启动映像中。
例如,使用 Kleaf,您或许可使用以下代码构建 GKI 启动映像:
tools/bazel run //common:kernel_aarch64_dist -- --dist_dir=$DIST_DIR
借助 build/build.sh
,您或许可使用以下代码构建 GKI 启动映像:
BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
GKI 启动映像位于 $DIST_DIR 中。
在不使用 init_boot
的情况下为设备构建启动映像
对于没有 init_boot
分区的设备来说,您需要一个 ramdisk 二进制文件,该二进制文件可以通过下载 GKI 启动映像后解压缩来获取。关联的 Android 版本中的任何 GKI 启动映像都可以使用。
tools/mkbootimg/unpack_bootimg.py --boot_img=boot-5.4-gz.img
mv $KERNEL_ROOT/out/ramdisk gki-ramdisk.lz4
目标文件夹是内核树的顶级目录(当前的工作目录)。
如果您使用 AOSP master 进行开发,则可以从 ci.android.com 上的 aosp_arm64 build 中下载 ramdisk-recovery.img
构建工件,并将其用作 ramdisk 二进制文件。
当您拥有 ramdisk 二进制文件并将其复制到内核 build 的根目录中的 gki-ramdisk.lz4
时,可以通过执行以下命令来生成启动映像:
BUILD_BOOT_IMG=1 SKIP_VENDOR_BOOT=1 KERNEL_BINARY=Image GKI_RAMDISK_PREBUILT_BINARY=gki-ramdisk.lz4 BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
如果您使用的是基于 x86 的架构,请将 Image
替换为 bzImage
,将 aarch64
替换为 x86_64
:
BUILD_BOOT_IMG=1 SKIP_VENDOR_BOOT=1 KERNEL_BINARY=bzImage GKI_RAMDISK_PREBUILT_BINARY=gki-ramdisk.lz4 BUILD_CONFIG=common/build.config.gki.x86_64 build/build.sh
该文件位于工件目录 $KERNEL_ROOT/out/$KERNEL_VERSION/dist
中。
启动映像位于 out/<kernel branch>/dist/boot.img
。