本頁詳細介紹了為 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-qpr1 |
Pixel 6a(藍鳥) | 設備/谷歌/bluejay 內核 | android-gs-bluejay-5.10-android13-qpr1 |
Pixel 6(金鶯) Pixel 6 Pro(烏鴉) | 設備/谷歌/餛飩內核 | android-gs-raviole-5.10-android13-qpr1 |
Pixel 5a(巴貝特) 像素 5(紅鰭) Pixel 4a (5G)(荊棘) | 設備/谷歌/紅牛內核 | android-msm-redbull-4.19-android13-qpr1 |
Pixel 4a(翻車魚) | 設備/谷歌/翻車魚內核 | android-msm-sunfish-4.14-android13-qpr1 |
像素 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 通用-android14-6.1 通用安卓主線 |
構建內核
然後用這個構建內核:
build/build.sh
內核二進製文件、模塊和相應的映像位於out/ BRANCH /dist
目錄中。
使用 Bazel (Kleaf) 構建
Android 13 引入了使用Bazel構建內核,取代了build/build.sh
。
要為 aarch64 架構構建 GKI 內核,請查看不早於 Android 13 的 Android Common Kernel 分支,然後運行以下命令:
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 通用-android14-6.1 通用安卓主線 | ✅ | ❌ |
db845c | 通用-android13-5.10 | ❌ | ✅ |
db845c | 通用-android13-5.15 | ✅ | ✅(官方) 1 |
db845c | 通用-android14-5.15 通用-android14-6.1 通用安卓主線 | ✅ | ❌ |
虛擬設備(x86_64、arm64) | 通用-android13-5.10 通用-android13-5.15 | ✅(官方) 1 | ⚠️(無人維護) 2 |
虛擬設備(x86_64、arm64) | 通用-android14-5.15 通用-android14-6.1 通用安卓主線 | ✅ | ❌ |
虛擬設備(i686、arm) | 通用-android13-5.10 通用-android13-5.15 | ❌ | ✅ |
虛擬設備(i686、arm) | 通用-android14-5.15 通用-android14-6.1 通用安卓主線 | ✅ | ❌ |
Rockpi4 | 通用-android13-5.10 通用-android13-5.15 | ❌ | ✅ |
Rockpi4 | 通用-android14-5.15 通用-android14-6.1 通用安卓主線 | ✅ | ❌ |
海客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
構建引導映像
可以使用內核構建環境構建引導映像。
使用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構建下載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
。