Na tej stronie znajdziesz szczegółowe informacje o procesie tworzenia niestandardowych jąder na urządzenia z Androidem. Te instrukcje przeprowadzą Cię przez proces wybierania odpowiednich źródeł, kompilowania jądra i osadzania wyników w obrazie systemu utworzonym na podstawie projektu Android Open Source Project (AOSP).
Pobieranie źródeł i narzędzi do kompilacji
W przypadku najnowszych jąder użyj polecenia repo
, aby pobrać źródła, łańcuch narzędzi i skrypty kompilacji.
Niektóre kernele (np. kernele Pixela 3) wymagają źródeł z wielu repozytoriów Git, a inne (np. kernele wspólne) tylko jednego źródła. Zastosowanie podejścia repo
zapewnia prawidłową konfigurację katalogu źródłowego.
Pobierz źródła odpowiedniej gałęzi:
mkdir android-kernel && cd android-kernel
repo init -u https://android.googlesource.com/kernel/manifest -b BRANCH
repo sync
Listę gałęzi repozytorium (BRANCH), których można używać z poprzednim poleceniem `repo init`, znajdziesz w artykule Gałęzie jądra i ich systemy kompilacji.
Szczegółowe informacje o pobieraniu i kompilowaniu jąder na urządzenia Pixel znajdziesz w artykule Tworzenie jąder Pixela.
Kompilowanie jądra
Kompilowanie za pomocą Bazela (Kleaf)
W Androidzie 13 wprowadzono możliwość tworzenia jąder za pomocą narzędzia Bazel.
Aby utworzyć dystrybucję jądra GKI dla architektury aarch64, sprawdź gałąź Android Common Kernel nie starszą niż Android 13, a następnie uruchom to polecenie:
tools/bazel run //common:kernel_aarch64_dist [-- --destdir=$DIST_DIR]
Następnie plik binarny jądra, moduły i odpowiednie obrazy znajdują się w katalogu $DIST_DIR
. Jeśli --destdir
nie jest określony, lokalizację artefaktów znajdziesz w danych wyjściowych polecenia. Szczegółowe informacje znajdziesz w dokumentacji AOSP.
Kompilowanie za pomocą build.sh (starsza wersja)
W przypadku gałęzi w wersji Androida 12 lub starszej LUB gałęzi bez Kleaf:
build/build.sh
Plik binarny jądra, moduły i odpowiedni obraz znajdują się w katalogu out/BRANCH/dist
.
Kompilowanie modułów dostawcy dla urządzenia wirtualnego
W Androidzie 13 wprowadzono kompilowanie jąder za pomocą Bazela (Kleaf), które zastąpiło build.sh
.
Aby utworzyć dystrybucję modułów virtual_device
, uruchom:
tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist [-- --destdir=$DIST_DIR]
Więcej informacji o tworzeniu jąder Androida za pomocą Bazela znajdziesz w tym artykule. Kleaf – Building Android Kernels with Bazel
Szczegółowe informacje o obsłudze Kleaf w przypadku poszczególnych architektur znajdziesz w artykule Obsługa Kleaf na urządzeniach i w jądrach.
Tworzenie modułów dostawcy dla urządzenia wirtualnego za pomocą skryptu build.sh (starsza wersja)
W Androidzie 12 Cuttlefish i Goldfish są zbieżne, więc mają to samo jądro: virtual_device
. Aby utworzyć moduły tego jądra, użyj tej konfiguracji kompilacji:
BUILD_CONFIG=common-modules/virtual-device/build.config.virtual_device.x86_64 build/build.sh
W Androidzie 11 wprowadzono GKI, czyli ogólny obraz jądra, który dzieli jądro na obraz jądra utrzymywany przez Google i moduły utrzymywane przez dostawcę, które są kompilowane oddzielnie.
Ten przykład pokazuje konfigurację obrazu jądra:
BUILD_CONFIG=common/build.config.gki.x86_64 build/build.sh
Ten przykład pokazuje konfigurację modułu (Cuttlefish i emulator):
BUILD_CONFIG=common-modules/virtual-device/build.config.cuttlefish.x86_64 build/build.sh
Uruchamianie jądra
Istnieje kilka sposobów uruchamiania niestandardowego jądra. Poniżej znajdziesz znane sposoby odpowiednie w różnych scenariuszach programowania.
Umieść w kompilacji obrazu Androida
Skopiuj plik Image.lz4-dtb
do odpowiedniej lokalizacji binarnej jądra w drzewie AOSP i ponownie utwórz obraz rozruchowy.
Możesz też zdefiniować zmienną TARGET_PREBUILT_KERNEL
podczas używania polecenia make bootimage
(lub dowolnego innego polecenia wiersza poleceń make
, które tworzy obraz rozruchowy). Ta zmienna jest obsługiwana przez wszystkie urządzenia, ponieważ jest konfigurowana za pomocą device/common/populate-new-device.sh
. Na przykład:
export TARGET_PREBUILT_KERNEL=DIST_DIR/Image.lz4-dtb
Flashowanie i uruchamianie jąder za pomocą narzędzia fastboot
Najnowsze urządzenia mają rozszerzenie programu rozruchowego, które upraszcza proces generowania i uruchamiania obrazu rozruchowego.
Aby uruchomić jądro bez flashowania:
adb reboot bootloader
fastboot boot Image.lz4-dtb
W ten sposób jądro nie jest faktycznie flashowane i nie będzie się utrzymywać po ponownym uruchomieniu.
Uruchamianie jąder na platformie Cuttlefish
Na urządzeniach Cuttlefish możesz uruchamiać kernele w wybranej architekturze.
Aby uruchomić urządzenie Cuttlefish z określonym zestawem artefaktów jądra, uruchom polecenie cvd create
z artefaktami jądra docelowego jako parametrami. W tym przykładowym poleceniu użyto artefaktów jądra dla platformy arm64 z common-android14-6.1
manifestu jądra.
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
Więcej informacji znajdziesz w artykule Tworzenie jąder na urządzeniu Cuttlefish.
Dostosowywanie kompilacji jądra
Informacje o dostosowywaniu kompilacji jądra w przypadku kompilacji Kleaf znajdziesz w dokumentacji Kleaf.
Dostosowywanie kompilacji jądra za pomocą skryptu build.sh (starsza wersja)
W przypadku build/build.sh
na proces kompilacji i jego wynik mogą mieć wpływ zmienne środowiskowe.
Większość z nich jest opcjonalna, a każda gałąź jądra powinna mieć odpowiednią konfigurację domyślną. Najczęściej używane z nich są wymienione poniżej. Pełną (i aktualną) listę znajdziesz w build/build.sh
.
Zmienna środowiskowa | Opis | Przykład |
---|---|---|
BUILD_CONFIG |
Plik konfiguracji kompilacji, z którego inicjujesz środowisko kompilacji.
Lokalizacja musi być zdefiniowana względem katalogu głównego repozytorium. Domyślna wartość to build.config .Obowiązkowe w przypadku wspólnych jąder. |
BUILD_CONFIG=common/build.config.gki.aarch64 |
CC |
Zastąpienie kompilatora, który ma być używany. Wracanie do domyślnego kompilatora zdefiniowanego przez build.config . |
CC=clang |
DIST_DIR |
Podstawowy katalog wyjściowy dystrybucji jądra. | DIST_DIR=/path/to/my/dist |
OUT_DIR |
Podstawowy katalog wyjściowy kompilacji jądra. | OUT_DIR=/path/to/my/out |
SKIP_DEFCONFIG |
Pomiń make defconfig |
SKIP_DEFCONFIG=1 |
SKIP_MRPROPER |
Pomiń make mrproper |
SKIP_MRPROPER=1 |
Niestandardowa konfiguracja jądra w przypadku kompilacji lokalnych
W Androidzie 14 i nowszych wersjach możesz używać fragmentów defconfig do dostosowywania konfiguracji jądra. Więcej informacji znajdziesz w dokumentacji Kleaf na temat fragmentów defconfig.
Konfiguracja niestandardowego jądra w przypadku kompilacji lokalnych z konfiguracjami kompilacji (starsza wersja)
W przypadku Androida 13 i starszych wersji wykonaj te czynności.
Jeśli musisz regularnie przełączać opcję konfiguracji jądra, np. podczas pracy nad funkcją, lub jeśli potrzebujesz opcji ustawionej na potrzeby programowania, możesz uzyskać taką elastyczność, utrzymując lokalną modyfikację lub kopię konfiguracji kompilacji.
Ustaw zmienną POST_DEFCONFIG_CMDS na instrukcję, która jest wykonywana bezpośrednio po zwykłym kroku make defconfig
. Ponieważ pliki build.config
są wczytywane do środowiska kompilacji, funkcje zdefiniowane w pliku build.config
można wywoływać w ramach poleceń wykonywanych po poleceniu defconfig.
Typowym przykładem jest wyłączenie optymalizacji w czasie łączenia (LTO) w przypadku jąder crosshatch podczas programowania. LTO jest korzystne w przypadku wydanych jąder, ale obciążenie w czasie kompilacji może być znaczne. Ten fragment kodu dodany do lokalnego pliku build.config
trwale wyłącza LTO podczas korzystania z 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)
}
Określanie wersji jądra
Prawidłową wersję do utworzenia możesz znaleźć w 2 źródłach: w drzewie AOSP i obrazie systemu.
Wersja jądra z drzewa AOSP
Drzewo AOSP zawiera wstępnie skompilowane wersje jądra. Dziennik git zawiera prawidłową wersję w wiadomości o zatwierdzeniu:
cd $AOSP/device/VENDOR/NAME
git log --max-count=1
Jeśli wersja jądra nie jest wymieniona w logu git, uzyskaj ją z obrazu systemu, jak opisano poniżej.
Wersja jądra z obrazu systemu
Aby określić wersję jądra używaną w obrazie systemu, uruchom to polecenie w pliku jądra:
file kernel
W przypadku plików Image.lz4-dtb
wpisz:
grep -a 'Linux version' Image.lz4-dtb
Tworzenie obrazu rozruchowego
Obraz rozruchowy można utworzyć za pomocą środowiska kompilacji jądra.
Tworzenie obrazu rozruchowego dla urządzeń z init_boot
W przypadku urządzeń z partycją init_boot
obraz rozruchowy jest tworzony razem z jądrem. initramfs
Obraz nie jest osadzony
w obrazie rozruchowym.
Na przykład za pomocą Kleaf możesz utworzyć obraz rozruchowy GKI za pomocą tego polecenia:
tools/bazel run //common:kernel_aarch64_dist [-- --destdir=$DIST_DIR]
W przypadku build/build.sh
(starsza wersja) możesz utworzyć obraz rozruchowy GKI za pomocą:
BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
Obraz rozruchowy GKI znajduje się w $DIST_DIR.
Tworzenie obrazu rozruchowego dla urządzeń bez init_boot (starsza wersja)
W przypadku urządzeń bez partycji init_boot
potrzebujesz pliku binarnego ramdisk, który możesz uzyskać, pobierając obraz rozruchowy GKI i go rozpakowując. Działać będzie dowolny obraz rozruchowy GKI z powiązanej wersji Androida.
tools/mkbootimg/unpack_bootimg.py --boot_img=boot-5.4-gz.img
mv $KERNEL_ROOT/out/ramdisk gki-ramdisk.lz4
Folder docelowy to katalog najwyższego poziomu drzewa jądra (bieżący katalog roboczy).
Jeśli tworzysz oprogramowanie na podstawie najnowszej gałęzi AOSP, możesz zamiast tego pobrać ramdisk-recovery.img
artefakt kompilacji z kompilacji aosp_arm64 na stronie ci.android.com i użyć go jako pliku binarnego dysku RAM.
Gdy masz plik binarny dysku RAM i skopiujesz go do gki-ramdisk.lz4
w katalogu głównym kompilacji jądra, możesz wygenerować obraz rozruchowy, wykonując to polecenie:
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
Jeśli pracujesz z architekturą opartą na x86, zastąp Image
wartością bzImage
, a aarch64
wartością 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
Ten plik znajduje się w katalogu artefaktów $KERNEL_ROOT/out/$KERNEL_VERSION/dist
.
Obraz rozruchowy znajduje się w lokalizacji out/<kernel branch>/dist/boot.img
.