追記
こちらに有志による和訳を見つけました。
環境構築は、こちらのほうを読んだほうがわかりやすいです。
こういうドキュメントの和訳は本当に助かります。ありがとうございます。
想定読者
-
- Rustが好きだ!Rustが使いたいんだ!でも、ラズパイに向けたクロスコンパイル方法がわからない!
-
- クロスコンパイルのやり方は知らなくても、どんなのかは知っている
-
- Dockerにアレルギー反応を起こさない
-
- アーキテクチャの名前にアナフィラキシー・ショックを起こさない
- ツールチェイン、リンカという言葉に拒絶反応を起こさない
という人向けの、初心者による初心者のための記事です。
(というか私の備忘録です。)
環境
開発環境
OS:Ubuntu 20.04 LTS
アーキテクチャ:x86_64
実行環境
ハードウェア:RaspberryPi4 typeB 4GB
OS:Raspbian(Version: May 2020)
アーキテクチャ:ARMv8
(2020/12/01;ラズバイのアーキテクチャを修正。ARMv8はARMv7と互換性1があるためARMv7のソフトウェアを実行できます。)
目標
rust-pushordを用いたRust製GUIアプリケーションをRaspberryPi用にクロスコンパイルして、Raspbian上でも動かすこと。
流れ
rustの公式Dockerイメージを使って開発環境を整える
コンテナ内に「Hello World」を用意する。
CargoへARMv7向けにコンパイルするように設定する
ツールチェインとリンカを用意する
コンパイルの確認
rust-pushordの依存ライブラリを用意する(SDL2)
rust-pushordのexampleをコンパイルする
RaspberryPi上で実行する
喜びの舞を踊る(option)
1. rustの公式Dockerイメージを使って開発環境を整える
Dockerのインストール等は割愛させていただきます。
インストールが終わったら早速、Rustの公式イメージゲットだぜ!
docker container run -v ホスト:コンテナ -it --rm rust:latest /bin/bash
(注:もしかしたらsudoがいるかもね。)
将来的なことを考えるとDockerfileを用意したほうがいい気がするけど、ここでは「初心者による初心者のための」ということで作りません。
2. コンテナ内に「Hello World」を用意する。
初めに、コンテナ内で「Hello World」のコードを作り、確認のため普通(開発環境アーキテクチャ向け)に実行します。
root@abcd12345:/# export USER=root
root@abcd12345:~# cd
root@abcd12345:~# cargo new hello
root@abcd12345:~# cd hello
root@abcd12345:~/hello# cargo run
これで「Hello World」が帰ってきたらOK。
3. CargoへARMv7向けにコンパイルするように設定する
次に「.cargo/config」を作成しクロスコンパイルをするための設定を記述します。
root@abcd12345:~/hello# mkdir .cargo
root@abcd12345:~/hello# cat <<EOF > .cargo/config
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
EOF
これは
「cargoでtargetにarmv7-unknown-linux-gnueabihfが指定されたら、リンカにarm-linux-gnueabihf-gccを使ってね!」
とcargoにお願いするためのものです。
4. ツールチェインとリンカを用意する
さて、次に用意しないと行けないのが「ARMv7用の、ツールチェインとリンカ」です。
# ツールチェインの追加
rustup target add armv7-unknown-linux-gnueabihf
# 備考:用意されているツールチェインは次のコマンドで表示できます
# rustup target list
# リンカの用意
apt install gcc-arm-linux-gnueabihf
5. コンパイルの確認
さぁ、準備ができたので、コンパイルがちゃんと通るか確かめて見ましょう!
root@abcd12345:~/hello# cargo build --target=armv7-unknown-linux-gnueabihf
実際にARMv7上で動くかは、RaspbianのDockerイメージを使ってみたり、実機でテストしてください。
6. rust-pushordの依存ライブラリを用意する(SDL2)
CUIだと寂しいのでGUIアプリをコンパイルしてみましょう!
クロスプラットフォームでさくっとできるのにrust-pushordというのがあるので、これを使います。
任意の場所にGitHubからクローンして、コンパイルの設定を行い、exampleをコンパイルしましょう。
(2020/07/03追記)
root@abcd12345:~# git clone https://github.com/KenSuenobu/rust-pushrod.git
root@abcd12345:~# cd rust-pushrod
root@abcd12345:~/rust-pushrod# mkdir .cargo
root@abcd12345:~/rust-pushrod# cat <<EOF > .cargo/config
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
EOF
root@abcd12345:~/rust-pushrod# cargo build --target=armv7-unknown-linux-gnueabihf --example timer
残念なことに、失敗しますね。。かなしみ。
... "-ldl" "-lutil"
= note: /usr/lib/gcc-cross/arm-linux-gnueabihf/8/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lSDL2
/usr/lib/gcc-cross/arm-linux-gnueabihf/8/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lSDL2_image
/usr/lib/gcc-cross/arm-linux-gnueabihf/8/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lSDL2_ttf
collect2: error: ld returned 1 exit status
error: aborting due to previous error
error: could not compile `rust-pushrod`.
To learn more, run the command again with --verbose.
どうやらrust-pushordに必要なSDL2が足りていないようです。
では「依存関係を解決するためにapt install libsdl2-devすればいいのか」というと、そうは問屋がおろしません。
なぜなら、必要としているSDL2は「ARMv7向け」だからです。
ということで、次のようにしないといけません。
# マルチアーキテクチャでarmhfを有効にする。
# また有効にしたあと、updateが必要です。(2020/07/03追記)
dpkg --add-architecture armhf
apt update
# 本当は、armhf向けのパッケージが必要とする必須の
# 基本的なarmhf向けのアプリをインストールする必要があります。
# しかし、Rustの公式Dockerイメージには、もうすでに入ってるのでスキップします。
# apt install crossbuild-essential-armhf
# 必要なSDL2のライブラリをインストール
apt install libsdl2-dev:armhf libsdl2-image-dev:armhf libsdl2-ttf-dev:armhf
これで依存ライブラリも揃いました。もう一度コンパイルして、うまく行くことを確認してみてください。
root@abcd12345:~/rust-pushrod# cargo build --target=armv7-unknown-linux-gnueabihf --example timer
8. RaspberryPi上で実行する
コンパイルしてできたものを共有フォルダに移し、ホスト側に取り出し、RaspberryPiに持っていってください。
そして実行ししっかりと動くか確認してみましょう。
ついに、RustがRaspberryPi上で動くはずです。
9. 喜びの舞を踊る(option)
♪(((^-^)八(^∇^)))♪
お疲れ様でした。今回、私自身が「Rustで組み込み!初クロスコンパイル!」ということで、情報を漁るも、簡単には見つからなかったため、記事にさせていただきました。(特にライブラリの依存関係を解消するあたり)
誰かの参考になれば幸いです。
マイナビニュース「ARM、64ビットアーキテクチャ「ARMv8」の概要を公開」 ↩