Creazione di kernel

In questa pagina viene descritta la procedura di creazione di kernel personalizzati per i dispositivi Android. Queste istruzioni ti guidano nella procedura di selezione delle origini corrette, di compilazione del kernel e di incorporamento dei risultati in un'immagine di sistema creata dal progetto Android Open Source (AOSP).

Puoi acquisire sorgenti del kernel più recenti utilizzando Repo; compilale senza ulteriore configurazione eseguendo build/build.sh dalla radice del tuo checkout del codice sorgente.

Scaricare origini e strumenti di compilazione

Per i kernel recenti, usa repo per scaricare i sorgenti, la toolchain e gli script di build. Alcuni kernel (ad esempio i kernel di Pixel 3) richiedono sorgenti di più repository git, mentre altri (ad esempio i kernel comuni) richiedono solo una singola sorgente. L'utilizzo dell'approccio repo garantisce una configurazione corretta della directory di origine.

Scarica le origini per il ramo appropriato:

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

Per un elenco dei rami di repository (BRANCH) che possono essere utilizzati con il comando "repo init" precedente, consulta Ramo del kernel e relativi sistemi di build.

Per maggiori dettagli sul download e la compilazione dei kernel per i dispositivi Pixel, consulta la pagina relativa alla creazione di kernel Pixel.

Compila il kernel

Crea con Bazel (Kleaf)

Android 13 ha introdotto la compilazione dei kernel con Bazel.

Per creare una distribuzione per il kernel GKI per l'architettura aarch64, controlla un ramo del kernel Android Common non precedente ad Android 13 e poi esegui il seguente comando:

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

Dopodiché, il programma binario del kernel, i moduli e le immagini corrispondenti si trovano nella directory $DIST_DIR. Se --destdir non è specificato, consulta l'output del comando per la posizione degli elementi. Per maggiori dettagli, consulta la documentazione su AOSP.

Crea con build.sh (legacy)

Per i branch con Android 12 o versioni precedenti OPPURE branch senza Kleaf:

build/build.sh

Il file binario del kernel, i moduli e l'immagine corrispondente si trovano nella directory out/BRANCH/dist.

Crea i moduli del fornitore per il dispositivo virtuale

Android 13 ha introdotto la compilazione dei kernel con Bazel (Kleaf), sostituendo build.sh.

Per creare una distribuzione per i moduli di virtual_device, esegui:

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

Per maggiori dettagli sulla compilazione dei kernel Android con Bazel, consulta Kleaf - Building Android Kernels with Bazel.

Per informazioni dettagliate sul supporto di Kleaf per le singole architetture, consulta Supporto di Kleaf per dispositivi e kernel.

Crea i moduli del fornitore per il dispositivo virtuale con build.sh (legacy)

In Android 12, Cuttlefish e Goldfish convergono, quindi condividono lo stesso kernel: virtual_device. Per creare i moduli del kernel, usa questa configurazione di compilazione:

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

Android 11 ha introdotto GKI, che separa il kernel in un'immagine del kernel gestita da Google e in moduli gestiti dal fornitore, che vengono compilati separatamente.

Questo esempio mostra una configurazione dell'immagine del kernel:

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

Questo esempio mostra una configurazione del modulo (Cuttlefish ed emulatore):

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

Esegui il kernel

Esistono diversi modi per eseguire un kernel personalizzato. Di seguito sono riportati metodi noti adatti a vari scenari di sviluppo.

Incorporare nella compilazione dell'immagine Android

Copia Image.lz4-dtb nella rispettiva posizione del file binario del kernel all'interno dell'albero AOSP e ricostruisci l'immagine di avvio.

In alternativa, definisci la variabile TARGET_PREBUILT_KERNEL durante l'utilizzo di make bootimage (o di qualsiasi altra riga di comando make che genera un'immagine di avvio). Questa variabile è supportata da tutti i dispositivi perché è configurata tramite device/common/populate-new-device.sh. Ad esempio:

export TARGET_PREBUILT_KERNEL=DIST_DIR/Image.lz4-dtb

Eseguire il flashing e l'avvio dei kernel con fastboot

I dispositivi più recenti dispongono di un'estensione del bootloader per semplificare il processo di generazione e avvio di un'immagine di avvio.

Per avviare il kernel senza eseguire il flashing:

adb reboot bootloader
fastboot boot Image.lz4-dtb

Con questo metodo, il kernel non viene effettivamente eseguito il flashing e non persiste dopo un riavvio.

.

Esegui i kernel su Cuttlefish

Puoi eseguire i kernel nell'architettura che preferisci sui dispositivi Cuttlefish.

Per avviare un dispositivo Cuttlefish con un determinato insieme di elementi del kernel, esegui il comando cvd create con gli elementi del kernel di destinazione come parametri. Il seguente comando di esempio utilizza gli elementi del kernel per un target arm64 dal manifest del kernel common-android14-6.1.

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

Per ulteriori informazioni, consulta Sviluppare kernel su Cuttlefish.

Personalizzare la compilazione del kernel

Per personalizzare le build del kernel per le build Kleaf, consulta la documentazione di Kleaf.

Personalizzare la compilazione del kernel con build.sh (legacy)

Per build/build.sh, il processo di compilazione e il risultato possono essere influenzati dalle variabili di ambiente. La maggior parte è facoltativa e ogni ramo del kernel dovrebbe essere dotato di una configurazione predefinita corretta. Le più utilizzate sono elencate qui. Per un elenco completo (e aggiornato), consulta build/build.sh.

Variabile di ambiente Descrizione Esempio
BUILD_CONFIG File di configurazione della build da cui viene inizializzato l'ambiente di compilazione. La località deve essere definita relativa alla directory radice del repository. Il valore predefinito è build.config.
Obbligatorio per i kernel comuni.
BUILD_CONFIG=common/build.config.gki.aarch64
CC Esegui l'override del compilatore da utilizzare. Viene utilizzato il compilatore predefinito definito da build.config. CC=clang
DIST_DIR Directory di output di base per la distribuzione del kernel. DIST_DIR=/path/to/my/dist
OUT_DIR Directory di output di base per la compilazione del kernel. OUT_DIR=/path/to/my/out
SKIP_DEFCONFIG Salta make defconfig SKIP_DEFCONFIG=1
SKIP_MRPROPER Salta make mrproper SKIP_MRPROPER=1

Configurazione del kernel personalizzata per le build locali

In Android 14 e versioni successive, puoi utilizzare i frammenti defconfig per personalizzare le configurazioni del kernel. Consulta la documentazione di Kleaf sui frammenti defconfig.

Configurazione del kernel personalizzata per le build locali con configurazioni di build (legacy)

In Android 13 e versioni precedenti, vedi quanto segue.

Se devi cambiare regolarmente un'opzione di configurazione del kernel, ad esempio quando lavori a una funzionalità, o se devi impostare un'opzione per scopi di sviluppo, puoi ottenere questa flessibilità mantenendo una modifica o una copia locale della configurazione di compilazione.

Imposta la variabile POST_DEFCONFIG_CMDS su un'istruzione che viene valutata subito dopo il completamento del consueto passaggio make defconfig. Poiché i file build.config vengono inseriti nell'ambiente di compilazione, le funzioni definite in build.config possono essere chiamate nell'ambito dei comandi post-defconfig.

Un esempio comune è la disattivazione dell'ottimizzazione in fase di linking (LTO) per i kernel a tratteggiato durante lo sviluppo. Sebbene l'LTO sia vantaggioso per i kernel rilasciati, l'overhead in fase di build può essere significativo. Il seguente snippet aggiunto al build.config locale disabilita l'LTO in modo permanente quando utilizzi build/build.sh.

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

Identificare le versioni del kernel

Puoi identificare la versione corretta da compilare da due origini: la struttura AOSP e l'immagine di sistema.

Versione del kernel dall'albero AOSP

L'albero AOSP contiene versioni del kernel predefinite. Il log Git rivela la versione corretta come parte del messaggio di commit:

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

Se la versione del kernel non è elencata nel log di git, ottienila dall'immagine di sistema, come descritto di seguito.

Versione del kernel dall'immagine di sistema

Per determinare la versione del kernel utilizzata in un'immagine di sistema, esegui il seguente comando sul file del kernel:

file kernel

Per i file Image.lz4-dtb, esegui:

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

Crea un'immagine di avvio

È possibile creare un'immagine di avvio utilizzando l'ambiente di build del kernel.

Crea un'immagine di avvio per i dispositivi con init_boot

Per i dispositivi con la partizione init_boot, l'immagine di avvio viene compilata insieme al kernel. L'immagine initramfs non è incorporata nell'immagine di avvio.

Ad esempio, con Kleaf, puoi creare l'immagine di avvio GKI con:

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

Con build/build.sh (legacy), puoi creare l'immagine di avvio GKI con:

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

L'immagine di avvio GKI si trova in $DIST_DIR.

Crea un'immagine di avvio per i dispositivi senza init_boot (legacy)

Per i dispositivi senza la partizione init_boot, è necessario un file binario ramdisk, che puoi ottenere scaricando un'immagine di avvio GKI e scompattandola. È possibile utilizzare qualsiasi immagine di avvio GKI della release Android associata.

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

La cartella di destinazione è la directory di primo livello dell'albero del kernel (la directory di lavoro corrente).

Se stai sviluppando con AOSP main, puoi invece scaricare l'ramdisk-recovery.img elemento dell'artifact di compilazione da una compilazione aosp_arm64 su ci.android.com e utilizzarlo come file binario del ramdisk.

Quando hai un file binario ramdisk e lo hai copiato in gki-ramdisk.lz4 nella directory principale della compilazione del kernel, puoi generare un'immagine di avvio eseguendo:

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

Se utilizzi un'architettura basata su x86, sostituisci Image con bzImage e aarch64 con 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

Il file si trova nella directory degli elementi $KERNEL_ROOT/out/$KERNEL_VERSION/dist.

L'immagine di avvio si trova in out/<kernel branch>/dist/boot.img.