背景
- Raspberry Pi 5を買ったので今後いろいろ遊びたい
- お仕事ではしつらえられたビルド環境が整っているので、一回自分でクロスコンパイルを一からやってみて流れを理解したい
環境
ターゲット
- Raspberry Pi 5 8GB
- Raspbian GNU/Linux 12
ホスト
- WSL 1 on Windows 11
- Ubuntu 16.04.5
実験
- 適当にサンプルコードをつくる
// hello.cpp
#include<iostream>
int main()
{
std::cout << "Hello World!" << std::endl;
}
- g++でビルドし、動作確認
# host
$ g++ -o hello_host hello.cpp
$ ./hello_host
Hello World!
- fileコマンドでファイルタイプを確認するとx86-64アーキテクチャで動くことがわかった
# host
$ file hello_host
hello_host: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=be8acdcf26aa2e574315f088440fa65e8619df1f, not stripped
- RasPi上でuname -m を実行するとaarch64というアーキテクチャであることが分かった
# target
$ uname -m
aarch64
- ビルドしたバイナリをRaspberry Piに転送し実行するも、当然Exec format errorで失敗する
# host
$ scp hello_host <user>@<raspi address>:/home/
# target
$ ./hello_host
-bash: ./hello_host: cannot execute binary file: Exec format error
- ググったらg++-aarch64-linux-gnuがARM64向けのクロスコンパイラらしいのでインストールしてみる
# host
$ sudo apt install g++-aarch64-linux-gnu
- ビルドしてファイルタイプを確認するとアーキテクチャもARM aarch64となっている
# host
$ aarch64-linux-gnu-g++ -o hello_target hello.cpp
$ file hello_target
hello_target: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[sha1]=23145953038cc20552029576ca61ddc777ccbac3, not stripped
- RaspPi側に転送し実行するも、required file not foundだと怒られた
# target
$ ./hello_target
-bash: ./hello_target: cannot execute: required file not found
- 動的リンクの問題かと考えlddしてみてもnot a dynamic executableと表示されてしまった
# target
$ ldd hello_target
not a dynamic executable
- fileコマンドの出力を見直すと、インタプリタとして
/lib/ld-linux-aarch64.so.1
と指定されていた - /lib下にld-linux-aarch64.so.1は無かったがld-linux-armhf.so.3という名前のローダは見つかった
- armhfというのは32bitアーキテクチャのようなので、32bit向けにビルドしたら実行できた
# host
# g++のarmfh向けのクロスコンパイラをインストール
$ sudo apt install g++-arm-linux-gnueabihf
# ビルド
$ arm-linux-gnueabihf-g++ -o hello_armhf hello.cpp
$ file hello_armhf
hello_armhf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=5d079ab5090bb0a0d30d6de532b28dd081c2f47f, not stripped
# target
$ ./hello_armhf
Hello World!
学んだことと課題
- CPUアーキテクチャが64bitだとしてもELFローダも64bitに対応していないと実行できない
- 宿題として64bit向けにビルドしたバイナリを実行する方法を調べる
追記(2025/2/28)
- このフォーラムの投稿によるとRaspberry Pi 5自体は64bitだとしても32bit版のOSがインストールされているとこのような問題が起こるそうだ
- 64bit版のOSをインストールしなおしたら正常に動作した
- 自分はOSがプリインストールされているキットを買ったので、そのあたりを意識していなかったのがつまづいた原因のようだ
$ ./hello_target
Hello World!
参考