LoginSignup
7
2

More than 5 years have passed since last update.

Linux KernelのImageやDevice TreeをARM用にクロスコンパイルする方法

Posted at

Yocto ばかり使っていると、たまにコンパイルする時に凡ミスをするのでメモ。

動作環境
  • Ubuntu Ubuntu 16.04.6 LTS
ターゲット
  • Aarch64(ARMv8)

事前準備

ツールチェインの取得

ここでは Linaro GCC (執筆時点の最新 7.4-2019.02)を使用していますが、
違うツールチェインでも以降の操作における基本的な手順は同じです。

# 作業用ディレクトリの作成
$ mkdir ~/work
$ export WORK=~/work
# ツールチェインの取得と展開
## aarch64-linux-gnu : Linux 64-bit binaries for the Aarch64 Linux cross-toolchain
$ wget https://releases.linaro.org/components/toolchain/binaries/7.4-2019.02/aarch64-linux-gnu/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz
$ tar Jxvf ./gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu
## arm-linux-gnueabi : Linux 64-bit binaries for the ARMv7 Linux soft float cross-toolchain
$ wget https://releases.linaro.org/components/toolchain/binaries/7.4-2019.02/arm-linux-gnueabi/gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabi.tar.xz
$ tar Jxvf ./gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabi.tar.xz
## arm-linux-gnueabihf : Linux 64-bit binaries for the ARMv7 Linux hard float cross-toolchain
$ wget https://releases.linaro.org/components/toolchain/binaries/7.4-2019.02/arm-linux-gnueabihf/gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabihf.tar.xz
$ tar Jxvf ./gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabihf.tar.xz

Kernel の ソースコードの取得

執筆時点の最新のStable Kernelは5.0.9です。
最新バージョンは https://www.kernel.org/ で確認できます。

# 作業用ディレクトリへの移動
$ cd ${WORK}
# tarball の場合
$ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.0.9.tar.xz
$ tar Jxvf ./linux-5.0.9.tar.xz
$ cd ./linux-5.0.9/
# git の場合
$ git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ -b linux-5.0.y
cd ./linux

クロスコンパイル

環境変数の設定

# ツールチェインのパスを追加 (Linux 64-bit binaries for the Aarch64 Linux cross-toolchain)
export PATH="${WORK}/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin:$PATH"
# CPUアーキテクチャの指定
export ARCH=arm64
# クロスコンパイラの指定 (設定した${PATH}の配下に"aarch64-linux-gnu-gcc"や"aarch64-linux-gnu-g++"がある)
export CROSS_COMPILE="aarch64-linux-gnu-"
# 同時に実行可能なジョブ(コマンド)数の指定 = コンパイルの並列化 (※)
export JOBS=`grep -c "processor" /proc/cpuinfo`

コンパイル(make)の並列化

マルチコア環境で指定すると並列処理できるため、ビルド時間が短縮されます。
CPUの物理コア数、論理コア数(スレッド数)等の情報は"/proc/cpuinfo"で確認できます。
指定する値=コア数 or コア数×2+1 等、諸説ありますが、上ではスレッド数を指定しています。

# 物理コア数を指定する場合
export JOBS=`grep cpu.cores /proc/cpuinfo | sort -u | cut -f 3 -d " "`
# スレッド数を指定する場合
export JOBS=`grep -c "processor" /proc/cpuinfo`
# スレッド数 × 2 を指定する場合
export JOBS=`expr `grep -c "processor" /proc/cpuinfo` \* 2`

Kernel v5.09 での並列化によるビルド時間の比較 (クリックすると展開されます)

ホストPCやコンパイルのターゲットが変われば、傾向も大きく変わる可能性がありますので
以下の結果は参考程度に見てください。(make Image での結果です)
並列化数 Intel i7-4790K @ 4.00GHz Intel i7-4785T @ 2.20GHz 備考
1 25m56.608s 39m26.194s 並列化無し
4 8m23.280s 12m31.039s 物理コア数
5 8m18.921s 12m3.865s 物理コア数 + 1
8 7m49.529s 11m7.954s スレッド数
9 7m51.041s 11m16.613s スレッド数 + 1
16 8m0.959s 11m35.233s スレッド数 * 2

クロスコンパイル

# Default の Config を読み込み
$ make -j ${JOBS} defconfig
# Config をカスタマイズ
$ make menuconfig
# コンパイル
$ make -j ${JOBS} Image dtbs modules

コンパイル時の各引数は以下のものを作成することを指定しています。

  • Image : Kernel Image の作成。(出力先:arch/arm64/boot/Image)
  • dtbs : Device Tree Blob(DTB)の作成。(出力先:arch/arm/boot/dts/${ベンダー名}/*.dtb)
  • modules : Loadable module の作成。(出力先:各ドライバ依存)

TIPS

DTC (Device Tree Compiler) を使った Device Tree のコンパイル

Device Tree は DTC (Device Tree Compiler) を使って、単体でもコンパイルすることが出来ます。

DTS(Device Tree Source) から DTB (Device Tree Blob) へ

# Kernelのソースツリーに含まれるDTCを使う場合
$ cd ${WORK}/arch/${ARCH}/boot/dts/${ベンダー名}/
$ ${WORK}/scripts/dtc/dtc -I dts -O dtb -o hogehoge.dtb hogehoge.dts
# DTCをホストPCにインストールする場合
$ sudo apt-get install device-tree-compiler
$ dtc -I dts -O dtb -o hogehoge.dtb hogehoge.dts

DTB(Device Tree Blob) から DTS (Device Tree Source) へ

# Kernelのソースツリーに含まれるDTCを使う場合
$ cd ${WORK}/arch/${ARCH}/boot/dts/${ベンダー名}/
$ ${WORK}/scripts/dtc/dtc -I dtb -O dts -o hogehoge.dts hogehoge.dtb
# DTCをホストPCにインストールする場合
$ sudo apt-get install device-tree-compiler
$ dtc -I dtb -O dts -o hogehoge.dts hogehoge.dtb

通常、DTS は.dtsiや他の.dtbをincludeしていることが多く、
読み解く場合や比較する場合に見づらいことがあります。
その場合、一度 DTB にコンパイルした後、DTS に戻せば1ファイルになるので読みやすくなります。

Kernel Config の保存と比較

Kernel Config を比較する時 (特にどうやって作られたか分からないdefconfigや.configなどを渡された時など)
比較対象をそのまま diff で比較すると、実際にはそんなに差分が無いにも関わらず、
依存関係等の影響で大量の差分が表示されてしまい、時間がかかることがあります。

そんな時は savedefconfig を使うとすっきりした defconfig ファイルを出力してくれるので便利です。

# 比較元の Config を A_defconfig として保存
$ make hogehogeA_defconfig
$ make savedefconfig
$ mv defconfig A_defconfig
# 比較先の Config を B_defconfig として保存
$ make hogehogeB_defconfig
$ make savedefconfig
$ mv defconfig B_defconfig
# 比較
$ diff -ur A_defconfig B_defconfig

menuconfig で カスタマイズした defconfig を保存、比較したい場合も
menuconfig の後にsavedefconfig を実行すれば OK です。
.configからdefconfigを生成してくれます。

# Config をカスタマイズ
$ make menuconfig
# defconfig ファイルを作成
$ make savedefconfig
7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2