Multi-platform Builds
Platform-specific Compatibility of cargo buckal
Introduction
Buckal can generate BUCK files that work across Linux, macOS and Windows without regenerating on each host. The key idea is to preserve Cargo’s platform-conditional dependencies in the generated rules.
What gets generated
os_deps: OS-scoped dependencies (e.g., a Windows-only dep lands underos_deps["windows"]).os_named_deps: same asos_deps, but for renamed dependencies.compatible_with: applied to a small allowlist of known OS-only crates to prevent Buck2 from building them on the wrong OS.
The generated rules use canonical Buck prelude OS constraint labels: prelude//os/constraints:{linux,macos,windows}.
Supported platforms
Platform-aware dependency mapping and bundled sample platforms currently target these Rust Tier-1 host triples:
- Linux:
x86_64-unknown-linux-gnu - Windows:
x86_64-pc-windows-msvc - macOS:
aarch64-apple-darwin
How platform matching works
Cargo encodes target-specific dependencies in cargo metadata as platform predicates (for example, cfg(target_os = "windows")). During migrate, buckal maps those predicates to a set of OS keys (linux/macos/windows) by evaluating them against cached rustc --print=cfg --target <triple> snapshots for Rust Tier-1 host targets.
If a predicate can’t be mapped to linux/macos/windows, cargo-buckal treats the dependency as unconditional by default (to preserve build success).
Using it
-
Generate BUCK files:
For first-time setup (initializes Buck2 at
<repo_root>and generates BUCK files):cargo buckal migrate --init [<repo_root>]Or, for incremental updates (when Buck2 is already initialized):
cargo buckal migrateThis regenerates BUCK files based on current
Cargo.toml/Cargo.lockchanges without reinitializing Buck2. Use this after adding/removing dependencies or updatingCargo.toml. -
Build with a target platform:
buck2 build //... --target-platforms //platforms:x86_64-pc-windows-msvcBuckal configures a
buckalcell (Buckal bundles). The bundles provide sample platforms under//platforms:*. You can also use your own platform definitions; any platform you use must include the appropriate OS constraint value (prelude//os/constraints:windowsin the example above) soselect()picks up the rightos_depsbranch.To update the pinned Buckal bundles revision, run:
cargo buckal migrate --fetchIf you want to use the bundled toolchain config too, point the
toolchainscell at it in.buckconfig:[cells] toolchains = buckal/toolchains -
Validate multi-platform builds by building against multiple target platforms:
Linux:
buck2 build //... --target-platforms //platforms:x86_64-unknown-linux-gnuWindows:
buck2 build //... --target-platforms //platforms:x86_64-pc-windows-msvcmacOS (bundled sample platforms):
buck2 build //... --target-platforms //platforms:aarch64-apple-darwin
Skipping tests for cross-compilation
When cross-compiling or when the target binaries cannot run on the host, you can
skip rust_test targets by passing -c cross.skip_test=true. cargo-buckal
marks generated rust_test targets with a target_compatible_with constraint
that matches the //platforms:cross config setting when this config is set.
Examples:
buck2 test //... --target-platforms //platforms:x86_64-unknown-linux-gnu -c cross.skip_test=true
buck2 test //... --target-platforms //platforms:x86_64-pc-windows-msvc -c cross.skip_test=trueTroubleshooting
- If you see warnings about
rustc --print=cfg --target ...failing, install the missing Rust targets (or expect fewer platform predicates to be mapped). - If OS-specific deps appear in the default
depslist, the corresponding predicate likely couldn’t be mapped; rerun with more Rust targets installed. - If Buck2 fails to parse generated BUCK files due to missing support for
os_deps/os_named_deps(or missing symbols likerust_testinwrapper.bzl), update the Buckal bundles (trycargo buckal migrate --fetch) or pin a bundles revision that supports these attributes.