macOS 系统下交叉编译 Rust 为 Linux musl 目标(x86_64 和 aarch64 架构)

Published: 2023-09-27

Tags: Rust

本文总阅读量

Rust 支持交叉编译,可以 macOS 平台编译出 Linux 或者 Windows 可运行的程序,或者在 Linux 平台编译 macOS 或者 Windows 可运行的程序。

这篇文章主要讲解 Mac 平台编译为 Linux 平台的二进制程序。

环境

Build:macOS

OS:Apple M2 - Darwin Kernel Version 22.1.0 / arm64 rustc:rustc 1.72.1 (d5c2e9c34 2023-09-13) rustup:rustup 1.26.0 (5af9b9484 2023-04-05)

Target:linux x86_64

OS:18.04.1-Ubuntu x86_64 GNU/Linux

Target:linux aarch64

OS:20.04.1-Ubuntu aarch64 GNU/Linux

准备示例

$ cargo new --bin hello-rust

文件 main.rs

fn main() {
    println!("Hello World!\n");
}

编译为 Linux 平台(x86_64)

先介绍下 musl:musl 源自 Michael Rolington 提出的 μClibc 微型 C 库计划,μ来自于希腊字母μ(mu),代表“微小”或“微型”,Rolington 之后离开了 μClibc 项目,此后 μClibc 由 Erik Andersen 继续开发,2008年,Rolington 又创建了一个新的微型 C 库项目 musl libc,取名 musl 是为纪念 μClibc 计划 —— AI

要实现 Linux 平台可以运行的程序,那么需要使用 musl 来替代 glibc,musl 实现了 Linux libc。

musl 工具链在 macOS 上使用 musl-cross 进行安装,musl-cross 是用来专门编译到 Linux 的工具链:

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

不指定参数默认安装的是 x86_64 工具链

添加 Target

$ rustup target add x86_64-unknown-linux-musl

将以下内容写入配置文件:.cargo/config

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

编译

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

如果不修改 .cargo/config 配置文件,可以执行 $ RUSTFLAGS="-C linker=x86_64-linux-musl-gcc" cargo build --target=x86_64-unknown-linux-musl

编译后,在 target 目录下的 x86_64-unknown-linux-musl 文件夹可以找到编译后的程序

将程序拷贝到目标机器执行

# ubuntu @ ip-172-11-22-33 in ~ [3:35:37]
$ uname -a
Linux ip-172-11-22-33 5.4.0-1103-aws #111~18.04.1-Ubuntu SMP Tue May 23 20:04:10 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

# ubuntu @ ip-172-11-22-33 in ~ [3:35:40]
$ /tmp/hello-rust
Hello, world!

编译为 Linux 平台(aarch64)

musl-cross 不支持同时安装多个交叉编译环境,需重新安装,需要注意这会导致 x86_64 工具链失效。

$ brew reinstall FiloSottile/musl-cross/musl-cross --without-x86_64 --with-aarch64

添加 Target

$ rustup target add aarch64-unknown-linux-musl

将以下内容写入配置文件:.cargo/config

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

编译

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

将程序拷贝到目标机器执行

 ubuntu@ip-172-22-33-44 ~ $ uname -a
Linux ip-172-22-33-44 5.15.0-1028-aws #32~20.04.1-Ubuntu SMP Mon Jan 9 18:02:12 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux
 ubuntu@ip-172-22-33-44 ~ $ /tmp/hello-rust
Hello, world!

参考