Ядра сборки

На этой странице подробно описан процесс сборки пользовательских ядер для устройств Android. Эти инструкции помогут вам выбрать правильные исходные коды, собрать ядро ​​и встроить результаты в образ системы, созданный на основе проекта Android Open Source Project (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

Список веток репозитория ( BRANCH ), которые можно использовать с предыдущей командой `repo init`, см. в разделе «Ветви ядра и их системы сборки» .

Подробную информацию о загрузке и компиляции ядер для устройств Pixel см. в разделе «Сборка ядер Pixel» .

Собрать ядро

Сборка с помощью Bazel (Kleaf)

В Android 13 появилась возможность сборки ядер с помощью Bazel .

Чтобы создать дистрибутив ядра GKI для архитектуры aarch64, клонируйте ветку Android Common Kernel не старше Android 13, а затем выполните следующую команду:

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]

Для получения более подробной информации о сборке ядер Android с помощью Bazel см. Kleaf — Сборка ядер Android с помощью Bazel .

Подробную информацию о поддержке Kleaf для отдельных архитектур см. в разделе «Поддержка Kleaf для устройств и ядер» .

Соберите модули поставщика для виртуального устройства с помощью 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 и Emulator):

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

Запустите ядро

Существует несколько способов запуска ядра, собранного на заказ. Ниже перечислены известные способы, подходящие для различных сценариев разработки.

Встроить в сборку образа Android.

Скопируйте Image.lz4-dtb в соответствующее местоположение исполняемого файла ядра в дереве AOSP и пересоберите образ загрузки.

В качестве альтернативы, определите переменную TARGET_PREBUILT_KERNEL при использовании make bootimage (или любой другой команды make , которая создает образ загрузки). Эта переменная поддерживается всеми устройствами, поскольку она устанавливается через 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 указав в качестве параметров артефакты ядра для целевого устройства. В следующем примере команды используются артефакты ядра для целевого устройства arm64 из манифеста ядра 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

Для получения дополнительной информации см. раздел «Разработка ядер для каракатицы» .

Настройка сборки ядра

Для настройки сборок ядра для сборок Kleaf см. документацию 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 Skip make mrproper SKIP_MRPROPER=1

Пользовательская конфигурация ядра для локальных сборок

В Android 14 и выше вы можете использовать фрагменты defconfig для настройки конфигураций ядра. См. документацию Kleaf по фрагментам defconfig .

Пользовательская конфигурация ядра для локальных сборок с использованием конфигураций сборки (устаревшая версия)

В Android 13 и более ранних версиях см. следующее.

Если вам необходимо регулярно менять параметр конфигурации ядра, например, при работе над новой функцией или если вам нужно установить параметр для целей разработки, вы можете обеспечить такую ​​гибкость, сохраняя локальную модификацию или копию конфигурации сборки.

Установите переменную POST_DEFCONFIG_CMDS в значение оператора, который выполняется сразу после выполнения обычного шага make defconfig . Поскольку файлы build.config подключаются к среде сборки, функции, определенные в build.config могут быть вызваны в рамках команд post-defconfig.

Распространенный пример — отключение оптимизации на этапе компоновки (LTO) для ядер с перекрестной маркировкой во время разработки. Хотя LTO полезна для выпущенных ядер, накладные расходы на этапе сборки могут быть значительными. Следующий фрагмент кода, добавленный в локальный build.config отключает LTO на постоянной основе при использовании 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)
}

Определить версии ядра

Определить правильную версию для сборки можно из двух источников: дерева 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 [-- --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 . Подойдет любой образ загрузки GKI из соответствующего релиза Android.

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

Целевая папка — это корневой каталог дерева ядра (текущий рабочий каталог).

Если вы разрабатываете приложение с использованием последней версии AOSP, вы можете вместо этого загрузить артефакт сборки ramdisk-recovery.img из сборки aosp_arm64 на ci.android.com и использовать его в качестве исполняемого файла для оперативной памяти.

Если у вас есть исполняемый файл 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 .