Rust 软件编译为 Windows、macOS、Linux 的正确方法
wxk1991 Lv5

Rust 软件编译为 Windows、macOS、Linux 的正确方法

Rust 可以很方便地生成原生二进制文件,但“能编译”和“正确发布”不是一回事。真正做跨平台发布时,需要关心 target triple、C 依赖、动态库、系统证书、CPU 架构和 CI 构建环境。

这篇文章整理一套比较稳的做法。


一、先确认目标平台

Rust 用 target triple 描述编译目标。常见目标有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Windows 64 位,MSVC 工具链
x86_64-pc-windows-msvc

# macOS Intel
x86_64-apple-darwin

# macOS Apple Silicon
aarch64-apple-darwin

# Linux glibc
x86_64-unknown-linux-gnu
aarch64-unknown-linux-gnu

# Linux musl,常用于静态链接
x86_64-unknown-linux-musl
aarch64-unknown-linux-musl

查看本机默认目标:

1
rustc -vV

其中 host 字段就是当前工具链默认目标。


二、添加编译目标

使用 rustup target add 安装目标标准库:

1
2
3
rustup target add x86_64-unknown-linux-gnu
rustup target add x86_64-pc-windows-msvc
rustup target add aarch64-apple-darwin

然后可以指定目标构建:

1
cargo build --release --target x86_64-unknown-linux-gnu

产物一般在:

1
target/x86_64-unknown-linux-gnu/release/

Windows 下可执行文件是 .exe,macOS 和 Linux 通常没有扩展名。


三、不要低估 C 依赖

纯 Rust 项目跨平台最轻松。如果项目依赖了 OpenSSL、SQLite、libclang、zlib 这类 C 库,交叉编译就会复杂很多。

常见表现是:

1
error: failed to run custom build command

或者链接阶段报找不到库。解决思路有三种:

  1. 尽量使用纯 Rust 实现,比如 TLS 优先考虑 rustls
  2. 在目标平台原生构建,减少交叉链接问题。
  3. 使用 Docker 或 CI 的 matrix,让每个平台自己编译自己的产物。

对业务项目来说,第三种通常最稳。


四、Linux 构建要注意 glibc 版本

如果你在很新的 Linux 发行版上构建,再拿到旧服务器运行,可能遇到 glibc 版本不兼容。

一个常见策略是在较旧的基础镜像里构建,例如 Debian stable 或 Ubuntu LTS。这样产物在更多服务器上可运行。

如果想减少运行时依赖,可以考虑 musl:

1
2
rustup target add x86_64-unknown-linux-musl
cargo build --release --target x86_64-unknown-linux-musl

但 musl 不是万能答案。涉及 DNS、证书、系统库、性能细节时,仍然要在目标环境里测试。


五、macOS 产物要区分 Intel 和 Apple Silicon

macOS 现在至少要考虑两个架构:

1
2
cargo build --release --target x86_64-apple-darwin
cargo build --release --target aarch64-apple-darwin

如果需要合并成 universal binary,可以使用 lipo

1
2
3
4
lipo -create \
target/x86_64-apple-darwin/release/myapp \
target/aarch64-apple-darwin/release/myapp \
-output target/release/myapp-universal

命令行工具内部使用没有问题。如果要分发给普通用户,还可能涉及签名、公证和 Gatekeeper,这些属于 macOS 发布流程的一部分,不只是 Rust 编译问题。


六、Windows 推荐使用 MSVC 目标

Windows 上更常见、更推荐的目标是:

1
x86_64-pc-windows-msvc

构建:

1
cargo build --release --target x86_64-pc-windows-msvc

如果项目包含 C/C++ 依赖,通常需要安装 Visual Studio Build Tools。MinGW 目标也能用,但在和 Windows 原生生态集成时,MSVC 往往更省心。


七、用 cargo zigbuild 简化交叉编译

如果你经常从一台机器构建多个 Linux 目标,可以考虑 cargo-zigbuild

1
2
cargo install cargo-zigbuild
cargo zigbuild --release --target x86_64-unknown-linux-gnu

它利用 Zig 的链接能力,能缓解一部分交叉链接问题。适合 CLI、小型服务和依赖比较清晰的项目。

但它不是替代测试的工具。最终产物仍然要在真实目标系统上跑一遍。


八、推荐的 CI 构建方式

最稳的跨平台发布方式,是让 GitHub Actions 或其他 CI 在不同系统上原生构建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
name: release

on:
push:
tags:
- "v*"

jobs:
build:
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: windows-latest
target: x86_64-pc-windows-msvc
- os: macos-latest
target: aarch64-apple-darwin

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- run: cargo build --release --target ${{ matrix.target }}

这个方式比在本机硬做所有交叉编译更可控。尤其是带 C 依赖、GUI、系统调用、证书路径的项目,原生构建会少很多麻烦。


九、发布前检查清单

发布 Rust 二进制前,建议至少检查这些内容:

  • --release 是否开启。
  • 版本号、Git commit、构建时间是否写入产物。
  • Windows、macOS、Linux 是否分别测试启动。
  • CLI 参数、配置文件路径、日志路径是否跨平台。
  • 是否依赖外部动态库。
  • 压缩包里是否包含 README、LICENSE、示例配置。

构建命令只是第一步。真正可靠的跨平台发布,需要把编译、打包、测试和发布流程一起设计好。


十、实践建议

如果项目是纯 Rust CLI,可以先从 rustup target addcargo build --target 开始。如果项目依赖系统库,优先考虑 CI matrix 原生构建。如果要做 Linux 静态发布,再评估 musl 或 cargo-zigbuild

不要把所有平台都当成“只是换个 target”。Windows、macOS、Linux 的文件系统、证书、动态库、权限模型都有差异。正确方法不是追求一条命令打天下,而是让每个平台在合适的环境里构建,并在真实环境里验证。