同一份 Rust 代码,为什么能编译成别的 CPU、别的系统的程序?要装什么、链接器怎么配、产物怎么确认是对的?这篇用本机的 arm64 macOS,把几个目标逐个编出来,并如实标出哪些真正运行过、哪些只验证了文件格式。
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 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。
退出码 0
u169p.wasm:368 字节;file: WebAssembly (wasm) binary module version 0x1 (MVP)
node 调用:
exports: add,pointer_bits
add(2,3) = 5
pointer_bits() = 32 默认链接器(本机 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 退出码 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 项目持续集成。