Núcleos de construcción

Esta página detalla el proceso de creación de kernels personalizados para dispositivos Android. Estas instrucciones lo guían a través del proceso de selección de las fuentes adecuadas, compilación del kernel e incorporación de los resultados en una imagen del sistema creada a partir del Proyecto de código abierto de Android (AOSP).

Puede adquirir fuentes del kernel más recientes utilizando Repo ; constrúyalos sin configuración adicional ejecutando build/build.sh desde la raíz de su pago de origen.

Descarga de fuentes y herramientas de compilación

Para kernels recientes, use repo para descargar las fuentes, la cadena de herramientas y los scripts de compilación. Algunos núcleos (por ejemplo, los núcleos de Pixel 3) requieren fuentes de múltiples repositorios de git, mientras que otros (por ejemplo, los núcleos comunes) requieren solo una única fuente. El uso del enfoque repo garantiza una configuración correcta del directorio de origen.

Descargue las fuentes para la rama correspondiente:

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

Para obtener una lista de ramas de repositorio ( BRANCH ) que se pueden usar con el comando `repo init` anterior, consulte Ramas del kernel y sus sistemas de compilación .

Para obtener detalles sobre la descarga y compilación de kernels para dispositivos Pixel, consulte Creación de kernels de Pixel .

Construyendo el núcleo

Construyendo con Bazel (Kleaf)

Android 13 introdujo la construcción de kernels con Bazel .

Para compilar el kernel GKI para la arquitectura aarch64, consulte una rama del kernel común de Android no anterior a Android 13 y luego ejecute el siguiente comando:

tools/bazel build //common:kernel_aarch64_dist

Para crear una distribución, ejecute:

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

A partir de entonces, el binario del kernel, los módulos y las imágenes correspondientes se ubican en el directorio $DIST_DIR . Si no se especifica --dist_dir , consulte el resultado del comando para conocer la ubicación de los artefactos. Para obtener más información, consulte la documentación sobre AOSP .

Construyendo con build.sh (heredado)

Para sucursales con Android 12 o menos, O sucursales sin Kleaf:

build/build.sh

El binario del kernel, los módulos y la imagen correspondiente se encuentran en el directorio out/ BRANCH /dist .

Creación de módulos de proveedor para el dispositivo virtual

Android 13 introdujo la compilación de kernels con Bazel (Kleaf), reemplazando build.sh .

Para construir los módulos del virtual_device , ejecute:

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

Para crear una distribución, ejecute:

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

Para obtener más detalles sobre la creación de kernels de Android con Bazel, consulte. Kleaf: creación de kernels de Android con Bazel .

Para obtener detalles sobre el soporte de Kleaf para arquitecturas individuales, consulte Soporte de Kleaf para dispositivos y kernels .

Creación de módulos de proveedor para el dispositivo virtual con build.sh (heredado)

En Android 12 Cuttlefish y Goldfish convergen, por lo que comparten el mismo kernel: virtual_device . Para construir los módulos de ese kernel, use esta configuración de compilación:

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

Android 11 introdujo GKI , que separa el kernel en una imagen del kernel mantenida por Google y módulos mantenidos por el proveedor, que se crean por separado.

Este ejemplo muestra una configuración de imagen del kernel:

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

Este ejemplo muestra la configuración de un módulo (Sepia y Emulador):

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

Ejecutando el kernel

Hay varias formas de ejecutar un kernel personalizado. Las siguientes son formas conocidas adecuadas para diversos escenarios de desarrollo.

Incrustar en la compilación de imágenes de Android

Copie Image.lz4-dtb a la ubicación binaria del kernel respectiva dentro del árbol AOSP y reconstruya la imagen de arranque.

Alternativamente, defina la variable TARGET_PREBUILT_KERNEL mientras usa make bootimage (o cualquier otra línea de comando make que cree una imagen de arranque). Esta variable es compatible con todos los dispositivos, ya que se configura a través de device/common/populate-new-device.sh . Por ejemplo:

export TARGET_PREBUILT_KERNEL=DIST_DIR/Image.lz4-dtb

Flasheo y arranque de kernels con fastboot

Los dispositivos más recientes tienen una extensión de cargador de arranque para agilizar el proceso de generación e inicio de una imagen de inicio.

Para iniciar el kernel sin flashear:

adb reboot bootloader
fastboot boot Image.lz4-dtb

Con este método, el kernel en realidad no se actualiza y no persistirá durante el reinicio.

Ejecutar granos en sepia

Puede ejecutar kernels en la arquitectura que elija en dispositivos Cuttlefish .

Para iniciar un dispositivo Cuttlefish con un conjunto particular de artefactos del kernel , ejecute el comando cvd start con los artefactos del kernel de destino como parámetros. El siguiente comando de ejemplo utiliza artefactos del kernel para un objetivo arm64 del manifiesto del kernel 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

Para obtener más información, consulte Desarrollar núcleos en sepia .

Personalizando la compilación del kernel

Para personalizar las compilaciones del kernel para las compilaciones de Kleaf, consulte la documentación de Kleaf .

Personalizando la compilación del kernel con build.sh (heredado)

Para build/build.sh , el proceso de construcción y el resultado pueden verse influenciados por variables de entorno. La mayoría de ellos son opcionales y cada rama del kernel debe venir con una configuración predeterminada adecuada. Los más utilizados se enumeran aquí. Para obtener una lista completa (y actualizada), consulte build/build.sh .

Variable ambiental Descripción Ejemplo
BUILD_CONFIG Cree el archivo de configuración desde donde inicializa el entorno de compilación. La ubicación debe definirse en relación con el directorio raíz del repositorio. El valor predeterminado es build.config .
Obligatorio para núcleos comunes.
BUILD_CONFIG=common/build.config.gki.aarch64
CC Anular el compilador que se utilizará. Vuelve al compilador predeterminado definido por build.config . CC=clang
DIST_DIR Directorio de salida base para la distribución del kernel. DIST_DIR=/path/to/my/dist
OUT_DIR Directorio de salida base para la compilación del kernel. OUT_DIR=/path/to/my/out
SKIP_DEFCONFIG Saltar make defconfig SKIP_DEFCONFIG=1
SKIP_MRPROPER Saltar make mrproper SKIP_MRPROPER=1

Configuración de kernel personalizada para compilaciones locales

En Android 14 y versiones posteriores, puede usar fragmentos defconfig para personalizar las configuraciones del kernel. consulte la documentación de Kleaf sobre fragmentos defconfig .

Configuración de kernel personalizada para compilaciones locales con configuraciones de compilación (heredadas)

En Android 13 y versiones anteriores, consulte lo siguiente.

Si necesita cambiar una opción de configuración del kernel con regularidad, por ejemplo, cuando trabaja en una función, o si necesita configurar una opción para fines de desarrollo, puede lograr esa flexibilidad manteniendo una modificación local o una copia de la configuración de compilación.

Establezca la variable POST_DEFCONFIG_CMDS en una declaración que se evalúe justo después de realizar el paso habitual make defconfig . Como los archivos build.config se obtienen en el entorno de compilación, las funciones definidas en build.config se pueden llamar como parte de los comandos post-defconfig.

Un ejemplo común es deshabilitar la optimización del tiempo de enlace (LTO) para núcleos rayados durante el desarrollo. Si bien LTO es beneficioso para los núcleos lanzados, la sobrecarga en el momento de la compilación puede ser significativa. El siguiente fragmento agregado al build.config local deshabilita LTO de manera persistente cuando se usa 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)
}

Identificar versiones del kernel

Puede identificar la versión correcta para compilar a partir de dos fuentes: el árbol AOSP y la imagen del sistema.

Versión del kernel del árbol AOSP

El árbol AOSP contiene versiones del kernel prediseñadas. El registro de git revela la versión correcta como parte del mensaje de confirmación:

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

Si la versión del kernel no aparece en el registro de git, consígala de la imagen del sistema, como se describe a continuación.

Versión del kernel a partir de la imagen del sistema

Para determinar la versión del kernel utilizada en una imagen del sistema, ejecute el siguiente comando en el archivo del kernel:

file kernel

Para archivos Image.lz4-dtb , ejecute:

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

Construyendo una imagen de arranque

Es posible crear una imagen de arranque utilizando el entorno de compilación del kernel.

Creación de una imagen de arranque para dispositivos con init_boot

Para dispositivos con la partición init_boot , la imagen de arranque se crea junto con el kernel. La imagen initramfs no está incrustada en la imagen de inicio.

Por ejemplo, con Kleaf, puedes crear la imagen de arranque de GKI con:

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

Con build/build.sh (heredado), puede crear la imagen de arranque de GKI con:

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

La imagen de arranque de GKI se encuentra en $DIST_DIR .

Creación de una imagen de arranque para dispositivos sin init_boot (heredado)

Para dispositivos sin la partición init_boot , necesita un binario ramdisk, que puede obtener descargando una imagen de arranque GKI y descomprimiéndola. Cualquier imagen de arranque de GKI de la versión de Android asociada funcionará.

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

La carpeta de destino es el directorio de nivel superior del árbol del kernel (el directorio de trabajo actual).

Si está desarrollando con AOSP principal, puede descargar el artefacto de compilación ramdisk-recovery.img desde una compilación aosp_arm64 en ci.android.com y usarlo como su binario ramdisk.

Cuando tenga un binario ramdisk y lo haya copiado en gki-ramdisk.lz4 en el directorio raíz de la compilación del kernel, puede generar una imagen de arranque ejecutando:

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

Si está trabajando con una arquitectura basada en x86, reemplace Image con bzImage y 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

Ese archivo se encuentra en el directorio de artefactos $KERNEL_ROOT/out/$KERNEL_VERSION/dist .

La imagen de arranque se encuentra en out/<kernel branch>/dist/boot.img .