bigywater.tech
Rust · 169

Cross 编译

同一份 Rust 代码,为什么能编译成别的 CPU、别的系统的程序?要装什么、链接器怎么配、产物怎么确认是对的?这篇用本机的 arm64 macOS,把几个目标逐个编出来,并如实标出哪些真正运行过、哪些只验证了文件格式。

332
本机 nightly rustc 支持的目标数(--print target-list)
32 / 64
wasm32 与其它三个目标的 target_pointer_width
4
本机无法运行、只验证了编译与文件格式的目标数(x86_64 Mach-O、x86_64 musl、aarch64 musl、iOS)

目标三元组

实测 · 本机执行输出
  nightly rustc 的 --print target-list:332 个目标;host = aarch64-apple-darwin
  aarch64-apple-darwin:
    llvm-target          arm64-apple-macosx
    arch                 aarch64
    os                   macos
    data-layout          e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32
    linker-flavor        darwin-cc
    max-atomic-width     128
  x86_64-unknown-linux-musl:
    llvm-target          x86_64-unknown-linux-musl
    arch                 x86_64
    os                   linux
    data-layout          e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128
    linker-flavor        gnu-cc
    crt-static-default   True
    max-atomic-width     64
  wasm32-unknown-unknown:
    llvm-target          wasm32-unknown-unknown
    arch                 wasm32
    os                   unknown
    data-layout          e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20
    linker-flavor        wasm-lld
    max-atomic-width     64
    panic-strategy       abort
  --print cfg(三个目标的 cfg,选 target_arch / target_os / target_pointer_width / target_endian):
    aarch64-apple-darwin         {'target_arch': 'aarch64', 'target_os': 'macos', 'target_pointer_width': '64', 'target_endian': 'little'}
    x86_64-unknown-linux-musl    {'target_arch': 'x86_64', 'target_os': 'linux', 'target_pointer_width': '64', 'target_endian': 'little'}
    wasm32-unknown-unknown       {'target_arch': 'wasm32', 'target_os': 'unknown', 'target_pointer_width': '32', 'target_endian': 'little'}
    aarch64-apple-ios            {'target_arch': 'aarch64', 'target_os': 'ios', 'target_pointer_width': '64', 'target_endian': 'little'}

条件编译的写法见跨平台路径处理,WebAssembly 见WASI 与 WebAssembly。

缺少标准库

实测 · 本机执行输出
  退出码 101
       Compiling u169b v0.1.0 (<实验目录>/proj/u169b)
    error[E0463]: can't find crate for `std`
      |
      = note: the `aarch64-apple-ios` target may not be installed
      = help: consider downloading the target with `rustup target add aarch64-apple-ios`
    
    For more information about this error, try `rustc --explain E0463`.
    error: could not compile `u169b` (bin "u169b") due to 1 previous error

另一种 CPU

实测 · 本机执行输出
  cargo build --target x86_64-apple-darwin:退出码 0
    warning: u169p@0.1.0: build.rs 在 HOST=aarch64-apple-darwin 上运行(它自己的 arch=aarch64),为 TARGET=x86_64-apple-darwin 编译
  file: Mach-O 64-bit executable x86_64
  直接运行:退出码 -1  OSError [Errno 86] Bad CPU type in executable
  用 arch -x86_64 运行:退出码 1  arch: posix_spawnp: <实验目录> Bad CPU type in executable  (本机没有 Rosetta)

宿主与目标

实测 · 本机执行输出
  (无 --target)               warning: u169p@0.1.0: build.rs 在 HOST=aarch64-apple-darwin 上运行(它自己的 arch=aarch64),为 TARGET=aarch64-apple-darwin 编译
  x86_64-apple-darwin        warning: u169p@0.1.0: build.rs 在 HOST=aarch64-apple-darwin 上运行(它自己的 arch=aarch64),为 TARGET=x86_64-apple-darwin 编译
  wasm32-unknown-unknown     warning: u169p@0.1.0: build.rs 在 HOST=aarch64-apple-darwin 上运行(它自己的 arch=aarch64),为 TARGET=wasm32-unknown-unknown 编译
  target/ 下的目录:无 --target 时 ['debug'];再加 --target x86_64-apple-darwin 后 ['debug', 'x86_64-apple-darwin'](带 --target 的产物放在以三元组命名的子目录里,宿主的产物仍在 debug/)

build.rs 的更多细节见build.rs。

WebAssembly

实测 · 本机执行输出
  退出码 0
  u169p.wasm:368 字节;file: WebAssembly (wasm) binary module version 0x1 (MVP)
  node 调用:
    exports: add,pointer_bits
    add(2,3) = 5
    pointer_bits() = 32

Linux musl 与 zig

实测 · 本机执行输出
  默认链接器(本机 cc):退出码 101
    error: linking with `cc` failed: exit status: 1
      = note: ld: unknown options: --as-needed -Bstatic -Bdynamic --eh-frame-hdr -z --gc-sections -z -z
              clang: error: linker command failed with exit code 1 (use -v to see invocation)
    error: could not compile `u169p` (bin "u169p") due to 1 previous error
  换成 zig cc 当链接器(只设 linker):退出码 101
    error: linking with `<实验目录>/zigw/zcc-x86_64` failed: exit status: 1
    ld.lld: error: duplicate symbol: _start
    ld.lld: error: duplicate symbol: _start_c
    error: could not compile `u169p` (bin "u169p") due to 1 previous error
  aarch64 目标,zig 链接器不做任何参数过滤:退出码 101
    = note: error: unsupported linker arg: --fix-cortex-a53-843419
  (给 aarch64 的包装脚本加一行,过滤掉这个参数后再试:)
  x86_64-unknown-linux-musl(linker = zig cc -target x86_64-linux-musl,RUSTFLAGS = -C link-self-contained=no):退出码 0
    file: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
    大小 361 KiB;ELF e_machine = 62(x86-64);程序头里是否有 PT_INTERP(动态链接器):False
    在 macOS 上直接运行:退出码 -1,OSError [Errno 8] Exec format error
  aarch64-unknown-linux-musl(linker = zig cc -target aarch64-linux-musl,RUSTFLAGS = -C link-self-contained=no):退出码 0
    file: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, stripped
    大小 345 KiB;ELF e_machine = 183(AArch64);程序头里是否有 PT_INTERP(动态链接器):False
    在 macOS 上直接运行:退出码 -1,OSError [Errno 8] Exec format error

iOS

实测 · 本机执行输出
  退出码 0
    warning: u169p@0.1.0: build.rs 在 HOST=aarch64-apple-darwin 上运行(它自己的 arch=aarch64),为 TARGET=aarch64-apple-ios 编译
  file: Mach-O 64-bit executable arm64
  otool -l:加载命令 LC_VERSION_MIN_IPHONEOS,version = 10.0,sdk = 27.0
  对比本机构建:platform = 1,minos = 11.0(platform 1 = macOS)
  在 macOS 上直接运行:退出码 -9 

能运行的目标

实测 · 本机执行输出
  本机 aarch64-apple-darwin 运行: os=macos arch=aarch64 pointer=64bit endian=little
  wasm32-unknown-unknown:pointer_bits() = 32 (cfg 里 target_pointer_width = 32)

把这些步骤放进自动化见Rust 项目持续集成。

分步演示

交叉编译
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / rustc 1.98.1(brew)/ cargo 1.98.1;单个文件用 rustc 直接编译,需要依赖时用 cargo(经代理从 crates.io 下载);计时用 std::time::Instant,数字每次运行会有小幅抖动。nightly 工具链用 rustup 装在隔离目录(不影响 brew 的 rustc):rustc 1.101.0-nightly (21b707e3f 2026-09-30)、miri 0.1.0 (21b707e3f9 2026-09-30)。rustup 装的目标:x86_64-apple-darwin、x86_64-unknown-linux-musl、aarch64-unknown-linux-musl、wasm32-unknown-unknown、aarch64-apple-ios;zig 0.16.0(pip ziglang)当 Linux 目标的链接器;node v26.10.0 运行 wasm;本机无 Rosetta、无 Linux 环境
    • 没有验证:Linux 目标的实际运行(只检查了 ELF 头与是否静态链接)、gnu 目标(glibc 版本问题)、cargo-zigbuild 与 cross(基于容器)等工具、Windows 目标、iOS 模拟器或真机运行、wasm32-wasip1 的运行(上一批文章里的 WASI 篇已覆盖)
    • 包装脚本里去掉 -Wl,--fix-cortex-a53-843419 是针对这次 zig 0.16.0 报错的处理,没有验证它对运行结果的影响
    京ICP备2026067502号-1京公网安备11010502063487号