如何配置 cross 工具?
解读
在国内面试中,“如何配置 cross” 并不是单纯问“装个插件”,而是考察候选人是否真正在非 x86 嵌入式或 CI 场景里解决过交叉编译痛点。面试官想听的是:
- 你能否一行命令把
x86_64-unknown-linux-gnu的二进制编译成aarch64-unknown-linux-musl并直接跑在板子上; - 是否知道国内镜像源、Docker 拉取失败、openssl-sys 交叉编译失败这三座大山的具体解法;
- 能否把配置固化到项目里,让同事
git clone后无需任何手动步骤即可重现。
答不到“镜像 + Docker 缓存 + 自定义镜像”这一层,基本会被认为“只是跑过 demo”。
知识点
- cross 本质:一个用 Docker/Qemu 封装的
cargowrapper,把“工具链 + 目标 sysroot + 链接器”全部放进容器,零污染主机。 - 国内网络:Docker Hub 间歇性抽风,rustup 默认源在国外,必须换清华/中科大镜像。
- 自定义镜像:当需要
libudev-dev、libssl-dev等 C 库时,必须写Cross.toml指定image = "registry.cn-hangzhou.aliyuncs.com/xxx/my-cross:aarch64",否则链接阶段报cannot find -lssl。 - 缓存:CI 里把
/target与~/.cargo/registry/cache挂到 actions/cache,每次节省 3-5 min。 - 安全:公司内网要求“不允许自动拉取外部镜像”,需
docker save/load把镜像预置到 Runner,cross 的DOCKER_OPTS="--network none"可禁用外网。
答案
步骤一:安装与换源
# 1. 安装(cargo 国内源已配好)
cargo install cross --git https://github.com/cross-rs/cross.git --tag v0.2.5
# 2. 换 rustup 镜像
export RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup
rustup default stable
步骤二:项目级固化配置
在项目根新建 Cross.toml:
[target.aarch64-unknown-linux-musl]
image = "registry.cn-hangzhou.aliyuncs.com/company/cross:aarch64-musl-1.75"
# 公司内网无公网,关闭 DNS 解析
dockerfile = "./docker/cross-aarch64.Dockerfile"
步骤三:自定义镜像(解决 openssl-sys 问题)
docker/cross-aarch64.Dockerfile:
FROM ghcr.io/cross-rs/aarch64-unknown-linux-musl:edge
RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://mirrors.tuna.tsinghua.edu.cn/alpine|g' /etc/apk/repositories \
&& apk add --no-cache openssl-dev openssl-libs-static
步骤四:一键交叉编译
cross build --release --target aarch64-unknown-linux-musl
产物直接 scp 到板子运行,无需再装任何运行时库。
步骤五:CI 固化(GitHub Actions 示例)
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry/cache
target
key: ${{ runner.os }}-cross-${{ hashFiles('Cargo.lock') }}
- run: |
docker login -u ${{ secrets.ALIYUN_USER }} -p ${{ secrets.ALIYUN_PASS }} registry.cn-hangzhou.aliyuncs.com
cross build --release --target aarch64-unknown-linux-musl
全程无人工干预,编译通过即正确。
拓展思考
- 无 Docker 场景:某些军工项目禁用容器,可改用
cargo-zigbuild+zig cc做纯静态链接,同样生成 musl 可执行文件,但需自己写.cargo/config.toml指定linker = "zig"。 - 多目标并行:在
matrix里同时编armv7-unknown-linux-gnueabihf、riscv64gc-unknown-linux-gnu,cross 会自动拉取对应镜像,但镜像体积总和超 20 GB,需用docker system prune --volumes定时清理。 - 调试:板子跑崩时,在
Cross.toml加runner = "qemu-aarch64 -g 1234",主机gdb target/debug/mybin可源码级调试,无需 JTAG。