Rust交叉编译
实际上 Cargo 已经准备了很多目标平台,我们可以通过 rustup target list
命令来查看可以交叉编译的平台。
x86_64-apple-darwin (installed)
x86_64-apple-ios
x86_64-fortanix-unknown-sgx
x86_64-linux-android
x86_64-pc-solaris
x86_64-pc-windows-gnu (installed)
x86_64-pc-windows-gnullvm
x86_64-pc-windows-msvc
x86_64-unknown-freebsd
x86_64-unknown-fuchsia
x86_64-unknown-illumos
x86_64-unknown-linux-gnu (installed)
x86_64-unknown-linux-gnux32
x86_64-unknown-linux-musl
x86_64-unknown-linux-ohos
x86_64-unknown-netbsd
x86_64-unknown-none
对于 Windows 和 Linux 而言,大多数情况下,通过rustup target add xxx
安装目标平台的支持之后,就可以使用
cargo build -r --target xxx
来编译出对应平台的可执行文件。但是在编译 MacOS 的时候遇到了问题,它需要 macOS SDK,对于普通场景而言,你只需要在 MacOS 上编译就行了,但是对于自动化的构建流程而言,这将是极大的麻烦。但是 zig 有一个强大的工具链,支持交叉编译和多版本的 glibc(Rust 不支持低版本的 glibc)。我们借助 zig 的编译链来增强 rust 的交叉编译能力。
cargo-zigbuild
cargo-zigbuild 项目使用 zig 作为链接器来编译 rust 项目,极大的方便我们交叉编译 rust 项目。
安装
可以使用 cargo install 来安装
cargo install --locked cargo-zigbuild
也可以使用 pip 来安装
pip install cargo-zigbuild
无论是那种方式,都会自动安装 ziglang
除此之外,该项目还提供了一个 Docker 镜像,除了 cargo-zigbuild 和 Rust 之外,它还预装了 macOS SDK,来帮助我们针对 MacOS 进行编译。例如,针对 x86_64 架构的 MacOS 进行构建。
在 rust 项目目录下,执行下面的命令,即可针对 x86_64 架构的 MacOS 进行构建
docker run --rm -it -v $(pwd):/io -w /io messense/cargo-zigbuild cargo zigbuild --release --target x86_64-apple-darwin
当然了,你也可以分步操作,首先进入容器,然后在进行项目构建。在我们这里,可能需要对镜像做一个改造,因为镜像里的 rust 仓库是 crates.io,我们需要换源。也可以将准备好的配置文件挂载到容器上去。例如:
docker run --rm -it -v $(pwd):/io -v $(pwd)/config.toml:/usr/local/cargo/config.toml -w /io messense/cargo-zigbuild cargo zigbuild --release --target x86_64-apple-darwin
这样就可以将当前目录下的 config.toml 挂载到容器的 /usr/local/cargo/config.toml, 这样就可以使用国内的镜像源了,能够极大的提高下载速度。
使用
前面在 docker 镜像这里提到了如何使用,其实非常简单,只需要下面一行命令即可:
cargo zigbuild --target aarch64-unknown-linux-gnu --release
这样就完成了交叉编译到目标平台。
指定 glibc 版本
cargo zigbuild 支持在选项中传递 glibc 版本,例如, 要针对 glibc 2.17 进行编译,目标是:aarch64-unknown-linux-gnu
此时,你可以在目标后面加上 glibc 的版本:
cargo zigbuild --target aarch64-unknown-linux-gnu.2.17
macOS universal2 目标
cargo zigbuild 支持在 Rust 1.64.0 及更高版本上构建 macOS universal2 二进制文件/库的特殊目标
例如:
rustup target add x86_64-apple-darwin
rustup target add aarch64-apple-darwin
cargo zigbuild --target universal2-apple-darwin
对于编译完成的 MacOS 平台的二进制文件,你会发现有 strip 执行失败的警告。尝试手动使用 strip 命令去除符号和调试信息,也会失败。
这时候,我们需要安装 cargo-binutils,它可以帮助我们方便地调用 Rust 内置的 LLVM binutils
cargo install cargo-binutils
ustup component add llvm-tools-preview
安装完成 LLVM 套件之后,我们会有一个 rust-objcopy 的命令可用,可以通过 rust-objcopy 将可执行程序中的多余信息给剥离。
rust-objcopy xxx --strip-all -O binary xxx-darwin-universal2