Use when the user cross-compiles to another target triple, uses `rustup target add`, uses the `cross` crate, configures per-target linker via `.cargo/config.toml`, or guards code with `cfg(target_os = "...")`. Prevents missing target triple installation, picking wrong target for the use case (musl vs gnu, msvc vs gnu on Windows), and using `cfg` without `cfg_attr` for selective attributes. Covers: target triple format (arch-vendor-os-env), common triples (x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl, aarch64-apple-darwin, x86_64-pc-windows-msvc, x86_64-pc-windows-gnu, wasm32-unknown-unknown, wasm32-wasi), `rustup target add`, `cargo build --target <triple>`, `cross` crate (container-based), conditional compilation `cfg(target_os = "...", target_arch = "...", target_pointer_width = "...", target_feature = "...")`, `cfg_attr`, `.cargo/config.toml` for per-target linker / runner. Keywords: "cross-compile", "cross compile", "target triple", "rustup target add", "cargo build --target", "cross crate", "musl
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Use when the user cross-compiles to another target triple, uses `rustup target add`, uses the `cross` crate, configures per-target linker via `.cargo/config.toml`, or guards code with `cfg(target_os = "...")`. Prevents missing target triple installation, picking wrong target for the use case (musl vs gnu, msvc vs gnu on Windows), and using `cfg` without `cfg_attr` for selective attributes. Covers: target triple format (arch-vendor-os-env), common triples (x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl, aarch64-apple-darwin, x86_64-pc-windows-msvc, x86_64-pc-windows-gnu, wasm32-unknown-unknown, wasm32-wasi), `rustup target add`, `cargo build --target <triple>`, `cross` crate (container-based), conditional compilation `cfg(target_os = "...", target_arch = "...", target_pointer_width = "...", target_feature = "...")`, `cfg_attr`, `.cargo/config.toml` for per-target linker / runner. Keywords: "cross-compile", "cross compile", "target triple", "rustup target add", "cargo build --target", "cross crate", "musl static", "musl gnu", "msvc gnu", wasm32, "wasm32-unknown-unknown", "wasm32-wasi", "cfg target_os", "cfg target_arch", "target_pointer_width", "target_feature", cfg_attr, ".cargo/config.toml", linker, runner, "static linking".
license
MIT
compatibility
Designed for Claude Code. Requires Rust 1.85+, edition 2024.
metadata
{"author":"OpenAEC-Foundation","version":"1.0"}
rust-impl-cross-compile
The cross-compilation skill: how to build a Rust crate for a target other than the host. Covers target triple format and common triples, rustup target add to install standard library artifacts, cargo build --target <triple>, the cross crate for container-based toolchains, conditional compilation via cfg(target_os = ...) and related predicates, the cfg_attr attribute for selective attribute emission, and per-target linker / runner configuration via .cargo/config.toml.
Cross-references: [[rust-impl-cargo-project]] (single-crate Cargo.toml + profiles), [[rust-impl-build-scripts]] (build.rs that detects target via env vars), [[rust-impl-ffi-bindgen]] (cross-compile C deps and adjust sysroot), [[rust-core-toolchain]] (rustup channels, components, target lists).
When to use this skill
User runs cargo build and gets linker 'cc' not found or error: target may not be installed after switching --target.
User wants a portable static Linux binary and asks musl vs gnu.
User builds for Windows from Linux and asks pc-windows-msvc vs pc-windows-gnu.
User builds for macOS ARM (Apple Silicon) from x86_64 host.
User asks how to build a .wasm module and asks wasm32-unknown-unknown vs wasm32-wasip1.
User writes platform-conditional code with #[cfg(target_os = "...")] or cfg!(...).
User wants a single attribute (e.g. #[repr(C)], #[link(...)]) to appear only on one target.
User configures a custom linker for a target via [target.<triple>] linker = "..." in .cargo/config.toml.
User asks about the cross tool because installing native toolchains is tedious.
For host-only profile / lints / dependency tuning see [[rust-impl-cargo-project]]. For build-time target detection in build.rs see [[rust-impl-build-scripts]].
Target triple format
Rust target triples follow the shape <arch>-<vendor>-<os>-<env> where each field is a fixed identifier (see platform-support):
NOTE: wasm32-wasi was renamed to wasm32-wasip1 in Rust 1.81 (rust181). wasm32-wasi still works as a legacy alias but new code should use wasm32-wasip1 (or wasm32-wasip2 for WASIp2).
Common target triples
Decision rules per use case. Tier classification is from platform-support: Tier 1 has CI guarantees + host tools, Tier 2 with-host-tools has guaranteed std + tools, Tier 2 without-host-tools has guaranteed std only, Tier 3 is best-effort.
Target Triple
Tier
When to use it
x86_64-unknown-linux-gnu
1
Default 64-bit Linux. Dynamic linking against glibc 2.17+.
aarch64-unknown-linux-gnu
1
ARM64 Linux servers (AWS Graviton, RPi 64-bit, etc.).
x86_64-unknown-linux-musl
2-host
Fully static Linux binary, no glibc dependency.
aarch64-unknown-linux-musl
2-host
Static ARM64 Linux binary.
aarch64-apple-darwin
1
macOS on Apple Silicon (M1+).
x86_64-apple-darwin
1
macOS on Intel.
x86_64-pc-windows-msvc
1
Windows native, MSVC toolchain (needs Visual Studio Build Tools).
x86_64-pc-windows-gnu
1
Windows via MinGW-w64 (cross-compile-friendly from Linux).
aarch64-pc-windows-msvc
1
Windows on ARM64.
wasm32-unknown-unknown
2
Browser WebAssembly. No OS. Requires wasm-bindgen for browser glue.
wasm32-wasip1
2
WebAssembly with WASI Preview 1 (filesystem, env, clock).
Need a portable static binary that runs on any Linux distro (no glibc dep)?
YES -> *-unknown-linux-musl
NO -> *-unknown-linux-gnu (default, dynamic glibc, smaller binary, glibc 2.17+)
Will the binary load shared libraries with dlopen at runtime?
YES -> *-gnu (musl has known dlopen quirks)
NO -> either is fine, choose by static vs dynamic preference
Is the binary going into a `FROM scratch` Docker image?
YES -> *-musl is the only sane choice
Windows: msvc vs gnu
Compiling on Windows with Visual Studio Build Tools installed?
YES -> *-pc-windows-msvc (recommended, matches Microsoft ecosystem)
Cross-compiling from Linux / macOS to Windows?
*-pc-windows-gnu is easier (just install mingw-w64 cross gcc).
*-pc-windows-msvc also works via `cargo-xwin` or LLVM tooling but heavier setup.
Linking against a precompiled `.lib` from a vendor?
Match the vendor's ABI. MSVC libs require msvc; MinGW libs require gnu.
WebAssembly: unknown vs wasi
Browser target with JS interop? -> wasm32-unknown-unknown + wasm-bindgen.
CLI / serverless WASI runtime (wasmtime, wasmer)? -> wasm32-wasip1 (or wasip2 for component model).
Pure compute, no I/O, no DOM? -> wasm32-unknown-unknown (smaller, no OS shims).
Cross-compile workflow
Step 1 : install the target standard library
rustup target add x86_64-unknown-linux-musl
rustup target add installs ONLY the precompiled standard library for the target (rustup-cross). It does NOT install a linker, libc, or any platform SDK. The host toolchain (compiler) is reused; only libstd / libcore / liballoc are added.
List available targets : rustup target list. List installed : rustup target list --installed. Remove : rustup target remove <triple>.
Step 2 : ensure a target-compatible linker exists
Target
Linker needed on Linux host
x86_64-unknown-linux-musl
musl-gcc (Alpine native) or via cross
aarch64-unknown-linux-gnu
gcc-aarch64-linux-gnu (Debian/Ubuntu)
aarch64-unknown-linux-musl
musl-cross toolchain or cross
x86_64-pc-windows-gnu
gcc-mingw-w64-x86-64
x86_64-pc-windows-msvc
MSVC SDK + cargo-xwin, or cross
aarch64-apple-darwin
macOS SDK (must build on macOS host or use osxcross)
wasm32-unknown-unknown
none required, LLVM ships its own.
wasm32-wasip1
none required.
NEVER expect rustup target add to install gcc / clang / lld. ALWAYS install the host-side cross toolchain separately, or delegate to cross.
Step 3 : point Cargo at the linker via .cargo/config.toml
# .cargo/config.toml (project-local or in $CARGO_HOME)[target.aarch64-unknown-linux-gnu]linker = "aarch64-linux-gnu-gcc"[target.x86_64-unknown-linux-musl]linker = "musl-gcc"[target.x86_64-pc-windows-gnu]linker = "x86_64-w64-mingw32-gcc"
Now bare cargo build cross-builds without --target. NEVER do this in a library crate (forces all downstream users to install that target).
The cross tool (container-based)
cross (cross-rs) is a community wrapper that runs cargo inside a per-target Docker / Podman image. Each image bundles the cross linker + libc + sysroot, so the host needs only Docker.
Host toolchain setup is awkward (musl-cross on Debian, mingw-w64 on macOS, etc.).
You build many targets in CI and want hermetic, reproducible toolchains.
You want Windows / Android / BSD targets without installing each SDK.
NEVER use cross for aarch64-apple-darwin from a non-macOS host : Apple's SDK license forbids redistribution, so no Docker image exists. ALWAYS build Darwin targets on macOS hardware or via macOS CI runners.
cross reads Cross.toml for per-target image overrides, mounted volumes, and pre-build hooks. See [[references/methods.md]] for syntax.
Conditional compilation with cfg
cfg predicates select code that is compiled only when the predicate holds (reference-cfg). All cfg keys are evaluated at compile time against the current target.
Use all(...), any(...), not(...) for boolean composition. NEVER nest cfg attributes (#[cfg(a)] #[cfg(b)]) when you mean all ; while it works, cfg(all(a, b)) makes intent explicit.
Runtime cfg!(...) macro
ifcfg!(target_os = "linux") {
// executed only on Linux. Code is still type-checked on every target.
}
cfg!(...) returns a bool constant. Both arms of the if are compiled on every target, so they must type-check everywhere. For mutually exclusive code, prefer #[cfg(...)] on items.
cfg_attr for conditional attributes
#[cfg_attr(predicate, attr1, attr2, ...)] emits the listed attributes ONLY when the predicate is true ([reference-cfg]).
#[cfg_attr(target_os = "linux", repr(C))]structHeader {
magic: u32,
flags: u32,
}
// On Linux, expands to: #[repr(C)] struct Header { ... }// On other targets, no repr attribute is applied.#[cfg_attr(not(test), inline)]fnhot_path() { /* ... */ }
ALWAYS use cfg_attr when an attribute itself should be conditional. NEVER copy-paste the whole item under #[cfg(...)] just to vary one attribute.
rustup target list --installed | grep <triple> shows the target.
Linker is on PATH or pinned in .cargo/config.toml.
cargo build --target <triple> exits 0.
file target/<triple>/release/<bin> reports the expected ELF / PE / Wasm format.
For musl : ldd target/<triple>/release/<bin> reports not a dynamic executable.
For Wasm : wasm-objdump -h <bin>.wasm lists sections without errors.
Platform-conditional code paths were exercised on the actual target (or under an emulator) ; cfg! only verifies the predicate, not the runtime correctness.
Reference links
[[references/methods.md]] : full rustup / cargo / cross command catalogue, all [target.<triple>] keys, full cfg-key list with valid values, env-var equivalents.
[[references/examples.md]] : end-to-end recipes (musl static, Windows MinGW from Linux, macOS ARM, WASI, Cortex-M no_std, Cross.toml, GitHub Actions matrix).
[[references/anti-patterns.md]] : missing rustup target add, choosing musl for the wrong reason, wasm32-unknown-unknown for WASI workloads, hard-coding linker path, missing cfg_attr, untested conditional code paths.