目录
编译问题:rust交叉编译注意事项
起因是工作上生产环境为win7,比较老的版本,而开发机器是win11,因此,要想在win11上开发win7的Rust应用需要注意一些事情。
rust编译工具
组件
- rustc:Rust核心编译器,负责把 .rs 文件编译成机器码。
rustc --version
- Cargo:Rust 的包管理器 & 构建工具,类似于npm。
cargo --version
- rustfmt:代码格式化工具,版本与 rustc 对应。
rustfmt --version
- clippy:代码静态检查工具,版本跟随 rustc。
cargo clippy --version
- rustup:Rust的工具链管理器,统管上述所有工具的版本。
rustup show //显示全局默认、项目 override、已安装的工具链 rustup toolchain list rustup toolchain uninstall <version> //删除某个版本 rustup install 1.xx.x //安装指定工具链 rustup uninstall 1.xx.x //删除工具链 rustup default xxx //设置全局默认版本 rustup override set xxx //设置当前目录的工具链版本 rustup override unset //取消当前目录的工具链版本,恢复默认
一般来说,某个项目中使用的所有编译工具,版本号一致。
是因为Rust的生态是工具链绑定的,rustc决定编译器版本(语法、标准库 API),cargo 与 rustc 一起发布,clippy、rustfmt 都随 rustc 走。
因此,用户设置项目的编译时,只需要通过rustup就可以控制所有组件的版本。
rust版本
rust工具链版本对应不同的系统版本,是因为操作系统提供的API在不断升级,rust核心库支持的API也会随之升级。 例如,rust 1.75是最后一个支持Windows7,windows8的版本。
也就是说,想要开发运行在win7上的rust应用,rust编译链及其组件(rustc,cargo)最高版本为1.75。
因此在编译项目时,要先查看目标平台系统是否支持当前rust版本。
rust目标平台
和linux中的交叉编译类似,使用rust编译运行在不同操作系统上的代码时,需要指定并设置目标平台。
目标平台由三段式标识:
- x86_64 → 64 位架构
- pc-windows → Windows 系统
- gnu → 使用 GNU 工具链(MinGW)而不是 MSVC
Windows:
Target | 使用的工具链 | 特点 | 安装依赖 |
---|---|---|---|
x86_64-pc-windows-msvc | 微软官方 MSVC | 默认推荐,兼容 Visual Studio | visual studio |
x86_64-pc-windows-gnu | GNU(MinGW-w64) | 不依赖 MSVC,更开放但兼容性略差 | https://www.msys2.org/ |
与目标平台相对应的是本地平台,也就是代码编写的平台。例如我在win11上开发代码,本地平台就是x86_64-pc-windows-msvc;而我需要编译成可以在win7上运行的程序,对应的目标平台就是x86_64-pc-windows-gnu。
linux:
目标平台 | libc 实现 | 是否静态链接 | 是否可移植 | 是否需要系统依赖 | 文件体积 | 常用场景 |
---|---|---|---|---|---|---|
x86_64-unknown-linux-gnu | glibc | ❌ 动态链接 | ⛔ 否(受限于 glibc 版本) | ✅ 需要目标系统有相同或兼容 glibc | 较小 | 默认构建,开发时用 |
x86_64-unknown-linux-musl | musl libc | ✅ 静态链接 | ✅ 是(跨发行版运行) | ❌ 不依赖系统 libc 环境 | 稍大 | 静态发布,跨平台运行 |
注意:x86_64-unknown-linux-musl平台位于rust支持的第二级目标平台,也就是说rust保证构建,但是不保证可以正常运行。
rustup对平台的管理
在交叉编译时,目标平台的添加和删除也由rustup进行设置:
功能 | 命令 | 说明 |
---|---|---|
添加 target | rustup target add x86_64-pc-windows-gnu | 添加交叉编译目标 |
移除 target | rustup target remove aarch64-unknown-linux-gnu | 删除 target |
查看已安装 target | rustup target list --installed | 列出当前工具链已安装的 target |
针对指定工具链添加 target | rustup target add x86_64-pc-windows-gnu --toolchain 1.84.1 | 安装到指定版本 |
交叉编译设置
当项目中需要rust交叉编译,需要注意以下几点:
- 注意目标平台支持的最高的rust版本。
- 注意目标平台的架构
- 根据架构选择对应的编译工具链
有朋友疑惑,为什么还需要像gcc这样的编译器?程序编译的过程需要两个组件,一个是编译器,一个是链接器。
编译器用于将代码编译成.o的机器码,再由链接器linker把 .o 和 libc 等库链接成最终的可执行文件。
在rust中,rustc只负责生成.o 文件,不负责最终链接成可执行文件。
配置文件指定 vs 命令行指定
rust版本,架构,以及编译工具链的指定,都可以通过rustup命令设置或者通过环境变量自动查找。
但是为了更自由的控制,一般来说,较好的方法是通过项目内的配置文件来指定,而不是通过"rustup override set"命令指定。
rust-toolchain.toml
该文件存放在项目根目录,用于指定该项目的rust版本和目标平台。示例:
[toolchain]
channel = "1.75.0-x86_64-pc-windows-gnu"
然后执行rustup show 就会自动下载并指定
.cargo/config.toml
该文件夹存放在项目根目录,用于控制链接器行为(比如静态链接、跨平台编译、MinGW/LLVM link),上述中的编译工具链的位置指定,就是通过这个文件完成。 示例:
[target.x86_64-pc-windows-gnu]
linker = "D:\\Program Files\\msys64\\ucrt64\\bin\\x86_64-w64-mingw32-gcc.exe"
rustflags = ["-C", "link-args=-Wl,--subsystem,console"]
其中,上述内容仅在cargo build --release命令指定了--target x86_64-pc-windows-gnu参数后才生效。
示例
win
以目标平台为win7为例:
- Rust官方宣布1.75.0是支持win7/8的最后一个版本。
- 本地平台win11使用的是MSVC,win7使用的是GNU,所以必须额外下载GNU工具链以适配win7。因此,目标平台架构为x86_64-pc-windows-gnu。
- 工具链选择msys2。
完整流程(前提是编写完配置文件并安装GNU编译器 https://www.msys2.org/)
cd xxx
rustup show //下载对应rust编译版本及组件
rustup target add x86_64-pc-windows-gnu --toolchain 1.75.0 //指定目标平台并将其应用到特定的rust版本上
rustup show //查看激活的rust channel
cargo build --release --target x86_64-pc-windows-gnu
linux
使用ubuntu20开发其它linux平台(64位)的程序时,由于目标GLIBC版本太低导致无法运行,所以应该使用x86_64-unknown-linux-musl工具链。
rustup target add x86_64-unknown-linux-musl
apt-get install musl-tools
cargo build --release --target x86_64-unknown-linux-musl
其它注意事项
crate包
某些crate包依赖于较新的系统API,可能导致编译失败或运行失败,开发时要注意。