この記事ではmacOS上でRustをLinuxのバイナリにクロスコンパイルする方法を説明します。
まずx86_64-unknown-linux-gnuパッケージをbrewでインストールします。
brew install SergioBenitez/osxct/x86_64-unknown-linux-gnu
aarch64の場合はこっち
brew tap messense/macos-cross-toolchains
brew install aarch64-unknown-linux-gnu
つぎにrustにtargetを追加します。
rustup target add x86_64-unknown-linux-gnu
# aarch64
rustup target add aarch64-unknown-linux-gnu
そして ~/.cargo/config.toml`にlinkerの設定を追加します。
~/.cargo/config.toml
[target.x86_64-unknown-linux-gnu]
linker = "x86_64-unknown-linux-gnu-gcc"
# aarch64
# [target.aarch64-unknown-linux-gnu]
# linker = "aarch64-unknown-linux-gnu-gcc"
OpenSSLライブラリの設定
適当なディレクトリを作ります。
mkdir ~/rust/lib && cd ~/rust/lib
OpenSSLライブラリを取得して展開します。
curl -O https://debian.sipwise.com/debian-security/pool/main/o/openssl/libssl-dev_1.1.1d-0+deb10u6_amd64.deb
ar p libssl-dev_1.1.1d-0+deb10u6_amd64.deb data.tar.xz | tar xvf -
rm -rf libssl-dev_1.1.1d-0+deb10u6_amd64.deb
Aarch64の場合はこっち
curl -O https://debian.ignum.cz/debian-security/pool/main/o/openssl/libssl-dev_1.1.1d-0+deb10u6_arm64.deb
ar p libssl-dev_1.1.1d-0+deb10u6_arm64.deb data.tar.xz | tar xvf -
rm -rf libssl-dev_1.1.1d-0+deb10u6_arm64.deb
ビルド用環境変数の設定
export LIB_OPENSSL_DIR=~/rust/lib
# Linker for the target platform
# (cc can also be updated using .cargo/config)
export TARGET_CC="x86_64-unknown-linux-gnu-gcc"
# Library headers to link against
export TARGET_CFLAGS="-I ${LIB_OPENSSL_DIR}/usr/include/x86_64-linux-gnu -isystem ${LIB_OPENSSL_DIR}/usr/include"
# Libraries (shared objects) to link against
export LD_LIBRARY_PATH="${LIB_OPENSSL_DIR}/usr/lib/x86_64-linux-gnu;${LIB_OPENSSL_DIR}/lib/x86_64-linux-gnu"
# openssl-sys specific build flags
export OPENSSL_DIR="${LIB_OPENSSL_DIR}/usr/"
export OPENSSL_LIB_DIR="${LIB_OPENSSL_DIR}/usr/lib/x86_64-linux-gnu/"
# Aarch64
#!/bin/sh
export LIB_OPENSSL_DIR=$(pwd)/build
# Linker for the target platform
# (cc can also be updated using .cargo/config)
export TARGET_CC="aarch64-unknown-linux-gnu-gcc"
# Library headers to link against
export TARGET_CFLAGS="-I ${LIB_OPENSSL_DIR}/usr/include/aarch64-linux-gnu -isystem ${LIB_OPENSSL_DIR}/usr/include"
# Libraries (shared objects) to link against
export LD_LIBRARY_PATH="${LIB_OPENSSL_DIR}/usr/lib/aarch64-linux-gnu;${LIB_OPENSSL_DIR}/lib/aarch64-linux-gnu"
# openssl-sys specific build flags
export OPENSSL_DIR="${LIB_OPENSSL_DIR}/usr/"
export OPENSSL_LIB_DIR="${LIB_OPENSSL_DIR}/usr/lib/aarch64-linux-gnu/"
export CC_Aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnu-gcc
export CXX_Aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnu-g++
export AR_Aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnu-ar
export CARGO_TARGET_Aarch64_UNKNOWN_LINUX_GNU_LINKER=aarch64-unknown-linux-gnu-gcc
ビルド
最後にビルドを実行します。
cargo build --target=x86_64-unknown-linux-gnu
# aarch64
cargo build --target=aarch64-unknown-linux-gnu
コンパイル結果
下記ディレクトリにバイナリが出力されています。
target/x86_64-unknown-linux-gnu/debug/hoge
# aarch64
target/aarch64-unknown-linux-gnu/debug/hoge
fileコマンドでちゃんとELFになっているか確認してみます。
file target/x86_64-unknown-linux-gnu/debug/hoge
# aarch64
file target/aarch64-unknown-linux-gnu/debug/hoge
target/x86_64-unknown-linux-gnu/debug/h: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, with debug_info, not stripped
なってますね!!😄
参考
- Index of /debian-security/pool/main/o/openssl
- https://debian.ignum.cz/debian-security/pool/main/o/openssl/
- chinedufn/cross-compile-rust-from-mac-to-linux: An example of how to cross compile Rust from `macOS` to Linux `x86_64-unknown-linux-gnu`
- A “rustup target” Example: Using a Mac to cross-compile Linux binaries | Non-Recurring Engineering
- Cross-compiling Rust From Mac to Linux | by Merlin Fuchs | Better Programming