ラズパイで動くバイナリプログラムをRustでクロスコンパイルするための基本手順


※ 当ページには【広告/PR】を含む場合があります。
2022/04/14
蛸壺の中の工作室|ラズパイで動くバイナリプログラムをRustでクロスコンパイルするための基本手順



普段からラズパイを使う身としては、簡単なお役立ちツールをバイナリから動かしたい時が多々あります。
ただ、ラズパイはCPUアーキテクチャがARMv6~8で設計されているので、Linuxで動作していた自作のシェルコマンドを簡単に移植できるとは限りません。
ここでは、Rustのクロスコンパイルを使って、別の開発環境からビルドしたシェルプログラムを実際のラズパイ4で動かした際の手順を防備録的にまとめておきます。


開発機でラズパイ用バイナリプログラムをRustでビルドする



まずRustのビルドターゲットの設定についてですが、

            ARMv6(ラズパイゼロ/1系):
    rustup target add arm-unknown-linux-gnueabihf

ARMv7(2/3/4系):
    rustup target add armv7-unknown-linux-gnueabihf

        

で使い分けます。
なお、出力させるバイナリをgnuではなくmusl版で仕上げることを所望する場合には、

            ARMv6(ラズパイゼロ/1系):
    rustup target add arm-unknown-linux-musleabihf

ARMv7(2/3/4系):
    rustup target add armv7-unknown-linux-musleabihf

        

とするのが作法のようです。


ツールチェーンを準備する



次にARMアーキテクチャ向けのツールチェーンを確認しましょう。
ARMデベロッパーサイト公式から最新のGNUツールチェーンをダウンロードします。

GNU Toolchain Downloads

今回は開発環境をLinuxOSで行うのでターゲットに合わせて、

            ラズパイゼロ/1用:
    AArch32 target with hard float (arm-linux-gnueabihf)

ラズパイ2/3/4用:
    AArch32 target with hard float (arm-none-linux-gnueabihf)

        

を拾ってきます。
ファイルがダウンロードできたら、解凍後に中身を何処かに保管しておきます。
コンパイラが利用できるようにするため、PATH変数を通しておきましょう。

            export PATH="$HOME/ツールチェーンを展開したフォルダ/bin:$PATH"
#例としてラズパイゼロ/1の場合:
#export PATH="$HOME/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin:$PATH"
#例としてラズパイ2/3/4の場合:
#export PATH="$HOME/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf/bin:$PATH"

        

必要に応じて
.bashrc 等に記述しておけば楽に使えます。
なお、直接公式からツールチェーンをダウンロードして来なくとも、特定のOSではパッケージ版が提供されているので、場合によりそちらを使った方が楽にインストールできます。
例えばUbuntu/Debian系の場合、

            $ sudo apt install gcc-arm-linux-gnueabihf

        

からダウンロードできます。
Debian系の場合には、

            $ sudo apt install binutils-arm-linux-gnueabihf

        

が同様に利用できます。

Rust公式のDockerイメージ はDebianベースになりますので、Dockerコンテナで開発する場合にはこちらを使うと良いでしょう。
また、MacOSからはhomebrewを使って、

            $ brew install arm-linux-gnueabihf-binutils

        

からインストール可能です。


新規でRustプロジェクトを作成する



Cargoから簡単なプロジェクトを新規作成します。
ここでは
my_app という名前でRustプロジェクトを作成してみましょう。

            $ cargo new my_app
$ cd my_app && mkdir .cargo
$ touch .cargo/config.toml

        

ここで作った
.cargo/config.toml は、以下の構成で編集します。

            [build]

#ラズパイゼロ/1のgnuリンカ
[target.arm-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"

#ラズパイ2/3/4のgnuリンカ
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-none-linux-gnueabihf-gcc"

        

もしもgnu(動的リンク)ではなくmusl(静的リンク)でリンカーを構成する際にはターゲットの方を、

            #...以下を追記

[target.armv7-unknown-linux-musleabihf]
linker = "arm-linux-gnueabihf-ld"

[target.arm-unknown-linux-musleabihf]
linker = "arm-linux-gnueabihf-ld"

        

として追加してあげると良いでしょう。

プログラムのビルド



では先程のプロジェクト・
my-app をビルドしてみます。
今回はラズパイ4でmuslターゲットでビルドするようにします。

            #👇ラズパイゼロ/1でgnuの場合
#TARGET=arm-unknown-linux-gnueabihf
#👇ラズパイゼロ/1でmuslの場合
#TARGET=arm-unknown-linux-musleabihf
#👇ラズパイ2/3/4でgnuターゲット
#TARGET=armv7-unknown-linux-gnueabihf
#👇ラズパイ2/3/4でmuslターゲット
$ TARGET=armv7-unknown-linux-musleabihf

#バイナリをリリースビルド
$ cargo build --target $TARGET --release

        

これでバイナリが正常に生成されていればラズパイで動くバイナリが仕上がりました。
なお、出力されたバイナリはプロジェクトフォルダ内の
target/[ターゲット名]/release/my_app として出ているものを使います。
デフォルトでは、プロジェクト名がそのままバイナリプログラム名になるのでご注意ください。


ラズパイ実機での動作確認



先程作ったバイナリがラズパイ4で動くかどうか確認してみます。
ラズパイ実機とは基本的にSSHで接続して利用することの方が多いと思いますので、scpで先程のバイナリを送ってみます。
とりあえずは例としてユーザー名を
pi 、ローカルの固定IPを 192.168.1.234 、SSHのポート番号(デフォルトでは22)を 12345 と割り振ったラズパイ4で動かすとして、現在のプロジェクトからこのラズパイ実機へscpコマンドでファイル送信します。

            $ scp -P 12345 -r ./target/$TARGET/release/my_app pi@192.168.1.234:/home/pi

        

後はSSHでインタラクティブでバイナリを実行してみます。
ターミナルからSSH接続を介し、


            $ ssh pi@192.168.1.234 -p 12345 './my_app'
Hello, world!

        

と標準出力されたら正常に動作しています。


まとめ



今回はラズパイ用のバイナリプログラムを自作する際に、別環境でRustからクロスコンパイルを使って作成する方法を解説してみました。

参考サイト

Cross Compiling Rust for the Raspberry PiCross-compiling static Rust binaries in Docker for Raspberry PiRustのLinux muslターゲット (その1:Linux向けのポータブルなバイナリを作る)