カーネルのビルド

このページでは、Android デバイス用にカスタム カーネルをビルドする手順について詳しく説明します。適切なソースを選択する手順、カーネルをビルドする手順、そのビルド結果を Android オープンソース プロジェクト(AOSP)ベースでビルドされたシステム イメージに埋め込む手順について以下で説明します。

最近のカーネルソースは、Repo を使用して取得することが可能で、ソース チェックアウトのルートから build/build.sh を実行することにより、追加構成を行うことなくビルドできます。

ソースとビルドツールをダウンロードする

最近のカーネルの場合、repo を使用してソース、ツールチェーン、ビルド スクリプトをダウンロードします。Pixel 3 カーネルなど、カーネルによっては、複数の Git リポジトリのソースが必要になることがあります。それ以外のカーネルの場合(共通カーネルなど)、必要なのは単一のソースだけです。repo アプローチを使用すると、ソース ディレクトリを確実に正しくセットアップできます。

以下のコマンドで、適切なブランチのソースをダウンロードします。

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

前の「repo init」コマンドで使用できる Repo ブランチ(BRANCH)のリストの場合は、カーネル ブランチとビルドシステムをご覧ください。

Google Pixel のカーネルのダウンロードとコンパイルの詳細については、Google Pixel カーネルのビルドをご覧ください。

カーネルをビルドする

Bazel(Kleaf)を使用してビルドする

Android 13 では、Bazel を使用したカーネルのビルドが導入されました。

aarch64 アーキテクチャ用の GKI カーネルのディストリビューションを作成するには、Android 13 以降の Android 共通カーネルのブランチをチェックアウトしてから、次のコマンドを実行します。

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 では、build.sh に代わって Bazel を使用したカーネルのビルド(Kleaf)が導入されました。

virtual_device のモジュール用のディストリビューションを作成するには、次を実行します。

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

Bazel を使用した Android カーネルのビルドについて詳しくは、Kleaf - Building Android Kernels with Bazel(Kleaf - 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 とエミュレータ)を示しています。

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 コマンドを実行します。次のコマンドの例は、common-android14-6.1 カーネル マニフェストから arm64 ターゲットのカーネル アーティファクトを使用しています。

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

詳しくは、Cuttlefish でカーネルを開発するをご覧ください。

カーネルビルドをカスタマイズする

Kleaf ビルドのカーネルビルドをカスタマイズするには、Kleaf のドキュメントをご覧ください。

(以前の)build.sh でビルドされたカーネルをカスタマイズする

build/build.sh の場合、ビルドプロセスとビルド結果は、環境変数の影響を受けることがあります。環境変数のほとんどは省略可能であり、各カーネル ブランチには適切なデフォルト構成が用意されています。主な環境変数のリストを以下に示します。最新の全リストについては、build/build.sh をご覧ください。

環境変数 説明
BUILD_CONFIG ビルド環境の初期化を行うビルド構成ファイル。ビルドの場所は、Repo ルート ディレクトリを基準とする相対パスで定義する必要があります。デフォルトは 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 make mrproper をスキップします。 SKIP_MRPROPER=1

ローカルビルド用のカスタム カーネル構成

Android 14 以降では、defconfig フラグメントを使用してカーネル構成をカスタマイズできます。defconfig フラグメントに関する Kleaf のドキュメントをご覧ください。

(以前の)ビルド構成を持つローカルビルド用のカスタム カーネル構成

Android 13 以前では、以下を参照してください。

機能の開発時など、カーネル構成オプションを定期的に切り替える必要がある場合や、開発上の目的でオプションを設定する必要がある場合は、ビルド構成をローカルレベルで編集したりコピーしたりすることで、そのような柔軟性を実現することができます。

POST_DEFCONFIG_CMDS 変数を、通常の make defconfig ステップの実行直後に評価されるステートメントに設定します。build.config ファイルはビルド環境に供給されるため、build.config 内で定義されている関数は post-defconfig コマンドの一部として呼び出すことができます。

たとえば、開発段階では、クロスハッチ カーネルのリンク時最適化(LTO)を無効にすることができます。LTO はリリース カーネルにとってはメリットがありますが、ビルド時のオーバーヘッドは相当なものになります。以下のスニペットをローカル build.config に追加することで、build/build.sh の使用時に LTO を永続的に無効にできます。

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 ツリーとシステム イメージという 2 つのソースから識別できます。

AOSP ツリーのカーネル バージョン

AOSP ツリーには、ビルド済みのカーネル バージョンが含まれています。Git ログにより、commit メッセージの一部として正しいバージョンを確認できます。

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 パーティションがないデバイスの場合は、RAM ディスク バイナリが必要です。これは、GKI ブートイメージをダウンロードして展開すると取得できます。関連する Android リリースの GKI ブートイメージであれば使用可能です。

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

ターゲット フォルダはカーネルツリーの最上位ディレクトリ(現在の作業ディレクトリ)です。

AOSP main を使用して開発している場合は、代わりに ci.android.com にある aosp_arm64 ビルドから ramdisk-recovery.img ビルド アーティファクトをダウンロードして、RAM ディスク バイナリとして使用できます。

取得した RAM ディスク バイナリをカーネルビルドのルート ディレクトリにある 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 ベースのアーキテクチャを使用している場合は、ImagebzImage に、aarch64x86_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 に生成されます。