MPDとRustとRaspberryPiで遊んでみる6

前回で、とりあえず Rust で1本つくってみたわけですが、CentOS8 上で作ったので当然 CentOS8 上でしかうごきません。 将来的には Raspberry Pi 上で動くものを作りたいわけです。 そーしたばあい、『Raspberry Pi に Rust を入れてコンパイル』することになるかと思うのですが、 Rustはコンパイルが速いわけでも無さそーですし、RPi も早いわけではない。ディスクそこまで早くない。

ってことで、こんな時こそ『クロスコンパイル』です。

で、いろいろ Google 先生にお伺いたててみたのですが、母艦が Ubunt の記事しか見当たらない!

うむ~、うちの母艦は、CentOS8だしなぁ... どぉ~しようかなぁ...

を!あった。

qiita.com

って、自作自演です。頑張ってみました。

で、さっそく前回作った mpdsh を RPi 用にコンパイルします。

github.com

.cargo/config をちょっと修正しまして...

[target.armv7-unknown-linux-gnueabihf]
linker = "/home/zuntan/cross_rp_3/bin/arm-linux-gnueabihf-gcc"

ビルド!

cargo build --target armv7-unknown-linux-gnueabihf

あっさりできました。

file target/armv7-unknown-linux-gnueabihf/debug/mpdsh
target/armv7-unknown-linux-gnueabihf/debug/mpdsh: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, with debug_info, not stripped

ファイルがでかい!けどまぁいいか

$ ls -lh mpdsh
-rwxr-xr-x 1 zuntan zuntan 22M Jun 17 18:39 mpdsh

で、RPi にもっていって実行!

$ ./mpdsh
Connecting... localhost:6600
connected OK MPD 0.21.11

mpdsh:/> ls
directory   : RADIO
mpdsh:/> cd RADIO
mpdsh:/RADIO> ls
file        : NPO Radio 2.pls
file        : France Inter Paris (FIP).pls
file        : Audiophile Baroque.pls
file        : WRTI Philadelphia 90.1 - Classical.pls
file        : BBC Radio 3.pls
:
:

ちゃんと動きました。

Rust による『クロスコンパイル』の手ごたえを見るための実験でしたが、良いですね。大きな問題は無さそーです。

次はもーちょっと本格的なものをビルドしてみます。

actix-web を ビルド!

volumio や moore のような MDPのフロントエンドを作ろうとしたら、webサービス形式となるわけです。

actix-web は いわゆる web application framework ってやつで、これがコンパイルできて RPi で動けば、よさそうな感じとなります。

github.com

Example にある内容をもとに、IPアドレスとポート番号だけ変更して普通にコンパイルしてみたところ、サクッと動きます。 では、次に arm版のビルドをします。

$ cargo build --target armv7-unknown-linux-gnueabihf
:
:
   Compiling brotli-sys v0.3.2
error: failed to run custom build command for `brotli-sys v0.3.2`

Caused by:
  process didn't exit successfully: `/home/zuntan/rust_test/actix-web/target/debug/build/brotli-sys-df9db23f522cf66e/build-script-build` (exit code: 1)
--- stdout
cargo:include=/home/zuntan/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-sys-0.3.2/brotli/include
TARGET = Some("armv7-unknown-linux-gnueabihf")
OPT_LEVEL = Some("0")
HOST = Some("x86_64-unknown-linux-gnu")
CC_armv7-unknown-linux-gnueabihf = None
CC_armv7_unknown_linux_gnueabihf = None
TARGET_CC = None
CC = None
CROSS_COMPILE = None
CFLAGS_armv7-unknown-linux-gnueabihf = None
CFLAGS_armv7_unknown_linux_gnueabihf = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
DEBUG = Some("true")
CARGO_CFG_TARGET_FEATURE = None
running: "arm-linux-gnueabihf-gcc" "-O0" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "-march=armv7-a" "-I" "brotli/include" "-o" "/home/zuntan/rust_test/actix-web/target/armv7-unknown-linux-gnueabihf/debug/build/brotli-sys-c4c720afbb1107ee/out/brotli/common/dictionary.o" "-c" "brotli/common/dictionary.c"

--- stderr
fatal: not a git repository (or any of the parent directories): .git


error occurred: Failed to find tool. Is `arm-linux-gnueabihf-gcc` installed?



warning: build failed, waiting for other jobs to finish...
error: build failed

あらら。

C のコードをコンパイルしようとして失敗しているよーですね。

error occurred: Failed to find tool. Is `arm-linux-gnueabihf-gcc` installed?

ってことは arm-linux-gnueabihf-gcc が参照できればいけるのかな? 自作の arm-linux-gnueabihf-gcc があるディレクトリにパスを通してもう一度実行してみたところ、見事にビルド完了。やったぜ!

$ export PATH=/home/zuntan/cross_rp_3/bin:$PATH
$ echo $PATH
/home/zuntan/cross_rp_3/bin:/home/zuntan/.cargo/bin:/home/zuntan/.local/bin:/home/zuntan/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/zuntan/.dotnet/tools
$ cargo build --target armv7-unknown-linux-gnueabihf
:
:
   Compiling serde_urlencoded v0.6.1
   Compiling actix-router v0.2.4
   Compiling actix-http v1.0.1
   Compiling awc v1.0.1
   Compiling actix-web v2.0.0
   Compiling actix-web v0.1.0 (/home/zuntan/rust_test/actix-web)
    Finished dev [unoptimized + debuginfo] target(s) in 39.66s
$ file target/armv7-unknown-linux-gnueabihf/debug/actix-web
target/armv7-unknown-linux-gnueabihf/debug/actix-web: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, with debug_info, not stripped

で、できた target/armv7-unknown-linux-gnueabihf/debug/actix-web を RPi にもっていって、実行すると見事に動きました。

ちなみにファイルサイズは、78M

ls -lh target/armv7-unknown-linux-gnueabihf/debug/actix-web
-rwxrwxr-x 2 zuntan zuntan 78M  6月 17 20:51 target/armv7-unknown-linux-gnueabihf/debug/actix-web

リリースビルドもしてみました

$ cargo build --release --target armv7-unknown-linux-gnueabihf
   Compiling libc v0.2.71
   Compiling proc-macro2 v1.0.18
   Compiling unicode-xid v0.
:
:
   Compiling actix-http v1.0.1
   Compiling awc v1.0.1
   Compiling actix-web v2.0.0
   Compiling actix-web v0.1.0 (/home/zuntan/rust_test/actix-web)
    Finished release [optimized] target(s) in 1m 08s

170近くある外部モジュールのコンパイルを考えれば、1m 08s でコンパイルできるのはすごく早いのかもしれませんね。

$ file target/armv7-unknown-linux-gnueabihf/release/actix-web
target/armv7-unknown-linux-gnueabihf/release/actix-web: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, with debug_info, not stripped
$ ls -lh target/armv7-unknown-linux-gnueabihf/release/actix-web
-rwxrwxr-x 2 zuntan zuntan 6.2M  6月 17 21:06 target/armv7-unknown-linux-gnueabihf/release/actix-web

with debug_info, not stripped って書いてある割には、 6.2M です。C/C++が埋め込むよーな内容を Rustが埋め込んでいないからだと推測します。 試しにファイルをコピーして strip してみました。

$ cp target/armv7-unknown-linux-gnueabihf/release/actix-web{,-ns}
$ /home/zuntan/cross_rp_3/bin/arm-linux-gnueabihf-stri
arm-linux-gnueabihf-strings  arm-linux-gnueabihf-strip
$ file target/armv7-unknown-linux-gnueabihf/release/actix-web
target/armv7-unknown-linux-gnueabihf/release/actix-web: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, stripped
$ /home/zuntan/cross_rp_3/bin/arm-linux-gnueabihf-strip target/armv7-unknown-linux-gnueabihf/release/actix-web
$ ls -lh target/armv7-unknown-linux-gnueabihf/release/actix-web*
-rwxrwxr-x 2 zuntan zuntan 2.7M  6月 17 21:12 target/armv7-unknown-linux-gnueabihf/release/actix-web
-rwxrwxr-x 1 zuntan zuntan 6.2M  6月 17 21:11 target/armv7-unknown-linux-gnueabihf/release/actix-web-ns
-rw-rw-r-- 1 zuntan zuntan 136  6月 17 21:06 target/armv7-unknown-linux-gnueabihf/release/actix-web.d

2.7M まで小さくなりました。

actix-web を RPi にもっていって実行してみました。ちゃーんと動きました。

Rust すごい

Rust の クロスコンパイルを試してみました。

少なくとも CentOS8があれば、RPi でコンパイルしなくても作れるってことが分かりました。

Windows でのクロスコンパイルは、そこそこ記事が検索できたので、たぶんそっちも問題ないんだと思います。

すばらしいポータビリティーです。(一時はヒヤッとしましたが...)

ロマン

やっぱり『クロスコンパイル』はロマンがありますねぇ~

やべぇ、『 windowsで走る arm用 gcclinuxでビルド』したらどーなるのかと...思っちゃいました。なんかできーそーだけどね。 VSCode 使って Windows で開発するほーが楽そーだしなぁ... やべぇ、隣の山を登りだしそうだ...