LoginSignup
5
6

More than 3 years have passed since last update.

ラズパイに向けてRustをクロスコンパイル!

Last updated at Posted at 2020-06-30

追記

こちらに有志による和訳を見つけました。

環境構築は、こちらのほうを読んだほうがわかりやすいです。

こういうドキュメントの和訳は本当に助かります。ありがとうございます。

想定読者

  • 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上でも動かすこと。

流れ

  1. rustの公式Dockerイメージを使って開発環境を整える
  2. コンテナ内に「Hello World」を用意する。
  3. CargoへARMv7向けにコンパイルするように設定する
  4. ツールチェインとリンカを用意する
  5. コンパイルの確認
  6. rust-pushordの依存ライブラリを用意する(SDL2)
  7. rust-pushordのexampleをコンパイルする
  8. RaspberryPi上で実行する
  9. 喜びの舞を踊る(option

1. rustの公式Dockerイメージを使って開発環境を整える

Dockerのインストール等は割愛させていただきます。

インストールが終わったら早速、Rustの公式イメージゲットだぜ!

bash
docker container run -v ホスト:コンテナ -it --rm rust:latest /bin/bash

(注:もしかしたらsudoがいるかもね。)

将来的なことを考えるとDockerfileを用意したほうがいい気がするけど、ここでは「初心者による初心者のための」ということで作りません。

2. コンテナ内に「Hello World」を用意する。

初めに、コンテナ内で「Hello World」のコードを作り、確認のため普通(開発環境アーキテクチャ向け)に実行します。

bash
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」を作成しクロスコンパイルをするための設定を記述します。

bash
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用の、ツールチェインとリンカ」です。

bash
# ツールチェインの追加
rustup target add armv7-unknown-linux-gnueabihf

# 備考:用意されているツールチェインは次のコマンドで表示できます
# rustup target list

# リンカの用意
apt install gcc-arm-linux-gnueabihf

5. コンパイルの確認

さぁ、準備ができたので、コンパイルがちゃんと通るか確かめて見ましょう!

bash
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追記)

bash
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向け」だからです。

ということで、次のようにしないといけません。

bash
# マルチアーキテクチャで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

これで依存ライブラリも揃いました。もう一度コンパイルして、うまく行くことを確認してみてください。

bash
root@abcd12345:~/rust-pushrod# cargo build --target=armv7-unknown-linux-gnueabihf --example timer

8. RaspberryPi上で実行する

コンパイルしてできたものを共有フォルダに移し、ホスト側に取り出し、RaspberryPiに持っていってください。

そして実行ししっかりと動くか確認してみましょう。
ついに、RustがRaspberryPi上で動くはずです。

(画像は明日くらいに載せます。(現在:2020/6/30))
(2020/07/03追記)
Screenshot from 2020-07-03 17-11-04.png

9. 喜びの舞を踊る(option

♪(((^-^)八(^∇^)))♪

お疲れ様でした。今回、私自身が「Rustで組み込み!初クロスコンパイル!」ということで、情報を漁るも、簡単には見つからなかったため、記事にさせていただきました。(特にライブラリの依存関係を解消するあたり)

誰かの参考になれば幸いです。

5
6
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
5
6