You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fbuild currently pins Rust/MSRV 1.94.1, while std::cfg_select! is stable in Rust 1.95.0. A preliminary source scan found 386 host-cfg match lines across 93 Rust files under crates/. The largest concentrations are fbuild-toolchain (85), fbuild-core (68), fbuild-deploy (59), fbuild-daemon (46), fbuild-cli (37), and fbuild-serial (34). Direct native API usage appears in 21 files, including:
Native dependencies are also distributed: windows-sys is declared in fbuild-cli, fbuild-deploy, and fbuild-serial; libc is declared in fbuild-core and fbuild-daemon; and interprocess is consumed by fbuild-daemon.
This is not all one category. fbuild must keep three concepts distinct:
Host mechanics ? what OS/architecture the fbuild executable is running on; this belongs behind the platform boundary.
Host artifact policy ? which compiler, emulator, deploy tool, or archive must be downloaded for that host; product code owns the policy but must consume neutral host facts instead of compile-time cfg.
Embedded build target ? the PlatformIO/board/MCU target being compiled or flashed; fbuild_core::Platform, board policy, toolchain target triples, and orchestrator dispatch remain outside the host-platform layer.
The existing monocrate rule forbids adding a fbuild-platform crate for new functionality. fbuild-core is dependency-cycle-safe and is already the foundational dependency for the workspace, so the fbuild-specific adaptation should be an internal fbuild_core::platform module.
Proposal
Adopt the rule:
One module selects the host. Every fbuild crate consumes a neutral platform facade.
1. Raise the toolchain to Rust 1.95.x
Update every declaration of fbuild's own MSRV/toolchain from 1.94.1 to the same pinned Rust 1.95.x release:
workspace rust-version
rust-toolchain.toml
MSRV/fmt/Dylint/native-build workflows
Docker and serial-test bootstrap scripts
repository guidance and workflow documentation
focused regression coverage that prevents the declarations drifting
Do not rewrite fixtures that intentionally model arbitrary user or embedded toolchains.
2. Bootstrap the single host-selection boundary in fbuild-core
Create fbuild_core::platform as a module, not a new workspace member. Its root contains the only production host-selection site, using std::cfg_select! with explicit Windows, Linux, and macOS arms and no fallback arm.
The research phase must lock the exact layout, but the neutral capability surface should cover at least:
platform::process: command configuration, background spawn, containment, termination, PID/image inspection, and exit interpretation; delegate to running-process wherever it already owns the portable primitive.
platform::host: neutral HostOs, HostArch, path-list separator, home/runtime facts, and host keys consumed by toolchain/package/deploy artifact policy.
platform::device: serial-port, USB/PnP, sysfs/IOKit/SetupAPI, removable-volume, and topology primitives required by fbuild-serial and deployers.
Neutral facade types must prevent raw handles/fds, Win32 structs, Unix extension traits, concrete socket/pipe types, and concrete OS modules from escaping into shared callers. Every new directory must include its required README.md.
Do not duplicate platform behavior already provided by running-process, serialport, interprocess, or other dependencies. Wrap/delegate where their neutral API is sufficient; own only fbuild-specific seams and types.
3. Research, freeze, and ratchet the migration inventory
Before moving implementations:
Inventory host selectors, native imports/paths, target-specific dependency tables, compile-time host facts, and concrete platform-module references across all handwritten Rust sources, including inactive cfg branches, inline tests, integration tests, examples, benches, and build.rs.
Reconcile Windows, Linux, and macOS inventories.
Classify every occurrence as:
host mechanic to migrate;
host artifact policy that should consume neutral runtime/const host facts;
embedded build-target policy that must remain outside this refactor;
generated/vendor source;
narrowly justified specialized artifact, if one truly cannot use the facade.
Freeze an exact-occurrence ledger keyed by normalized repo-relative path, finding kind, construct, and ordinal.
Make ordinary migration PRs delete ledger rows only. A stale row, new unlisted occurrence, duplicate row, changed total, or Dylint/scanner disagreement must fail CI.
The preliminary 386-line scan is discovery evidence, not the authoritative ledger total.
4. Migrate by capability
Split implementation into ordered, reviewable phases after the ledger is frozen. Each phase must:
begin with focused RED characterization or boundary evidence;
move one coherent capability behind fbuild_core::platform;
replace caller-side cfg!/#[cfg] decisions with the neutral facade;
remove the exact corresponding ledger rows in the same PR;
report before/after global and affected-crate counts;
prove the stale-row and new-occurrence checks;
finish GREEN on focused tests plus the repository validation appropriate to the touched crates.
Suggested order: host/executable facts used by artifact selection; process/containment; filesystem/path mechanics; daemon IPC/lifecycle; serial/USB/device mechanics; specialized deploy/emulator cases; final zero-baseline enforcement.
5. Permanently enforce the boundary
Add a pre-expansion Dylint plus an independent whole-tree scanner, following the soldr/zccache/running-process precedent.
Outside the selector and private Windows/Linux/macOS implementation trees, reject:
host selectors in #[cfg], #[cfg_attr], cfg!(), cfg_if!, and macro token trees;
compile-time host escape routes such as std::env::consts::{OS, ARCH} or CARGO_CFG_TARGET_* when used to select host mechanics;
native imports/paths such as std::os::*, windows-sys, libc, native interprocess transports, raw handles/fds, and concrete platform modules;
direct references to the selected implementation alias;
new target-specific native dependency tables outside the platform implementation boundary.
The checker must distinguish explicit embedded compiler/build-target policy from host selection. Tests are not an escape hatch: generic tests exercise the neutral facade, while implementation-specific tests live beside the relevant private implementation.
At zero, delete the transitional ledger/dump escape hatch and retain the permanent zero-violation Dylint, whole-tree scanner, manifest checker, and three-host behavior coverage.
Acceptance criteria
RED: focused fixtures prove current private/inactive host cfg, native API access, concrete implementation references, and test-only occurrences evade the proposed boundary.
fbuild's MSRV and every canonical toolchain declaration are updated consistently from 1.94.1 to the selected Rust 1.95.x release, with drift coverage.
No new workspace crate is added; the boundary lives in fbuild_core::platform in accordance with the monocrate policy.
Exactly one production cfg_select! selects Windows, Linux, or macOS, with no fallback arm.
The reviewed three-host inventory classifies host mechanics, host artifact policy, embedded target policy, and any specialized artifacts without conflating them.
All shared callers use neutral platform facade types/functions and cannot name native OS APIs, raw native types, or concrete implementations.
A Linux-hosted build regression proves that selecting a Windows/macOS embedded toolchain artifact or firmware target does not select non-Linux host mechanics.
Windows, Linux, and macOS CI exercise representative process, filesystem, executable/host, IPC, serial/USB/device, deploy, and emulator behavior through the same facade paths.
The exact-occurrence ledger monotonically reaches zero; the permanent Dylint, scanner, and manifest checker reject new host-platform leakage.
GREEN: focused tests and the repository's full validation entrypoints pass for each migration phase and at final closeout.
Decisions
Priority: P2 architectural debt; behavior works today, but the breadth of distributed host selection makes portability changes and review increasingly risky.
Use fbuild-core, not a new fbuild-platform crate, because the repository explicitly keeps functionality in the existing crate set and the dependency graph makes fbuild-core the cycle-safe shared home.
Require Rust 1.95.x because stable std::cfg_select! is the mechanism used by the soldr/zccache precedent and gives an exhaustive compile-time selector.
Treat the six capability namespaces as the initial architecture; the frozen inventory may merge an empty namespace or split a demonstrably overloaded one without weakening the single-selector rule.
Keep embedded target selection and package/tool artifact policy in their current product owners; only raw host facts and mechanics move behind the facade.
Use an exact-occurrence ratchet rather than a file allowlist so migrated files cannot silently acquire new platform debt.
Context
Soldr and zccache have completed the same architectural upgrade, and running-process is executing its adaptation now:
cfg_select!boundary.fbuild currently pins Rust/MSRV 1.94.1, while
std::cfg_select!is stable in Rust 1.95.0. A preliminary source scan found 386 host-cfg match lines across 93 Rust files undercrates/. The largest concentrations arefbuild-toolchain(85),fbuild-core(68),fbuild-deploy(59),fbuild-daemon(46),fbuild-cli(37), andfbuild-serial(34). Direct native API usage appears in 21 files, including:fbuild-core::{containment,path,process_identity,subprocess}Native dependencies are also distributed:
windows-sysis declared infbuild-cli,fbuild-deploy, andfbuild-serial;libcis declared infbuild-coreandfbuild-daemon; andinterprocessis consumed byfbuild-daemon.This is not all one category. fbuild must keep three concepts distinct:
fbuild_core::Platform, board policy, toolchain target triples, and orchestrator dispatch remain outside the host-platform layer.The existing monocrate rule forbids adding a
fbuild-platformcrate for new functionality.fbuild-coreis dependency-cycle-safe and is already the foundational dependency for the workspace, so the fbuild-specific adaptation should be an internalfbuild_core::platformmodule.Proposal
Adopt the rule:
1. Raise the toolchain to Rust 1.95.x
Update every declaration of fbuild's own MSRV/toolchain from 1.94.1 to the same pinned Rust 1.95.x release:
rust-versionrust-toolchain.tomlDo not rewrite fixtures that intentionally model arbitrary user or embedded toolchains.
2. Bootstrap the single host-selection boundary in
fbuild-coreCreate
fbuild_core::platformas a module, not a new workspace member. Its root contains the only production host-selection site, usingstd::cfg_select!with explicit Windows, Linux, and macOS arms and no fallback arm.The research phase must lock the exact layout, but the neutral capability surface should cover at least:
platform::process: command configuration, background spawn, containment, termination, PID/image inspection, and exit interpretation; delegate to running-process wherever it already owns the portable primitive.platform::fs: file identity, links/reparse behavior, permissions, atomic replacement, volume/mount facts, and native error normalization.platform::ipc: fbuild-owned endpoint/listener/peer mechanics not already abstracted by running-process/interprocess.platform::executable: native executable names, PATH/PATHEXT candidates, current/sibling image discovery, and runnable-image materialization.platform::host: neutralHostOs,HostArch, path-list separator, home/runtime facts, and host keys consumed by toolchain/package/deploy artifact policy.platform::device: serial-port, USB/PnP, sysfs/IOKit/SetupAPI, removable-volume, and topology primitives required byfbuild-serialand deployers.Neutral facade types must prevent raw handles/fds, Win32 structs, Unix extension traits, concrete socket/pipe types, and concrete OS modules from escaping into shared callers. Every new directory must include its required
README.md.Do not duplicate platform behavior already provided by running-process, serialport, interprocess, or other dependencies. Wrap/delegate where their neutral API is sufficient; own only fbuild-specific seams and types.
3. Research, freeze, and ratchet the migration inventory
Before moving implementations:
build.rs.The preliminary 386-line scan is discovery evidence, not the authoritative ledger total.
4. Migrate by capability
Split implementation into ordered, reviewable phases after the ledger is frozen. Each phase must:
fbuild_core::platform;cfg!/#[cfg]decisions with the neutral facade;Suggested order: host/executable facts used by artifact selection; process/containment; filesystem/path mechanics; daemon IPC/lifecycle; serial/USB/device mechanics; specialized deploy/emulator cases; final zero-baseline enforcement.
5. Permanently enforce the boundary
Add a pre-expansion Dylint plus an independent whole-tree scanner, following the soldr/zccache/running-process precedent.
Outside the selector and private Windows/Linux/macOS implementation trees, reject:
#[cfg],#[cfg_attr],cfg!(),cfg_if!, and macro token trees;std::env::consts::{OS, ARCH}orCARGO_CFG_TARGET_*when used to select host mechanics;std::os::*,windows-sys,libc, native interprocess transports, raw handles/fds, and concrete platform modules;The checker must distinguish explicit embedded compiler/build-target policy from host selection. Tests are not an escape hatch: generic tests exercise the neutral facade, while implementation-specific tests live beside the relevant private implementation.
At zero, delete the transitional ledger/dump escape hatch and retain the permanent zero-violation Dylint, whole-tree scanner, manifest checker, and three-host behavior coverage.
Acceptance criteria
fbuild_core::platformin accordance with the monocrate policy.cfg_select!selects Windows, Linux, or macOS, with no fallback arm.Decisions
fbuild-core, not a newfbuild-platformcrate, because the repository explicitly keeps functionality in the existing crate set and the dependency graph makesfbuild-corethe cycle-safe shared home.std::cfg_select!is the mechanism used by the soldr/zccache precedent and gives an exhaustive compile-time selector.Related issues
cfg_select!host-platform architecture.