建構核心

本頁詳細說明為 Android 裝置建構自訂核心的程序。這些指示會逐步引導您選取合適的來源、建構核心,以及將結果嵌入從 Android 開放原始碼計畫 (AOSP) 建構的系統映像檔。

下載來源和建構工具

如要使用近期推出的核心,請使用 repo 下載來源、工具鍊和建構指令碼。部分核心 (例如 Pixel 3 核心) 需要多個 Git 存放區的來源,其他核心 (例如通用核心) 則只需要單一來源。使用 repo 方法可確保來源目錄設定正確無誤。

下載適當分支的來源:

mkdir android-kernel && cd android-kernel
repo init -u https://android.googlesource.com/kernel/manifest -b BRANCH
repo sync

如需可與先前的 `repo init` 指令搭配使用的 Repo 分支 (BRANCH) 清單,請參閱「核心分支及其建構系統」。

如要瞭解如何下載及編譯 Pixel 裝置的 Kernel,請參閱「 建構 Pixel Kernel」。

建構核心

使用 Bazel (Kleaf) 建構

Android 13 導入了使用 Bazel 建構核心的功能。

如要為 aarch64 架構建立 GKI 核心的發行版本,請查看不早於 Android 13 的 Android Common Kernel 分支版本,然後執行下列指令:

tools/bazel run //common:kernel_aarch64_dist [-- --destdir=$DIST_DIR]

之後,核心二進位檔、模組和對應的映像檔會位於 $DIST_DIR 目錄中。如果未指定 --destdir,請參閱指令輸出內容,瞭解構件的位置。詳情請參閱 AOSP 說明文件

使用 build.sh 建構 (舊版)

如果是 Android 12 以下的分支版本,或是沒有 Kleaf 的分支版本:

build/build.sh

核心二進位檔、模組和對應的映像檔位於 out/BRANCH/dist 目錄中。

為虛擬裝置建構供應商模組

Android 13 導入了使用 Bazel (Kleaf) 建構核心的功能,取代 build.sh

如要為 virtual_device 的模組建立發布內容,請執行:

tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist [-- --destdir=$DIST_DIR]

如要進一步瞭解如何使用 Bazel 建構 Android 核心,請參閱。Kleaf - Building Android Kernels with Bazel

如要瞭解 Kleaf 對個別架構的支援情形,請參閱「Kleaf support for devices and kernels」。

使用 build.sh (舊版) 建構虛擬裝置的供應商模組

在 Android 12 中,Cuttlefish 和 Goldfish 會合併,因此共用相同的核心:virtual_device。如要建構該核心的模組,請使用下列建構設定:

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

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 映像檔建構作業

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

使用這個方法時,系統不會實際刷入核心,且重新啟動後不會保留核心。

在 Cuttlefish 上執行核心

您可以在Cuttlefish 裝置上,以所選架構執行核心。

如要使用特定的一組核心構件啟動 Cuttlefish 裝置,請執行 cvd create 指令,並將目標核心構件做為參數。下列範例指令會使用 common-android14-6.1 核心資訊清單中的 arm64 目標核心構件。

cvd create \
    -kernel_path=/$PATH/$TO/common-android14-6.1/out/android14-6.1/dist/Image \
    -initramfs_path=/$PATH/$TO/common-android14-6.1/out/android14-6.1/dist/initramfs.img

詳情請參閱「在 Cuttlefish 上開發核心」。

自訂核心建構作業

如要自訂 Kleaf 建構的 Kernel 建構作業,請參閱 Kleaf 說明文件

使用 build.sh 自訂核心建構作業 (舊版)

對於 build/build.sh,建構程序和結果可能會受到環境變數影響。其中大多數是選用項目,每個核心分支都應附有適當的預設設定。以下列出最常用的幾種。如需完整 (且最新) 的清單,請參閱 build/build.sh

環境變數 說明 範例
BUILD_CONFIG 建構設定檔,您可從中初始化建構環境。 位置必須相對於存放區根目錄定義。預設值為 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

本機建構作業的自訂核心設定

在 Android 14 以上版本中,您可以使用 defconfig 片段自訂核心設定。請參閱 Kleaf 說明文件中的 defconfig 片段

使用建構設定 (舊版) 為本機建構作業自訂核心設定

如果是 Android 13 以下版本,請參閱下列說明。

如果您需要定期切換核心設定選項 (例如開發功能時),或是需要為開發目的設定選項,可以維護建構設定的本機修改項目或副本,達到所需的彈性。

將變數 POST_DEFCONFIG_CMDS 設為陳述式,在完成一般 make defconfig 步驟後立即評估。由於 build.config 檔案會納入建構環境,因此可以呼叫 build.config 中定義的函式,做為 post-defconfig 指令的一部分。

常見的例子是在開發期間,停用 Crosshatch 核心的連結時間最佳化 (LTO)。雖然 LTO 對於發布的 Kernel 有益,但建構時的負擔可能相當大。以下程式碼片段新增至本機 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 樹狀結構和系統映像檔。

Android 開放原始碼計畫樹狀結構中的核心版本

Android 開放原始碼計畫樹狀結構包含預先建構的核心版本。git log 會在提交訊息中顯示正確版本:

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 [-- --destdir=$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 發布分支版本進行開發,可以改為從 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 取代為 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