このページでは、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 build //common:kernel_aarch64_dist
ディストリビューションを作成するには、次のコマンドを実行します。
tools/bazel run //common:kernel_aarch64_dist -- --dist_dir=$DIST_DIR
その後、カーネルのバイナリ、モジュール、対応するイメージが $DIST_DIR
ディレクトリに配置されます。--dist_dir
を指定していない場合のアーティファクトの場所については、コマンドの出力を参照してください。詳しくは、AOSP のドキュメントをご覧ください。
(以前の)build.sh を使用してビルドする
Android 12 以前のブランチ、または Kleaf のないブランチの場合:
build/build.sh
カーネル バイナリや、モジュール、対応するイメージは、out/BRANCH/dist
ディレクトリにあります。
仮想デバイスのベンダー モジュールをビルドする
Android 13 では、build.sh
に代わって Bazel を使用したカーネルのビルド(Kleaf)が導入されました。
virtual_device
のモジュールをビルドするには、次のコマンドを実行します。
tools/bazel build //common-modules/virtual-device:virtual_device_x86_64_dist
ディストリビューションを作成するには、次のコマンドを実行します。
tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist -- --dist_dir=$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 -- --dist_dir=$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 ベースのアーキテクチャを使用している場合は、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
に生成されます。