构建内核

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

本页详细介绍了为 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 树中的二进制路径回购分支
Pixel 7(黑豹)
Pixel 7 Pro(猎豹)
设备/谷歌/pantah-内核android-gs-pantah-5.10-android13-d1
Pixel 6a(蓝鸟)设备/谷歌/bluejay 内核android-gs-bluejay-5.10-android13
Pixel 6(金莺)
Pixel 6 Pro(乌鸦)
设备/谷歌/馄饨内核android-gs-raviole-5.10-android13
Pixel 5a(巴贝特)设备/谷歌/barbet 内核android-msm-barbet-4.19-android13
像素 5(红鳍)
Pixel 4a (5G)(荆棘)
设备/谷歌/红牛内核android-msm-redbull-4.19-android13
Pixel 4a(翻车鱼)设备/谷歌/翻车鱼内核android-msm-sunfish-4.14-android13
像素 4(火焰)
Pixel 4 XL(珊瑚色)
设备/谷歌/珊瑚内核android-msm-coral-4.14-android13
像素 3a (sargo)
Pixel 3a XL(鲣鱼)
设备/谷歌/鲣鱼内核android-msm-bonito-4.9-android12L
Pixel 3(蓝线)
Pixel 3 XL(交叉影线)
设备/谷歌/交叉影线内核android-msm-crosshatch-4.9-android12
Pixel 2(角膜白斑)
Pixel 2 XL (taimen)
设备/谷歌/wahoo 内核android-msm-wahoo-4.4-android10-qpr3
像素(旗鱼)
Pixel XL(马林鱼)
设备/谷歌/马林内核android-msm-marlin-3.18-pie-qpr2
海客960设备/linaro/hikey-内核hikey-linaro-android-4.14
hikey-linaro-android-4.19
通用-android12-5.4
通用-android13-5.10
比格犬 x15设备/ti/beagle_x15-内核omap-beagle-x15-android-4.14
omap-beagle-x15-android-4.19
安卓通用内核不适用common-android-4.4
common-android-4.9
common-android-4.14
common-android-4.19
common-android-4.19-stable
通用-android11-5.4
通用-android12-5.4
通用-android12-5.10
通用-android13-5.10
通用-android13-5.15
通用-android14-5.15
通用安卓主线

构建内核

然后用这个构建内核:

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 和 Emulator):

BUILD_CONFIG=common-modules/virtual-device/build.config.cuttlefish.x86_64 build/build.sh

在 Android 12 中,Cuttlefish 和 Goldfish 融合在一起,因此它们共享同一个内核: virtual_device 。要构建该内核的模块,请使用此构建配置:

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 对单个设备内核的支持。对于未列出的设备,请联系设备制造商。

设备回购分支Kleaf 支持build/build.sh支持
安卓通用内核
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
通用-android11-5.4
通用-android12-5.4
通用-android12-5.10
安卓通用内核通用-android13-5.10
通用-android13-5.15
✅(官方) 1
安卓通用内核通用-android14-5.15
通用安卓主线
db845c通用-android13-5.10
db845c通用-android13-5.15 ✅(官方) 1
db845c通用-android14-5.15
通用安卓主线
虚拟设备(x86_64、arm64)通用-android13-5.10
通用-android13-5.15
✅(官方) 1 ⚠️(无人维护) 2
虚拟设备(x86_64、arm64)通用-android14-5.15
通用安卓主线
虚拟设备(i686、arm)通用-android13-5.10
通用-android13-5.15
虚拟设备(i686、arm)通用-android14-5.15
通用安卓主线
Rockpi4通用-android13-5.10
通用-android13-5.15
Rockpi4通用-android14-5.15
通用安卓主线
海客960 hikey-linaro-android-4.14
hikey-linaro-android-4.19
通用-android12-5.4
通用-android13-5.10
fips140模块通用-android12-5.10
通用-android13-5.10
通用-android13-5.15
fips140模块通用-android14-5.15
通用安卓主线

1 “官方”意味着这是构建内核的官方方式,即使也可以使用替代方式来构建内核。

2 “Unmaintained”意味着用这种方法构建内核应该可以工作,但构建方法没有被持续测试。它可能会在未来停止建设。使用“官方”方式来构建。

运行内核

有多种方法可以运行定制内核。以下是适用于各种开发场景的已知方式。

嵌入到 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

使用这种方法,内核实际上并没有刷新,也不会在重启后持续存在。

自定义内核构建

要为 Kleaf 构建自定义内核构建,请参阅Kleaf 文档

对于build/build.sh ,构建过程和结果可能会受到环境变量的影响。它们中的大多数是可选的,每个内核分支都应该有一个合适的默认配置。这里列出了最常用的。有关完整(和最新)列表,请参阅build/build.sh

环境变量描述例子
BUILD_CONFIG从初始化构建环境的地方构建配置文件。该位置必须相对于 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内核构建的基本输出目录。 OUT_DIR=/path/to/my/out
SKIP_DEFCONFIG跳过make defconfig SKIP_DEFCONFIG=1
SKIP_MRPROPER跳过make mrproper SKIP_MRPROPER=1

本地构建的自定义内核配置

如果您需要定期切换内核配置选项,例如,在处理某个功能时,或者如果您需要为开发目的设置一个选项,您可以通过维护本地修改或构建配置的副本来实现这种灵活性。

将变量POST_DEFCONFIG_CMDS设置为在通常的make defconfig步骤完成后立即评估的语句。由于build.config文件来源于构建环境, build.config中定义的函数可以作为 post-defconfig 命令的一部分调用。

一个常见的例子是在开发期间禁用交叉影线内核的链接时间优化 (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

构建引导映像

可以使用内核构建环境构建引导映像。为此,您需要一个 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构建下载ramdisk-recovery.img构建工件,并将其用作您的 ramdisk 二进制文件。

当您拥有 ramdisk 二进制文件并将其复制到内核构建的根目录中的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替换为bzImageaarch64x86_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