Rust 使用cross交叉编译及缩小build文件体积记录
Rust 使用cross交叉编译及缩小build文件体积记录
type: Post
status: Published
date: 2024/10/16
slug: Rust
category: 技术分享
0x1 背景
最近在折腾rust 在Mac Apple M3 上交叉编译一些windows程序总是遇到各种依赖问题。前前后后困扰了我很久,终于找到了好的方案记录下。
主要用到了cross 基于docker 进行交叉编译类似于golang的开源项目xgo
0x2 cross安装及配置
按照官方文档,如果已经配置好了rust环境直接
cargo install cross --git [https://github.com/cross-rs/cross](https://github.com/cross-rs/cross)
2.1 配置及用法
官方文档里写到
“您可以将 Cross.toml 文件放置在 Cargo 项目的根目录中,或使用CROSS_CONFIG
环境变量来调整 cross 的行为。您还可以在Cargo.toml
中使用package.metadata.cross.KEY
,设置的优先级是环境变量覆盖Cross.toml
选项,从而覆盖Cargo.toml
选项。”
这是我的配置,写在在项目下的Cross.toml
[target.target.x86_64-pc-windows-gnu]
image = "ghcr.io/cross-rs/x86_64-pc-windows-gnu:main
更多配置参数参照官方文档,直接在项目中和cargo的用法一样,需要提前安装docker 指定target后第一次运行会自动去拉images可能时间会久点。
cross build --release --target x86_64-pc-windows-gnu
cross build --release --target i686-pc-windows-gnu
编译后的文件在
/target/{you_target}/release
2.1 进阶配置交叉编译MSVC 和 Apple Darwin
Additional Dockerfiles for other targets can be found in
cross-toolchains. These include MSVC and Apple Darwin targets, which we cannot ship pre-built images of.
其他目标的附加 Dockerfile 可以在以下位置找到 跨工具链。其中包括 MSVC 和 Apple Darwin 目标,我们无法提供其预构建图像。
**cross-toolchains
**这是Cross生成用于为其他目标构建映像的其他 Dockerfile 和 crosstool-ng 配置文件。这些允许使用其他目标以及不同的 glibc 或 GCC 版本。
安装:
// 拉取项目到本地
git clone [https://github.com/cross-rs/cross](https://github.com/cross-rs/cross)
cd cross
// 初始化和更新 Git 仓库中的子模块
git submodule update --init --remote
// 指定Targets 配置与构建 crosstool 相关的所有配置文件,以便生成交叉编译工具链(crosstoolchain)镜像,不指定则生成全部
cargo xtask configure-crosstool i686-pc-windows-msvc-cross
// 编译Docker image
cargo build-docker-image i686-pc-windows-msvc-cross --tag local
项目下配置Cross.toml
[target.x86_64-pc-windows-msvc]
image = "ghcr.io/cross-rs/x86_64-pc-windows-msvc-cross:local"
[target.i686-pc-windows-msvc]
image = "ghcr.io/cross-rs/i686-pc-windows-msvc-cross:local"
0x3 缩小rust 编译文件体积
通过之前的调研比对,我使用了以下参数
# 配置优化编译的二进制文件体积
[profile.release]
lto = true # LTO 允许编译器在链接时对整个程序进行优化。
strip = true # 通过在编译时去除符号信息,可以减小二进制文件的体积
debug = false # 禁用默认的 debug 信息
panic = 'abort' # 发生panic立即终止程序,稍后由OS来清理内存
incremental = false # 默认情况下,Cargo 开启了增量编译来提高构建速度。然而,对于最小化体积而言,可以尝试禁用增量编译。
codegen-units = 1 # 选项指定了编译器在一次编译中生成的代码单元的数量。减小这个数字可能会减小生成的二进制文件的体积。
codegen = ["-C", "opt-level=z"] # -C 是用来传递编译器代码生成选项的标志,而 opt-level=z 则表示启用最大程度的优化
效果对比:
未配置参数
配置参数后
rust在使用在unwrap,panic之类的调用里面会自动记录源代码路径,而cargo默认目录在%users%下面,这会导致编译的二进制文件会存在编译者的目录信息。
设置环境变量
export CARGO_HOME="${CARGO_HOME:-$HOME/.cargo}"
export RUSTFLAGS="--remap-path-prefix=$CARGO_HOME/registry=registry_src --remap-path-prefix=$CARGO_HOME/registry/src=src"
编译后的效果
msvc的配置,减少编译体积不要PDB调试文件
[target.x86_64-pc-windows-msvc]
image = "ghcr.io/cross-rs/x86_64-pc-windows-msvc-cross:local"
[target.x86_64-pc-windows-msvc.env]
passthrough = [
"RUSTFLAGS=--remap-path-prefix=/Users/orz/.cargo/registry=registry_src --remap-path-prefix=/Users/orz/.cargo/registry/src=src -C opt-level=3 -C lto=true -C codegen-units=1 -C target-feature=+crt-static -C panic=abort -C debuginfo=0 -C strip=symbols -C link-args=/DEBUG:NONE -C link-args=/PDB:none"
]
[target.i686-pc-windows-msvc]
image = "ghcr.io/cross-rs/i686-pc-windows-msvc-cross:local"
[target.i686-pc-windows-msvc.env]
passthrough = [
"RUSTFLAGS=--remap-path-prefix=/Users/orz/.cargo/registry=registry_src --remap-path-prefix=/Users/orz/.cargo/registry/src=src -C opt-level=3 -C lto=true -C codegen-units=1 -C target-feature=+crt-static -C panic=abort -C debuginfo=0 -C strip=symbols -C link-args=/DEBUG:NONE -C link-args=/PDB:none"
]
本文仅供参考,只是我日常工作中遇到的问题做个记录,如果有什么不对的地方可留言。