之前我没有试过 C++ 之外的交叉编译环境,以前在用 C++ 开发游戏的时候,会把逻辑代码用 Android Studio 编译出安卓版本,以及使用 iOS 的 toolchain 编译成 iOS 的版本。

假如没有对应的 toolchain 的话,我可能也就束手无策了,我还没折腾过用 https://github.com/richfelker/musl-cross-make 这个工具进行交叉编译,不过今天在学 Rust 的时候,发现交叉编译 Rust 程序的步骤非常简单,就先记在这里。

这里我只用 macOS 来示范,因为今天只在这个平台上试过。

安装链接器

musl-cross 似乎是在链接时候起作用的(不知道我这个说法对不对)。

首先通过 brew 安装 musl-cross 工具,其中 musl-cross 是用来专门编译到 linux 的工具链,而 mingw-w64 是用来编译到 windows 的工具链。根据你的目标平台自己装一个就好。

$ brew install FiloSottile/musl-cross/musl-cross  
$ brew install mingw-w64  

我装的是 musl-cross,装好后到 ~/.cargo/config 文件中添加上:

[target.x86_64-unknown-linux-musl]
linker = "x86_64-linux-musl-gcc"

注意一下等于号后面跟的是 x86_64-linux-musl-gcc

rustup 配置

rustup 是 Rust 的包管理工具,用它来配置工具链可以很省心。

运行 rustup target list 你可以看到很多的目标平台。

$ rustup target list
aarch64-apple-ios
aarch64-linux-android
aarch64-unknown-fuchsia
aarch64-unknown-linux-gnu
aarch64-unknown-linux-musl
arm-linux-androideabi
arm-unknown-linux-gnueabi
arm-unknown-linux-gnueabihf
arm-unknown-linux-musleabi
arm-unknown-linux-musleabihf
armv5te-unknown-linux-gnueabi
armv5te-unknown-linux-musleabi
armv7-apple-ios
armv7-linux-androideabi
armv7-unknown-linux-gnueabihf
armv7-unknown-linux-musleabihf
armv7s-apple-ios
asmjs-unknown-emscripten
i386-apple-ios
i586-pc-windows-msvc
i586-unknown-linux-gnu
i586-unknown-linux-musl
i686-apple-darwin
i686-linux-android
i686-pc-windows-gnu
i686-pc-windows-msvc
i686-unknown-freebsd
i686-unknown-linux-gnu
i686-unknown-linux-musl
mips-unknown-linux-gnu
mips-unknown-linux-musl
mips64-unknown-linux-gnuabi64
mips64el-unknown-linux-gnuabi64
mipsel-unknown-linux-gnu
mipsel-unknown-linux-musl
powerpc-unknown-linux-gnu
powerpc64-unknown-linux-gnu
powerpc64le-unknown-linux-gnu
s390x-unknown-linux-gnu
sparc64-unknown-linux-gnu
sparcv9-sun-solaris
thumbv6m-none-eabi
thumbv7em-none-eabi
thumbv7em-none-eabihf
thumbv7m-none-eabi
wasm32-unknown-emscripten
wasm32-unknown-unknown
x86_64-apple-darwin (default)
x86_64-apple-ios
x86_64-linux-android
x86_64-pc-windows-gnu
x86_64-pc-windows-msvc
x86_64-rumprun-netbsd
x86_64-sun-solaris
x86_64-unknown-cloudabi
x86_64-unknown-freebsd
x86_64-unknown-fuchsia
x86_64-unknown-linux-gnu
x86_64-unknown-linux-gnux32
x86_64-unknown-linux-musl
x86_64-unknown-netbsd
x86_64-unknown-redox

我们之前只设置了 target.x86_64-unknown-linux-musl,所以现在也只装对应的这个目标平台相关工具:

$ rustup target add x86_64-unknown-linux-musl

这一步如果很慢可以在你的 .bashrc 或者 .zshrc 中添加这一行,中科大的源加速很靠谱:

export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static

编译

接着只要在运行 build 命令时指定 target 就可以了。

$ cargo build --target=x86_64-unknown-linux-musl

接着你可以看到类似这样的文件结构:

├── build
└── target
    └── x86_64-unknown-linux-musl
        └── debug
            ├── build
            ├── deps
            ├── examples
            ├── incremental
            └── native

找到你对应编译好的可执行文件,扔到你的 linux 机子上跑,就可以了。

你可以用 file 命令确认一下:

$ file target/x86_64-unknown-linux-musl/debug/rust-test
target/x86_64-unknown-linux-musl/debug/rust-test: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, with debug_info, not stripped