MPDとRustとRaspberryPiで遊んでみる6
前回で、とりあえず Rust で1本つくってみたわけですが、CentOS8 上で作ったので当然 CentOS8 上でしかうごきません。 将来的には Raspberry Pi 上で動くものを作りたいわけです。 そーしたばあい、『Raspberry Pi に Rust を入れてコンパイル』することになるかと思うのですが、 Rustはコンパイルが速いわけでも無さそーですし、RPi も早いわけではない。ディスクそこまで早くない。
ってことで、こんな時こそ『クロスコンパイル』です。
で、いろいろ Google 先生にお伺いたててみたのですが、母艦が Ubunt の記事しか見当たらない!
うむ~、うちの母艦は、CentOS8だしなぁ... どぉ~しようかなぁ...
を!あった。
って、自作自演です。頑張ってみました。
で、さっそく前回作った mpdsh を RPi 用にコンパイルします。
.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 で動けば、よさそうな感じとなります。
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用 gcc を linuxでビルド』したらどーなるのかと...思っちゃいました。なんかできーそーだけどね。 VSCode 使って Windows で開発するほーが楽そーだしなぁ... やべぇ、隣の山を登りだしそうだ...