建構核心

本頁詳細說明為 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` 指令搭配使用的存放區分支 (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 複製到 Android 開放原始碼計畫 樹狀結構中的相應核心二進位檔位置,然後重建開機映像檔。

或者,您也可以在使用 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 中定義的函式,做為後置 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