如何配置 cross 工具?

解读

在国内面试中,“如何配置 cross” 并不是单纯问“装个插件”,而是考察候选人是否真正在非 x86 嵌入式或 CI 场景里解决过交叉编译痛点。面试官想听的是:

  1. 你能否一行命令x86_64-unknown-linux-gnu 的二进制编译成 aarch64-unknown-linux-musl 并直接跑在板子上;
  2. 是否知道国内镜像源、Docker 拉取失败、openssl-sys 交叉编译失败这三座大山的具体解法;
  3. 能否把配置固化到项目里,让同事 git clone 后无需任何手动步骤即可重现。
    答不到“镜像 + Docker 缓存 + 自定义镜像”这一层,基本会被认为“只是跑过 demo”。

知识点

  1. cross 本质:一个用 Docker/Qemu 封装的 cargo wrapper,把“工具链 + 目标 sysroot + 链接器”全部放进容器,零污染主机
  2. 国内网络:Docker Hub 间歇性抽风,rustup 默认源在国外,必须换清华/中科大镜像
  3. 自定义镜像:当需要 libudev-devlibssl-dev 等 C 库时,必须写 Cross.toml 指定 image = "registry.cn-hangzhou.aliyuncs.com/xxx/my-cross:aarch64"否则链接阶段报 cannot find -lssl
  4. 缓存:CI 里把 /target~/.cargo/registry/cache 挂到 actions/cache,每次节省 3-5 min
  5. 安全:公司内网要求“不允许自动拉取外部镜像”,需 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

全程无人工干预,编译通过即正确

拓展思考

  1. 无 Docker 场景:某些军工项目禁用容器,可改用 cargo-zigbuild + zig cc 做纯静态链接,同样生成 musl 可执行文件,但需自己写 .cargo/config.toml 指定 linker = "zig"
  2. 多目标并行:在 matrix 里同时编 armv7-unknown-linux-gnueabihfriscv64gc-unknown-linux-gnucross 会自动拉取对应镜像,但镜像体积总和超 20 GB,需用 docker system prune --volumes 定时清理。
  3. 调试:板子跑崩时,在 Cross.tomlrunner = "qemu-aarch64 -g 1234",主机 gdb target/debug/mybin源码级调试,无需 JTAG。