Kernel bauen

Auf dieser Seite wird der Prozess zum Erstellen benutzerdefinierter Kernel für Android-Geräte detailliert beschrieben. Diese Anweisungen führen Sie durch den Prozess der Auswahl der richtigen Quellen, der Erstellung des Kernels und der Einbettung der Ergebnisse in ein Systemabbild, das auf der Grundlage des Android Open Source Project (AOSP) erstellt wurde.

Sie können neuere Kernel-Quellen erwerben, indem Sie Repo verwenden. Erstellen Sie sie ohne weitere Konfiguration, indem Sie build/build.sh im Stammverzeichnis Ihres Quellcodes ausführen.

Herunterladen von Quellen und Build-Tools

Verwenden Sie für aktuelle Kernel repo , um die Quellen, die Toolchain und Build-Skripte herunterzuladen. Einige Kernel (z. B. die Pixel 3-Kernel) erfordern Quellen aus mehreren Git-Repositorys, während andere (z. B. die allgemeinen Kernel) nur eine einzige Quelle erfordern. Die Verwendung des repo Ansatzes stellt eine korrekte Einrichtung des Quellverzeichnisses sicher.

Laden Sie die Quellen für die entsprechende Branche herunter:

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

Eine Liste der Repo-Zweige ( BRANCH ), die mit dem vorherigen Befehl „repo init“ verwendet werden können, finden Sie unter Kernel-Zweige und ihre Build-Systeme .

Einzelheiten zum Herunterladen und Kompilieren von Kerneln für Pixel-Geräte finden Sie unter Erstellen von Pixel-Kerneln .

Aufbau des Kernels

Bauen mit Bazel (Kleaf)

Mit Android 13 wurde das Erstellen von Kerneln mit Bazel eingeführt.

Um den GKI-Kernel für die aarch64-Architektur zu erstellen, überprüfen Sie einen Android Common Kernel-Zweig, der nicht älter als Android 13 ist, und führen Sie dann den folgenden Befehl aus:

tools/bazel build //common:kernel_aarch64_dist

Um eine Verteilung zu erstellen, führen Sie Folgendes aus:

tools/bazel run //common:kernel_aarch64_dist -- --dist_dir=$DIST_DIR

Danach befinden sich die Kernel-Binärdatei, die Module und die entsprechenden Bilder im Verzeichnis $DIST_DIR . Wenn --dist_dir nicht angegeben ist, finden Sie in der Ausgabe des Befehls den Speicherort der Artefakte. Einzelheiten finden Sie in der Dokumentation zu AOSP .

Erstellen mit build.sh (Legacy)

Für Filialen mit oder unter Android 12 ODER Filialen ohne Kleaf:

build/build.sh

Die Kernel-Binärdatei, die Module und das entsprechende Image befinden sich im Verzeichnis out/ BRANCH /dist .

Erstellen der Anbietermodule für das virtuelle Gerät

Android 13 führte das Erstellen von Kerneln mit Bazel (Kleaf) ein und ersetzte build.sh .

Führen Sie Folgendes aus, um die Module von virtual_device zu erstellen:

tools/bazel build //common-modules/virtual-device:virtual_device_x86_64_dist

Um eine Verteilung zu erstellen, führen Sie Folgendes aus:

tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist -- --dist_dir=$DIST_DIR

Weitere Informationen zum Erstellen von Android-Kerneln mit Bazel finden Sie unter. Kleaf – Erstellen von Android-Kerneln mit Bazel .

Einzelheiten zur Kleaf-Unterstützung für einzelne Architekturen finden Sie unter Kleaf-Unterstützung für Geräte und Kernel .

Erstellen der Herstellermodule für das virtuelle Gerät mit build.sh (Legacy)

In Android 12 laufen Cuttlefish und Goldfish zusammen, sodass sie denselben Kernel verwenden: virtual_device . Um die Module dieses Kernels zu erstellen, verwenden Sie diese Build-Konfiguration:

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

Mit Android 11 wurde GKI eingeführt, das den Kernel in ein von Google verwaltetes Kernel-Image und vom Hersteller verwaltete Module unterteilt, die separat erstellt werden.

Dieses Beispiel zeigt eine Kernel-Image-Konfiguration:

BUILD_CONFIG=common/build.config.gki.x86_64 build/build.sh

Dieses Beispiel zeigt eine Modulkonfiguration (Cuttlefish und Emulator):

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

Ausführen des Kernels

Es gibt mehrere Möglichkeiten, einen benutzerdefinierten Kernel auszuführen. Im Folgenden sind bekannte Methoden aufgeführt, die für verschiedene Entwicklungsszenarien geeignet sind.

Einbettung in den Android-Image-Build

Kopieren Sie Image.lz4-dtb an den entsprechenden Kernel-Binärspeicherort im AOSP-Baum und erstellen Sie das Boot-Image neu.

Alternativ können Sie die Variable TARGET_PREBUILT_KERNEL definieren, während Sie make bootimage (oder eine andere make Befehlszeile, die ein Boot-Image erstellt) verwenden. Diese Variable wird von allen Geräten unterstützt, da sie über device/common/populate-new-device.sh eingerichtet wird. Zum Beispiel:

export TARGET_PREBUILT_KERNEL=DIST_DIR/Image.lz4-dtb

Flashen und Booten von Kerneln mit Fastboot

Die meisten neueren Geräte verfügen über eine Bootloader-Erweiterung, um den Prozess des Generierens und Bootens eines Boot-Images zu optimieren.

So booten Sie den Kernel ohne Flashen:

adb reboot bootloader
fastboot boot Image.lz4-dtb

Bei dieser Methode wird der Kernel nicht wirklich geflasht und bleibt auch nach einem Neustart nicht bestehen.

Ausführen von Kerneln auf Tintenfisch

Sie können Kernel in der Architektur Ihrer Wahl auf Cuttlefish-Geräten ausführen.

Um ein Cuttlefish-Gerät mit einem bestimmten Satz von Kernel-Artefakten zu starten, führen Sie den Befehl cvd start mit den Ziel-Kernel-Artefakten als Parameter aus. Der folgende Beispielbefehl verwendet Kernel-Artefakte für ein arm64-Ziel aus dem Kernel-Manifest common-android14-6.1 .

cvd start \
    -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

Weitere Informationen finden Sie unter Kernel auf Cuttlefish entwickeln .

Anpassen des Kernel-Builds

Informationen zum Anpassen der Kernel-Builds für Kleaf-Builds finden Sie in der Kleaf-Dokumentation .

Anpassen des Kernel-Builds mit build.sh (Legacy)

Für build/build.sh können der Build-Prozess und das Build-Ergebnis durch Umgebungsvariablen beeinflusst werden. Die meisten davon sind optional und jeder Kernelzweig sollte über eine ordnungsgemäße Standardkonfiguration verfügen. Die am häufigsten verwendeten sind hier aufgelistet. Eine vollständige (und aktuelle) Liste finden Sie unter build/build.sh .

Umgebungsvariable Beschreibung Beispiel
BUILD_CONFIG Build-Konfigurationsdatei, von der aus Sie die Build-Umgebung initialisieren. Der Speicherort muss relativ zum Repo-Stammverzeichnis definiert werden. Standardmäßig ist build.config .
Obligatorisch für gängige Kernel.
BUILD_CONFIG=common/build.config.gki.aarch64
CC Überschreiben Sie den zu verwendenden Compiler. Greift auf den durch build.config definierten Standard-Compiler zurück. CC=clang
DIST_DIR Basisausgabeverzeichnis für die Kernel-Distribution. DIST_DIR=/path/to/my/dist
OUT_DIR Basisausgabeverzeichnis für den Kernel-Build. OUT_DIR=/path/to/my/out
SKIP_DEFCONFIG Überspringen Sie make defconfig SKIP_DEFCONFIG=1
SKIP_MRPROPER Überspringen Sie make mrproper SKIP_MRPROPER=1

Benutzerdefinierte Kernelkonfiguration für lokale Builds

In Android 14 und höher können Sie Defconfig-Fragmente verwenden, um Kernel-Konfigurationen anzupassen. siehe Kleaf-Dokumentation zu Defconfig-Fragmenten .

Benutzerdefinierte Kernel-Konfiguration für lokale Builds mit Build-Konfigurationen (Legacy)

In Android 13 und niedriger finden Sie Folgendes.

Wenn Sie eine Kernel-Konfigurationsoption regelmäßig ändern müssen, beispielsweise wenn Sie an einer Funktion arbeiten, oder wenn Sie eine Option für Entwicklungszwecke festlegen müssen, können Sie diese Flexibilität erreichen, indem Sie eine lokale Änderung oder Kopie der Build-Konfiguration beibehalten.

Setzen Sie die Variable POST_DEFCONFIG_CMDS auf eine Anweisung, die direkt nach Abschluss des üblichen Schritts make defconfig ausgewertet wird. Da die build.config Dateien aus der Build-Umgebung stammen, können in build.config definierte Funktionen als Teil der Post-defconfig-Befehle aufgerufen werden.

Ein häufiges Beispiel ist die Deaktivierung der Link Time Optimization (LTO) für Crosshatch-Kernel während der Entwicklung. Während LTO für veröffentlichte Kernel von Vorteil ist, kann der Overhead zur Build-Zeit erheblich sein. Das folgende zur lokalen build.config hinzugefügte Snippet deaktiviert LTO dauerhaft, wenn build/build.sh verwendet wird.

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)
}

Identifizieren von Kernel-Versionen

Sie können die richtige Version zum Erstellen aus zwei Quellen ermitteln: dem AOSP-Baum und dem System-Image.

Kernelversion aus dem AOSP-Baum

Der AOSP-Baum enthält vorgefertigte Kernelversionen. Das Git-Protokoll zeigt die richtige Version als Teil der Commit-Nachricht:

cd $AOSP/device/VENDOR/NAME
git log --max-count=1

Wenn die Kernel-Version nicht im Git-Protokoll aufgeführt ist, rufen Sie sie wie unten beschrieben aus dem System-Image ab.

Kernel-Version aus dem System-Image

Um die in einem Systemabbild verwendete Kernelversion zu ermitteln, führen Sie den folgenden Befehl für die Kerneldatei aus:

file kernel

Führen Sie für Image.lz4-dtb Dateien Folgendes aus:

grep -a 'Linux version' Image.lz4-dtb

Erstellen eines Boot-Images

Es ist möglich, mithilfe der Kernel-Build-Umgebung ein Boot-Image zu erstellen.

Erstellen eines Boot-Images für Geräte mit init_boot

Bei Geräten mit der init_boot Partition wird das Boot-Image zusammen mit dem Kernel erstellt. Das initramfs Image ist nicht in das Boot-Image eingebettet.

Mit Kleaf können Sie beispielsweise das GKI-Boot-Image erstellen mit:

tools/bazel run //common:kernel_aarch64_dist -- --dist_dir=$DIST_DIR

Mit build/build.sh (Legacy) können Sie das GKI-Boot-Image erstellen mit:

BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh

Das GKI-Boot-Image befindet sich in $DIST_DIR .

Erstellen eines Boot-Images für Geräte ohne init_boot (Legacy)

Für Geräte ohne die init_boot Partition benötigen Sie eine Ramdisk-Binärdatei, die Sie erhalten können, indem Sie ein GKI-Boot-Image herunterladen und entpacken. Jedes GKI-Boot-Image der zugehörigen Android-Version funktioniert.

tools/mkbootimg/unpack_bootimg.py --boot_img=boot-5.4-gz.img
mv $KERNEL_ROOT/out/ramdisk gki-ramdisk.lz4

Der Zielordner ist das Verzeichnis der obersten Ebene des Kernelbaums (das aktuelle Arbeitsverzeichnis).

Wenn Sie mit AOSP Main entwickeln, können Sie stattdessen das Build-Artefakt ramdisk-recovery.img von einem aosp_arm64-Build auf ci.android.com herunterladen und dieses als Ihre Ramdisk-Binärdatei verwenden.

Wenn Sie über eine Ramdisk-Binärdatei verfügen und diese nach gki-ramdisk.lz4 im Stammverzeichnis des Kernel-Builds kopiert haben, können Sie ein Boot-Image generieren, indem Sie Folgendes ausführen:

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

Wenn Sie mit einer x86-basierten Architektur arbeiten, ersetzen Sie Image durch bzImage und aarch64 durch 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

Diese Datei befindet sich im Artefaktverzeichnis $KERNEL_ROOT/out/$KERNEL_VERSION/dist .

Das Boot-Image befindet sich unter out/<kernel branch>/dist/boot.img .