2019年2月23日土曜日

RustをUbuntu(x86_64)でRaspbian(ARM v6かv7)向けにビルドしてみた


背景

Rustとはコンパイルして実行可能ファイルを作成できるプログラミング言語の1つです。
Rustにはクロスコンパイルの仕組みがあるので、IntelのCPUで動かしている64bitのUbuntuでARM v6(A, B, A+, B+, Zero)かv7(2B, 3B, 3B+)で動いているRaspbian用の実行ファイルをビルドしてみました。

備忘録としてまとめつつ、やったことを共有します。

使ったもの

Ubuntu18.04にRustをインストールしたPC

利用したrustupとcargoのバージョンはこちらです。
$ rustup --version
rustup 1.16.0 (beab5ac2b 2018-12-06)
$ cargo --version
cargo 1.32.0 (8610973aa 2019-01-02)

Raspberry Pi + Raspbian

Raspberry Pi の Zero(ARM v6) と 3B+(ARM v7) を 2018.11リリース版Stretchで動かして動作確認しました。

Cargoプロジェクト

今回はironというwebフレームワークを利用したwebアプリを例としてビルド方法を説明します。(前回の記事で取り組んだものです。)

下記のように~/gitprojects/rustの中に配置した前提で話を進めます。
sudo apt install git
mkdir -p ~/gitprojects/rust
cd ~/gitprojects/rust
git clone https://github.com/asukiaaa/rust_iron_template_sample.git

UbuntuでARM向けのビルド環境を構築

ARM v6

ARM v6向けのgccをUbuntuにインストールします。
sudo apt install gcc-arm-linux-gnueabi

rustupにARM v6向けのターゲットを追加します。
rustup target add arm-unknown-linux-gnueabi

Cargoのconfigファイル(無ければ新規作成)に、先ほどインストールしたgccをARM v6のビルドで利用することを記述します。
~/.cargo/config
[target.arm-unknown-linux-gnueabi]
linker = "arm-linux-gnueabi-gcc"

これでCargoでARM v6向けのビルドができるようになりました。

ARM v7

ARM v7向けのgccをUbuntuにインストールします。
sudo apt install gcc-arm-linux-gnueabihf

rustupにARM v7向けのターゲットを追加します。
rustup target add armv7-unknown-linux-gnueabihf

Cargoのconfigファイル(無ければ新規作成)に、先ほどインストールしたgccをARM v7のビルドで利用することを記述します。
~/.cargo/config
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"

これでCargoでARM v7向けのビルドができるようになりました。

ARM向けにビルド

ARM v6

Cargoプロジェクトのディレクトリに移動します。
cd ~/gitprojects/rust/rust_iron_template_sample

下記のコマンドでARM向けにビルドできます。
cargo build --target arm-unknown-linux-gnueabi

ビルドしたファイルは下記のパスにあります。
ls target/arm-unknown-linux-gnueabi/debug/rust_iron_template_sample -la
-rwxr-xr-x 2 asuki asuki 42230084  2月 23 22:14 target/arm-unknown-linux-gnueabi/debug/rust_iron_template_sample

--releaseを付けると、ビルドの時間は長くなりますがサイズが小さくて処理が早いファイルを生成してくれます。
cargo build --target arm-unknown-linux-gnueabi --release
ls target/arm-unknown-linux-gnueabi/release/rust_iron_template_sample -la
-rwxr-xr-x 2 asuki asuki 6240404  2月 21 19:42 target/arm-unknown-linux-gnueabi/release/rust_iron_template_sample

ARM v7

Cargoプロジェクトのディレクトリに移動します。
cd ~/gitprojects/rust/rust_iron_template_sample

下記のコマンドでARM向けにビルドできます。
cargo build --target armv7-unknown-linux-gnueabihf

ビルドしたファイルは下記のパスにあります。
ls target/armv7-unknown-linux-gnueabihf/debug/rust_iron_template_sample -la
-rwxr-xr-x 2 asuki asuki 41570772  2月 19 07:12 target/armv7-unknown-linux-gnueabihf/debug/rust_iron_template_sample

--releaseを付けると、ビルドの時間は長くなりますがサイズが小さくて処理が早いファイルを生成してくれます。
cargo build --target armv7-unknown-linux-gnueabihf --release
ls target/armv7-unknown-linux-gnueabihf/release/rust_iron_template_sample -la
-rwxr-xr-x 2 asuki asuki 6198612  2月 19 07:16 target/armv7-unknown-linux-gnueabihf/release/rust_iron_template_sample

関連ファイルをzipで固めてRaspbianに配置

実行ファイルだけで動くプロジェクトなら、ARM v6向けはZeroなどに、ARM v7向けは3Bなどにファイル(先ほどの手順でlsで確認したもの)を配置して実行できます。

しかし、今回ビルドしたプロジェクトはhandlebars-ironというテンプレートファイルを利用するライブラリ使っているため、Cargoで生成した実行ファイルに加えて、htmlを描画するためのテンプレートファイル一式(templatesディレクトリ)が必要です。
さらに、(サンプルプロジェクトには無いですけど)ironで扱う静的ファイルもビルドには含まれないため、publicディレクトリも一緒に扱う必要があります。

ということで、今回はそれらを下記のようなコマンドでzipに固めます。
ARM v6向け
mkdir -p releases/armv6
cp target/arm-unknown-linux-gnueabi/release/rust_iron_practice releases/armv6/
cp -r public releases/armv6/
cp -r templates releases/armv6/
cd releases
zip -r armv6.zip armv6
cd ../
ARM v7向け
mkdir -p releases/armv7
cp target/armv7-unknown-linux-gnueabihf/release/rust_iron_practice releases/armv7/
cp -r public releases/armv7/
cp -r templates releases/armv7/
cd releases
zip -r armv7.zip armv7
cd ../

作成したzipファイルは、scpで転送したり、SDカードをPCに接続してコピーしたりして、Raspbianに配置してください。

Raspbianで動作確認

ここからのコマンドはRaspberry Pi上で実行します。

Raspberry PiのIpを調べておきます。
ip a show | grep 192

ファイルを展開してからプログラムを実行します。
ARM v6向け
unzip arm6.zip
cd arm6
./rust_iron_template_sample
ARM v7向け
unzip arm7.zip
cd arm7
./rust_iron_template_sample


Raspberry Piと同じWiFiに接続しているPCから。Raspberry PiのIPのRustのプログラムが管理しているポート(このプロジェクトの場合は3000番)にブラウザでアクセスすると、Raspberry Piが配信する内容を確認できます。


Rustで書いたWebアプリがRaspbianで動いていることを確認できました。

余談: rusqliteを使うプロジェクトもbundleオプションを付ければビルド可能

rusqliteとはsqlite3というデータベースを利用するライブラリです。
このライブラリを利用するプロジェクトをコンパイルする場合、以前は関連するlinuxパッケージをPCにインストールする必要があったようです。
しかし、自分が試したときは、Cargo.tmolのbundleオプションを有効にすれば、ビルドできました。
Cargo.toml
[dependencies]
rusqlite = { version = "0.16", features = ["bundled"] }

ライブラリの更新によって上記の設定だけでビルドできるようになったのかもしれません。

まとめ

UbuntuでビルドしたファイルをRaspbianで動かせました。
また、sqliteを利用するライブラリも難なくビルド出来ることが分かりました。

何かの参考になれば嬉しいです。

参考

Cross Compiling Rust for the Raspberry Pi on Linux
Rust でクロスコンパイルして Raspberry Pi Zero W で動かす

0 件のコメント :