← 返回首页

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可能时间会久点。

image.png

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

image.png

项目下配置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 则表示启用最大程度的优化

效果对比:

未配置参数

image.png

配置参数后

image.png

rust在使用在unwrap,panic之类的调用里面会自动记录源代码路径,而cargo默认目录在%users%下面,这会导致编译的二进制文件会存在编译者的目录信息。

image.png

设置环境变量

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"

编译后的效果

image.png

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"
]

本文仅供参考,只是我日常工作中遇到的问题做个记录,如果有什么不对的地方可留言。