M1 Mac上のRustでクロスコンパイルする

作成日:

最近RustでCGIを書くなんてことをしていたのですが、諸事情でサーバー側にRustのコンパイラを入れられず、別のマシンでビルドしたバイナリをコピーして動かしました。その時はLinuxの別マシンでビルドしたのですが、開発機であるM1 Macでビルドできた方が楽なので、その方法を調べました。

クロスコンパイラをインストールする

まずは別のCPUを対象としてコンパイルするためのコンパイラ(クロスコンパイラ)をインストールする必要があります。今回は messense/homebrew-macos-cross-toolchains を使わせてもらいます。Homebrewでもインストールできるようですが、Release にあるビルド済みバイナリを用いるとお手軽です1

Releaseのページにはたくさんのtar.gzが並んでいるので、目的にあったバイナリをダウンロードします。私の場合は「M1 Mac (aarch64-darwin)上で」「x86_64のLinuxで動く、CライブラリとしてMUSLを使ったバイナリ(x86_64-unknown-linux-musl)を作る」ため、x86_64-unknown-linux-musl-aarch64-darwin.tar.gzをダウンロードしました2

そして、これを解凍し、中のbinディレクトリにパスを通します。

現時点(2021/05/16)での最新版(v10.3.0)を使う場合、以上のことをするコマンドは次の通りです。

$ mkdir -p $HOME/tools && cd $HOME/tools # 適当なディレクトリ
$ wget https://github.com/messense/homebrew-macos-cross-toolchains/releases/download/v10.3.0/x86_64-unknown-linux-musl-aarch64-darwin.tar.gz
$ tar xf x86_64-unknown-linux-musl-aarch64-darwin.tar.gz # 解凍
$ export PATH="$HOME/tools/x86_64-unknown-linux-musl/bin:$PATH" # パスを通す
$ x86_64-unknown-linux-musl-gcc # パスが通っているか確かめる
x86_64-unknown-linux-musl-gcc: fatal error: no input files
compilation terminated.

なお、永続的に設定したい場合はexport.zshrcなりのシェル設定ファイルに書いて下さい(以下同じ)。

Rustでクロスコンパイルできるようにする

まず、Rust側でターゲットを追加します。

$ rustup target add x86_64-unknown-linux-musl

これだけではRustがクロスコンパイラを見つけてくれないため、messense/homebrew-macos-cross-toolchainsのREADMEに従って次のように環境変数を設定します。

$ export CC_x86_64_unknown_linux_musl=x86_64-unknown-linux-musl-gcc
$ export CXX_x86_64_unknown_linux_musl=x86_64-unknown-linux-musl-g++
$ export AR_x86_64_unknown_linux_musl=x86_64-unknown-linux-musl-ar
$ export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=x86_64-unknown-linux-musl-gcc

クロスコンパイルしてみる

以上で設定ができたはずなので、Hello worldプロジェクトで確かめてみます。

$ cargo new etude-cross
$ cd etude-cross
$ cargo build --target x86_64-unknown-linux-musl --release # クロスコンパイル
$ file target/x86_64-unknown-linux-musl/release/etude-cross # ファイル形式を確かめる
target/x86_64-unknown-linux-musl/release/etude-cross: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, with debug_info, not stripped

確かにELF 64-bitのバイナリができあがりました。

参考文献


  1. 変なバイナリである可能性を排除できないのでセキュリティ的にはよろしくないかもしれませんが。 ↩︎

  2. 例えばラズパイで動かすバイナリが欲しいなど、別のアーキテクチャ用のバイナリが欲しい場合は以下の文章のx86_64-unknown-linux-muslの部分を適宜読み替えてください。 ↩︎



© 神和電子 2017-2020