From 8bb4c93e67b56a0780be81b526103035fe826465 Mon Sep 17 00:00:00 2001 From: zackees Date: Thu, 20 Aug 2026 07:04:58 -0700 Subject: [PATCH 1/5] refactor(platform): migrate host and executable facts --- ci/enforce_platform_boundary.py | 17 +- ci/platform_boundary_ledger.tsv | 233 ------------- ci/platform_boundary_research.py | 3 + ci/platform_boundary_research.tsv | 309 +++--------------- ci/test_enforce_platform_boundary.py | 69 +++- .../src/generic_arm/arm_linker.rs | 2 +- .../src/teensy/teensy_linker.rs | 4 +- .../fbuild-build-engine/src/compiler_tests.rs | 2 +- crates/fbuild-build-engine/src/linker.rs | 2 +- .../fbuild-build-engine/src/script_runtime.rs | 2 +- .../fbuild-build-engine/src/source_scanner.rs | 2 +- .../src/esp32/esp32_compiler.rs | 2 +- .../src/esp32/esp32_linker.rs | 2 +- .../tests/cache_survives_tar_extract.rs | 8 +- .../fbuild-build/tests/clangd_check_parity.rs | 8 +- .../fbuild-build/tests/flag_escaping_lint.rs | 6 +- .../tests/lite_scons_acceptance.rs | 2 +- .../tests/zccache_embedded_smoke.rs | 28 +- crates/fbuild-cli/src/cli/build.rs | 6 +- crates/fbuild-cli/src/cli/compile_many.rs | 2 +- crates/fbuild-cli/src/cli/daemon_cmd.rs | 28 +- crates/fbuild-cli/src/cli/debug.rs | 11 +- crates/fbuild-cli/src/cli/deploy.rs | 2 +- crates/fbuild-cli/src/cli/ide.rs | 28 +- crates/fbuild-cli/src/cli/pio.rs | 14 +- crates/fbuild-cli/src/cli/port_doctor.rs | 6 +- crates/fbuild-cli/src/cli/port_doctor_fix.rs | 2 +- crates/fbuild-cli/src/cli/symbols_cmd.rs | 4 +- crates/fbuild-cli/src/cli/tests.rs | 6 +- crates/fbuild-cli/src/cli/usb_recovery.rs | 2 +- crates/fbuild-cli/src/daemon_client.rs | 24 +- .../fbuild-cli/src/daemon_client/identity.rs | 2 +- crates/fbuild-cli/src/update_check.rs | 2 +- .../fbuild-cli/tests/daemon_crash_recovery.rs | 12 +- crates/fbuild-config/src/ini_parser/tests.rs | 6 +- crates/fbuild-config/src/ini_parser/values.rs | 2 +- crates/fbuild-core/src/containment.rs | 4 +- crates/fbuild-core/src/path.rs | 2 +- crates/fbuild-core/src/platform/README.md | 5 + crates/fbuild-core/src/platform/executable.rs | 121 +++++++ crates/fbuild-core/src/platform/host.rs | 138 ++++++++ crates/fbuild-core/src/platform/linux/mod.rs | 12 +- crates/fbuild-core/src/platform/macos/mod.rs | 12 +- .../fbuild-core/src/platform/windows/mod.rs | 12 +- crates/fbuild-core/src/process_identity.rs | 4 +- crates/fbuild-core/src/response_file.rs | 2 +- crates/fbuild-core/src/subprocess.rs | 36 +- .../src/bin/containment_harness.rs | 4 +- crates/fbuild-daemon/src/broker/service.rs | 17 +- crates/fbuild-daemon/src/broker/session.rs | 2 +- crates/fbuild-daemon/src/context.rs | 2 +- .../src/handlers/emulator/avr8js_npm.rs | 4 +- .../src/handlers/emulator/runners.rs | 10 +- .../src/handlers/emulator/shared.rs | 2 +- crates/fbuild-daemon/src/handlers/locks.rs | 4 +- .../src/handlers/operations/deploy.rs | 13 +- crates/fbuild-daemon/src/main.rs | 4 +- .../tests/legacy_daemon_transition.rs | 8 +- crates/fbuild-deploy/src/lpc.rs | 23 +- .../fbuild-deploy/src/lpc_debugger_reflash.rs | 18 +- crates/fbuild-deploy/src/probe_rs.rs | 43 +-- crates/fbuild-deploy/src/rp2040.rs | 16 +- crates/fbuild-deploy/src/rp2040_picotool.rs | 6 +- .../fbuild-deploy/src/teensy/soft_reboot.rs | 2 +- crates/fbuild-deploy/src/wchisp.rs | 37 +-- crates/fbuild-deploy/src/wlink.rs | 27 +- crates/fbuild-library/src/library/esptool.rs | 15 +- .../src/library/library_compiler.rs | 4 +- .../src/library/library_spec.rs | 2 +- .../fbuild-packages-fetch/src/install_lock.rs | 4 +- crates/fbuild-paths/src/daemon_ownership.rs | 3 +- crates/fbuild-paths/src/lib.rs | 63 ++-- crates/fbuild-paths/src/running_process.rs | 53 ++- crates/fbuild-python/src/daemon.rs | 16 +- crates/fbuild-python/src/messages.rs | 2 +- crates/fbuild-serial/src/boards.rs | 2 +- crates/fbuild-serial/src/crash_decoder.rs | 11 +- crates/fbuild-serial/src/manager.rs | 12 +- crates/fbuild-toolchain/src/toolchain/arm.rs | 23 +- .../src/toolchain/arm_gcc8.rs | 10 +- crates/fbuild-toolchain/src/toolchain/avr.rs | 23 +- .../fbuild-toolchain/src/toolchain/clang.rs | 38 +-- .../fbuild-toolchain/src/toolchain/esp32.rs | 27 +- .../src/toolchain/esp32_metadata.rs | 12 +- .../fbuild-toolchain/src/toolchain/esp8266.rs | 27 +- .../src/toolchain/esp_qemu.rs | 68 ++-- .../fbuild-toolchain/src/toolchain/riscv.rs | 23 +- .../src/toolchain/rp2040_picotool.rs | 18 +- .../src/toolchain/rp2040_pqt.rs | 27 +- .../src/toolchain/teensy_arm.rs | 31 +- docs/architecture/portability.md | 8 + docs/platform-boundary-research-inventory.md | 46 ++- docs/platform-boundary-research.md | 19 ++ .../src/baseline.txt | 239 -------------- dylints/enforce_platform_boundary/src/lib.rs | 16 + .../ui/disallowed.rs | 1 + .../ui/disallowed.stderr | 11 +- 97 files changed, 1017 insertions(+), 1287 deletions(-) diff --git a/ci/enforce_platform_boundary.py b/ci/enforce_platform_boundary.py index 5f559cb92..9c1aabdb6 100644 --- a/ci/enforce_platform_boundary.py +++ b/ci/enforce_platform_boundary.py @@ -25,7 +25,12 @@ LEDGER = ROOT / "ci/platform_boundary_ledger.tsv" DYLINT_BASELINE = ROOT / "dylints/enforce_platform_boundary/src/baseline.txt" PLATFORM_ROOT = "crates/fbuild-core/src/platform/" -CONCRETE_PREFIXES = tuple(PLATFORM_ROOT + host + "/" for host in ("windows", "linux", "macos")) +CONCRETE_PREFIXES = ( + *(PLATFORM_ROOT + host + "/" for host in ("windows", "linux", "macos")), +) +AUTHORIZED_BOUNDARY_FINDINGS = { + (PLATFORM_ROOT + "executable.rs", "native_path", "std::env::current_exe"), +} LEDGER_KINDS = { "attr_cfg", "cfg_macro", @@ -76,6 +81,12 @@ def rows_from_findings(findings: list[research.Finding]) -> list[LedgerRow]: ordinals: collections.Counter[tuple[str, str, str]] = collections.Counter() rows: list[LedgerRow] = [] for finding in findings: + if finding.path.startswith(CONCRETE_PREFIXES) or ( + finding.path, + finding.kind, + finding.normalized, + ) in AUTHORIZED_BOUNDARY_FINDINGS: + continue key = (finding.path, finding.kind, finding.normalized) ordinal = ordinals[key] ordinals[key] += 1 @@ -181,7 +192,9 @@ def scanner_dylint_counts(rows: list[LedgerRow]) -> collections.Counter[tuple[st counts[(row.path, row.kind, identifier)] += 1 elif row.kind == "native_path": normalized = row.normalized - if normalized.startswith("std::os::"): + if normalized == "std::env::current_exe": + key = normalized + elif normalized.startswith("std::os::"): parts = normalized.split("::") key = "::".join(parts[:3]) else: diff --git a/ci/platform_boundary_ledger.tsv b/ci/platform_boundary_ledger.tsv index 80ebcfd79..afc5ecdae 100644 --- a/ci/platform_boundary_ledger.tsv +++ b/ci/platform_boundary_ledger.tsv @@ -1,53 +1,17 @@ path kind normalized ordinal capability classification -crates/fbuild-build-arm/src/generic_arm/arm_linker.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-build-arm/src/teensy/teensy_linker.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-build-arm/src/teensy/teensy_linker.rs cfg_macro cfg!(windows) 1 host host_mechanic -crates/fbuild-build-engine/src/compiler_tests.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-build-engine/src/linker.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-build-engine/src/script_runtime.rs cfg_macro cfg!(windows) 0 host host_mechanic crates/fbuild-build-engine/src/script_runtime_tests.rs attr_cfg #[cfg(windows)] 0 host host_mechanic -crates/fbuild-build-esp/src/esp32/esp32_compiler.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-build-esp/src/esp32/esp32_linker.rs cfg_macro cfg!(windows) 0 host host_mechanic crates/fbuild-build/tests/avr_build.rs attr_cfg #[cfg(not(windows))] 0 host host_mechanic crates/fbuild-build/tests/avr_build.rs attr_cfg #[cfg(windows)] 0 host host_mechanic -crates/fbuild-build/tests/cache_survives_tar_extract.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-build/tests/cache_survives_tar_extract.rs cfg_macro cfg!(windows) 1 host host_mechanic -crates/fbuild-build/tests/clangd_check_parity.rs cfg_macro cfg!(windows) 0 host host_mechanic crates/fbuild-build/tests/esp32_build.rs attr_cfg #[cfg(not(windows))] 0 host host_mechanic crates/fbuild-build/tests/esp32_build.rs attr_cfg #[cfg(windows)] 0 host host_mechanic -crates/fbuild-build/tests/lite_scons_acceptance.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-build/tests/zccache_embedded_smoke.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-build/tests/zccache_embedded_smoke.rs cfg_macro cfg!(windows) 1 host host_mechanic crates/fbuild-cli/Cargo.toml native_dependency windows-sys 0 process host_mechanic crates/fbuild-cli/Cargo.toml target_dependency_table [target.'cfg(windows)'.dependencies] 0 host host_mechanic -crates/fbuild-cli/src/cli/build.rs cfg_macro cfg!(target_os=) 0 host host_mechanic -crates/fbuild-cli/src/cli/build.rs cfg_macro cfg!(target_os=) 1 host host_mechanic -crates/fbuild-cli/src/cli/build.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-cli/src/cli/compile_many.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-cli/src/cli/daemon_cmd.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-cli/src/cli/daemon_cmd.rs cfg_macro cfg!(windows) 1 host host_mechanic crates/fbuild-cli/src/cli/debug.rs attr_cfg #[cfg(windows)] 0 host host_mechanic crates/fbuild-cli/src/cli/debug.rs attr_cfg #[cfg(windows)] 1 host host_mechanic -crates/fbuild-cli/src/cli/debug.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-cli/src/cli/debug.rs cfg_macro cfg!(windows) 1 host host_mechanic crates/fbuild-cli/src/cli/deploy.rs attr_cfg #[cfg(not(windows))] 0 host host_mechanic crates/fbuild-cli/src/cli/deploy.rs attr_cfg #[cfg(windows)] 0 host host_mechanic -crates/fbuild-cli/src/cli/deploy.rs cfg_macro cfg!(windows) 0 host host_mechanic crates/fbuild-cli/src/cli/ide.rs attr_cfg #[cfg(windows)] 0 host host_mechanic -crates/fbuild-cli/src/cli/ide.rs cfg_macro cfg!(target_os=) 0 host host_mechanic -crates/fbuild-cli/src/cli/ide.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-cli/src/cli/ide.rs cfg_macro cfg!(windows) 1 host host_mechanic -crates/fbuild-cli/src/cli/ide.rs cfg_macro cfg!(windows) 2 host host_mechanic -crates/fbuild-cli/src/cli/ide.rs cfg_macro cfg!(windows) 3 host host_mechanic crates/fbuild-cli/src/cli/ide.rs native_path std::os::windows::process::CommandExt 0 process host_mechanic -crates/fbuild-cli/src/cli/pio.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-cli/src/cli/pio.rs cfg_macro cfg!(windows) 1 host host_mechanic -crates/fbuild-cli/src/cli/port_doctor.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-cli/src/cli/port_doctor.rs cfg_macro cfg!(windows) 1 host host_mechanic -crates/fbuild-cli/src/cli/port_doctor.rs cfg_macro cfg!(windows) 2 host host_mechanic -crates/fbuild-cli/src/cli/port_doctor_fix.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-cli/src/cli/symbols_cmd.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-cli/src/cli/tests.rs cfg_macro cfg!(windows) 0 host host_mechanic crates/fbuild-cli/src/cli/usb_recovery.rs attr_cfg #[cfg(not(windows))] 0 host host_mechanic crates/fbuild-cli/src/cli/usb_recovery.rs attr_cfg #[cfg(windows)] 0 host host_mechanic crates/fbuild-cli/src/cli/usb_recovery.rs attr_cfg #[cfg(windows)] 1 host host_mechanic @@ -62,13 +26,8 @@ crates/fbuild-cli/src/cli/usb_recovery.rs native_path windows_sys:: 4 process ho crates/fbuild-cli/src/daemon_client.rs attr_cfg #[cfg(windows)] 0 ipc host_mechanic crates/fbuild-cli/src/daemon_client.rs attr_cfg #[cfg(windows)] 1 ipc host_mechanic crates/fbuild-cli/src/daemon_client.rs attr_cfg #[cfg(windows)] 2 ipc host_mechanic -crates/fbuild-cli/src/daemon_client/identity.rs cfg_macro cfg!(windows) 0 ipc host_mechanic -crates/fbuild-cli/tests/daemon_crash_recovery.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-cli/tests/daemon_crash_recovery.rs cfg_macro cfg!(windows) 1 host host_mechanic crates/fbuild-config/src/bin/enrich_boards.rs attr_cfg #[cfg(not(windows))] 0 host host_mechanic crates/fbuild-config/src/bin/enrich_boards.rs attr_cfg #[cfg(windows)] 0 host host_mechanic -crates/fbuild-config/src/ini_parser/tests.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-config/src/ini_parser/values.rs cfg_macro cfg!(windows) 0 host host_mechanic crates/fbuild-core/Cargo.toml native_dependency libc 0 process host_mechanic crates/fbuild-core/Cargo.toml target_dependency_table [target.'cfg(unix)'.dependencies] 0 host host_mechanic crates/fbuild-core/src/containment.rs attr_cfg #[cfg(not(unix))] 0 process host_mechanic @@ -84,8 +43,6 @@ crates/fbuild-core/src/containment.rs attr_cfg #[cfg(windows)] 0 process host_me crates/fbuild-core/src/containment.rs attr_cfg #[cfg(windows)] 1 process host_mechanic crates/fbuild-core/src/containment.rs attr_cfg #[cfg(windows)] 2 process host_mechanic crates/fbuild-core/src/containment.rs attr_cfg #[cfg(windows)] 3 process host_mechanic -crates/fbuild-core/src/containment.rs cfg_macro cfg!(windows) 0 process host_mechanic -crates/fbuild-core/src/containment.rs cfg_macro cfg!(windows) 1 process host_mechanic crates/fbuild-core/src/containment.rs native_path libc:: 0 process host_mechanic crates/fbuild-core/src/containment.rs native_path libc:: 1 process host_mechanic crates/fbuild-core/src/containment.rs native_path libc:: 2 process host_mechanic @@ -119,7 +76,6 @@ crates/fbuild-core/src/path.rs attr_cfg #[cfg(windows)] 5 fs host_mechanic crates/fbuild-core/src/path.rs attr_cfg #[cfg(windows)] 6 fs host_mechanic crates/fbuild-core/src/path.rs attr_cfg #[cfg(windows)] 7 fs host_mechanic crates/fbuild-core/src/path.rs attr_cfg #[cfg(windows)] 8 fs host_mechanic -crates/fbuild-core/src/path.rs cfg_macro cfg!(windows) 0 fs host_mechanic crates/fbuild-core/src/path.rs native_path std::os::unix::fs::symlink 0 fs host_mechanic crates/fbuild-core/src/process_identity.rs attr_cfg #[cfg(all(unix,not(target_os=)))] 0 process host_mechanic crates/fbuild-core/src/process_identity.rs attr_cfg #[cfg(not(any(unix,windows)))] 0 process host_mechanic @@ -131,7 +87,6 @@ crates/fbuild-core/src/process_identity.rs attr_cfg #[cfg(unix)] 1 process host_ crates/fbuild-core/src/process_identity.rs attr_cfg #[cfg(windows)] 0 process host_mechanic crates/fbuild-core/src/process_identity.rs attr_cfg #[cfg(windows)] 1 process host_mechanic crates/fbuild-core/src/process_identity.rs attr_cfg #[cfg(windows)] 2 process host_mechanic -crates/fbuild-core/src/process_identity.rs cfg_macro cfg!(windows) 0 process host_mechanic crates/fbuild-core/src/process_identity.rs native_path libc:: 0 process host_mechanic crates/fbuild-core/src/process_identity.rs native_path libc:: 1 process host_mechanic crates/fbuild-core/src/process_identity.rs native_path libc:: 2 process host_mechanic @@ -143,7 +98,6 @@ crates/fbuild-core/src/process_identity.rs native_path libc:: 7 process host_mec crates/fbuild-core/src/process_identity.rs native_path std::os::windows::raw::HANDLE 0 process host_mechanic crates/fbuild-core/src/process_identity.rs native_path std::os::windows::raw::HANDLE 1 process host_mechanic crates/fbuild-core/src/process_identity.rs native_path std::os::windows::raw::HANDLE 2 process host_mechanic -crates/fbuild-core/src/response_file.rs cfg_macro cfg!(windows) 0 fs host_mechanic crates/fbuild-core/src/subprocess.rs attr_cfg #[cfg(not(unix))] 0 process host_mechanic crates/fbuild-core/src/subprocess.rs attr_cfg #[cfg(not(windows))] 0 process host_mechanic crates/fbuild-core/src/subprocess.rs attr_cfg #[cfg(unix)] 0 process host_mechanic @@ -155,18 +109,6 @@ crates/fbuild-core/src/subprocess.rs attr_cfg #[cfg(windows)] 3 process host_mec crates/fbuild-core/src/subprocess.rs attr_cfg #[cfg(windows)] 4 process host_mechanic crates/fbuild-core/src/subprocess.rs attr_cfg #[cfg(windows)] 5 process host_mechanic crates/fbuild-core/src/subprocess.rs attr_cfg #[cfg(windows)] 6 process host_mechanic -crates/fbuild-core/src/subprocess.rs cfg_macro cfg!(windows) 0 process host_mechanic -crates/fbuild-core/src/subprocess.rs cfg_macro cfg!(windows) 1 process host_mechanic -crates/fbuild-core/src/subprocess.rs cfg_macro cfg!(windows) 2 process host_mechanic -crates/fbuild-core/src/subprocess.rs cfg_macro cfg!(windows) 3 process host_mechanic -crates/fbuild-core/src/subprocess.rs cfg_macro cfg!(windows) 4 process host_mechanic -crates/fbuild-core/src/subprocess.rs cfg_macro cfg!(windows) 5 process host_mechanic -crates/fbuild-core/src/subprocess.rs cfg_macro cfg!(windows) 6 process host_mechanic -crates/fbuild-core/src/subprocess.rs cfg_macro cfg!(windows) 7 process host_mechanic -crates/fbuild-core/src/subprocess.rs cfg_macro cfg!(windows) 8 process host_mechanic -crates/fbuild-core/src/subprocess.rs cfg_macro cfg!(windows) 9 process host_mechanic -crates/fbuild-core/src/subprocess.rs cfg_macro cfg!(windows) 10 process host_mechanic -crates/fbuild-core/src/subprocess.rs cfg_macro cfg!(windows) 11 process host_mechanic crates/fbuild-core/src/subprocess.rs native_path std::os::unix::fs::PermissionsExt 0 fs host_mechanic crates/fbuild-core/src/subprocess.rs native_path std::os::unix::process::ExitStatusExt 0 process host_mechanic crates/fbuild-core/src/subprocess.rs native_path std::os::windows::process::CommandExt 0 process host_mechanic @@ -181,35 +123,17 @@ crates/fbuild-daemon/src/broker/backend.rs native_path interprocess::local_socke crates/fbuild-daemon/src/broker/backend.rs native_path interprocess::local_socket 1 process host_mechanic crates/fbuild-daemon/src/broker/backend.rs native_path interprocess::local_socket 2 process host_mechanic crates/fbuild-daemon/src/broker/backend.rs native_path interprocess::local_socket 3 process host_mechanic -crates/fbuild-daemon/src/broker/service.rs cfg_macro cfg!(windows) 0 ipc host_mechanic -crates/fbuild-daemon/src/broker/service.rs cfg_macro cfg!(windows) 1 ipc host_mechanic -crates/fbuild-daemon/src/broker/service.rs cfg_macro cfg!(windows) 2 ipc host_mechanic -crates/fbuild-daemon/src/broker/service.rs cfg_macro cfg!(windows) 3 ipc host_mechanic -crates/fbuild-daemon/src/broker/service.rs cfg_macro cfg!(windows) 4 ipc host_mechanic -crates/fbuild-daemon/src/broker/session.rs cfg_macro cfg!(windows) 0 ipc host_mechanic crates/fbuild-daemon/src/handlers/emulator/avr8js_headless.rs attr_cfg #[cfg(windows)] 0 host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/emulator/avr8js_npm.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/emulator/avr8js_npm.rs cfg_macro cfg!(windows) 1 host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/emulator/runners.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/emulator/runners.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/emulator/runners.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy crates/fbuild-daemon/src/handlers/emulator/shared.rs attr_cfg #[cfg(not(windows))] 0 host_executable host_artifact_policy crates/fbuild-daemon/src/handlers/emulator/shared.rs attr_cfg #[cfg(windows)] 0 host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/emulator/shared.rs cfg_macro cfg!(any(target_os=,target_os=)) 0 host_executable host_artifact_policy crates/fbuild-daemon/src/handlers/emulator/tests_npm_cache.rs attr_cfg #[cfg(windows)] 0 host_executable host_artifact_policy crates/fbuild-daemon/src/handlers/emulator/tests_process.rs attr_cfg #[cfg(not(windows))] 0 host_executable host_artifact_policy crates/fbuild-daemon/src/handlers/emulator/tests_process.rs attr_cfg #[cfg(windows)] 0 host_executable host_artifact_policy crates/fbuild-daemon/src/handlers/locks.rs attr_cfg #[cfg(not(any(unix,windows)))] 0 host host_mechanic crates/fbuild-daemon/src/handlers/locks.rs attr_cfg #[cfg(unix)] 0 host host_mechanic crates/fbuild-daemon/src/handlers/locks.rs attr_cfg #[cfg(windows)] 0 host host_mechanic -crates/fbuild-daemon/src/handlers/locks.rs cfg_macro cfg!(any(windows,target_os=)) 0 host host_mechanic -crates/fbuild-daemon/src/handlers/locks.rs cfg_macro cfg!(windows) 0 host host_mechanic crates/fbuild-daemon/src/handlers/locks.rs native_path libc:: 0 process host_mechanic crates/fbuild-daemon/src/handlers/locks.rs native_path libc:: 1 process host_mechanic -crates/fbuild-daemon/src/handlers/operations/deploy.rs cfg_macro cfg!(windows) 0 host host_mechanic -crates/fbuild-daemon/src/handlers/operations/deploy.rs cfg_macro cfg!(windows) 1 host host_mechanic -crates/fbuild-daemon/src/handlers/operations/deploy.rs cfg_macro cfg!(windows) 2 host host_mechanic -crates/fbuild-daemon/src/handlers/operations/deploy.rs cfg_macro cfg!(windows) 3 host host_mechanic crates/fbuild-daemon/src/main.rs attr_cfg #[cfg(not(any(unix,windows)))] 0 host host_mechanic crates/fbuild-daemon/src/main.rs attr_cfg #[cfg(not(windows))] 0 host host_mechanic crates/fbuild-daemon/src/main.rs attr_cfg #[cfg(unix)] 0 host host_mechanic @@ -222,7 +146,6 @@ crates/fbuild-daemon/src/main.rs native_path libc:: 0 process host_mechanic crates/fbuild-daemon/src/main.rs native_path std::os::windows::io::AsRawSocket 0 process host_mechanic crates/fbuild-daemon/tests/legacy_daemon_transition.rs attr_cfg #[cfg(unix)] 0 host host_mechanic crates/fbuild-daemon/tests/legacy_daemon_transition.rs attr_cfg #[cfg(windows)] 0 host host_mechanic -crates/fbuild-daemon/tests/legacy_daemon_transition.rs cfg_macro cfg!(windows) 0 host host_mechanic crates/fbuild-daemon/tests/legacy_daemon_transition.rs native_path libc:: 0 process host_mechanic crates/fbuild-daemon/tests/legacy_daemon_transition.rs native_path libc:: 1 process host_mechanic crates/fbuild-daemon/tests/port_recovery.rs attr_cfg #[cfg(unix)] 0 host host_mechanic @@ -242,23 +165,9 @@ crates/fbuild-deploy/src/lpc.rs attr_cfg #[cfg(not(target_os=))] 0 device host_m crates/fbuild-deploy/src/lpc.rs attr_cfg #[cfg(not(windows))] 0 device host_mechanic crates/fbuild-deploy/src/lpc.rs attr_cfg #[cfg(target_os=)] 0 device host_mechanic crates/fbuild-deploy/src/lpc.rs attr_cfg #[cfg(windows)] 0 device host_mechanic -crates/fbuild-deploy/src/lpc.rs cfg_macro cfg!(windows) 0 device host_mechanic -crates/fbuild-deploy/src/lpc.rs cfg_macro cfg!(windows) 1 device host_mechanic -crates/fbuild-deploy/src/lpc.rs cfg_macro cfg!(windows) 2 device host_mechanic -crates/fbuild-deploy/src/lpc.rs cfg_macro cfg!(windows) 3 device host_mechanic crates/fbuild-deploy/src/lpc_debugger_reflash.rs attr_cfg #[cfg(target_os=)] 0 device host_mechanic -crates/fbuild-deploy/src/lpc_debugger_reflash.rs cfg_macro cfg!(target_os=) 0 device host_mechanic -crates/fbuild-deploy/src/lpc_debugger_reflash.rs cfg_macro cfg!(target_os=) 1 device host_mechanic -crates/fbuild-deploy/src/lpc_debugger_reflash.rs cfg_macro cfg!(windows) 0 device host_mechanic -crates/fbuild-deploy/src/lpc_debugger_reflash.rs cfg_macro cfg!(windows) 1 device host_mechanic crates/fbuild-deploy/src/probe_rs.rs attr_cfg #[cfg(unix)] 0 device host_mechanic crates/fbuild-deploy/src/probe_rs.rs attr_cfg #[cfg(windows)] 0 device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs cfg_macro cfg!(windows) 0 device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs cfg_macro cfg!(windows) 1 device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs cfg_macro cfg!(windows) 2 device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs cfg_macro cfg!(windows) 3 device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs compile_host_fact std::env::consts::ARCH 0 device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs compile_host_fact std::env::consts::OS 0 device host_mechanic crates/fbuild-deploy/src/probe_rs.rs native_path std::os::unix::fs::PermissionsExt 0 fs host_mechanic crates/fbuild-deploy/src/rp2040.rs attr_cfg #[cfg(not(windows))] 0 device host_mechanic crates/fbuild-deploy/src/rp2040.rs attr_cfg #[cfg(not(windows))] 1 device host_mechanic @@ -266,12 +175,6 @@ crates/fbuild-deploy/src/rp2040.rs attr_cfg #[cfg(windows)] 0 device host_mechan crates/fbuild-deploy/src/rp2040.rs attr_cfg #[cfg(windows)] 1 device host_mechanic crates/fbuild-deploy/src/rp2040.rs attr_cfg #[cfg(windows)] 2 device host_mechanic crates/fbuild-deploy/src/rp2040.rs attr_cfg #[cfg(windows)] 3 device host_mechanic -crates/fbuild-deploy/src/rp2040.rs cfg_macro cfg!(target_os=) 0 device host_mechanic -crates/fbuild-deploy/src/rp2040.rs cfg_macro cfg!(target_os=) 1 device host_mechanic -crates/fbuild-deploy/src/rp2040.rs cfg_macro cfg!(windows) 0 device host_mechanic -crates/fbuild-deploy/src/rp2040.rs cfg_macro cfg!(windows) 1 device host_mechanic -crates/fbuild-deploy/src/rp2040.rs cfg_macro cfg!(windows) 2 device host_mechanic -crates/fbuild-deploy/src/rp2040.rs cfg_macro cfg!(windows) 3 device host_mechanic crates/fbuild-deploy/src/rp2040.rs native_path std::os::windows::fs::OpenOptionsExt 0 fs host_mechanic crates/fbuild-deploy/src/rp2040.rs native_path std::os::windows::fs::OpenOptionsExt 1 fs host_mechanic crates/fbuild-deploy/src/rp2040.rs native_path std::os::windows::io::AsRawHandle 0 device host_mechanic @@ -280,9 +183,6 @@ crates/fbuild-deploy/src/rp2040_mount.rs attr_cfg #[cfg(any(target_os=,test))] 0 crates/fbuild-deploy/src/rp2040_mount.rs attr_cfg #[cfg(any(target_os=,test))] 1 device host_mechanic crates/fbuild-deploy/src/rp2040_mount.rs attr_cfg #[cfg(not(target_os=))] 0 device host_mechanic crates/fbuild-deploy/src/rp2040_mount.rs attr_cfg #[cfg(target_os=)] 0 device host_mechanic -crates/fbuild-deploy/src/rp2040_picotool.rs cfg_macro cfg!(windows) 0 device host_mechanic -crates/fbuild-deploy/src/rp2040_picotool.rs cfg_macro cfg!(windows) 1 device host_mechanic -crates/fbuild-deploy/src/rp2040_picotool.rs cfg_macro cfg!(windows) 2 device host_mechanic crates/fbuild-deploy/src/rp2040_topology.rs attr_cfg #[cfg(any(windows,test))] 0 device host_mechanic crates/fbuild-deploy/src/rp2040_topology.rs attr_cfg #[cfg(any(windows,test))] 1 device host_mechanic crates/fbuild-deploy/src/rp2040_topology.rs attr_cfg #[cfg(any(windows,test))] 2 device host_mechanic @@ -295,36 +195,15 @@ crates/fbuild-deploy/src/rp2040_topology.rs attr_cfg #[cfg(windows)] 0 device ho crates/fbuild-deploy/src/rp2040_topology.rs attr_cfg #[cfg(windows)] 1 device host_mechanic crates/fbuild-deploy/src/rp2040_topology.rs attr_cfg #[cfg(windows)] 2 device host_mechanic crates/fbuild-deploy/src/rp2040_topology.rs native_path std::os::windows::ffi::OsStrExt 0 device host_mechanic -crates/fbuild-deploy/src/teensy/soft_reboot.rs cfg_macro cfg!(windows) 0 device host_mechanic crates/fbuild-deploy/src/wchisp.rs attr_cfg #[cfg(unix)] 0 device host_mechanic -crates/fbuild-deploy/src/wchisp.rs cfg_macro cfg!(windows) 0 device host_mechanic -crates/fbuild-deploy/src/wchisp.rs cfg_macro cfg!(windows) 1 device host_mechanic -crates/fbuild-deploy/src/wchisp.rs cfg_macro cfg!(windows) 2 device host_mechanic -crates/fbuild-deploy/src/wchisp.rs cfg_macro cfg!(windows) 3 device host_mechanic -crates/fbuild-deploy/src/wchisp.rs compile_host_fact std::env::consts::ARCH 0 device host_mechanic -crates/fbuild-deploy/src/wchisp.rs compile_host_fact std::env::consts::OS 0 device host_mechanic crates/fbuild-deploy/src/wchisp.rs native_path std::os::unix::fs::PermissionsExt::from_mode 0 fs host_mechanic crates/fbuild-deploy/src/wlink.rs attr_cfg #[cfg(unix)] 0 device host_mechanic -crates/fbuild-deploy/src/wlink.rs cfg_macro cfg!(windows) 0 device host_mechanic -crates/fbuild-deploy/src/wlink.rs cfg_macro cfg!(windows) 1 device host_mechanic -crates/fbuild-deploy/src/wlink.rs cfg_macro cfg!(windows) 2 device host_mechanic -crates/fbuild-deploy/src/wlink.rs cfg_macro cfg!(windows) 3 device host_mechanic -crates/fbuild-deploy/src/wlink.rs compile_host_fact std::env::consts::ARCH 0 device host_mechanic -crates/fbuild-deploy/src/wlink.rs compile_host_fact std::env::consts::OS 0 device host_mechanic crates/fbuild-deploy/src/wlink.rs native_path std::os::unix::fs::PermissionsExt::from_mode 0 fs host_mechanic crates/fbuild-library/src/library/esptool.rs attr_cfg #[cfg(unix)] 0 host_executable host_artifact_policy crates/fbuild-library/src/library/esptool.rs attr_cfg #[cfg(unix)] 1 host_executable host_artifact_policy -crates/fbuild-library/src/library/esptool.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-library/src/library/esptool.rs compile_host_fact std::env::consts::ARCH 0 host_executable host_artifact_policy -crates/fbuild-library/src/library/esptool.rs compile_host_fact std::env::consts::ARCH 1 host_executable host_artifact_policy -crates/fbuild-library/src/library/esptool.rs compile_host_fact std::env::consts::OS 0 host_executable host_artifact_policy -crates/fbuild-library/src/library/esptool.rs compile_host_fact std::env::consts::OS 1 host_executable host_artifact_policy crates/fbuild-library/src/library/esptool.rs native_path std::os::unix::fs::PermissionsExt 0 fs host_mechanic crates/fbuild-library/src/library/esptool.rs native_path std::os::unix::fs::PermissionsExt 1 fs host_mechanic -crates/fbuild-library/src/library/library_compiler.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-library/src/library/library_compiler.rs cfg_macro cfg!(windows) 1 host_executable host_artifact_policy crates/fbuild-library/src/library/library_spec.rs attr_cfg #[cfg(windows)] 0 host host_mechanic -crates/fbuild-library/src/library/library_spec.rs cfg_macro cfg!(windows) 0 host host_mechanic crates/fbuild-packages-fetch/src/disk_cache/budget.rs attr_cfg #[cfg(not(any(unix,windows)))] 0 fs host_mechanic crates/fbuild-packages-fetch/src/disk_cache/budget.rs attr_cfg #[cfg(unix)] 0 fs host_mechanic crates/fbuild-packages-fetch/src/disk_cache/budget.rs attr_cfg #[cfg(unix)] 1 fs host_mechanic @@ -333,35 +212,8 @@ crates/fbuild-packages-fetch/src/disk_cache/budget.rs attr_cfg #[cfg(windows)] 1 crates/fbuild-packages-fetch/src/disk_cache/index/pid.rs attr_cfg #[cfg(not(any(unix,windows)))] 0 fs host_mechanic crates/fbuild-packages-fetch/src/disk_cache/index/pid.rs attr_cfg #[cfg(unix)] 0 fs host_mechanic crates/fbuild-packages-fetch/src/disk_cache/index/pid.rs attr_cfg #[cfg(windows)] 0 fs host_mechanic -crates/fbuild-packages-fetch/src/install_lock.rs cfg_macro cfg!(windows) 0 fs host_mechanic -crates/fbuild-paths/src/lib.rs attr_cfg #[cfg(not(target_os=))] 0 host host_mechanic -crates/fbuild-paths/src/lib.rs attr_cfg #[cfg(not(windows))] 0 host host_mechanic -crates/fbuild-paths/src/lib.rs attr_cfg #[cfg(not(windows))] 1 host host_mechanic -crates/fbuild-paths/src/lib.rs attr_cfg #[cfg(not(windows))] 2 host host_mechanic -crates/fbuild-paths/src/lib.rs attr_cfg #[cfg(not(windows))] 3 host host_mechanic -crates/fbuild-paths/src/lib.rs attr_cfg #[cfg(target_os=)] 0 host host_mechanic -crates/fbuild-paths/src/lib.rs attr_cfg #[cfg(windows)] 0 host host_mechanic -crates/fbuild-paths/src/lib.rs attr_cfg #[cfg(windows)] 1 host host_mechanic -crates/fbuild-paths/src/lib.rs attr_cfg #[cfg(windows)] 2 host host_mechanic -crates/fbuild-paths/src/lib.rs attr_cfg #[cfg(windows)] 3 host host_mechanic -crates/fbuild-paths/src/running_process.rs attr_cfg #[cfg(all(unix,not(target_os=)))] 0 host host_mechanic -crates/fbuild-paths/src/running_process.rs attr_cfg #[cfg(all(unix,not(target_os=)))] 1 host host_mechanic -crates/fbuild-paths/src/running_process.rs attr_cfg #[cfg(any(target_os=,all(unix,not(target_os=))))] 0 host host_mechanic -crates/fbuild-paths/src/running_process.rs attr_cfg #[cfg(not(windows))] 0 host host_mechanic -crates/fbuild-paths/src/running_process.rs attr_cfg #[cfg(target_os=)] 0 host host_mechanic -crates/fbuild-paths/src/running_process.rs attr_cfg #[cfg(windows)] 0 host host_mechanic -crates/fbuild-paths/src/running_process.rs attr_cfg #[cfg(windows)] 1 host host_mechanic -crates/fbuild-python/src/daemon.rs attr_cfg #[cfg(not(windows))] 0 host host_mechanic -crates/fbuild-python/src/daemon.rs attr_cfg #[cfg(not(windows))] 1 host host_mechanic -crates/fbuild-python/src/daemon.rs attr_cfg #[cfg(windows)] 0 host host_mechanic -crates/fbuild-python/src/daemon.rs attr_cfg #[cfg(windows)] 1 host host_mechanic crates/fbuild-serial/Cargo.toml native_dependency windows-sys 0 device host_mechanic crates/fbuild-serial/Cargo.toml target_dependency_table [target.'cfg(windows)'.dependencies] 0 device host_mechanic -crates/fbuild-serial/src/boards.rs cfg_macro cfg!(windows) 0 device host_mechanic -crates/fbuild-serial/src/crash_decoder.rs cfg_macro cfg!(windows) 0 device host_mechanic -crates/fbuild-serial/src/crash_decoder.rs cfg_macro cfg!(windows) 1 device host_mechanic -crates/fbuild-serial/src/manager.rs cfg_macro cfg!(windows) 0 device host_mechanic -crates/fbuild-serial/src/manager.rs cfg_macro cfg!(windows) 1 device host_mechanic crates/fbuild-serial/src/port_class.rs attr_cfg #[cfg(not(any(target_os=,target_os=,target_os=)))] 0 device host_mechanic crates/fbuild-serial/src/port_class.rs attr_cfg #[cfg(target_os=)] 0 device host_mechanic crates/fbuild-serial/src/port_class.rs attr_cfg #[cfg(target_os=)] 1 device host_mechanic @@ -402,42 +254,6 @@ crates/fbuild-serial/src/usb_recovery.rs attr_cfg #[cfg(windows)] 1 device host_ crates/fbuild-serial/src/usb_recovery.rs native_path windows:: 0 device host_mechanic crates/fbuild-serial/src/usb_recovery.rs native_path windows_sys:: 0 device host_mechanic crates/fbuild-serial/src/usb_recovery.rs native_path windows_sys:: 1 device host_mechanic -crates/fbuild-toolchain/src/toolchain/arm.rs cfg_macro cfg!(target_arch=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm.rs cfg_macro cfg!(windows) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/avr.rs cfg_macro cfg!(target_arch=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/avr.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/avr.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/avr.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/avr.rs cfg_macro cfg!(windows) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro cfg!(target_arch=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro cfg!(windows) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro cfg!(windows) 2 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro cfg!(windows) 3 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32.rs cfg_macro cfg!(target_arch=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32.rs cfg_macro cfg!(target_arch=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32.rs cfg_macro cfg!(windows) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs cfg_macro cfg!(target_arch=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs cfg_macro cfg!(target_arch=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp8266.rs cfg_macro cfg!(target_arch=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp8266.rs cfg_macro cfg!(target_arch=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp8266.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp8266.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp8266.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp8266.rs cfg_macro cfg!(windows) 1 host_executable host_artifact_policy crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg #[cfg(not(target_os=))] 0 host_executable host_mechanic crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg #[cfg(not(windows))] 0 host_executable host_mechanic crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg #[cfg(not(windows))] 1 host_executable host_mechanic @@ -451,55 +267,6 @@ crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg #[cfg(windows)] 3 hos crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg #[cfg(windows)] 4 host_executable host_mechanic crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg #[cfg(windows)] 5 host_executable host_mechanic crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg #[cfg(windows)] 6 host_executable host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_arch=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_arch=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_arch=) 2 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_arch=) 3 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_arch=) 4 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_arch=) 5 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_arch=) 6 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_arch=) 7 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_arch=) 8 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_arch=) 9 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_os=) 2 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_os=) 3 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_os=) 4 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_os=) 5 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_os=) 6 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_os=) 7 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_os=) 8 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(target_os=) 9 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro cfg!(windows) 1 fs host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs compile_host_fact std::env::consts::ARCH 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs compile_host_fact std::env::consts::ARCH 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs compile_host_fact std::env::consts::OS 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs compile_host_fact std::env::consts::OS 1 host_executable host_artifact_policy crates/fbuild-toolchain/src/toolchain/esp_qemu.rs native_path std::os::unix::fs::PermissionsExt 0 fs host_mechanic crates/fbuild-toolchain/src/toolchain/esp_qemu.rs native_path std::os::unix::fs::PermissionsExt 1 fs host_mechanic crates/fbuild-toolchain/src/toolchain/mod.rs attr_cfg #[cfg(windows)] 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/riscv.rs cfg_macro cfg!(target_arch=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/riscv.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/riscv.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/riscv.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/riscv.rs cfg_macro cfg!(windows) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs cfg_macro cfg!(target_arch=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs cfg_macro cfg!(target_arch=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs cfg_macro cfg!(target_arch=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs cfg_macro cfg!(target_arch=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs cfg_macro cfg!(windows) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro cfg!(target_arch=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro cfg!(target_arch=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro cfg!(target_arch=) 2 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro cfg!(target_os=) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro cfg!(target_os=) 1 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro cfg!(windows) 0 host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro cfg!(windows) 1 host_executable host_artifact_policy diff --git a/ci/platform_boundary_research.py b/ci/platform_boundary_research.py index 76059c906..8537e0612 100644 --- a/ci/platform_boundary_research.py +++ b/ci/platform_boundary_research.py @@ -46,6 +46,7 @@ CFG_MACRO_START = re.compile(r"\bcfg\s*!\s*\(") IDENTIFIER = re.compile(r"\b[A-Za-z_][A-Za-z0-9_]*\b") NATIVE_PATHS = ( + re.compile(r"\bstd\s*::\s*env\s*::\s*current_exe\b"), re.compile( r"\bstd\s*::\s*os\s*::\s*(?:windows|unix|linux|macos)\b" r"(?:\s*::\s*[A-Za-z_][A-Za-z0-9_]*)*" @@ -210,6 +211,8 @@ def enclosing_function(text: str, offset: int) -> str: def classify(path: str, kind: str, normalized: str = "", context: str = "") -> tuple[str, str]: """Assign the phase-1 owner class; phase 2 validates this per occurrence.""" if kind in {"native_import", "native_path", "native_dependency"}: + if normalized == "std::env::current_exe": + return "host_executable", "host_mechanic" if "::fs" in normalized or "permissions" in normalized.lower(): return "fs", "host_mechanic" if "/fbuild-serial/" in f"/{path}/" or "/fbuild-deploy/" in f"/{path}/": diff --git a/ci/platform_boundary_research.tsv b/ci/platform_boundary_research.tsv index a8ab6b846..8bc56dbae 100644 --- a/ci/platform_boundary_research.tsv +++ b/ci/platform_boundary_research.tsv @@ -1,53 +1,17 @@ path line kind normalized capability classification -crates/fbuild-build-arm/src/generic_arm/arm_linker.rs 181 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-build-arm/src/teensy/teensy_linker.rs 185 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-build-arm/src/teensy/teensy_linker.rs 278 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-build-engine/src/compiler_tests.rs 62 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-build-engine/src/linker.rs 596 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-build-engine/src/script_runtime.rs 326 cfg_macro cfg!(windows) host host_mechanic crates/fbuild-build-engine/src/script_runtime_tests.rs 600 attr_cfg #[cfg(windows)] host host_mechanic -crates/fbuild-build-esp/src/esp32/esp32_compiler.rs 64 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-build-esp/src/esp32/esp32_linker.rs 446 cfg_macro cfg!(windows) host host_mechanic crates/fbuild-build/tests/avr_build.rs 45 attr_cfg #[cfg(windows)] host host_mechanic crates/fbuild-build/tests/avr_build.rs 49 attr_cfg #[cfg(not(windows))] host host_mechanic -crates/fbuild-build/tests/cache_survives_tar_extract.rs 164 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-build/tests/cache_survives_tar_extract.rs 186 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-build/tests/clangd_check_parity.rs 91 cfg_macro cfg!(windows) host host_mechanic crates/fbuild-build/tests/esp32_build.rs 31 attr_cfg #[cfg(windows)] host host_mechanic crates/fbuild-build/tests/esp32_build.rs 35 attr_cfg #[cfg(not(windows))] host host_mechanic -crates/fbuild-build/tests/lite_scons_acceptance.rs 41 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-build/tests/zccache_embedded_smoke.rs 21 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-build/tests/zccache_embedded_smoke.rs 92 cfg_macro cfg!(windows) host host_mechanic crates/fbuild-cli/Cargo.toml 44 target_dependency_table [target.'cfg(windows)'.dependencies] host host_mechanic crates/fbuild-cli/Cargo.toml 45 native_dependency windows-sys process host_mechanic -crates/fbuild-cli/src/cli/build.rs 7 cfg_macro cfg!(target_os=) host host_mechanic -crates/fbuild-cli/src/cli/build.rs 9 cfg_macro cfg!(target_os=) host host_mechanic -crates/fbuild-cli/src/cli/build.rs 162 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/compile_many.rs 11 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/daemon_cmd.rs 699 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/daemon_cmd.rs 734 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/debug.rs 250 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/debug.rs 331 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/debug.rs 750 attr_cfg #[cfg(windows)] host host_mechanic -crates/fbuild-cli/src/cli/debug.rs 756 attr_cfg #[cfg(windows)] host host_mechanic -crates/fbuild-cli/src/cli/deploy.rs 290 cfg_macro cfg!(windows) host host_mechanic +crates/fbuild-cli/src/cli/debug.rs 749 attr_cfg #[cfg(windows)] host host_mechanic +crates/fbuild-cli/src/cli/debug.rs 755 attr_cfg #[cfg(windows)] host host_mechanic crates/fbuild-cli/src/cli/deploy.rs 294 attr_cfg #[cfg(windows)] host host_mechanic crates/fbuild-cli/src/cli/deploy.rs 310 attr_cfg #[cfg(not(windows))] host host_mechanic -crates/fbuild-cli/src/cli/ide.rs 258 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/ide.rs 264 cfg_macro cfg!(target_os=) host host_mechanic -crates/fbuild-cli/src/cli/ide.rs 284 cfg_macro cfg!(windows) host host_mechanic crates/fbuild-cli/src/cli/ide.rs 323 attr_cfg #[cfg(windows)] host host_mechanic crates/fbuild-cli/src/cli/ide.rs 325 native_path std::os::windows::process::CommandExt process host_mechanic -crates/fbuild-cli/src/cli/ide.rs 844 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/ide.rs 865 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/pio.rs 11 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/pio.rs 36 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/port_doctor.rs 499 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/port_doctor.rs 536 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/port_doctor.rs 563 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/port_doctor_fix.rs 67 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/symbols_cmd.rs 216 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/src/cli/tests.rs 248 cfg_macro cfg!(windows) host host_mechanic crates/fbuild-cli/src/cli/usb_recovery.rs 240 attr_cfg #[cfg(windows)] host host_mechanic crates/fbuild-cli/src/cli/usb_recovery.rs 243 attr_cfg #[cfg(windows)] host host_mechanic crates/fbuild-cli/src/cli/usb_recovery.rs 250 native_path windows_sys:: process host_mechanic @@ -59,16 +23,11 @@ crates/fbuild-cli/src/cli/usb_recovery.rs 424 attr_cfg #[cfg(windows)] host host crates/fbuild-cli/src/cli/usb_recovery.rs 426 native_path std::os::windows::ffi::OsStrExt process host_mechanic crates/fbuild-cli/src/cli/usb_recovery.rs 427 native_path windows_sys:: process host_mechanic crates/fbuild-cli/src/cli/usb_recovery.rs 451 attr_cfg #[cfg(not(windows))] host host_mechanic -crates/fbuild-cli/src/daemon_client.rs 1070 attr_cfg #[cfg(windows)] ipc host_mechanic -crates/fbuild-cli/src/daemon_client.rs 1099 attr_cfg #[cfg(windows)] ipc host_mechanic -crates/fbuild-cli/src/daemon_client.rs 1126 attr_cfg #[cfg(windows)] ipc host_mechanic -crates/fbuild-cli/src/daemon_client/identity.rs 119 cfg_macro cfg!(windows) ipc host_mechanic -crates/fbuild-cli/tests/daemon_crash_recovery.rs 35 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-cli/tests/daemon_crash_recovery.rs 173 cfg_macro cfg!(windows) host host_mechanic +crates/fbuild-cli/src/daemon_client.rs 1064 attr_cfg #[cfg(windows)] ipc host_mechanic +crates/fbuild-cli/src/daemon_client.rs 1093 attr_cfg #[cfg(windows)] ipc host_mechanic +crates/fbuild-cli/src/daemon_client.rs 1120 attr_cfg #[cfg(windows)] ipc host_mechanic crates/fbuild-config/src/bin/enrich_boards.rs 74 attr_cfg #[cfg(windows)] host host_mechanic crates/fbuild-config/src/bin/enrich_boards.rs 78 attr_cfg #[cfg(not(windows))] host host_mechanic -crates/fbuild-config/src/ini_parser/tests.rs 318 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-config/src/ini_parser/values.rs 110 cfg_macro cfg!(windows) host host_mechanic crates/fbuild-core/Cargo.toml 47 target_dependency_table [target.'cfg(unix)'.dependencies] host host_mechanic crates/fbuild-core/Cargo.toml 48 native_dependency libc process host_mechanic crates/fbuild-core/src/containment.rs 120 attr_cfg #[cfg(windows)] process host_mechanic @@ -100,9 +59,6 @@ crates/fbuild-core/src/containment.rs 319 attr_cfg #[cfg(not(unix))] process hos crates/fbuild-core/src/containment.rs 328 attr_cfg #[cfg(windows)] process host_mechanic crates/fbuild-core/src/containment.rs 339 attr_cfg #[cfg(not(windows))] process host_mechanic crates/fbuild-core/src/containment.rs 350 attr_cfg #[cfg(windows)] process host_mechanic -crates/fbuild-core/src/containment.rs 471 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/containment.rs 521 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/path.rs 153 cfg_macro cfg!(windows) fs host_mechanic crates/fbuild-core/src/path.rs 251 attr_cfg #[cfg(windows)] fs host_mechanic crates/fbuild-core/src/path.rs 266 attr_cfg #[cfg(not(windows))] fs host_mechanic crates/fbuild-core/src/path.rs 326 attr_cfg #[cfg(windows)] fs host_mechanic @@ -121,6 +77,10 @@ crates/fbuild-core/src/path.rs 739 attr_cfg #[cfg(windows)] fs host_mechanic crates/fbuild-core/src/path.rs 814 attr_cfg #[cfg(unix)] fs host_mechanic crates/fbuild-core/src/path.rs 822 native_path std::os::unix::fs::symlink fs host_mechanic crates/fbuild-core/src/path.rs 829 attr_cfg #[cfg(windows)] fs host_mechanic +crates/fbuild-core/src/platform/executable.rs 55 native_path std::env::current_exe host_executable host_mechanic +crates/fbuild-core/src/platform/linux/mod.rs 6 compile_host_fact std::env::consts::ARCH host host_mechanic +crates/fbuild-core/src/platform/macos/mod.rs 6 compile_host_fact std::env::consts::ARCH host host_mechanic +crates/fbuild-core/src/platform/windows/mod.rs 6 compile_host_fact std::env::consts::ARCH host host_mechanic crates/fbuild-core/src/process_identity.rs 26 attr_cfg #[cfg(unix)] process host_mechanic crates/fbuild-core/src/process_identity.rs 37 native_path libc:: process host_mechanic crates/fbuild-core/src/process_identity.rs 37 native_path libc:: process host_mechanic @@ -132,7 +92,6 @@ crates/fbuild-core/src/process_identity.rs 83 attr_cfg #[cfg(all(unix,not(target crates/fbuild-core/src/process_identity.rs 98 attr_cfg #[cfg(windows)] process host_mechanic crates/fbuild-core/src/process_identity.rs 101 native_path std::os::windows::raw::HANDLE process host_mechanic crates/fbuild-core/src/process_identity.rs 133 attr_cfg #[cfg(not(any(unix,windows)))] process host_mechanic -crates/fbuild-core/src/process_identity.rs 153 cfg_macro cfg!(windows) process host_mechanic crates/fbuild-core/src/process_identity.rs 164 attr_cfg #[cfg(unix)] process host_mechanic crates/fbuild-core/src/process_identity.rs 169 native_path libc:: process host_mechanic crates/fbuild-core/src/process_identity.rs 169 native_path libc:: process host_mechanic @@ -143,7 +102,6 @@ crates/fbuild-core/src/process_identity.rs 175 native_path libc:: process host_m crates/fbuild-core/src/process_identity.rs 179 attr_cfg #[cfg(windows)] process host_mechanic crates/fbuild-core/src/process_identity.rs 182 native_path std::os::windows::raw::HANDLE process host_mechanic crates/fbuild-core/src/process_identity.rs 205 attr_cfg #[cfg(not(any(unix,windows)))] process host_mechanic -crates/fbuild-core/src/response_file.rs 27 cfg_macro cfg!(windows) fs host_mechanic crates/fbuild-core/src/subprocess.rs 38 attr_cfg #[cfg(windows)] process host_mechanic crates/fbuild-core/src/subprocess.rs 514 attr_cfg #[cfg(unix)] process host_mechanic crates/fbuild-core/src/subprocess.rs 516 native_path std::os::unix::process::ExitStatusExt process host_mechanic @@ -154,22 +112,10 @@ crates/fbuild-core/src/subprocess.rs 658 attr_cfg #[cfg(windows)] process host_m crates/fbuild-core/src/subprocess.rs 703 attr_cfg #[cfg(not(windows))] process host_mechanic crates/fbuild-core/src/subprocess.rs 720 attr_cfg #[cfg(windows)] process host_mechanic crates/fbuild-core/src/subprocess.rs 732 attr_cfg #[cfg(windows)] process host_mechanic -crates/fbuild-core/src/subprocess.rs 789 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/subprocess.rs 827 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/subprocess.rs 838 attr_cfg #[cfg(windows)] process host_mechanic -crates/fbuild-core/src/subprocess.rs 854 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/subprocess.rs 877 attr_cfg #[cfg(windows)] process host_mechanic -crates/fbuild-core/src/subprocess.rs 885 attr_cfg #[cfg(unix)] process host_mechanic -crates/fbuild-core/src/subprocess.rs 887 native_path std::os::unix::fs::PermissionsExt fs host_mechanic -crates/fbuild-core/src/subprocess.rs 897 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/subprocess.rs 921 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/subprocess.rs 947 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/subprocess.rs 959 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/subprocess.rs 980 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/subprocess.rs 1099 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/subprocess.rs 1136 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/subprocess.rs 1153 cfg_macro cfg!(windows) process host_mechanic -crates/fbuild-core/src/subprocess.rs 1167 cfg_macro cfg!(windows) process host_mechanic +crates/fbuild-core/src/subprocess.rs 842 attr_cfg #[cfg(windows)] process host_mechanic +crates/fbuild-core/src/subprocess.rs 881 attr_cfg #[cfg(windows)] process host_mechanic +crates/fbuild-core/src/subprocess.rs 889 attr_cfg #[cfg(unix)] process host_mechanic +crates/fbuild-core/src/subprocess.rs 891 native_path std::os::unix::fs::PermissionsExt fs host_mechanic crates/fbuild-daemon/Cargo.toml 58 native_dependency interprocess process host_mechanic crates/fbuild-daemon/Cargo.toml 73 target_dependency_table [target.'cfg(unix)'.dependencies] host host_mechanic crates/fbuild-daemon/Cargo.toml 74 native_dependency libc process host_mechanic @@ -181,35 +127,17 @@ crates/fbuild-daemon/src/broker/backend.rs 189 attr_cfg #[cfg(unix)] ipc host_me crates/fbuild-daemon/src/broker/backend.rs 195 native_path interprocess::local_socket process host_mechanic crates/fbuild-daemon/src/broker/backend.rs 200 attr_cfg #[cfg(windows)] ipc host_mechanic crates/fbuild-daemon/src/broker/backend.rs 202 native_path interprocess::local_socket process host_mechanic -crates/fbuild-daemon/src/broker/service.rs 227 cfg_macro cfg!(windows) ipc host_mechanic -crates/fbuild-daemon/src/broker/service.rs 325 cfg_macro cfg!(windows) ipc host_mechanic -crates/fbuild-daemon/src/broker/service.rs 446 cfg_macro cfg!(windows) ipc host_mechanic -crates/fbuild-daemon/src/broker/service.rs 451 cfg_macro cfg!(windows) ipc host_mechanic -crates/fbuild-daemon/src/broker/service.rs 492 cfg_macro cfg!(windows) ipc host_mechanic -crates/fbuild-daemon/src/broker/session.rs 175 cfg_macro cfg!(windows) ipc host_mechanic crates/fbuild-daemon/src/handlers/emulator/avr8js_headless.rs 70 attr_cfg #[cfg(windows)] host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/emulator/avr8js_npm.rs 9 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/emulator/avr8js_npm.rs 165 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/emulator/runners.rs 242 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/emulator/runners.rs 265 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/emulator/runners.rs 267 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/emulator/shared.rs 97 cfg_macro cfg!(any(target_os=,target_os=)) host_executable host_artifact_policy crates/fbuild-daemon/src/handlers/emulator/shared.rs 159 attr_cfg #[cfg(windows)] host_executable host_artifact_policy crates/fbuild-daemon/src/handlers/emulator/shared.rs 172 attr_cfg #[cfg(not(windows))] host_executable host_artifact_policy crates/fbuild-daemon/src/handlers/emulator/tests_npm_cache.rs 146 attr_cfg #[cfg(windows)] host_executable host_artifact_policy crates/fbuild-daemon/src/handlers/emulator/tests_process.rs 9 attr_cfg #[cfg(windows)] host_executable host_artifact_policy crates/fbuild-daemon/src/handlers/emulator/tests_process.rs 21 attr_cfg #[cfg(not(windows))] host_executable host_artifact_policy -crates/fbuild-daemon/src/handlers/locks.rs 40 cfg_macro cfg!(windows) host host_mechanic crates/fbuild-daemon/src/handlers/locks.rs 129 attr_cfg #[cfg(unix)] host host_mechanic crates/fbuild-daemon/src/handlers/locks.rs 135 native_path libc:: process host_mechanic crates/fbuild-daemon/src/handlers/locks.rs 138 native_path libc:: process host_mechanic crates/fbuild-daemon/src/handlers/locks.rs 141 attr_cfg #[cfg(windows)] host host_mechanic crates/fbuild-daemon/src/handlers/locks.rs 160 attr_cfg #[cfg(not(any(unix,windows)))] host host_mechanic -crates/fbuild-daemon/src/handlers/locks.rs 463 cfg_macro cfg!(any(windows,target_os=)) host host_mechanic -crates/fbuild-daemon/src/handlers/operations/deploy.rs 32 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-daemon/src/handlers/operations/deploy.rs 39 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-daemon/src/handlers/operations/deploy.rs 51 cfg_macro cfg!(windows) host host_mechanic -crates/fbuild-daemon/src/handlers/operations/deploy.rs 977 cfg_macro cfg!(windows) host host_mechanic crates/fbuild-daemon/src/main.rs 319 attr_cfg #[cfg(windows)] host host_mechanic crates/fbuild-daemon/src/main.rs 582 attr_cfg #[cfg(unix)] host host_mechanic crates/fbuild-daemon/src/main.rs 587 native_path libc:: process host_mechanic @@ -224,7 +152,6 @@ crates/fbuild-daemon/tests/legacy_daemon_transition.rs 54 attr_cfg #[cfg(unix)] crates/fbuild-daemon/tests/legacy_daemon_transition.rs 60 native_path libc:: process host_mechanic crates/fbuild-daemon/tests/legacy_daemon_transition.rs 60 native_path libc:: process host_mechanic crates/fbuild-daemon/tests/legacy_daemon_transition.rs 64 attr_cfg #[cfg(windows)] host host_mechanic -crates/fbuild-daemon/tests/legacy_daemon_transition.rs 208 cfg_macro cfg!(windows) host host_mechanic crates/fbuild-daemon/tests/port_recovery.rs 80 attr_cfg #[cfg(unix)] host host_mechanic crates/fbuild-daemon/tests/port_recovery.rs 85 native_path libc:: process host_mechanic crates/fbuild-daemon/tests/port_recovery.rs 85 native_path libc:: process host_mechanic @@ -240,49 +167,26 @@ crates/fbuild-deploy/Cargo.toml 47 target_dependency_table [target.'cfg(windows) crates/fbuild-deploy/Cargo.toml 50 native_dependency windows-sys device host_mechanic crates/fbuild-deploy/src/lpc.rs 27 attr_cfg #[cfg(target_os=)] device host_mechanic crates/fbuild-deploy/src/lpc.rs 31 attr_cfg #[cfg(not(target_os=))] device host_mechanic -crates/fbuild-deploy/src/lpc.rs 47 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/lpc.rs 103 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/lpc.rs 186 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/lpc.rs 875 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/lpc.rs 981 attr_cfg #[cfg(windows)] device host_mechanic -crates/fbuild-deploy/src/lpc.rs 996 attr_cfg #[cfg(not(windows))] device host_mechanic -crates/fbuild-deploy/src/lpc_debugger_reflash.rs 53 cfg_macro cfg!(target_os=) device host_mechanic -crates/fbuild-deploy/src/lpc_debugger_reflash.rs 55 cfg_macro cfg!(target_os=) device host_mechanic -crates/fbuild-deploy/src/lpc_debugger_reflash.rs 119 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/lpc_debugger_reflash.rs 298 attr_cfg #[cfg(target_os=)] device host_mechanic -crates/fbuild-deploy/src/lpc_debugger_reflash.rs 397 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs 81 compile_host_fact std::env::consts::ARCH device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs 81 compile_host_fact std::env::consts::OS device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs 132 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs 273 attr_cfg #[cfg(unix)] device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs 275 native_path std::os::unix::fs::PermissionsExt fs host_mechanic -crates/fbuild-deploy/src/probe_rs.rs 313 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs 519 attr_cfg #[cfg(windows)] device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs 670 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/probe_rs.rs 683 cfg_macro cfg!(windows) device host_mechanic +crates/fbuild-deploy/src/lpc.rs 972 attr_cfg #[cfg(windows)] device host_mechanic +crates/fbuild-deploy/src/lpc.rs 987 attr_cfg #[cfg(not(windows))] device host_mechanic +crates/fbuild-deploy/src/lpc_debugger_reflash.rs 294 attr_cfg #[cfg(target_os=)] device host_mechanic +crates/fbuild-deploy/src/probe_rs.rs 272 attr_cfg #[cfg(unix)] device host_mechanic +crates/fbuild-deploy/src/probe_rs.rs 274 native_path std::os::unix::fs::PermissionsExt fs host_mechanic +crates/fbuild-deploy/src/probe_rs.rs 514 attr_cfg #[cfg(windows)] device host_mechanic crates/fbuild-deploy/src/rp2040.rs 383 attr_cfg #[cfg(windows)] device host_mechanic crates/fbuild-deploy/src/rp2040.rs 387 attr_cfg #[cfg(not(windows))] device host_mechanic -crates/fbuild-deploy/src/rp2040.rs 638 cfg_macro cfg!(target_os=) device host_mechanic -crates/fbuild-deploy/src/rp2040.rs 642 cfg_macro cfg!(target_os=) device host_mechanic crates/fbuild-deploy/src/rp2040.rs 845 attr_cfg #[cfg(windows)] device host_mechanic crates/fbuild-deploy/src/rp2040.rs 847 native_path std::os::windows::io::AsRawHandle device host_mechanic crates/fbuild-deploy/src/rp2040.rs 848 native_path windows_sys:: device host_mechanic crates/fbuild-deploy/src/rp2040.rs 857 attr_cfg #[cfg(not(windows))] device host_mechanic crates/fbuild-deploy/src/rp2040.rs 1012 attr_cfg #[cfg(windows)] device host_mechanic crates/fbuild-deploy/src/rp2040.rs 1014 native_path std::os::windows::fs::OpenOptionsExt fs host_mechanic -crates/fbuild-deploy/src/rp2040.rs 1775 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/rp2040.rs 2003 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/rp2040.rs 2230 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/rp2040.rs 2249 cfg_macro cfg!(windows) device host_mechanic crates/fbuild-deploy/src/rp2040.rs 3789 attr_cfg #[cfg(windows)] device host_mechanic crates/fbuild-deploy/src/rp2040.rs 3792 native_path std::os::windows::fs::OpenOptionsExt fs host_mechanic crates/fbuild-deploy/src/rp2040_mount.rs 3 attr_cfg #[cfg(any(target_os=,test))] device host_mechanic crates/fbuild-deploy/src/rp2040_mount.rs 6 attr_cfg #[cfg(any(target_os=,test))] device host_mechanic crates/fbuild-deploy/src/rp2040_mount.rs 23 attr_cfg #[cfg(target_os=)] device host_mechanic crates/fbuild-deploy/src/rp2040_mount.rs 53 attr_cfg #[cfg(not(target_os=))] device host_mechanic -crates/fbuild-deploy/src/rp2040_picotool.rs 174 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/rp2040_picotool.rs 297 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/rp2040_picotool.rs 304 cfg_macro cfg!(windows) device host_mechanic crates/fbuild-deploy/src/rp2040_topology.rs 8 attr_cfg #[cfg(windows)] device host_mechanic crates/fbuild-deploy/src/rp2040_topology.rs 16 attr_cfg #[cfg(windows)] device host_mechanic crates/fbuild-deploy/src/rp2040_topology.rs 21 attr_cfg #[cfg(not(windows))] device host_mechanic @@ -295,35 +199,14 @@ crates/fbuild-deploy/src/rp2040_topology.rs 109 attr_cfg #[cfg(any(windows,test) crates/fbuild-deploy/src/rp2040_topology.rs 129 attr_cfg #[cfg(windows)] device host_mechanic crates/fbuild-deploy/src/rp2040_topology.rs 132 native_path std::os::windows::ffi::OsStrExt device host_mechanic crates/fbuild-deploy/src/rp2040_topology.rs 529 attr_cfg #[cfg(not(windows))] device host_mechanic -crates/fbuild-deploy/src/teensy/soft_reboot.rs 98 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/wchisp.rs 20 compile_host_fact std::env::consts::ARCH device host_mechanic -crates/fbuild-deploy/src/wchisp.rs 20 compile_host_fact std::env::consts::OS device host_mechanic -crates/fbuild-deploy/src/wchisp.rs 48 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/wchisp.rs 63 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/wchisp.rs 117 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/wchisp.rs 130 attr_cfg #[cfg(unix)] device host_mechanic -crates/fbuild-deploy/src/wchisp.rs 131 native_path std::os::unix::fs::PermissionsExt::from_mode fs host_mechanic -crates/fbuild-deploy/src/wchisp.rs 174 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/wlink.rs 25 compile_host_fact std::env::consts::ARCH device host_mechanic -crates/fbuild-deploy/src/wlink.rs 25 compile_host_fact std::env::consts::OS device host_mechanic -crates/fbuild-deploy/src/wlink.rs 45 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/wlink.rs 60 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/wlink.rs 111 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-deploy/src/wlink.rs 120 attr_cfg #[cfg(unix)] device host_mechanic -crates/fbuild-deploy/src/wlink.rs 121 native_path std::os::unix::fs::PermissionsExt::from_mode fs host_mechanic -crates/fbuild-deploy/src/wlink.rs 150 cfg_macro cfg!(windows) device host_mechanic +crates/fbuild-deploy/src/wchisp.rs 127 attr_cfg #[cfg(unix)] device host_mechanic +crates/fbuild-deploy/src/wchisp.rs 128 native_path std::os::unix::fs::PermissionsExt::from_mode fs host_mechanic +crates/fbuild-deploy/src/wlink.rs 125 attr_cfg #[cfg(unix)] device host_mechanic +crates/fbuild-deploy/src/wlink.rs 126 native_path std::os::unix::fs::PermissionsExt::from_mode fs host_mechanic crates/fbuild-library/src/library/esptool.rs 162 attr_cfg #[cfg(unix)] host_executable host_artifact_policy crates/fbuild-library/src/library/esptool.rs 164 native_path std::os::unix::fs::PermissionsExt fs host_mechanic -crates/fbuild-library/src/library/esptool.rs 281 compile_host_fact std::env::consts::ARCH host_executable host_artifact_policy -crates/fbuild-library/src/library/esptool.rs 281 compile_host_fact std::env::consts::OS host_executable host_artifact_policy -crates/fbuild-library/src/library/esptool.rs 299 compile_host_fact std::env::consts::OS host_executable host_artifact_policy -crates/fbuild-library/src/library/esptool.rs 300 compile_host_fact std::env::consts::ARCH host_executable host_artifact_policy -crates/fbuild-library/src/library/esptool.rs 307 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-library/src/library/esptool.rs 521 attr_cfg #[cfg(unix)] host_executable host_artifact_policy -crates/fbuild-library/src/library/esptool.rs 524 native_path std::os::unix::fs::PermissionsExt fs host_mechanic -crates/fbuild-library/src/library/library_compiler.rs 466 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-library/src/library/library_compiler.rs 655 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-library/src/library/library_spec.rs 72 cfg_macro cfg!(windows) host host_mechanic +crates/fbuild-library/src/library/esptool.rs 520 attr_cfg #[cfg(unix)] host_executable host_artifact_policy +crates/fbuild-library/src/library/esptool.rs 523 native_path std::os::unix::fs::PermissionsExt fs host_mechanic crates/fbuild-library/src/library/library_spec.rs 266 attr_cfg #[cfg(windows)] host host_mechanic crates/fbuild-packages-fetch/src/disk_cache/budget.rs 104 attr_cfg #[cfg(windows)] fs host_mechanic crates/fbuild-packages-fetch/src/disk_cache/budget.rs 108 attr_cfg #[cfg(unix)] fs host_mechanic @@ -333,35 +216,8 @@ crates/fbuild-packages-fetch/src/disk_cache/budget.rs 148 attr_cfg #[cfg(unix)] crates/fbuild-packages-fetch/src/disk_cache/index/pid.rs 5 attr_cfg #[cfg(unix)] fs host_mechanic crates/fbuild-packages-fetch/src/disk_cache/index/pid.rs 14 attr_cfg #[cfg(windows)] fs host_mechanic crates/fbuild-packages-fetch/src/disk_cache/index/pid.rs 31 attr_cfg #[cfg(not(any(unix,windows)))] fs host_mechanic -crates/fbuild-packages-fetch/src/install_lock.rs 239 cfg_macro cfg!(windows) fs host_mechanic -crates/fbuild-paths/src/lib.rs 93 attr_cfg #[cfg(windows)] host host_mechanic -crates/fbuild-paths/src/lib.rs 95 attr_cfg #[cfg(windows)] host host_mechanic -crates/fbuild-paths/src/lib.rs 98 attr_cfg #[cfg(not(windows))] host host_mechanic -crates/fbuild-paths/src/lib.rs 100 attr_cfg #[cfg(not(windows))] host host_mechanic -crates/fbuild-paths/src/lib.rs 450 attr_cfg #[cfg(target_os=)] host host_mechanic -crates/fbuild-paths/src/lib.rs 454 attr_cfg #[cfg(not(target_os=))] host host_mechanic -crates/fbuild-paths/src/lib.rs 529 attr_cfg #[cfg(not(windows))] host host_mechanic -crates/fbuild-paths/src/lib.rs 539 attr_cfg #[cfg(windows)] host host_mechanic -crates/fbuild-paths/src/lib.rs 559 attr_cfg #[cfg(windows)] host host_mechanic -crates/fbuild-paths/src/lib.rs 561 attr_cfg #[cfg(not(windows))] host host_mechanic -crates/fbuild-paths/src/running_process.rs 49 attr_cfg #[cfg(windows)] host host_mechanic -crates/fbuild-paths/src/running_process.rs 51 attr_cfg #[cfg(not(windows))] host host_mechanic -crates/fbuild-paths/src/running_process.rs 227 attr_cfg #[cfg(windows)] host host_mechanic -crates/fbuild-paths/src/running_process.rs 240 attr_cfg #[cfg(target_os=)] host host_mechanic -crates/fbuild-paths/src/running_process.rs 252 attr_cfg #[cfg(all(unix,not(target_os=)))] host host_mechanic -crates/fbuild-paths/src/running_process.rs 263 attr_cfg #[cfg(any(target_os=,all(unix,not(target_os=))))] host host_mechanic -crates/fbuild-paths/src/running_process.rs 322 attr_cfg #[cfg(all(unix,not(target_os=)))] host host_mechanic -crates/fbuild-python/src/daemon.rs 14 attr_cfg #[cfg(windows)] host host_mechanic -crates/fbuild-python/src/daemon.rs 16 attr_cfg #[cfg(not(windows))] host host_mechanic -crates/fbuild-python/src/daemon.rs 478 attr_cfg #[cfg(windows)] host host_mechanic -crates/fbuild-python/src/daemon.rs 480 attr_cfg #[cfg(not(windows))] host host_mechanic crates/fbuild-serial/Cargo.toml 32 target_dependency_table [target.'cfg(windows)'.dependencies] device host_mechanic crates/fbuild-serial/Cargo.toml 33 native_dependency windows-sys device host_mechanic -crates/fbuild-serial/src/boards.rs 947 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-serial/src/crash_decoder.rs 393 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-serial/src/crash_decoder.rs 765 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-serial/src/manager.rs 124 cfg_macro cfg!(windows) device host_mechanic -crates/fbuild-serial/src/manager.rs 752 cfg_macro cfg!(windows) device host_mechanic crates/fbuild-serial/src/port_class.rs 105 attr_cfg #[cfg(target_os=)] device host_mechanic crates/fbuild-serial/src/port_class.rs 109 attr_cfg #[cfg(target_os=)] device host_mechanic crates/fbuild-serial/src/port_class.rs 113 attr_cfg #[cfg(target_os=)] device host_mechanic @@ -402,104 +258,19 @@ crates/fbuild-serial/src/usb_recovery.rs 263 attr_cfg #[cfg(not(windows))] devic crates/fbuild-serial/src/usb_recovery.rs 278 attr_cfg #[cfg(windows)] device host_mechanic crates/fbuild-serial/src/usb_recovery.rs 282 native_path windows_sys:: device host_mechanic crates/fbuild-serial/src/usb_recovery.rs 288 native_path windows_sys:: device host_mechanic -crates/fbuild-toolchain/src/toolchain/arm.rs 197 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm.rs 199 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm.rs 201 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm.rs 242 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm.rs 270 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs 123 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs 128 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs 165 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/avr.rs 204 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/avr.rs 206 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/avr.rs 208 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/avr.rs 251 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/avr.rs 383 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs 109 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs 247 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs 349 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs 351 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs 359 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs 420 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/clang.rs 435 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32.rs 296 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32.rs 298 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32.rs 299 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32.rs 304 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32.rs 369 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32.rs 403 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs 41 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs 43 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs 44 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs 49 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp8266.rs 194 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp8266.rs 196 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp8266.rs 197 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp8266.rs 202 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp8266.rs 242 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp8266.rs 268 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 74 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 215 attr_cfg #[cfg(not(target_os=))] host_executable host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 221 attr_cfg #[cfg(target_os=)] host_executable host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 367 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 367 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 372 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 372 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 377 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 377 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 382 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 382 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 387 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 387 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 395 compile_host_fact std::env::consts::OS host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 396 compile_host_fact std::env::consts::ARCH host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 402 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 402 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 407 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 407 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 412 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 412 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 417 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 417 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 422 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 422 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 430 compile_host_fact std::env::consts::OS host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 431 compile_host_fact std::env::consts::ARCH host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 554 attr_cfg #[cfg(windows)] host_executable host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 568 attr_cfg #[cfg(windows)] host_executable host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 574 attr_cfg #[cfg(windows)] host_executable host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 605 attr_cfg #[cfg(not(windows))] host_executable host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 610 attr_cfg #[cfg(not(windows))] host_executable host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 615 attr_cfg #[cfg(windows)] host_executable host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 642 attr_cfg #[cfg(windows)] host_executable host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 759 attr_cfg #[cfg(windows)] host_executable host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 786 attr_cfg #[cfg(windows)] host_executable host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 879 cfg_macro cfg!(windows) fs host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 884 attr_cfg #[cfg(unix)] fs host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 886 native_path std::os::unix::fs::PermissionsExt fs host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 899 attr_cfg #[cfg(target_os=)] fs host_mechanic -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 902 native_path std::os::unix::fs::PermissionsExt fs host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 220 attr_cfg #[cfg(not(target_os=))] host_executable host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 226 attr_cfg #[cfg(target_os=)] host_executable host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 563 attr_cfg #[cfg(windows)] host_executable host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 577 attr_cfg #[cfg(windows)] host_executable host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 583 attr_cfg #[cfg(windows)] host_executable host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 614 attr_cfg #[cfg(not(windows))] host_executable host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 619 attr_cfg #[cfg(not(windows))] host_executable host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 624 attr_cfg #[cfg(windows)] host_executable host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 651 attr_cfg #[cfg(windows)] host_executable host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 779 attr_cfg #[cfg(windows)] host_executable host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 806 attr_cfg #[cfg(windows)] host_executable host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 904 attr_cfg #[cfg(unix)] fs host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 906 native_path std::os::unix::fs::PermissionsExt fs host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 919 attr_cfg #[cfg(target_os=)] fs host_mechanic +crates/fbuild-toolchain/src/toolchain/esp_qemu.rs 922 native_path std::os::unix::fs::PermissionsExt fs host_mechanic crates/fbuild-toolchain/src/toolchain/mod.rs 20 attr_cfg #[cfg(windows)] host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/riscv.rs 295 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/riscv.rs 297 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/riscv.rs 299 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/riscv.rs 343 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/riscv.rs 371 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs 154 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs 156 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs 157 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs 162 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs 187 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs 194 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs 196 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs 197 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs 202 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs 238 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs 264 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs 191 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs 193 cfg_macro cfg!(target_os=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs 195 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs 197 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs 199 cfg_macro cfg!(target_arch=) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs 235 cfg_macro cfg!(windows) host_executable host_artifact_policy -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs 264 cfg_macro cfg!(windows) host_executable host_artifact_policy diff --git a/ci/test_enforce_platform_boundary.py b/ci/test_enforce_platform_boundary.py index 22f2a745b..5fcc379ce 100644 --- a/ci/test_enforce_platform_boundary.py +++ b/ci/test_enforce_platform_boundary.py @@ -1,6 +1,7 @@ from __future__ import annotations import dataclasses +import re import unittest from ci import enforce_platform_boundary as boundary @@ -13,10 +14,76 @@ def setUpClass(cls) -> None: cls.observed = boundary.rows_from_findings(boundary.research.inventory()) def test_committed_exact_occurrence_ledger_matches_whole_tree(self) -> None: - self.assertEqual(len(self.expected), 504) + self.assertEqual(len(self.expected), 271) self.assertFalse(boundary.validate_ledger(self.expected)) self.assertFalse(boundary.compare(self.expected, self.observed)) + def test_private_platform_implementation_findings_are_not_baselined(self) -> None: + finding = boundary.research.Finding( + "crates/fbuild-core/src/platform/windows/example.rs", + 1, + "compile_host_fact", + "std::env::consts::ARCH", + "host", + "host_mechanic", + ) + + self.assertEqual(boundary.rows_from_findings([finding]), []) + + image_finding = boundary.research.Finding( + "crates/fbuild-core/src/platform/executable.rs", + 1, + "native_path", + "std::env::current_exe", + "host_executable", + "host_mechanic", + ) + self.assertEqual(boundary.rows_from_findings([image_finding]), []) + + unauthorized_facade_finding = dataclasses.replace( + image_finding, + kind="cfg_macro", + normalized='cfg!(windows)', + ) + self.assertEqual( + boundary.rows_from_findings([unauthorized_facade_finding]), + [ + boundary.LedgerRow( + unauthorized_facade_finding.path, + unauthorized_facade_finding.kind, + unauthorized_facade_finding.normalized, + 0, + unauthorized_facade_finding.capability, + unauthorized_facade_finding.classification, + ) + ], + ) + + def test_no_raw_host_fact_reads_remain_outside_the_boundary(self) -> None: + self.assertFalse( + [ + row + for row in self.expected + if row.kind in {"cfg_macro", "compile_host_fact"} + ] + ) + + def test_executable_spelling_does_not_bypass_the_executable_facade(self) -> None: + host_selected_exe = re.compile( + r"if\s+(?:fbuild_core|crate)::platform::host::is_windows\(\)" + r"\s*\{.{0,240}?\.exe", + re.DOTALL, + ) + bypasses = [] + for source in boundary.research.source_files(): + text = source.read_text(encoding="utf-8") + for match in host_selected_exe.finditer(text): + if "platform::executable" not in match.group(0): + bypasses.append( + f"{source.relative_to(boundary.ROOT).as_posix()}:{text.count(chr(10), 0, match.start()) + 1}" + ) + self.assertFalse(bypasses, bypasses) + def test_duplicate_and_non_contiguous_ordinal_are_rejected(self) -> None: malformed = [*self.expected, self.expected[0]] failures = boundary.validate_ledger(malformed) diff --git a/crates/fbuild-build-arm/src/generic_arm/arm_linker.rs b/crates/fbuild-build-arm/src/generic_arm/arm_linker.rs index a67abdd12..ebb86750a 100644 --- a/crates/fbuild-build-arm/src/generic_arm/arm_linker.rs +++ b/crates/fbuild-build-arm/src/generic_arm/arm_linker.rs @@ -178,7 +178,7 @@ impl Linker for ArmLinker { // FastLED/fbuild#809: bound the link step at 3 min — large // STM32 HAL builds are still well inside this budget. let link_timeout = Some(std::time::Duration::from_secs(180)); - let result = if cfg!(windows) && args.len() > 50 { + let result = if fbuild_core::platform::host::is_windows() && args.len() > 50 { let temp_dir = output_dir.join("tmp"); std::fs::create_dir_all(&temp_dir)?; // FastLED/fbuild#911 — path-shape slash normalization goes diff --git a/crates/fbuild-build-arm/src/teensy/teensy_linker.rs b/crates/fbuild-build-arm/src/teensy/teensy_linker.rs index 5342d770b..17b2d71f8 100644 --- a/crates/fbuild-build-arm/src/teensy/teensy_linker.rs +++ b/crates/fbuild-build-arm/src/teensy/teensy_linker.rs @@ -182,7 +182,7 @@ impl Linker for TeensyLinker { // FastLED/fbuild#809: bound the link step at 3 min — teensy41 // links comfortably under this budget. let link_timeout = Some(std::time::Duration::from_secs(180)); - let result = if cfg!(windows) && args.len() > 50 { + let result = if fbuild_core::platform::host::is_windows() && args.len() > 50 { let temp_dir = output_dir.join("tmp"); std::fs::create_dir_all(&temp_dir)?; // FastLED/fbuild#911 — path-shape slash normalization goes @@ -275,7 +275,7 @@ mod tests { /// be absolute. #[test] fn link_runs_in_absolute_output_dir_not_inherited_cwd() { - let (out, core_dir) = if cfg!(windows) { + let (out, core_dir) = if fbuild_core::platform::host::is_windows() { ("C:\\proj\\.fbuild\\build\\release", "C:\\pkgs\\teensy4") } else { ("/proj/.fbuild/build/release", "/pkgs/teensy4") diff --git a/crates/fbuild-build-engine/src/compiler_tests.rs b/crates/fbuild-build-engine/src/compiler_tests.rs index 5d8904886..1c5c1be43 100644 --- a/crates/fbuild-build-engine/src/compiler_tests.rs +++ b/crates/fbuild-build-engine/src/compiler_tests.rs @@ -59,7 +59,7 @@ async fn compile_path_contract_pairs_cwd_and_output_arg_for_282() { #[test] fn absolute_from_cwd_is_identity_on_absolute_paths() { - let p = if cfg!(windows) { + let p = if fbuild_core::platform::host::is_windows() { std::path::PathBuf::from(r"C:\some\absolute\path") } else { std::path::PathBuf::from("/some/absolute/path") diff --git a/crates/fbuild-build-engine/src/linker.rs b/crates/fbuild-build-engine/src/linker.rs index 95365ce4f..9f303d1ff 100644 --- a/crates/fbuild-build-engine/src/linker.rs +++ b/crates/fbuild-build-engine/src/linker.rs @@ -593,7 +593,7 @@ mod tests { /// Absolute path for the running platform (`/x` is *not* absolute on /// Windows — it has a root but no drive prefix). fn abs(tail: &str) -> PathBuf { - if cfg!(windows) { + if fbuild_core::platform::host::is_windows() { PathBuf::from(format!("C:\\{}", tail.replace('/', "\\"))) } else { PathBuf::from(format!("/{tail}")) diff --git a/crates/fbuild-build-engine/src/script_runtime.rs b/crates/fbuild-build-engine/src/script_runtime.rs index 4cf13bd1b..e712b5f4d 100644 --- a/crates/fbuild-build-engine/src/script_runtime.rs +++ b/crates/fbuild-build-engine/src/script_runtime.rs @@ -323,7 +323,7 @@ pub async fn find_python() -> Option> { /// the daemon's spawn-time PATH (FastLED/fbuild#1219). The caller PATH /// *replaces* the inherited one for the probe; `None` = legacy behavior. pub async fn find_python_with_path(caller_path: Option<&str>) -> Option> { - let candidates: &[&[&str]] = if cfg!(windows) { + let candidates: &[&[&str]] = if fbuild_core::platform::host::is_windows() { &[&["python"], &["py", "-3"]] } else { &[&["python3"], &["python"]] diff --git a/crates/fbuild-build-engine/src/source_scanner.rs b/crates/fbuild-build-engine/src/source_scanner.rs index 4b77f761b..ebb6e803f 100644 --- a/crates/fbuild-build-engine/src/source_scanner.rs +++ b/crates/fbuild-build-engine/src/source_scanner.rs @@ -40,7 +40,7 @@ use walkdir::WalkDir; fn normalize_glob_separators(pattern: &str) -> String { // Glob-pattern normalization is INTENTIONALLY unconditional // (unlike `NormalizedPath::display_slash()` which gates on - // `cfg!(windows)`) — glob patterns come from `platformio.ini` and + // `fbuild_core::platform::host::is_windows()`) — glob patterns come from `platformio.ini` and // may contain a mix of `\` and `/` regardless of host OS. pattern.replace('\\', "/") } diff --git a/crates/fbuild-build-esp/src/esp32/esp32_compiler.rs b/crates/fbuild-build-esp/src/esp32/esp32_compiler.rs index 6e03bddba..dff90267c 100644 --- a/crates/fbuild-build-esp/src/esp32/esp32_compiler.rs +++ b/crates/fbuild-build-esp/src/esp32/esp32_compiler.rs @@ -61,7 +61,7 @@ impl Esp32Compiler { verbose, // On MSYS2/Git Bash, std::env::temp_dir() returns "/tmp/" which // native Windows GCC treats as "C:\tmp\". Use LOCALAPPDATA\Temp. - if cfg!(windows) { + if fbuild_core::platform::host::is_windows() { std::env::var("LOCALAPPDATA") .map(|la| PathBuf::from(la).join("Temp")) .unwrap_or_else(|_| std::env::temp_dir()) diff --git a/crates/fbuild-build-esp/src/esp32/esp32_linker.rs b/crates/fbuild-build-esp/src/esp32/esp32_linker.rs index 1d30c7460..8979fa99d 100644 --- a/crates/fbuild-build-esp/src/esp32/esp32_linker.rs +++ b/crates/fbuild-build-esp/src/esp32/esp32_linker.rs @@ -443,7 +443,7 @@ impl Linker for Esp32Linker { // link step in the codebase (LTO + large SDK archive). 5 min // is a generous upper bound — anything past that is a wedge. let link_timeout = Some(std::time::Duration::from_secs(300)); - let result = if cfg!(windows) { + let result = if fbuild_core::platform::host::is_windows() { let flags_for_rsp: Vec = link_args[1..].to_vec(); let rsp_dir = output_dir.join("tmp"); let rsp_path = fbuild_core::response_file::write_response_file( diff --git a/crates/fbuild-build/tests/cache_survives_tar_extract.rs b/crates/fbuild-build/tests/cache_survives_tar_extract.rs index 3369c3d6b..0e654d6c4 100644 --- a/crates/fbuild-build/tests/cache_survives_tar_extract.rs +++ b/crates/fbuild-build/tests/cache_survives_tar_extract.rs @@ -161,9 +161,9 @@ fn compiler_signature_survives_toolchain_path_change() { let toolchain_a = TempDir::new().unwrap(); let toolchain_b = TempDir::new().unwrap(); - let compiler_filename = if cfg!(windows) { "gcc.exe" } else { "gcc" }; - let path_a: PathBuf = toolchain_a.path().join(compiler_filename); - let path_b: PathBuf = toolchain_b.path().join(compiler_filename); + let compiler_filename = fbuild_core::platform::executable::native_name("gcc"); + let path_a: PathBuf = toolchain_a.path().join(&compiler_filename); + let path_b: PathBuf = toolchain_b.path().join(&compiler_filename); assert_ne!( path_a, path_b, "test setup invariant: the two compiler paths must differ as absolute path strings" @@ -183,7 +183,7 @@ fn compiler_signature_survives_toolchain_path_change() { See crates/fbuild-build/src/compiler.rs::compiler_identity." ); - let alt_filename = if cfg!(windows) { "clang.exe" } else { "clang" }; + let alt_filename = fbuild_core::platform::executable::native_name("clang"); let path_c = toolchain_a.path().join(alt_filename); let sig_c = build_rebuild_signature(&path_c, &flags, &pre_flags, &extra_flags, &build_unflags); assert_ne!( diff --git a/crates/fbuild-build/tests/clangd_check_parity.rs b/crates/fbuild-build/tests/clangd_check_parity.rs index d684e5642..179482aa1 100644 --- a/crates/fbuild-build/tests/clangd_check_parity.rs +++ b/crates/fbuild-build/tests/clangd_check_parity.rs @@ -88,13 +88,9 @@ fn uno_project_dir() -> PathBuf { /// `ClangComponentKind`'s variants. fn find_clangd_on_path() -> Option { let path_var = std::env::var_os("PATH")?; - let exe_name = if cfg!(windows) { - "clangd.exe" - } else { - "clangd" - }; + let exe_name = fbuild_core::platform::executable::native_name("clangd"); std::env::split_paths(&path_var) - .map(|dir| dir.join(exe_name)) + .map(|dir| dir.join(&exe_name)) .find(|candidate| candidate.is_file()) } diff --git a/crates/fbuild-build/tests/flag_escaping_lint.rs b/crates/fbuild-build/tests/flag_escaping_lint.rs index f4dd9dfd6..ee7a96f80 100644 --- a/crates/fbuild-build/tests/flag_escaping_lint.rs +++ b/crates/fbuild-build/tests/flag_escaping_lint.rs @@ -38,7 +38,7 @@ fn collect_rs_files(dir: &Path) -> Vec { /// Check that a compiler file that has a non-Windows `run_command` path /// also calls `prepare_flags_for_exec` in that path. /// -/// Heuristic: if a file contains both `run_command` and `cfg!(windows)` (the +/// Heuristic: if a file contains both `run_command` and `fbuild_core::platform::host::is_windows()` (the /// response-file branch pattern), it MUST also contain `prepare_flags_for_exec`. #[test] fn compiler_backends_must_sanitize_flags_for_exec() { @@ -63,7 +63,7 @@ fn compiler_backends_must_sanitize_flags_for_exec() { let has_run_command = content.contains("run_command"); let has_response_file = content.contains("write_response_file") || content.contains("@response"); - let has_cfg_windows = content.contains("cfg!(windows)"); + let has_cfg_windows = content.contains("fbuild_core::platform::host::is_windows()"); // Linker files use response files for link flags (not -D defines), // so they don't need prepare_flags_for_exec. @@ -96,7 +96,7 @@ fn compiler_backends_must_sanitize_flags_for_exec() { to strip backslash-escaped quotes from -D define flags.\n\n\ Violations:\n{}\n\n\ Fix: add `crate::compiler::prepare_flags_for_exec(all_flags)` in the else \ - branch of `cfg!(windows)`.", + branch of `fbuild_core::platform::host::is_windows()`.", violations.join("\n") ); } diff --git a/crates/fbuild-build/tests/lite_scons_acceptance.rs b/crates/fbuild-build/tests/lite_scons_acceptance.rs index f2e4801ee..49595607b 100644 --- a/crates/fbuild-build/tests/lite_scons_acceptance.rs +++ b/crates/fbuild-build/tests/lite_scons_acceptance.rs @@ -38,7 +38,7 @@ use fbuild_build::script_runtime::resolve_extra_script_overlay; fn python_available() -> bool { use std::time::{Duration, Instant}; - let probes: &[&[&str]] = if cfg!(windows) { + let probes: &[&[&str]] = if fbuild_core::platform::host::is_windows() { &[&["python", "--version"], &["py", "-3", "--version"]] } else { &[&["python3", "--version"], &["python", "--version"]] diff --git a/crates/fbuild-build/tests/zccache_embedded_smoke.rs b/crates/fbuild-build/tests/zccache_embedded_smoke.rs index 56ceb934a..563cbd31e 100644 --- a/crates/fbuild-build/tests/zccache_embedded_smoke.rs +++ b/crates/fbuild-build/tests/zccache_embedded_smoke.rs @@ -18,21 +18,25 @@ fn find_c_compiler() -> NormalizedPath { .find(|candidate| candidate.is_file()) .map(NormalizedPath::from) }; - if cfg!(windows) { - if let Some(candidate) = on_path("clang.exe") { - return candidate; + if fbuild_core::platform::host::is_windows() { + for name in fbuild_core::platform::executable::path_candidate_names("clang") { + if let Some(candidate) = on_path(&name) { + return candidate; + } } if let Some(program_files) = std::env::var_os("ProgramFiles") { let candidate = NormalizedPath::new(std::path::Path::new(&program_files)) .join("LLVM") .join("bin") - .join("clang.exe"); + .join(fbuild_core::platform::executable::native_name("clang")); if candidate.is_file() { return candidate; } } - if let Some(candidate) = on_path("gcc.exe") { - return candidate; + for name in fbuild_core::platform::executable::path_candidate_names("gcc") { + if let Some(candidate) = on_path(&name) { + return candidate; + } } panic!("clang.exe or gcc.exe must be installed for this smoke test"); } @@ -89,11 +93,13 @@ async fn embedded_compilation_cold_miss_then_warm_hit() { let tmp = tempfile::TempDir::new().expect("tempdir"); let cache_root = tmp.path().join("zccache"); let source = tmp.path().join("smoke.c"); - let object = tmp.path().join(if cfg!(windows) { - "smoke.obj" - } else { - "smoke.o" - }); + let object = tmp + .path() + .join(if fbuild_core::platform::host::is_windows() { + "smoke.obj" + } else { + "smoke.o" + }); std::fs::write(&source, "int smoke(void) { return 42; }\n").expect("write source"); let svc = FbuildZccacheService::start_in(cache_root) diff --git a/crates/fbuild-cli/src/cli/build.rs b/crates/fbuild-cli/src/cli/build.rs index b56d1b97b..06062895c 100644 --- a/crates/fbuild-cli/src/cli/build.rs +++ b/crates/fbuild-cli/src/cli/build.rs @@ -4,9 +4,9 @@ use crate::daemon_client::{self, BuildRequest, DaemonClient}; use crate::output; pub async fn open_in_browser(url: &str) -> fbuild_core::Result<()> { - let args: Vec<&str> = if cfg!(target_os = "windows") { + let args: Vec<&str> = if fbuild_core::platform::host::is_windows() { vec!["cmd", "/c", "start", "", url] - } else if cfg!(target_os = "macos") { + } else if fbuild_core::platform::host::is_macos() { vec!["open", url] } else { vec!["xdg-open", url] @@ -159,7 +159,7 @@ pub async fn run_build( /// Convert MSYS/Git-Bash paths (/c/Users/...) to native Windows paths and canonicalize. pub async fn normalize_path(path: &str) -> fbuild_core::Result { - let converted = if cfg!(windows) { + let converted = if fbuild_core::platform::host::is_windows() { // /c/foo → C:\foo let bytes = path.as_bytes(); if bytes.len() >= 3 diff --git a/crates/fbuild-cli/src/cli/compile_many.rs b/crates/fbuild-cli/src/cli/compile_many.rs index 713500343..ad52b36ad 100644 --- a/crates/fbuild-cli/src/cli/compile_many.rs +++ b/crates/fbuild-cli/src/cli/compile_many.rs @@ -8,7 +8,7 @@ use crate::output; /// PlatformIO follows `PATH`-style conventions: ';' on Windows, ':' elsewhere. /// Centralized here so the CLI handler and the unit tests agree. pub fn ci_lib_extra_dirs_sep() -> &'static str { - if cfg!(windows) { ";" } else { ":" } + fbuild_core::platform::host::path_list_separator_str() } /// Map a single `pio ci` positional argument to a project directory. diff --git a/crates/fbuild-cli/src/cli/daemon_cmd.rs b/crates/fbuild-cli/src/cli/daemon_cmd.rs index cb89ace62..61f9f64a7 100644 --- a/crates/fbuild-cli/src/cli/daemon_cmd.rs +++ b/crates/fbuild-cli/src/cli/daemon_cmd.rs @@ -306,13 +306,10 @@ fn run_daemon_running_process(json: bool) -> fbuild_core::Result<()> { } fn daemon_executable_candidate() -> std::path::PathBuf { - let Some(parent) = std::env::current_exe() - .ok() - .and_then(|p| p.parent().map(|d| d.to_path_buf())) - else { - return std::path::PathBuf::from(fbuild_paths::running_process::DAEMON_BINARY_NAME); - }; - parent.join(fbuild_paths::running_process::DAEMON_BINARY_NAME) + fbuild_core::platform::executable::current_image_sibling( + fbuild_paths::running_process::DAEMON_BINARY_NAME, + ) + .unwrap_or_else(|_| std::path::PathBuf::from(fbuild_paths::running_process::DAEMON_BINARY_NAME)) } pub async fn run_daemon_list(client: &DaemonClient) -> fbuild_core::Result<()> { @@ -696,7 +693,7 @@ pub async fn run_daemon_kill_all(force: bool) -> fbuild_core::Result<()> { pub async fn kill_process(pid: u32, force: bool) -> fbuild_core::Result<()> { let pid_str = pid.to_string(); - let argv: Vec<&str> = if cfg!(windows) { + let argv: Vec<&str> = if fbuild_core::platform::host::is_windows() { if force { vec!["taskkill", "/F", "/PID", &pid_str] } else { @@ -731,17 +728,14 @@ pub async fn kill_process(pid: u32, force: bool) -> fbuild_core::Result<()> { } pub async fn find_daemon_pids() -> fbuild_core::Result> { - if cfg!(windows) { + if fbuild_core::platform::host::is_windows() { // FastLED/fbuild#810: cap tasklist at 10s. + let image_filter = format!( + "IMAGENAME eq {}", + fbuild_core::platform::executable::native_name("fbuild-daemon") + ); let output = fbuild_core::subprocess::run_command( - &[ - "tasklist", - "/FI", - "IMAGENAME eq fbuild-daemon.exe", - "/FO", - "CSV", - "/NH", - ], + &["tasklist", "/FI", &image_filter, "/FO", "CSV", "/NH"], None, None, Some(std::time::Duration::from_secs(10)), diff --git a/crates/fbuild-cli/src/cli/debug.rs b/crates/fbuild-cli/src/cli/debug.rs index e3bd7c596..8f2735485 100644 --- a/crates/fbuild-cli/src/cli/debug.rs +++ b/crates/fbuild-cli/src/cli/debug.rs @@ -247,11 +247,7 @@ pub(crate) fn gdb_candidate_names(toolchain_prefix: &str) -> Vec { } fn exe_name(name: &str) -> String { - if cfg!(windows) { - format!("{name}.exe") - } else { - name.to_string() - } + fbuild_core::platform::executable::native_name(name) } /// Search a list of directories (in order) for the first existing @@ -328,7 +324,10 @@ fn resolve_gdb_path(elf_path: &Path, toolchain_prefix: &str) -> Result String { - if cfg!(windows) && !port.starts_with(r"\\.\") && !port.contains('/') { + if fbuild_core::platform::host::is_windows() + && !port.starts_with(r"\\.\") + && !port.contains('/') + { format!(r"\\.\{port}") } else { port.to_string() diff --git a/crates/fbuild-cli/src/cli/deploy.rs b/crates/fbuild-cli/src/cli/deploy.rs index 61ffe5a13..fca7dafd4 100644 --- a/crates/fbuild-cli/src/cli/deploy.rs +++ b/crates/fbuild-cli/src/cli/deploy.rs @@ -287,7 +287,7 @@ async fn maybe_recover_and_retry( .unwrap_or_default() )); let context = usb_recovery::RecoveryLaunchContext { - is_windows: cfg!(windows), + is_windows: fbuild_core::platform::host::is_windows(), is_ci: std::env::var_os("CI").is_some(), is_interactive: std::io::IsTerminal::is_terminal(&std::io::stdin()), }; diff --git a/crates/fbuild-cli/src/cli/ide.rs b/crates/fbuild-cli/src/cli/ide.rs index 527e27dfc..a8ceb7f3a 100644 --- a/crates/fbuild-cli/src/cli/ide.rs +++ b/crates/fbuild-cli/src/cli/ide.rs @@ -255,13 +255,13 @@ fn emit_zed_tasks( /// testable; callers are responsible for checking `.exists()`. fn known_zed_install_candidates() -> Vec { let mut candidates = Vec::new(); - if cfg!(windows) { + if fbuild_core::platform::host::is_windows() { if let Some(local_appdata) = std::env::var_os("LOCALAPPDATA") { let base = NormalizedPath::new(local_appdata); - candidates.push(base.join("Programs").join("Zed").join("zed.exe")); - candidates.push(base.join("Zed").join("zed.exe")); + candidates.push(base.join("Programs").join("Zed").join(zed_exe_name())); + candidates.push(base.join("Zed").join(zed_exe_name())); } - } else if cfg!(target_os = "macos") { + } else if fbuild_core::platform::host::is_macos() { candidates.push(NormalizedPath::new( "/Applications/Zed.app/Contents/MacOS/cli", )); @@ -272,16 +272,16 @@ fn known_zed_install_candidates() -> Vec { NormalizedPath::new(home) .join(".local") .join("bin") - .join("zed"), + .join(zed_exe_name()), ); } - candidates.push(NormalizedPath::new("/usr/bin/zed")); + candidates.push(NormalizedPath::new("/usr/bin").join(zed_exe_name())); } candidates } fn zed_exe_name() -> &'static str { - if cfg!(windows) { "zed.exe" } else { "zed" } + fbuild_core::platform::executable::name("zed", "zed.exe") } /// Find `zed` on PATH first, then fall back to known install locations. @@ -841,11 +841,12 @@ mod tests { // happen in `find_zed_executable`, which we deliberately don't // test here (must not launch/require zed in CI). let candidates = known_zed_install_candidates(); - if cfg!(windows) { + if fbuild_core::platform::host::is_windows() { + let executable = fbuild_core::platform::executable::name("zed", "zed.exe"); assert!( candidates .iter() - .all(|p| p.to_string_lossy().ends_with("zed.exe")) + .all(|p| p.to_string_lossy().ends_with(executable)) ); } else { // Case-insensitive: the macOS candidate is @@ -862,10 +863,9 @@ mod tests { #[test] fn zed_exe_name_matches_platform() { let name = zed_exe_name(); - if cfg!(windows) { - assert_eq!(name, "zed.exe"); - } else { - assert_eq!(name, "zed"); - } + assert_eq!( + name, + fbuild_core::platform::executable::name("zed", "zed.exe") + ); } } diff --git a/crates/fbuild-cli/src/cli/pio.rs b/crates/fbuild-cli/src/cli/pio.rs index 09b09a3ae..752c4d213 100644 --- a/crates/fbuild-cli/src/cli/pio.rs +++ b/crates/fbuild-cli/src/cli/pio.rs @@ -8,7 +8,7 @@ pub async fn find_pio() -> fbuild_core::Result { // Check PATH. FastLED/fbuild#810: cap `where` / `which` at 5s; they should // return instantly, but we don't want a wedged invocation to hang fbuild. - let locator = if cfg!(windows) { "where" } else { "which" }; + let locator = fbuild_core::platform::executable::name("which", "where"); if let Ok(output) = fbuild_core::subprocess::run_command( &[locator, "pio"], None, @@ -33,15 +33,13 @@ pub async fn find_pio() -> fbuild_core::Result { // Check fbuild cache (PlatformIO installed via iso_env) let cache = fbuild_paths::get_cache_root().join("platform"); - let candidates = if cfg!(windows) { - vec![ - cache.join("Scripts").join("pio.exe"), - cache.join("Scripts").join("pio"), - ] + let binary_dir = if fbuild_core::platform::host::is_windows() { + cache.join("Scripts") } else { - vec![cache.join("bin").join("pio")] + cache.join("bin") }; - for c in candidates { + for name in fbuild_core::platform::executable::path_candidate_names("pio") { + let c = binary_dir.join(name); if c.exists() { return Ok(c); } diff --git a/crates/fbuild-cli/src/cli/port_doctor.rs b/crates/fbuild-cli/src/cli/port_doctor.rs index 26b3fd2b6..579eed10b 100644 --- a/crates/fbuild-cli/src/cli/port_doctor.rs +++ b/crates/fbuild-cli/src/cli/port_doctor.rs @@ -496,7 +496,7 @@ pub fn run(only_port: Option<&str>, only_hub: Option<&str>, json: bool) -> Resul /// /// Read-only and best-effort; an empty result simply omits the per-port line. fn query_device_power_rows() -> Vec<(String, bool)> { - if !cfg!(windows) { + if !fbuild_core::platform::host::is_windows() { return Vec::new(); } let script = "Get-CimInstance -Namespace root\\wmi -ClassName MSPower_DeviceEnable \ @@ -533,7 +533,7 @@ fn query_device_power_rows() -> Vec<(String, bool)> { /// registry copy needs elevation. The CIM provider behind /// `Get-PnpDeviceProperty` answers unelevated for phantoms. fn query_last_seen_secs(instance_id: &str) -> Option { - if !cfg!(windows) { + if !fbuild_core::platform::host::is_windows() { return None; } let script = format!( @@ -560,7 +560,7 @@ fn query_last_seen_secs(instance_id: &str) -> Option { } pub(crate) fn query_selective_suspend() -> Option { - if !cfg!(windows) { + if !fbuild_core::platform::host::is_windows() { return None; } let out = fbuild_core::subprocess::run_command_blocking( diff --git a/crates/fbuild-cli/src/cli/port_doctor_fix.rs b/crates/fbuild-cli/src/cli/port_doctor_fix.rs index eb2d4dd2f..5a7b34ef7 100644 --- a/crates/fbuild-cli/src/cli/port_doctor_fix.rs +++ b/crates/fbuild-cli/src/cli/port_doctor_fix.rs @@ -64,7 +64,7 @@ pub fn run_fix(dry_run: bool, assume_yes: bool, no_elevate: bool) -> Result<()> if already_disabled || dry_run { return Ok(()); } - if !cfg!(windows) { + if !fbuild_core::platform::host::is_windows() { crate::output::result("not applicable on this platform"); return Ok(()); } diff --git a/crates/fbuild-cli/src/cli/symbols_cmd.rs b/crates/fbuild-cli/src/cli/symbols_cmd.rs index ef4a74c10..f34ebf127 100644 --- a/crates/fbuild-cli/src/cli/symbols_cmd.rs +++ b/crates/fbuild-cli/src/cli/symbols_cmd.rs @@ -213,10 +213,10 @@ fn resolve_elf(input: &Path) -> Result { /// Locate `nm` on PATH. The user can always override with `--nm`. fn find_nm_on_path() -> Result { - let exe_name = if cfg!(windows) { "nm.exe" } else { "nm" }; + let exe_name = fbuild_core::platform::executable::native_name("nm"); let path = std::env::var_os("PATH").ok_or_else(|| FbuildError::Other("PATH not set".into()))?; for dir in std::env::split_paths(&path) { - let candidate = dir.join(exe_name); + let candidate = dir.join(&exe_name); if candidate.exists() { return Ok(candidate); } diff --git a/crates/fbuild-cli/src/cli/tests.rs b/crates/fbuild-cli/src/cli/tests.rs index 992c4c27a..b178abf82 100644 --- a/crates/fbuild-cli/src/cli/tests.rs +++ b/crates/fbuild-cli/src/cli/tests.rs @@ -245,7 +245,11 @@ fn normalize_batch_preserves_order() { async fn build_pio_env_joins_libs_with_platform_separator() { let libs = vec!["a".to_string(), "b".to_string()]; let env = build_ci_pio_env(&libs, None).await; - let expected = if cfg!(windows) { "a;b" } else { "a:b" }; + let expected = if fbuild_core::platform::host::is_windows() { + "a;b" + } else { + "a:b" + }; assert_eq!( env.get("PLATFORMIO_LIB_EXTRA_DIRS").map(String::as_str), Some(expected) diff --git a/crates/fbuild-cli/src/cli/usb_recovery.rs b/crates/fbuild-cli/src/cli/usb_recovery.rs index 2197aa16e..56eb766d6 100644 --- a/crates/fbuild-cli/src/cli/usb_recovery.rs +++ b/crates/fbuild-cli/src/cli/usb_recovery.rs @@ -272,7 +272,7 @@ impl RecoveryHelperLauncher for WindowsUacLauncher { Ok(format!("\"{value}\"")) } - let executable = std::env::current_exe().map_err(|error| { + let executable = fbuild_core::platform::executable::current_image().map_err(|error| { fbuild_core::FbuildError::Other(format!( "cannot locate current fbuild executable: {error}" )) diff --git a/crates/fbuild-cli/src/daemon_client.rs b/crates/fbuild-cli/src/daemon_client.rs index 07903721f..b0f4cb2ab 100644 --- a/crates/fbuild-cli/src/daemon_client.rs +++ b/crates/fbuild-cli/src/daemon_client.rs @@ -86,7 +86,7 @@ pub fn capture_pio_env() -> BTreeMap { } pub fn runtime_diagnostic() -> String { - let exe = std::env::current_exe() + let exe = fbuild_core::platform::executable::current_image() .ok() .map(|p| p.display().to_string()) .unwrap_or_else(|| "".to_string()); @@ -185,14 +185,12 @@ pub fn last_daemon_acquisition() -> Option { } fn daemon_executable_hint() -> String { - let Some(parent) = std::env::current_exe() - .ok() - .and_then(|p| p.parent().map(|d| d.to_path_buf())) + let Ok(candidates) = + fbuild_core::platform::executable::current_image_sibling_candidates("fbuild-daemon") else { return "fbuild-daemon".to_string(); }; - let stem = parent.join("fbuild-daemon"); - for candidate in [stem.clone(), stem.with_extension("exe")] { + for candidate in candidates { if candidate.exists() { return candidate.display().to_string(); } @@ -676,7 +674,7 @@ fn shutdown_caller_headers() -> reqwest::header::HeaderMap { cwd.to_string_lossy().into_owned(), ); } - if let Ok(exe) = std::env::current_exe() { + if let Ok(exe) = fbuild_core::platform::executable::current_image() { insert_shutdown_header( &mut headers, "x-fbuild-client-exe", @@ -703,14 +701,10 @@ fn insert_shutdown_header( /// Compute the modification time of the fbuild-daemon binary on disk. fn compute_daemon_binary_mtime() -> f64 { - // Find the daemon binary next to our own executable - let daemon_path = std::env::current_exe() - .ok() - .and_then(|p| p.parent().map(|d| d.join("fbuild-daemon"))); - - if let Some(path) = daemon_path { - // Try with and without .exe extension - for candidate in [path.clone(), path.with_extension("exe")] { + if let Ok(candidates) = + fbuild_core::platform::executable::current_image_sibling_candidates("fbuild-daemon") + { + for candidate in candidates { if let Ok(meta) = candidate.metadata() { if let Ok(mtime) = meta.modified() { if let Ok(dur) = mtime.duration_since(std::time::UNIX_EPOCH) { diff --git a/crates/fbuild-cli/src/daemon_client/identity.rs b/crates/fbuild-cli/src/daemon_client/identity.rs index 9d34fb2d2..6fe7c509e 100644 --- a/crates/fbuild-cli/src/daemon_client/identity.rs +++ b/crates/fbuild-cli/src/daemon_client/identity.rs @@ -116,7 +116,7 @@ fn identity_path(path: &str) -> String { while normalized.ends_with('/') && normalized.len() > 1 { normalized.pop(); } - if cfg!(windows) { + if fbuild_core::platform::host::is_windows() { normalized.to_ascii_lowercase() } else { normalized diff --git a/crates/fbuild-cli/src/update_check.rs b/crates/fbuild-cli/src/update_check.rs index a7e3d92f7..dd3c18515 100644 --- a/crates/fbuild-cli/src/update_check.rs +++ b/crates/fbuild-cli/src/update_check.rs @@ -285,7 +285,7 @@ pub fn classify_install_source() -> InstallSource { } } - let Ok(exe) = std::env::current_exe() else { + let Ok(exe) = fbuild_core::platform::executable::current_image() else { return InstallSource::Unknown; }; diff --git a/crates/fbuild-cli/tests/daemon_crash_recovery.rs b/crates/fbuild-cli/tests/daemon_crash_recovery.rs index 1141ca1fe..8138bd382 100644 --- a/crates/fbuild-cli/tests/daemon_crash_recovery.rs +++ b/crates/fbuild-cli/tests/daemon_crash_recovery.rs @@ -32,7 +32,11 @@ use fbuild_paths::daemon_ownership::{DAEMON_EXE_STEM, RootOwnershipGuard}; /// The real user home, the same way the spawned daemon will resolve it. fn real_home() -> Option { - let key = if cfg!(windows) { "USERPROFILE" } else { "HOME" }; + let key = if fbuild_core::platform::host::is_windows() { + "USERPROFILE" + } else { + "HOME" + }; std::env::var_os(key).map(NormalizedPath::new) } @@ -170,11 +174,7 @@ fn client_recovers_after_daemon_is_killed_uncleanly() { // the CLI. Under `cargo test --workspace` (and any full build) it exists; // under an isolated `-p fbuild-cli` test run it may not — skip then. let cli = NormalizedPath::new(env!("CARGO_BIN_EXE_fbuild")); - let daemon_name = if cfg!(windows) { - "fbuild-daemon.exe" - } else { - "fbuild-daemon" - }; + let daemon_name = fbuild_core::platform::executable::name("fbuild-daemon", "fbuild-daemon.exe"); let sibling = cli .parent() .map(|d| NormalizedPath::new(d).join(daemon_name)); diff --git a/crates/fbuild-config/src/ini_parser/tests.rs b/crates/fbuild-config/src/ini_parser/tests.rs index efa8b1ba9..ea9d36c2c 100644 --- a/crates/fbuild-config/src/ini_parser/tests.rs +++ b/crates/fbuild-config/src/ini_parser/tests.rs @@ -315,7 +315,11 @@ framework = arduino lib_extra_dirs = ignored ", ); - let sep = if cfg!(windows) { ";" } else { ":" }; + let sep = if fbuild_core::platform::host::is_windows() { + ";" + } else { + ":" + }; let overrides = crate::pio_env::PioEnvOverrides::from_map( [( "PLATFORMIO_LIB_EXTRA_DIRS".to_string(), diff --git a/crates/fbuild-config/src/ini_parser/values.rs b/crates/fbuild-config/src/ini_parser/values.rs index 5c9f5c8ee..c4a3efd39 100644 --- a/crates/fbuild-config/src/ini_parser/values.rs +++ b/crates/fbuild-config/src/ini_parser/values.rs @@ -107,7 +107,7 @@ pub(super) fn parse_lib_deps(deps_str: &str) -> Vec { /// Parse a `PATH`-style list of paths from `PLATFORMIO_LIB_EXTRA_DIRS`. pub(super) fn parse_path_list(paths_str: &str) -> Vec { - let separator = if cfg!(windows) { ';' } else { ':' }; + let separator = fbuild_core::platform::host::path_list_separator(); let mut result = Vec::new(); for line in paths_str.lines() { diff --git a/crates/fbuild-core/src/containment.rs b/crates/fbuild-core/src/containment.rs index 74c51da4a..0630506b3 100644 --- a/crates/fbuild-core/src/containment.rs +++ b/crates/fbuild-core/src/containment.rs @@ -468,7 +468,7 @@ mod tests { // When no global group is installed, the helper should still be // able to spawn processes — this preserves behaviour for the // CLI binary and for unit tests. - let mut cmd = if cfg!(windows) { + let mut cmd = if crate::platform::host::is_windows() { // allow-direct-spawn: this IS the containment module's own test of spawn_contained. let mut c = Command::new("cmd"); c.args(["/C", "echo", "hello"]); @@ -518,7 +518,7 @@ mod tests { // AVR build's "gcc -dumpversion then compile" sequence that // reproduces the original bug. let build_cmd = || { - let mut cmd = if cfg!(windows) { + let mut cmd = if crate::platform::host::is_windows() { // allow-direct-spawn: regression test for this module's own containment behaviour. let mut c = Command::new("cmd"); c.args(["/C", "echo", "ok"]); diff --git a/crates/fbuild-core/src/path.rs b/crates/fbuild-core/src/path.rs index a33eb0447..ff012270a 100644 --- a/crates/fbuild-core/src/path.rs +++ b/crates/fbuild-core/src/path.rs @@ -150,7 +150,7 @@ impl NormalizedPath { #[must_use] pub fn display_slash(&self) -> String { let mut s = self.path.to_string_lossy().into_owned(); - if cfg!(windows) { + if crate::platform::host::is_windows() { s = s.replace('\\', "/"); if let Some(stripped) = s.strip_prefix("//?/") { s = stripped.to_string(); diff --git a/crates/fbuild-core/src/platform/README.md b/crates/fbuild-core/src/platform/README.md index c29682ea8..eb19cba30 100644 --- a/crates/fbuild-core/src/platform/README.md +++ b/crates/fbuild-core/src/platform/README.md @@ -6,3 +6,8 @@ expose neutral APIs; the private `windows`, `linux`, and `macos` trees own native implementation details. Embedded board/MCU selection and host artifact policy do not belong here. + +`host` exposes the current `HostPlatform` plus explicit values used by pure +product-owner tests. `executable` owns native executable and command-script +spelling. Product crates keep URL/checksum tables and embedded-target choices; +they pass or read neutral host facts instead of using raw `cfg!` queries. diff --git a/crates/fbuild-core/src/platform/executable.rs b/crates/fbuild-core/src/platform/executable.rs index 9c1b2b3da..d49f11930 100644 --- a/crates/fbuild-core/src/platform/executable.rs +++ b/crates/fbuild-core/src/platform/executable.rs @@ -1 +1,122 @@ //! Neutral executable naming, discovery, and materialization APIs. + +use super::host::{self, HostArch, HostPlatform}; +use std::io; +use std::path::{Path, PathBuf}; + +/// Select the spelling of an executable or command script for an explicit host. +pub const fn name_for<'a>(host: HostPlatform, non_windows: &'a str, windows: &'a str) -> &'a str { + if host.is_windows() { + windows + } else { + non_windows + } +} + +/// Select the spelling of an executable or command script for the current host. +pub const fn name<'a>(non_windows: &'a str, windows: &'a str) -> &'a str { + name_for( + HostPlatform::new(host::current_os(), HostArch::Other), + non_windows, + windows, + ) +} + +/// Add the native executable suffix to a tool stem for an explicit host. +pub fn native_name_for(host: HostPlatform, stem: &str) -> String { + if host.is_windows() { + format!("{stem}.exe") + } else { + stem.to_owned() + } +} + +/// Add the native executable suffix to a tool stem for the current host. +pub fn native_name(stem: &str) -> String { + native_name_for(host::current(), stem) +} + +/// Return ordered PATH/PATHEXT-compatible spellings for an explicit host. +pub fn path_candidate_names_for(host: HostPlatform, stem: &str) -> Vec { + if host.is_windows() { + vec![format!("{stem}.exe"), stem.to_owned()] + } else { + vec![stem.to_owned()] + } +} + +/// Return ordered PATH/PATHEXT-compatible spellings for the current host. +pub fn path_candidate_names(stem: &str) -> Vec { + path_candidate_names_for(host::current(), stem) +} + +/// Discover the path of the currently running executable image. +pub fn current_image() -> io::Result { + std::env::current_exe() +} + +/// Return a path next to the current executable image. +pub fn current_image_sibling(name: impl AsRef) -> io::Result { + let image = current_image()?; + let parent = image.parent().ok_or_else(|| { + io::Error::new( + io::ErrorKind::NotFound, + "current executable image has no parent directory", + ) + })?; + Ok(parent.join(name)) +} + +/// Return the conventional unsuffixed and `.exe` sibling candidates. +/// +/// Probing both preserves compatibility with archives that carry an explicit +/// Windows suffix even when inspected from another host. +pub fn current_image_sibling_candidates(stem: &str) -> io::Result<[PathBuf; 2]> { + let unsuffixed = current_image_sibling(stem)?; + let explicit_exe = unsuffixed.with_extension("exe"); + Ok([unsuffixed, explicit_exe]) +} + +#[cfg(test)] +mod tests { + use crate::platform::host::{HostArch, HostOs, HostPlatform}; + + #[test] + fn executable_and_command_script_names_follow_the_explicit_host() { + let windows = HostPlatform::new(HostOs::Windows, HostArch::X86_64); + let linux = HostPlatform::new(HostOs::Linux, HostArch::X86_64); + + assert_eq!(super::name_for(windows, "clang", "clang.exe"), "clang.exe"); + assert_eq!(super::name_for(linux, "clang", "clang.exe"), "clang"); + assert_eq!(super::name_for(windows, "npm", "npm.cmd"), "npm.cmd"); + assert_eq!(super::name_for(linux, "npm", "npm.cmd"), "npm"); + assert_eq!(super::native_name_for(windows, "tool"), "tool.exe"); + assert_eq!(super::native_name_for(linux, "tool"), "tool"); + assert_eq!( + super::path_candidate_names_for(windows, "pio"), + ["pio.exe", "pio"] + ); + assert_eq!(super::path_candidate_names_for(linux, "pio"), ["pio"]); + } + + #[test] + fn current_image_and_sibling_discovery_share_the_same_parent() { + let image = super::current_image().expect("current test image"); + let sibling = super::current_image_sibling("fbuild-sibling").expect("sibling path"); + assert_eq!(sibling.parent(), image.parent()); + assert_eq!( + sibling.file_name().and_then(|name| name.to_str()), + Some("fbuild-sibling") + ); + let candidates = + super::current_image_sibling_candidates("fbuild-daemon").expect("candidate paths"); + assert_eq!( + candidates[0].file_name().and_then(|name| name.to_str()), + Some("fbuild-daemon") + ); + assert_eq!( + candidates[1].file_name().and_then(|name| name.to_str()), + Some("fbuild-daemon.exe") + ); + } +} diff --git a/crates/fbuild-core/src/platform/host.rs b/crates/fbuild-core/src/platform/host.rs index ed7d403b4..aa47696a8 100644 --- a/crates/fbuild-core/src/platform/host.rs +++ b/crates/fbuild-core/src/platform/host.rs @@ -17,3 +17,141 @@ pub enum HostArch { Aarch64, Other, } + +/// The operating system and CPU architecture of the machine running fbuild. +/// +/// This is deliberately separate from every embedded board/compiler target. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct HostPlatform { + os: HostOs, + arch: HostArch, +} + +impl HostPlatform { + pub const fn new(os: HostOs, arch: HostArch) -> Self { + Self { os, arch } + } + + pub const fn os(self) -> HostOs { + self.os + } + + pub const fn arch(self) -> HostArch { + self.arch + } + + pub const fn is_windows(self) -> bool { + matches!(self.os, HostOs::Windows) + } + + pub const fn is_linux(self) -> bool { + matches!(self.os, HostOs::Linux) + } + + pub const fn is_macos(self) -> bool { + matches!(self.os, HostOs::Macos) + } + + pub const fn is_unix(self) -> bool { + matches!(self.os, HostOs::Linux | HostOs::Macos) + } + + pub const fn os_name(self) -> &'static str { + match self.os { + HostOs::Windows => "windows", + HostOs::Linux => "linux", + HostOs::Macos => "macos", + } + } + + pub const fn arch_name(self) -> &'static str { + match self.arch { + HostArch::X86 => "x86", + HostArch::X86_64 => "x86_64", + HostArch::Arm => "arm", + HostArch::Aarch64 => "aarch64", + HostArch::Other => "other", + } + } + + pub const fn path_list_separator(self) -> char { + if self.is_windows() { ';' } else { ':' } + } + + pub const fn path_list_separator_str(self) -> &'static str { + if self.is_windows() { ";" } else { ":" } + } +} + +/// Return facts for the machine running this fbuild executable. +pub fn current() -> HostPlatform { + HostPlatform::new(super::current_os(), super::selected::host_arch()) +} + +pub const fn current_os() -> HostOs { + super::current_os() +} + +pub const fn is_windows() -> bool { + matches!(current_os(), HostOs::Windows) +} + +pub const fn is_linux() -> bool { + matches!(current_os(), HostOs::Linux) +} + +pub const fn is_macos() -> bool { + matches!(current_os(), HostOs::Macos) +} + +pub const fn is_unix() -> bool { + matches!(current_os(), HostOs::Linux | HostOs::Macos) +} + +pub fn os_name() -> &'static str { + current().os_name() +} + +pub fn arch_name() -> &'static str { + current().arch_name() +} + +pub fn path_list_separator() -> char { + current().path_list_separator() +} + +pub fn path_list_separator_str() -> &'static str { + current().path_list_separator_str() +} + +#[cfg(test)] +mod tests { + use super::{HostArch, HostOs, HostPlatform}; + + #[test] + fn explicit_host_platform_keeps_os_arch_and_path_separator_together() { + let windows = HostPlatform::new(HostOs::Windows, HostArch::X86_64); + let linux = HostPlatform::new(HostOs::Linux, HostArch::Aarch64); + let macos = HostPlatform::new(HostOs::Macos, HostArch::Arm); + + assert_eq!(windows.os_name(), "windows"); + assert_eq!(windows.arch_name(), "x86_64"); + assert_eq!(windows.path_list_separator(), ';'); + assert_eq!(linux.os_name(), "linux"); + assert_eq!(linux.arch_name(), "aarch64"); + assert_eq!(linux.path_list_separator(), ':'); + assert_eq!(macos.os_name(), "macos"); + assert_eq!(macos.arch_name(), "arm"); + assert_eq!(macos.path_list_separator(), ':'); + } + + #[test] + fn current_host_is_a_supported_os_with_a_named_architecture() { + let current = super::current(); + assert!(matches!( + current.os(), + HostOs::Windows | HostOs::Linux | HostOs::Macos + )); + assert!(!current.arch_name().is_empty()); + } +} diff --git a/crates/fbuild-core/src/platform/linux/mod.rs b/crates/fbuild-core/src/platform/linux/mod.rs index 5a8b0451c..f25d1a9ec 100644 --- a/crates/fbuild-core/src/platform/linux/mod.rs +++ b/crates/fbuild-core/src/platform/linux/mod.rs @@ -1,3 +1,13 @@ -use super::host::HostOs; +use super::host::{HostArch, HostOs}; pub(super) const HOST_OS: HostOs = HostOs::Linux; + +pub(super) fn host_arch() -> HostArch { + match std::env::consts::ARCH { + "x86" => HostArch::X86, + "x86_64" => HostArch::X86_64, + "arm" => HostArch::Arm, + "aarch64" => HostArch::Aarch64, + _ => HostArch::Other, + } +} diff --git a/crates/fbuild-core/src/platform/macos/mod.rs b/crates/fbuild-core/src/platform/macos/mod.rs index 58adcb203..eda2832ce 100644 --- a/crates/fbuild-core/src/platform/macos/mod.rs +++ b/crates/fbuild-core/src/platform/macos/mod.rs @@ -1,3 +1,13 @@ -use super::host::HostOs; +use super::host::{HostArch, HostOs}; pub(super) const HOST_OS: HostOs = HostOs::Macos; + +pub(super) fn host_arch() -> HostArch { + match std::env::consts::ARCH { + "x86" => HostArch::X86, + "x86_64" => HostArch::X86_64, + "arm" => HostArch::Arm, + "aarch64" => HostArch::Aarch64, + _ => HostArch::Other, + } +} diff --git a/crates/fbuild-core/src/platform/windows/mod.rs b/crates/fbuild-core/src/platform/windows/mod.rs index 6856672c9..e6a49314d 100644 --- a/crates/fbuild-core/src/platform/windows/mod.rs +++ b/crates/fbuild-core/src/platform/windows/mod.rs @@ -1,3 +1,13 @@ -use super::host::HostOs; +use super::host::{HostArch, HostOs}; pub(super) const HOST_OS: HostOs = HostOs::Windows; + +pub(super) fn host_arch() -> HostArch { + match std::env::consts::ARCH { + "x86" => HostArch::X86, + "x86_64" => HostArch::X86_64, + "arm" => HostArch::Arm, + "aarch64" => HostArch::Aarch64, + _ => HostArch::Other, + } +} diff --git a/crates/fbuild-core/src/process_identity.rs b/crates/fbuild-core/src/process_identity.rs index bc896e33c..a1ba15186 100644 --- a/crates/fbuild-core/src/process_identity.rs +++ b/crates/fbuild-core/src/process_identity.rs @@ -150,7 +150,7 @@ pub fn pid_exe_stem_matches(pid: u32, expected_stem: &str) -> bool { let Some(stem) = path.file_stem().and_then(|s| s.to_str()) else { return false; }; - if cfg!(windows) { + if crate::platform::host::is_windows() { stem.eq_ignore_ascii_case(expected_stem) } else { stem == expected_stem @@ -261,7 +261,7 @@ mod tests { #[test] fn exe_stem_matches_current_exe_stem() { - let current_exe = std::env::current_exe().expect("current exe"); + let current_exe = crate::platform::executable::current_image().expect("current exe"); let stem = current_exe .file_stem() .and_then(|s| s.to_str()) diff --git a/crates/fbuild-core/src/response_file.rs b/crates/fbuild-core/src/response_file.rs index 7efb9f6b9..0efce5be6 100644 --- a/crates/fbuild-core/src/response_file.rs +++ b/crates/fbuild-core/src/response_file.rs @@ -24,7 +24,7 @@ const RESPONSE_FILE_STALE_AFTER: Duration = Duration::from_secs(7 * 24 * 60 * 60 /// Windows GCC treats as `C:\tmp\`. Use an app-owned directory under /// `~/.fbuild/{dev|prod}/tmp/response-files` instead. pub fn windows_temp_dir() -> PathBuf { - if cfg!(windows) { + if crate::platform::host::is_windows() { response_files_dir() } else { std::env::temp_dir() diff --git a/crates/fbuild-core/src/subprocess.rs b/crates/fbuild-core/src/subprocess.rs index 4ccdb2345..30a8a59ad 100644 --- a/crates/fbuild-core/src/subprocess.rs +++ b/crates/fbuild-core/src/subprocess.rs @@ -786,7 +786,7 @@ mod tests { #[tokio::test] async fn run_echo() { - let args = if cfg!(windows) { + let args = if crate::platform::host::is_windows() { vec!["cmd", "/C", "echo hello"] } else { vec!["echo", "hello"] @@ -824,12 +824,16 @@ mod tests { // Bare name without a caller PATH: keep legacy daemon-env behavior. assert_eq!(bare_name_path_overlay("esptool", None), None); // Absolute and relative paths never trigger a PATH lookup. - let absolute = if cfg!(windows) { - r"C:\tools\esptool\esptool.exe" + let absolute = if crate::platform::host::is_windows() { + std::path::PathBuf::from(r"C:\tools\esptool") } else { - "/usr/local/bin/esptool" - }; - assert_eq!(bare_name_path_overlay(absolute, Some("/opt/bin")), None); + std::path::PathBuf::from("/usr/local/bin") + } + .join(crate::platform::executable::native_name("esptool")); + assert_eq!( + bare_name_path_overlay(&absolute.to_string_lossy(), Some("/opt/bin")), + None + ); assert_eq!(bare_name_path_overlay("./esptool", Some("/opt/bin")), None); assert_eq!( bare_name_path_overlay("tools/esptool", Some("/opt/bin")), @@ -851,7 +855,7 @@ mod tests { async fn env_overlay_path_reaches_child_over_case_variant() { // `cmd` resolves via the OS system-dir fallback and `/bin/sh` is // absolute, so neither spawn depends on the clobbered PATH. - let args = if cfg!(windows) { + let args = if crate::platform::host::is_windows() { vec!["cmd", "/C", "echo %PATH%"] } else { vec!["/bin/sh", "-c", "echo \"$PATH\""] @@ -894,7 +898,7 @@ mod tests { let dir_str = dir.to_string_lossy(); let overlay = [("PATH", dir_str.as_ref())]; - let bare_args: Vec<&str> = if cfg!(windows) { + let bare_args: Vec<&str> = if crate::platform::host::is_windows() { vec!["fbuild_1219_probe", "/C", "echo overlay-marker"] } else { vec!["fbuild_1219_probe"] @@ -918,7 +922,7 @@ mod tests { // Absolute path, no overlay → normal operation is unaffected. let probe_str = probe_path.to_string_lossy(); - let abs_args: Vec<&str> = if cfg!(windows) { + let abs_args: Vec<&str> = if crate::platform::host::is_windows() { vec![probe_str.as_ref(), "/C", "echo overlay-marker"] } else { vec![probe_str.as_ref()] @@ -944,7 +948,7 @@ mod tests { #[test] fn run_command_blocking_works_from_sync_context() { - let args = if cfg!(windows) { + let args = if crate::platform::host::is_windows() { vec!["cmd", "/C", "echo blocking"] } else { vec!["echo", "blocking"] @@ -956,7 +960,7 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn run_command_blocking_works_from_tokio_worker() { - let args = if cfg!(windows) { + let args = if crate::platform::host::is_windows() { vec!["cmd", "/C", "echo blocking-runtime"] } else { vec!["echo", "blocking-runtime"] @@ -977,7 +981,7 @@ mod tests { .enable_all() .build() .expect("test runtime"); - let args = if cfg!(windows) { + let args = if crate::platform::host::is_windows() { vec!["cmd", "/C", "echo current-thread-runtime"] } else { vec!["echo", "current-thread-runtime"] @@ -1096,7 +1100,7 @@ mod tests { #[tokio::test] async fn run_captures_stderr() { // Verify that stderr is captured independently from stdout. - let args = if cfg!(windows) { + let args = if crate::platform::host::is_windows() { vec!["cmd", "/C", "echo err 1>&2"] } else { vec!["sh", "-c", "echo err 1>&2"] @@ -1133,7 +1137,7 @@ mod tests { // * Windows: `ping -n 30 127.0.0.1` waits ~29 s (sends 30 // pings 1 s apart) — far longer than our 200 ms cap. // * Unix: `sleep 30`. - let args = if cfg!(windows) { + let args = if crate::platform::host::is_windows() { vec!["ping", "-n", "30", "127.0.0.1"] } else { vec!["sleep", "30"] @@ -1150,7 +1154,7 @@ mod tests { // Audit-helper API still has to work for the legit unbounded // case — verify it returns Ok for a command that finishes // promptly. - let args = if cfg!(windows) { + let args = if crate::platform::host::is_windows() { vec!["cmd", "/C", "echo no-timeout"] } else { vec!["echo", "no-timeout"] @@ -1164,7 +1168,7 @@ mod tests { async fn run_command_with_stdin_pipes_payload() { // Round-trip: feed stdin → expect it back on stdout. `cat` on // unix, `findstr` on windows (matches everything via /R ".*"). - let args = if cfg!(windows) { + let args = if crate::platform::host::is_windows() { vec!["findstr", "/R", ".*"] } else { vec!["cat"] diff --git a/crates/fbuild-daemon/src/bin/containment_harness.rs b/crates/fbuild-daemon/src/bin/containment_harness.rs index 241bd4512..ffd6c3e76 100644 --- a/crates/fbuild-daemon/src/bin/containment_harness.rs +++ b/crates/fbuild-daemon/src/bin/containment_harness.rs @@ -44,7 +44,7 @@ fn run_parent() { .expect("init_global_containment"); // Spawn the child via the contained-spawn helper. - let self_exe = std::env::current_exe().expect("current_exe"); + let self_exe = fbuild_core::platform::executable::current_image().expect("current_exe"); // allow-direct-spawn: integration-test harness exercising spawn_contained itself. let mut cmd = std::process::Command::new(&self_exe); cmd.arg("child") @@ -96,7 +96,7 @@ fn run_child() { // // So here we use a plain `spawn()` and the grandchild still ends // up in the parent's containment group. - let self_exe = std::env::current_exe().expect("current_exe"); + let self_exe = fbuild_core::platform::executable::current_image().expect("current_exe"); // allow-direct-spawn: integration-test harness verifying grandchild containment inheritance. let mut cmd = std::process::Command::new(&self_exe); cmd.arg("grandchild") diff --git a/crates/fbuild-daemon/src/broker/service.rs b/crates/fbuild-daemon/src/broker/service.rs index ea01c7b3d..15bfa7fd1 100644 --- a/crates/fbuild-daemon/src/broker/service.rs +++ b/crates/fbuild-daemon/src/broker/service.rs @@ -224,11 +224,14 @@ mod tests { } fn abs_daemon() -> PathBuf { - if cfg!(windows) { - PathBuf::from(r"C:\opt\fbuild\bin\fbuild-daemon.exe") + if fbuild_core::platform::host::is_windows() { + PathBuf::from(r"C:\opt\fbuild\bin") } else { - PathBuf::from("/opt/fbuild/bin/fbuild-daemon") + PathBuf::from("/opt/fbuild/bin") } + .join(fbuild_core::platform::executable::native_name( + "fbuild-daemon", + )) } #[test] @@ -322,7 +325,7 @@ mod tests { #[test] fn cache_manifest_records_all_seven_roots() { - let runtime = if cfg!(windows) { + let runtime = if fbuild_core::platform::host::is_windows() { PathBuf::from(r"C:\opt\fbuild\bin") } else { PathBuf::from("/opt/fbuild/bin") @@ -443,12 +446,12 @@ mod tests { #[test] fn cache_data_root_is_stable_across_backend_versions() { let _env = ENV_LOCK.lock().unwrap(); - let runtime_v1 = if cfg!(windows) { + let runtime_v1 = if fbuild_core::platform::host::is_windows() { PathBuf::from(r"C:\opt\fbuild-1\bin") } else { PathBuf::from("/opt/fbuild-1/bin") }; - let runtime_v2 = if cfg!(windows) { + let runtime_v2 = if fbuild_core::platform::host::is_windows() { PathBuf::from(r"C:\opt\fbuild-2\bin") } else { PathBuf::from("/opt/fbuild-2/bin") @@ -489,7 +492,7 @@ mod tests { #[test] fn ci_cache_manifest_uses_explicit_trust_instance() { - let runtime = if cfg!(windows) { + let runtime = if fbuild_core::platform::host::is_windows() { PathBuf::from(r"C:\opt\fbuild\bin") } else { PathBuf::from("/opt/fbuild/bin") diff --git a/crates/fbuild-daemon/src/broker/session.rs b/crates/fbuild-daemon/src/broker/session.rs index 04dc51e26..2049af5ee 100644 --- a/crates/fbuild-daemon/src/broker/session.rs +++ b/crates/fbuild-daemon/src/broker/session.rs @@ -172,7 +172,7 @@ mod tests { // (2) hatch unset → a real (failing) dial against a bogus endpoint. std::env::remove_var("RUNNING_PROCESS_DISABLE"); - let endpoint = if cfg!(windows) { + let endpoint = if fbuild_core::platform::host::is_windows() { "fbuild-broker-test-does-not-exist" } else { "/tmp/fbuild-broker-test-does-not-exist.sock" diff --git a/crates/fbuild-daemon/src/context.rs b/crates/fbuild-daemon/src/context.rs index b2abb4209..ce15e0c27 100644 --- a/crates/fbuild-daemon/src/context.rs +++ b/crates/fbuild-daemon/src/context.rs @@ -116,7 +116,7 @@ use std::time::Duration; /// Compute the modification time of the running binary (for stale daemon detection). /// Returns 0.0 if the mtime cannot be determined. fn compute_binary_mtime() -> f64 { - std::env::current_exe() + fbuild_core::platform::executable::current_image() .ok() .and_then(|p| p.metadata().ok()) .and_then(|m| m.modified().ok()) diff --git a/crates/fbuild-daemon/src/handlers/emulator/avr8js_npm.rs b/crates/fbuild-daemon/src/handlers/emulator/avr8js_npm.rs index b637e3177..1e9b02ca6 100644 --- a/crates/fbuild-daemon/src/handlers/emulator/avr8js_npm.rs +++ b/crates/fbuild-daemon/src/handlers/emulator/avr8js_npm.rs @@ -6,7 +6,7 @@ use std::path::{Path, PathBuf}; pub(crate) async fn find_node() -> fbuild_core::Result { - let node = if cfg!(windows) { "node.exe" } else { "node" }; + let node = fbuild_core::platform::executable::name("node", "node.exe"); // Route through fbuild-core's `run_command` so the probe spawn is // captured by the daemon's containment group (issue #32). The probe // is short-lived (`node --version`) but a missing binary should @@ -162,7 +162,7 @@ pub(crate) async fn ensure_avr8js_npm_in( )) })?; - let npm = if cfg!(windows) { "npm.cmd" } else { "npm" }; + let npm = fbuild_core::platform::executable::name("npm", "npm.cmd"); // Route through `run_command` (which spawns via the daemon's // containment group) so an `npm install` killed mid-flight doesn't // leak node processes after the daemon dies. See FastLED/fbuild#32. diff --git a/crates/fbuild-daemon/src/handlers/emulator/runners.rs b/crates/fbuild-daemon/src/handlers/emulator/runners.rs index bff052f8e..61c4bc519 100644 --- a/crates/fbuild-daemon/src/handlers/emulator/runners.rs +++ b/crates/fbuild-daemon/src/handlers/emulator/runners.rs @@ -239,11 +239,7 @@ impl EmulatorRunner for Avr8jsRunner { /// - macOS: `brew install simavr` /// - Windows: build from source (MSYS2/MinGW) — limited support async fn find_simavr() -> fbuild_core::Result { - let simavr = if cfg!(windows) { - "simavr.exe" - } else { - "simavr" - }; + let simavr = fbuild_core::platform::executable::name("simavr", "simavr.exe"); // Try running simavr to verify it exists; route through containment // (issue #32). This is a short-lived probe so the containment // difference is purely consistency. @@ -262,9 +258,9 @@ async fn find_simavr() -> fbuild_core::Result { { Ok(_) => Ok(PathBuf::from(simavr)), Err(_) => { - let install_hint = if cfg!(target_os = "linux") { + let install_hint = if fbuild_core::platform::host::is_linux() { "Install via: apt install simavr (Debian/Ubuntu) or your distro's package manager" - } else if cfg!(target_os = "macos") { + } else if fbuild_core::platform::host::is_macos() { "Install via: brew install simavr" } else { "SimAVR has limited Windows support. Build from source via MSYS2/MinGW, \ diff --git a/crates/fbuild-daemon/src/handlers/emulator/shared.rs b/crates/fbuild-daemon/src/handlers/emulator/shared.rs index b045bd288..835b3acc6 100644 --- a/crates/fbuild-daemon/src/handlers/emulator/shared.rs +++ b/crates/fbuild-daemon/src/handlers/emulator/shared.rs @@ -94,7 +94,7 @@ pub(crate) fn qemu_session_dir(project_dir: &Path, env_name: &str) -> PathBuf { } pub(crate) fn build_linux_macos_qemu_hint(err: &str) -> String { - if cfg!(any(target_os = "linux", target_os = "macos")) { + if fbuild_core::platform::host::is_linux() || fbuild_core::platform::host::is_macos() { let prefix = if err.is_empty() { String::new() } else { diff --git a/crates/fbuild-daemon/src/handlers/locks.rs b/crates/fbuild-daemon/src/handlers/locks.rs index 91b42de9d..edb533f12 100644 --- a/crates/fbuild-daemon/src/handlers/locks.rs +++ b/crates/fbuild-daemon/src/handlers/locks.rs @@ -37,7 +37,7 @@ fn serial_client_lock_info(client: &SerialClientInfo) -> SerialClientLockInfo { } fn port_matches(actual: &str, requested: &str) -> bool { - if cfg!(windows) { + if fbuild_core::platform::host::is_windows() { actual.eq_ignore_ascii_case(requested) } else { actual == requested @@ -460,7 +460,7 @@ mod tests { let mixed = ctx.project_lock(Path::new("/Tmp/FBuild/Proj")); let lower = ctx.project_lock(Path::new("/tmp/fbuild/proj")); - if cfg!(any(windows, target_os = "macos")) { + if fbuild_core::platform::host::is_windows() || fbuild_core::platform::host::is_macos() { // Case-insensitive filesystem: one logical project, so the two // spellings must share a single serialization lock. Before the // fix these keyed distinct raw-`PathBuf` entries and returned diff --git a/crates/fbuild-daemon/src/handlers/operations/deploy.rs b/crates/fbuild-daemon/src/handlers/operations/deploy.rs index c8f50863b..0ce7d6463 100644 --- a/crates/fbuild-daemon/src/handlers/operations/deploy.rs +++ b/crates/fbuild-daemon/src/handlers/operations/deploy.rs @@ -29,14 +29,11 @@ use super::common::{native_verify_enabled, native_write_enabled}; /// try a bare `teensy_loader_cli` invocation, which will surface /// `command not found` to the user — clearer than a silent abort here. fn find_teensy_loader_cli() -> Option { - let exe_name = if cfg!(windows) { - "teensy_loader_cli.exe" - } else { - "teensy_loader_cli" - }; + let exe_name = + fbuild_core::platform::executable::name("teensy_loader_cli", "teensy_loader_cli.exe"); if let Ok(path_env) = std::env::var("PATH") { - let sep = if cfg!(windows) { ';' } else { ':' }; + let sep = fbuild_core::platform::host::path_list_separator(); for dir in path_env.split(sep) { let candidate = PathBuf::from(dir).join(exe_name); if candidate.is_file() { @@ -48,7 +45,7 @@ fn find_teensy_loader_cli() -> Option { // PlatformIO drops the binary here on every platform. Reusing it means a // user who already has PIO working doesn't need to install anything else // to deploy via fbuild. - let pio_root = if cfg!(windows) { + let pio_root = if fbuild_core::platform::host::is_windows() { std::env::var("USERPROFILE").ok() } else { std::env::var("HOME").ok() @@ -974,7 +971,7 @@ pub async fn deploy( let deploy_flashed = matches!(&deploy_result, Ok(r) if r.success); let cdc_unrecovered = port_discovery_owned && matches!(&deploy_result, Ok(r) if r.success && r.port.is_none()); - let usb_recovery_request = if cfg!(windows) + let usb_recovery_request = if fbuild_core::platform::host::is_windows() && platform == fbuild_core::Platform::RaspberryPi && (!deploy_flashed || cdc_unrecovered) { diff --git a/crates/fbuild-daemon/src/main.rs b/crates/fbuild-daemon/src/main.rs index 120719d1a..e8bfe97d4 100644 --- a/crates/fbuild-daemon/src/main.rs +++ b/crates/fbuild-daemon/src/main.rs @@ -258,7 +258,7 @@ async fn main() { // enumerating every `daemon-*.port` file. `current_exe()` failing is // not treated as fatal: skip the claim write and keep the daemon // running under the root-ownership lock alone. - match std::env::current_exe() { + match fbuild_core::platform::executable::current_image() { Ok(exe) => { let identity = fbuild_paths::running_process::DaemonCacheIdentity::discover(); let claim = fbuild_paths::daemon_ownership::OwnerClaim { @@ -287,7 +287,7 @@ async fn main() { // FastLED/fbuild#510 lands `connect_to_backend`. Best-effort: any // failure (read-only AppData, sandbox, etc.) is logged but does not // block daemon startup. See FastLED/fbuild#592. - match std::env::current_exe() { + match fbuild_core::platform::executable::current_image() { Ok(this_exe) => { let daemon_binary = this_exe .parent() diff --git a/crates/fbuild-daemon/tests/legacy_daemon_transition.rs b/crates/fbuild-daemon/tests/legacy_daemon_transition.rs index 88d225f2a..90958479e 100644 --- a/crates/fbuild-daemon/tests/legacy_daemon_transition.rs +++ b/crates/fbuild-daemon/tests/legacy_daemon_transition.rs @@ -82,7 +82,7 @@ fn subprocess_sleep_helper() { #[test] fn legacy_pid_stand_in_is_never_signaled() { - let bin = std::env::current_exe().expect("current test exe"); + let bin = fbuild_core::platform::executable::current_image().expect("current test exe"); // allow-direct-spawn: test driver spawns its own test binary in helper mode. let mut helper = Command::new(&bin) .args([ @@ -205,7 +205,11 @@ async fn real_daemon_root_ownership_released_on_kill() { let temp_home = tempfile::tempdir().expect("temp home"); let port = free_port(); let bin = env!("CARGO_BIN_EXE_fbuild-daemon"); - let home_key = if cfg!(windows) { "USERPROFILE" } else { "HOME" }; + let home_key = if fbuild_core::platform::host::is_windows() { + "USERPROFILE" + } else { + "HOME" + }; // allow-direct-spawn: test driver spawns the real fbuild-daemon binary under test. let mut daemon = Command::new(bin) diff --git a/crates/fbuild-deploy/src/lpc.rs b/crates/fbuild-deploy/src/lpc.rs index 7ee115c95..8f45ceb9f 100644 --- a/crates/fbuild-deploy/src/lpc.rs +++ b/crates/fbuild-deploy/src/lpc.rs @@ -44,11 +44,7 @@ fn home_dir() -> Option { /// Honors `FBUILD_DEV_MODE=1` → `~/.fbuild/dev/tools/…` to match the /// isolation the rest of `fbuild-paths` applies. pub fn managed_lpc21isp_path() -> Option { - let exe = if cfg!(windows) { - "lpc21isp.exe" - } else { - "lpc21isp" - }; + let exe = fbuild_core::platform::executable::native_name("lpc21isp"); let home = home_dir()?; let mode = if std::env::var_os("FBUILD_DEV_MODE").is_some() { "dev" @@ -100,11 +96,8 @@ pub fn find_lpc21isp() -> Option { /// deploy path. Kept as a standalone function so the test module can /// assert the exact URLs / paths without shelling out. pub(crate) fn lpc21isp_install_hint() -> String { - let (tools_dir, exe) = if cfg!(windows) { - ("~/.fbuild/prod/tools/", "lpc21isp.exe") - } else { - ("~/.fbuild/prod/tools/", "lpc21isp") - }; + let tools_dir = "~/.fbuild/prod/tools/"; + let exe = fbuild_core::platform::executable::native_name("lpc21isp"); format!( "lpc21isp not found on PATH or in any fbuild-managed tools dir.\n\ \n\ @@ -183,7 +176,7 @@ pub(crate) fn resolve_lpc21isp_baud( /// (or ports that already carry the prefix, or non-`COM*` names such as /// Linux `/dev/ttyUSB0`) the input is returned unchanged. pub(crate) fn normalize_lpc21isp_port(port: &str) -> String { - if !cfg!(windows) { + if !fbuild_core::platform::host::is_windows() { return port.to_string(); } // Already prefixed — nothing to do. @@ -872,11 +865,9 @@ mod tests { .lock() .unwrap_or_else(|error| error.into_inner()); let tmp = tempfile::TempDir::new().unwrap(); - let fake = tmp.path().join(if cfg!(windows) { - "lpc21isp.exe" - } else { - "lpc21isp" - }); + let fake = tmp + .path() + .join(fbuild_core::platform::executable::native_name("lpc21isp")); std::fs::write(&fake, b"stub").unwrap(); // SAFETY: single-threaded test process. diff --git a/crates/fbuild-deploy/src/lpc_debugger_reflash.rs b/crates/fbuild-deploy/src/lpc_debugger_reflash.rs index 74281546d..49fac442b 100644 --- a/crates/fbuild-deploy/src/lpc_debugger_reflash.rs +++ b/crates/fbuild-deploy/src/lpc_debugger_reflash.rs @@ -50,9 +50,9 @@ pub const CMSIS_DAP_V1_HEX_NAME: &str = "lpc-link2-cmsis-dap-v1.hex"; /// `ASSETS_BASE_URL`. Matches the filenames the framework repo PR /// (FastLED/framework-arduino-lpc8xx#37) committed. pub fn dfu_util_archive_name() -> &'static str { - if cfg!(target_os = "windows") { + if fbuild_core::platform::host::is_windows() { "dfu-util-0.11-windows-x86_64.zip" - } else if cfg!(target_os = "macos") { + } else if fbuild_core::platform::host::is_macos() { "dfu-util-0.11-darwin-x86_64.tar.gz" } else { // Everything else Linux-shaped. Users on OpenBSD/FreeBSD / other @@ -116,11 +116,7 @@ fn find_dfu_util_with_override(env_override: Option) -> Opti } } let tools = managed_tools_dir()?; - let exe = if cfg!(windows) { - "dfu-util.exe" - } else { - "dfu-util" - }; + let exe = fbuild_core::platform::executable::native_name("dfu-util"); let candidate = tools.join(exe); if candidate.is_file() { return Some(candidate); @@ -394,11 +390,9 @@ mod tests { #[test] fn find_dfu_util_env_var_wins_when_path_is_real() { let tmp = tempfile::TempDir::new().unwrap(); - let fake = tmp.path().join(if cfg!(windows) { - "dfu-util.exe" - } else { - "dfu-util" - }); + let fake = tmp + .path() + .join(fbuild_core::platform::executable::native_name("dfu-util")); std::fs::write(&fake, b"stub").unwrap(); let got = find_dfu_util_with_override(Some(fake.clone().into_os_string())); assert_eq!(got.as_ref().map(|p| p.as_path()), Some(fake.as_path())); diff --git a/crates/fbuild-deploy/src/probe_rs.rs b/crates/fbuild-deploy/src/probe_rs.rs index 3564f3c85..e7eca6273 100644 --- a/crates/fbuild-deploy/src/probe_rs.rs +++ b/crates/fbuild-deploy/src/probe_rs.rs @@ -78,7 +78,10 @@ impl ProbeRsReleaseAsset { /// Return the pinned FastLED/probe-rs release asset for this host. pub fn probe_rs_release_asset_for_host() -> Result { - match (std::env::consts::OS, std::env::consts::ARCH) { + match ( + fbuild_core::platform::host::os_name(), + fbuild_core::platform::host::arch_name(), + ) { ("windows", "x86_64") => Ok(ProbeRsReleaseAsset { name: "probe-rs-fastled-fastled-v0.31.2-nusb-v1-transport-x86_64-pc-windows-msvc.zip", sha256: "257e294988498218cf350a852bf60e57313b19f492f8019b92905df59095c7a1", @@ -129,11 +132,7 @@ pub fn managed_probe_rs_dir() -> Option { } pub fn managed_probe_rs_path() -> Option { - let exe = if cfg!(windows) { - "probe-rs.exe" - } else { - "probe-rs" - }; + let exe = fbuild_core::platform::executable::native_name("probe-rs"); Some(managed_probe_rs_dir()?.join(exe)) } @@ -310,12 +309,8 @@ fn probe_rs_temp_install_path(dest_path: &Path) -> NormalizedPath { } fn find_extracted_probe_rs_binary(root: &Path) -> Result { - let exe = if cfg!(windows) { - "probe-rs.exe" - } else { - "probe-rs" - }; - find_file_by_name(root, exe).ok_or_else(|| { + let exe = fbuild_core::platform::executable::native_name("probe-rs"); + find_file_by_name(root, &exe).ok_or_else(|| { FbuildError::PackageError(format!( "probe-rs binary `{exe}` not found after extracting {}", root.display() @@ -651,7 +646,13 @@ mod tests { let staging = tmp.path().join("probe-rs-install"); std::fs::create_dir_all(staging.join("extract")).unwrap(); std::fs::write(staging.join("archive.zip"), b"zip").unwrap(); - std::fs::write(staging.join("extract").join("probe-rs.exe"), b"exe").unwrap(); + std::fs::write( + staging + .join("extract") + .join(fbuild_core::platform::executable::native_name("probe-rs")), + b"exe", + ) + .unwrap(); cleanup_probe_rs_staging_dir(&staging).await; @@ -667,25 +668,15 @@ mod tests { let archive = tmp.path().join("probe-rs.zip"); let staging = tmp.path().join("staging"); let dest_dir = tmp.path().join("managed"); - let dest = dest_dir.join(if cfg!(windows) { - "probe-rs.exe" - } else { - "probe-rs" - }); + let binary_name = fbuild_core::platform::executable::native_name("probe-rs"); + let dest = dest_dir.join(&binary_name); std::fs::create_dir_all(&dest_dir).unwrap(); std::fs::write(&dest, b"old-probe-rs").unwrap(); let file = std::fs::File::create(&archive).unwrap(); let mut zip = zip::ZipWriter::new(file); zip.start_file( - format!( - "nested/{}", - if cfg!(windows) { - "probe-rs.exe" - } else { - "probe-rs" - } - ), + format!("nested/{binary_name}"), zip::write::SimpleFileOptions::default(), ) .unwrap(); diff --git a/crates/fbuild-deploy/src/rp2040.rs b/crates/fbuild-deploy/src/rp2040.rs index d2aff453a..665fc77ea 100644 --- a/crates/fbuild-deploy/src/rp2040.rs +++ b/crates/fbuild-deploy/src/rp2040.rs @@ -635,13 +635,13 @@ fn select_volume_after_reset( if let Some(error) = reset_error { return Err(FbuildError::DeployFailed(format!( "{error}; no RP2040 BOOTSEL transition was observed after the 1200-bps reset (discovery window is extendable with {BOOTLOADER_TIMEOUT_ENV}){}", - macos_accessory_hint(cfg!(target_os = "macos")) + macos_accessory_hint(fbuild_core::platform::host::is_macos()) ))); } - Err(FbuildError::DeployFailed(bootsel_not_found_message(cfg!( - target_os = "macos" - )))) + Err(FbuildError::DeployFailed(bootsel_not_found_message( + fbuild_core::platform::host::is_macos(), + ))) } fn prepare_uf2_artifact(firmware_path: &Path, family_id: u32) -> Result<(PathBuf, Uf2Target)> { @@ -1772,7 +1772,7 @@ async fn attempt_picotool_primary( target: &picotool::PicotoolTarget, load_timeout: Duration, ) -> std::result::Result { - let preflight_result = if cfg!(windows) { + let preflight_result = if fbuild_core::platform::host::is_windows() { let devices = tokio::task::spawn_blocking(fbuild_serial::ports::present_usb_problem_devices) .await @@ -2000,7 +2000,7 @@ impl Deployer for Rp2040Deployer { } else { application_reboot_target(false, runtime_target.as_ref()) }; - let native_reset_target = if cfg!(windows) && volume.is_none() { + let native_reset_target = if fbuild_core::platform::host::is_windows() && volume.is_none() { if let Some(target) = reset_only_target.clone() { Some(target) } else if let Some(target) = runtime_target.as_ref() { @@ -2227,7 +2227,7 @@ impl Deployer for Rp2040Deployer { picotool::FailureDirection::PicotoolPrimary, &mass_storage_context, &picotool_error_text, - cfg!(windows), + fbuild_core::platform::host::is_windows(), ), )); } @@ -2246,7 +2246,7 @@ impl Deployer for Rp2040Deployer { picotool::FailureDirection::PicotoolPrimary, &mass_storage_context, &picotool_error_text, - cfg!(windows), + fbuild_core::platform::host::is_windows(), ))); } }, diff --git a/crates/fbuild-deploy/src/rp2040_picotool.rs b/crates/fbuild-deploy/src/rp2040_picotool.rs index af51fbd60..3b438868f 100644 --- a/crates/fbuild-deploy/src/rp2040_picotool.rs +++ b/crates/fbuild-deploy/src/rp2040_picotool.rs @@ -171,7 +171,7 @@ pub(super) async fn load_with_managed_picotool( FailureDirection::PicotoolFallback, mass_storage_error.unwrap_or("unknown mass-storage error"), &tool_output, - cfg!(windows), + fbuild_core::platform::host::is_windows(), ), // Mass-storage has not run yet; the caller composes the final // combined message only if it also fails. @@ -294,14 +294,14 @@ pub(super) fn format_eject_failure( FailureDirection::PicotoolPrimary, mass_storage_error, picotool_error, - cfg!(windows), + fbuild_core::platform::host::is_windows(), ), Some(PriorTransportFailure::MassStoragePrimary(prior_mass_storage_error)) => { format_failure( FailureDirection::PicotoolFallback, prior_mass_storage_error, mass_storage_error, - cfg!(windows), + fbuild_core::platform::host::is_windows(), ) } None => mass_storage_error.to_string(), diff --git a/crates/fbuild-deploy/src/teensy/soft_reboot.rs b/crates/fbuild-deploy/src/teensy/soft_reboot.rs index 4df219144..d0c15ec72 100644 --- a/crates/fbuild-deploy/src/teensy/soft_reboot.rs +++ b/crates/fbuild-deploy/src/teensy/soft_reboot.rs @@ -95,7 +95,7 @@ mod tests { // Pure unit test: any host without a Teensy plugged at this port name // should return `Ok(false)` (no device). The point is to make sure // that a missing CDC port is never treated as a hard error. - let port = if cfg!(windows) { + let port = if fbuild_core::platform::host::is_windows() { "COM199" // unlikely to exist } else { "/tmp/fbuild-teensy-no-such-port" diff --git a/crates/fbuild-deploy/src/wchisp.rs b/crates/fbuild-deploy/src/wchisp.rs index ef0febb14..2de1ddafa 100644 --- a/crates/fbuild-deploy/src/wchisp.rs +++ b/crates/fbuild-deploy/src/wchisp.rs @@ -17,7 +17,10 @@ struct WchispAsset { } fn release_asset() -> Result { - match (std::env::consts::OS, std::env::consts::ARCH) { + match ( + fbuild_core::platform::host::os_name(), + fbuild_core::platform::host::arch_name(), + ) { ("windows", "x86_64") => Ok(WchispAsset { name: "wchisp-v0.3.0-win-x64.zip", sha256: "eba605bbc62f217f6454e7236d04ef1b8a6b4396dd7ce8dc26fc83016213c3aa", @@ -45,11 +48,13 @@ fn release_asset() -> Result { } fn managed_wchisp_path() -> Result { - let home = std::env::var_os(if cfg!(windows) { "USERPROFILE" } else { "HOME" }) - .map(PathBuf::from) - .ok_or_else(|| { - FbuildError::PackageError("could not determine home directory".to_string()) - })?; + let home = std::env::var_os(if fbuild_core::platform::host::is_windows() { + "USERPROFILE" + } else { + "HOME" + }) + .map(PathBuf::from) + .ok_or_else(|| FbuildError::PackageError("could not determine home directory".to_string()))?; let mode = if std::env::var_os("FBUILD_DEV_MODE").is_some() { "dev" } else { @@ -60,11 +65,7 @@ fn managed_wchisp_path() -> Result { .join(mode) .join("tools") .join("wchisp") - .join(if cfg!(windows) { - "wchisp.exe" - } else { - "wchisp" - })) + .join(fbuild_core::platform::executable::native_name("wchisp"))) } async fn ensure_wchisp_installed() -> Result { @@ -114,12 +115,8 @@ fn extract_wchisp(archive: &Path, staging: &Path, dest: &Path) -> Result<()> { .unpack(&extract_dir) .map_err(|e| FbuildError::PackageError(format!("extract wchisp archive: {e}")))?; } - let name = if cfg!(windows) { - "wchisp.exe" - } else { - "wchisp" - }; - let binary = find_file(&extract_dir, name) + let name = fbuild_core::platform::executable::native_name("wchisp"); + let binary = find_file(&extract_dir, &name) .ok_or_else(|| FbuildError::PackageError(format!("wchisp archive lacks {name}")))?; if let Some(parent) = dest.parent() { std::fs::create_dir_all(parent) @@ -171,11 +168,7 @@ impl WchispDeployer { executable: std::env::var_os("FBUILD_WCHISP_PATH") .map(PathBuf::from) .unwrap_or_else(|| { - PathBuf::from(if cfg!(windows) { - "wchisp.exe" - } else { - "wchisp" - }) + PathBuf::from(fbuild_core::platform::executable::native_name("wchisp")) }), } } diff --git a/crates/fbuild-deploy/src/wlink.rs b/crates/fbuild-deploy/src/wlink.rs index 10c2f30f6..156bdb2c1 100644 --- a/crates/fbuild-deploy/src/wlink.rs +++ b/crates/fbuild-deploy/src/wlink.rs @@ -22,7 +22,10 @@ struct WlinkAsset { } fn release_asset() -> Result { - match (std::env::consts::OS, std::env::consts::ARCH) { + match ( + fbuild_core::platform::host::os_name(), + fbuild_core::platform::host::arch_name(), + ) { ("windows", "x86_64") => Ok(WlinkAsset { name: "wlink-v0.1.2-win-x64.zip", sha256: "59b3989137a9d22c9c1e8c04fd9371af3f54fa43b4cb63c59d6fb4286a34c78a", @@ -42,11 +45,13 @@ fn release_asset() -> Result { } fn managed_wlink_path() -> Result { - let home = std::env::var_os(if cfg!(windows) { "USERPROFILE" } else { "HOME" }) - .map(PathBuf::from) - .ok_or_else(|| { - FbuildError::PackageError("could not determine home directory".to_string()) - })?; + let home = std::env::var_os(if fbuild_core::platform::host::is_windows() { + "USERPROFILE" + } else { + "HOME" + }) + .map(PathBuf::from) + .ok_or_else(|| FbuildError::PackageError("could not determine home directory".to_string()))?; let mode = if std::env::var_os("FBUILD_DEV_MODE").is_some() { "dev" } else { @@ -57,7 +62,7 @@ fn managed_wlink_path() -> Result { .join(mode) .join("tools") .join("wlink") - .join(if cfg!(windows) { "wlink.exe" } else { "wlink" })) + .join(fbuild_core::platform::executable::native_name("wlink"))) } async fn ensure_wlink_installed() -> Result { @@ -108,8 +113,8 @@ fn extract_wlink(archive: &Path, staging: &Path, dest: &Path) -> Result<()> { tar.unpack(&extract_dir) .map_err(|e| FbuildError::PackageError(format!("extract wlink archive: {e}")))?; } - let binary_name = if cfg!(windows) { "wlink.exe" } else { "wlink" }; - let binary = find_file(&extract_dir, binary_name) + let binary_name = fbuild_core::platform::executable::native_name("wlink"); + let binary = find_file(&extract_dir, &binary_name) .ok_or_else(|| FbuildError::PackageError(format!("wlink archive lacks {binary_name}")))?; if let Some(parent) = dest.parent() { std::fs::create_dir_all(parent) @@ -147,7 +152,9 @@ impl WlinkDeployer { pub fn new() -> Self { let executable = std::env::var_os("FBUILD_WLINK_PATH") .map(PathBuf::from) - .unwrap_or_else(|| PathBuf::from(if cfg!(windows) { "wlink.exe" } else { "wlink" })); + .unwrap_or_else(|| { + PathBuf::from(fbuild_core::platform::executable::native_name("wlink")) + }); Self { executable } } diff --git a/crates/fbuild-library/src/library/esptool.rs b/crates/fbuild-library/src/library/esptool.rs index ed60dda09..57c0e19b3 100644 --- a/crates/fbuild-library/src/library/esptool.rs +++ b/crates/fbuild-library/src/library/esptool.rs @@ -278,7 +278,10 @@ async fn verify_esptool_binary(bin: &Path) -> Result<()> { /// Returns `None` for hosts without a prebuilt binary, so the caller falls /// back to an `esptool` on PATH. fn tasmota_platform_tag() -> Option<&'static str> { - match (std::env::consts::OS, std::env::consts::ARCH) { + match ( + fbuild_core::platform::host::os_name(), + fbuild_core::platform::host::arch_name(), + ) { ("linux", "x86_64") => Some("linux-amd64"), ("linux", "aarch64") => Some("linux-aarch64"), ("linux", "arm") => Some("linux-armv7"), @@ -296,19 +299,15 @@ fn host_platform_tag() -> Result<&'static str> { FbuildError::PackageError(format!( "no prebuilt esptool binary for {}/{} — set {ESPTOOL_PATH_ENV_VAR} \ to an esptool executable", - std::env::consts::OS, - std::env::consts::ARCH + fbuild_core::platform::host::os_name(), + fbuild_core::platform::host::arch_name() )) }) } /// Executable name for the current platform. fn esptool_bin_name() -> &'static str { - if cfg!(windows) { - "esptool.exe" - } else { - "esptool" - } + fbuild_core::platform::executable::name("esptool", "esptool.exe") } /// Locate the `esptool` executable in an extracted tree, searching the root and diff --git a/crates/fbuild-library/src/library/library_compiler.rs b/crates/fbuild-library/src/library/library_compiler.rs index b9e71989c..57b7b4a52 100644 --- a/crates/fbuild-library/src/library/library_compiler.rs +++ b/crates/fbuild-library/src/library/library_compiler.rs @@ -463,7 +463,7 @@ async fn compile_one_source( } else { // On Windows, put ALL flags in a response file to avoid command-line // length limits (OS error 206): `[zccache] @response.rsp`. - let args = if cfg!(windows) { + let args = if fbuild_core::platform::host::is_windows() { let rsp_path = fbuild_core::response_file::write_response_file( &all_flags, &rsp_dir, @@ -652,7 +652,7 @@ async fn build_include_flags(include_dirs: &[PathBuf], _temp_dir: &Path) -> Resu .map(|d| format!("-I{}", d.display())) .collect(); - if cfg!(windows) && flags.len() > 100 { + if fbuild_core::platform::host::is_windows() && flags.len() > 100 { let rsp_dir = _temp_dir.join("tmp"); let rsp_path = fbuild_core::response_file::write_response_file(&flags, &rsp_dir, "lib_includes") diff --git a/crates/fbuild-library/src/library/library_spec.rs b/crates/fbuild-library/src/library/library_spec.rs index aa5f853af..a3ff0370e 100644 --- a/crates/fbuild-library/src/library/library_spec.rs +++ b/crates/fbuild-library/src/library/library_spec.rs @@ -69,7 +69,7 @@ impl LibrarySpec { } // `file:///C:/path` is the standard Windows spelling. Paths use a // leading slash in URI form, but Windows needs the drive prefix. - let path = if cfg!(windows) + let path = if fbuild_core::platform::host::is_windows() && path.len() > 2 && path.as_bytes()[0] == b'/' && path.as_bytes()[2] == b':' diff --git a/crates/fbuild-packages-fetch/src/install_lock.rs b/crates/fbuild-packages-fetch/src/install_lock.rs index a2aa010fd..f98fb172d 100644 --- a/crates/fbuild-packages-fetch/src/install_lock.rs +++ b/crates/fbuild-packages-fetch/src/install_lock.rs @@ -174,7 +174,7 @@ fn write_lock_owner(lock_dir: &Path, package_name: &str, package_version: &str) /// File stem of the running executable, used to make the liveness probe /// PID-recycling-safe. fn current_exe_stem() -> Option { - std::env::current_exe() + fbuild_core::platform::executable::current_image() .ok()? .file_stem() .and_then(|s| s.to_str()) @@ -236,7 +236,7 @@ fn owner_is_dead(owner: &LockOwner) -> bool { } fn stem_eq(left: &str, right: &str) -> bool { - if cfg!(windows) { + if fbuild_core::platform::host::is_windows() { left.eq_ignore_ascii_case(right) } else { left == right diff --git a/crates/fbuild-paths/src/daemon_ownership.rs b/crates/fbuild-paths/src/daemon_ownership.rs index 54f73d8a0..57e172fe1 100644 --- a/crates/fbuild-paths/src/daemon_ownership.rs +++ b/crates/fbuild-paths/src/daemon_ownership.rs @@ -369,7 +369,8 @@ mod tests { let path = temp.path().join("root-owner.lock"); let run_probe = |expected: &str| { - let executable = std::env::current_exe().expect("current test executable"); + let executable = fbuild_core::platform::executable::current_image() + .expect("current test executable"); let executable = executable.to_string_lossy(); let lock_path = path.to_string_lossy(); let args = [ diff --git a/crates/fbuild-paths/src/lib.rs b/crates/fbuild-paths/src/lib.rs index ed3a3a510..df56e7389 100644 --- a/crates/fbuild-paths/src/lib.rs +++ b/crates/fbuild-paths/src/lib.rs @@ -90,18 +90,14 @@ pub fn default_daemon_port() -> u16 { /// Map a hex endpoint key into the platform's default daemon-port window. /// Pure and deterministic (unit-tested). fn port_from_endpoint_key(key: &str) -> u16 { - #[cfg(windows)] - const LOW: u32 = 10000; - #[cfg(windows)] - const SPAN: u32 = 49152 - LOW; - - #[cfg(not(windows))] - const LOW: u32 = 49152; - #[cfg(not(windows))] - const SPAN: u32 = 65536 - LOW; + let (low, span): (u32, u32) = if fbuild_core::platform::host::is_windows() { + (10000, 49152 - 10000) + } else { + (49152, 65536 - 49152) + }; let n = u64::from_str_radix(key, 16).unwrap_or(0); - (LOW + (n % u64::from(SPAN)) as u32) as u16 + (low + (n % u64::from(span)) as u32) as u16 } /// Daemon port file path (written by daemon so clients can discover the port). @@ -447,12 +443,9 @@ pub fn find_firmware_dir(project_dir: &Path, env_name: &str) -> Option } fn dirs_next() -> Option { - #[cfg(target_os = "windows")] - { + if fbuild_core::platform::host::is_windows() { std::env::var("USERPROFILE").ok().map(PathBuf::from) - } - #[cfg(not(target_os = "windows"))] - { + } else { std::env::var("HOME").ok().map(PathBuf::from) } } @@ -526,24 +519,20 @@ mod tests { assert!(live.chars().all(|c| c.is_ascii_hexdigit())); } - #[cfg(not(windows))] - #[test] - fn default_daemon_port_is_in_dynamic_range() { - let p = default_daemon_port(); - assert!( - (49152..=65535).contains(&p), - "port {p} outside dynamic range" - ); - } - - #[cfg(windows)] #[test] - fn default_daemon_port_avoids_windows_dynamic_exclusion_range() { + fn default_daemon_port_is_in_host_range() { let p = default_daemon_port(); - assert!( - (10000..49152).contains(&p), - "Windows daemon port {p} overlaps the dynamic exclusion range" - ); + if fbuild_core::platform::host::is_windows() { + assert!( + (10000..49152).contains(&p), + "Windows daemon port {p} overlaps the dynamic exclusion range" + ); + } else { + assert!( + (49152..=65535).contains(&p), + "port {p} outside dynamic range" + ); + } } #[test] @@ -556,10 +545,14 @@ mod tests { ); for key in ["0000000000000000", "ffffffffffffffff", "deadbeefcafef00d"] { let p = port_from_endpoint_key(key); - #[cfg(windows)] - assert!((10000..49152).contains(&p), "key {key} → {p} out of range"); - #[cfg(not(windows))] - assert!((49152..=65535).contains(&p), "key {key} → {p} out of range"); + if fbuild_core::platform::host::is_windows() { + assert!((10000..49152).contains(&p), "key {key} -> {p} out of range"); + } else { + assert!( + (49152..=65535).contains(&p), + "key {key} -> {p} out of range" + ); + } } // Two distinct version/identity keys should not collapse to one port // for these representative values. diff --git a/crates/fbuild-paths/src/running_process.rs b/crates/fbuild-paths/src/running_process.rs index 2b51fc9b2..650033b09 100644 --- a/crates/fbuild-paths/src/running_process.rs +++ b/crates/fbuild-paths/src/running_process.rs @@ -46,10 +46,8 @@ pub const FBUILD_RUNNING_PROCESS_BROKER_ENV: &str = "FBUILD_RUNNING_PROCESS_BROK pub const FBUILD_CACHE_DIR_ENV: &str = "FBUILD_CACHE_DIR"; pub const LOCAL_TRUST_DOMAIN: &str = "local-shared"; -#[cfg(windows)] -pub const DAEMON_BINARY_NAME: &str = "fbuild-daemon.exe"; -#[cfg(not(windows))] -pub const DAEMON_BINARY_NAME: &str = "fbuild-daemon"; +pub const DAEMON_BINARY_NAME: &str = + fbuild_core::platform::executable::name("fbuild-daemon", "fbuild-daemon.exe"); #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum RunningProcessDaemonMode { @@ -224,33 +222,29 @@ impl CacheRoots { } } -#[cfg(windows)] fn platform_service_definition_dir() -> PathBuf { - std::env::var_os("APPDATA") - .map(PathBuf::from) - .or_else(|| { - std::env::var_os("USERPROFILE") - .map(|home| PathBuf::from(home).join("AppData").join("Roaming")) - }) - .unwrap_or_else(|| PathBuf::from(r"C:\ProgramData")) - .join("running-process") - .join("services") -} - -#[cfg(target_os = "macos")] -fn platform_service_definition_dir() -> PathBuf { - if let Some(home) = std::env::var_os("HOME") { - return PathBuf::from(home) - .join("Library") - .join("Application Support") + if fbuild_core::platform::host::is_windows() { + return std::env::var_os("APPDATA") + .map(PathBuf::from) + .or_else(|| { + std::env::var_os("USERPROFILE") + .map(|home| PathBuf::from(home).join("AppData").join("Roaming")) + }) + .unwrap_or_else(|| PathBuf::from(r"C:\ProgramData")) .join("running-process") .join("services"); } - fbuild_owned_service_definition_dir() -} - -#[cfg(all(unix, not(target_os = "macos")))] -fn platform_service_definition_dir() -> PathBuf { + if fbuild_core::platform::host::is_macos() { + return std::env::var_os("HOME") + .map(PathBuf::from) + .map(|home| { + home.join("Library") + .join("Application Support") + .join("running-process") + .join("services") + }) + .unwrap_or_else(fbuild_owned_service_definition_dir); + } if let Some(config_home) = std::env::var_os("XDG_CONFIG_HOME") .map(PathBuf::from) .or_else(|| std::env::var_os("HOME").map(|home| PathBuf::from(home).join(".config"))) @@ -260,7 +254,6 @@ fn platform_service_definition_dir() -> PathBuf { fbuild_owned_service_definition_dir() } -#[cfg(any(target_os = "macos", all(unix, not(target_os = "macos"))))] fn fbuild_owned_service_definition_dir() -> PathBuf { crate::get_cache_root() .join("running-process") @@ -319,9 +312,11 @@ mod tests { ); } - #[cfg(all(unix, not(target_os = "macos")))] #[test] fn service_definition_dir_falls_back_to_fbuild_cache_root_without_home() { + if !fbuild_core::platform::host::is_linux() { + return; + } let _env = ENV_LOCK.lock().unwrap(); let cache_root = crate::temp_subdir(&format!( "fbuild-service-def-cache-root-{}", diff --git a/crates/fbuild-python/src/daemon.rs b/crates/fbuild-python/src/daemon.rs index 7bcca954e..8c25f056a 100644 --- a/crates/fbuild-python/src/daemon.rs +++ b/crates/fbuild-python/src/daemon.rs @@ -11,10 +11,8 @@ use running_process::broker::client::RefusalKind; /// Windows ships `fbuild-daemon.exe`; Unix-like systems ship `fbuild-daemon`. /// Kept as a single constant so the venv-adjacent lookup and the PATH /// fallback agree on the name. -#[cfg(windows)] -const DAEMON_BIN_NAME: &str = "fbuild-daemon.exe"; -#[cfg(not(windows))] -const DAEMON_BIN_NAME: &str = "fbuild-daemon"; +const DAEMON_BIN_NAME: &str = + fbuild_core::platform::executable::name("fbuild-daemon", "fbuild-daemon.exe"); /// Look for `fbuild-daemon[.exe]` next to `sys.executable` (FastLED/fbuild#275). /// @@ -70,7 +68,7 @@ fn shutdown_caller_headers() -> reqwest::header::HeaderMap { cwd.to_string_lossy().into_owned(), ); } - if let Ok(exe) = std::env::current_exe() { + if let Ok(exe) = fbuild_core::platform::executable::current_image() { insert_shutdown_header( &mut headers, "x-fbuild-client-exe", @@ -475,10 +473,10 @@ mod tests { // The lookup file name must agree with what gets installed by // maturin / pip — on Windows that is `fbuild-daemon.exe`, on // Unix it is unsuffixed. - #[cfg(windows)] - assert_eq!(DAEMON_BIN_NAME, "fbuild-daemon.exe"); - #[cfg(not(windows))] - assert_eq!(DAEMON_BIN_NAME, "fbuild-daemon"); + assert_eq!( + DAEMON_BIN_NAME, + fbuild_core::platform::executable::name("fbuild-daemon", "fbuild-daemon.exe") + ); } #[test] diff --git a/crates/fbuild-python/src/messages.rs b/crates/fbuild-python/src/messages.rs index 5eaa06c8f..d1473130e 100644 --- a/crates/fbuild-python/src/messages.rs +++ b/crates/fbuild-python/src/messages.rs @@ -25,7 +25,7 @@ impl ClientMetadata { pub(crate) fn current() -> Self { Self { pid: Some(std::process::id()), - exe: std::env::current_exe() + exe: fbuild_core::platform::executable::current_image() .ok() .map(|p| p.to_string_lossy().into_owned()), cwd: std::env::current_dir() diff --git a/crates/fbuild-serial/src/boards.rs b/crates/fbuild-serial/src/boards.rs index 8d01342e8..ac8a144ee 100644 --- a/crates/fbuild-serial/src/boards.rs +++ b/crates/fbuild-serial/src/boards.rs @@ -944,7 +944,7 @@ pub fn family_for_port_or_default(name: &str) -> BoardFamily { } fn serial_port_name_matches(candidate: &str, requested: &str) -> bool { - if cfg!(windows) { + if fbuild_core::platform::host::is_windows() { candidate.eq_ignore_ascii_case(requested) } else { candidate == requested diff --git a/crates/fbuild-serial/src/crash_decoder.rs b/crates/fbuild-serial/src/crash_decoder.rs index 4db3626ed..8867793bf 100644 --- a/crates/fbuild-serial/src/crash_decoder.rs +++ b/crates/fbuild-serial/src/crash_decoder.rs @@ -390,8 +390,9 @@ pub fn derive_addr2line_path(cc_path: &Path) -> Option { } let prefix = &stem[..stem.len() - 3]; // e.g. "riscv32-esp-elf-" - let suffix = if cfg!(windows) { ".exe" } else { "" }; - let addr2line = cc_path.parent()?.join(format!("{prefix}addr2line{suffix}")); + let addr2line_name = + fbuild_core::platform::executable::native_name(&format!("{prefix}addr2line")); + let addr2line = cc_path.parent()?.join(addr2line_name); if addr2line.exists() { Some(addr2line) @@ -759,10 +760,10 @@ mod tests { let home = std::env::var("USERPROFILE") .or_else(|_| std::env::var("HOME")) .unwrap_or_default(); + let executable = + fbuild_core::platform::executable::native_name("xtensa-esp-elf-addr2line"); fbuild_core::path::NormalizedPath::from(format!( - "{}/.platformio/packages/toolchain-xtensa-esp-elf/bin/xtensa-esp-elf-addr2line{}", - home, - if cfg!(windows) { ".exe" } else { "" } + "{home}/.platformio/packages/toolchain-xtensa-esp-elf/bin/{executable}" )) .display_slash() })); diff --git a/crates/fbuild-serial/src/manager.rs b/crates/fbuild-serial/src/manager.rs index 4ffd9046a..9fcdc539d 100644 --- a/crates/fbuild-serial/src/manager.rs +++ b/crates/fbuild-serial/src/manager.rs @@ -121,7 +121,11 @@ impl SharedSerialManager { // permission denied, no device) bubble up quickly instead of stalling // the daemon's WebSocket clients for 4+ minutes. The previous schedule // had 30 retries × ~10s ≈ 5 minutes which deadlocked self-eviction. - let max_retries: usize = if cfg!(windows) { 8 } else { 6 }; + let max_retries: usize = if fbuild_core::platform::host::is_windows() { + 8 + } else { + 6 + }; let backoff_schedule = [250u64, 500, 1000, 2000, 3000]; // ms let port_name = port.to_string(); @@ -749,7 +753,11 @@ impl SharedSerialManager { session_key )) })?; - let max_retries: usize = if cfg!(windows) { 8 } else { 6 }; + let max_retries: usize = if fbuild_core::platform::host::is_windows() { + 8 + } else { + 6 + }; let serial_handle = Arc::new(Mutex::new( Self::open_physical_serial(new_port, baud_rate, max_retries).await?, )); diff --git a/crates/fbuild-toolchain/src/toolchain/arm.rs b/crates/fbuild-toolchain/src/toolchain/arm.rs index b502da038..b76c0ec58 100644 --- a/crates/fbuild-toolchain/src/toolchain/arm.rs +++ b/crates/fbuild-toolchain/src/toolchain/arm.rs @@ -194,11 +194,13 @@ fn all_platform_packages() -> [(&'static str, ArmPlatformPackage); 4] { /// Get the platform-specific download URL and optional checksum for the current host. fn platform_package() -> (String, Option) { - let key = if cfg!(target_os = "windows") { + let key = if fbuild_core::platform::host::is_windows() { "windows" - } else if cfg!(target_os = "macos") { + } else if fbuild_core::platform::host::is_macos() { "macos" - } else if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "linux-aarch64" } else { "linux-x86_64" @@ -239,11 +241,7 @@ fn find_bin_root(install_dir: &Path) -> PathBuf { /// Get the tool binary name with .exe extension on Windows. fn tool_name(name: &str) -> String { - if cfg!(windows) { - format!("{}.exe", name) - } else { - name.to_string() - } + fbuild_core::platform::executable::native_name(name) } /// Get the full path to a tool binary. @@ -267,11 +265,10 @@ mod tests { #[test] fn test_tool_name_platform() { let name = tool_name("arm-none-eabi-gcc"); - if cfg!(windows) { - assert_eq!(name, "arm-none-eabi-gcc.exe"); - } else { - assert_eq!(name, "arm-none-eabi-gcc"); - } + assert_eq!( + name, + fbuild_core::platform::executable::native_name("arm-none-eabi-gcc") + ); } #[test] diff --git a/crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs b/crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs index 42d59ffcc..42e75d56b 100644 --- a/crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs +++ b/crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs @@ -120,12 +120,12 @@ const PIO_DL_BASE: &str = "https://dl.registry.platformio.org/download/platformi /// Get the platform-specific download URL and optional SHA-256 checksum. fn platform_package() -> (&'static str, Option<&'static str>) { - if cfg!(target_os = "windows") { + if fbuild_core::platform::host::is_windows() { ( "toolchain-gccarmnoneeabi-windows_amd64-1.90201.191206.tar.gz", Some("31301e144002f2043f60c518b87327dfcfca9f1dc0c1add72322d553d5733f0e"), ) - } else if cfg!(target_os = "macos") { + } else if fbuild_core::platform::host::is_macos() { ( "toolchain-gccarmnoneeabi-darwin_x86_64-1.90201.191206.tar.gz", Some("309fb7cd5c1b12f1ba8daa6f7554cc95c96a81246b6ff4833cbb31436f8f6add"), @@ -162,11 +162,7 @@ fn find_bin_root(install_dir: &Path) -> PathBuf { } fn tool_name(name: &str) -> String { - if cfg!(windows) { - format!("{}.exe", name) - } else { - name.to_string() - } + fbuild_core::platform::executable::native_name(name) } fn tool_binary(bin_dir: &Path, name: &str) -> PathBuf { diff --git a/crates/fbuild-toolchain/src/toolchain/avr.rs b/crates/fbuild-toolchain/src/toolchain/avr.rs index 990b5b3b9..a8c2dfeb7 100644 --- a/crates/fbuild-toolchain/src/toolchain/avr.rs +++ b/crates/fbuild-toolchain/src/toolchain/avr.rs @@ -201,11 +201,13 @@ fn all_platform_packages() -> [(&'static str, AvrPlatformPackage); 4] { /// Get the platform-specific download URL and optional checksum for the current host. fn platform_package() -> (String, Option) { - let key = if cfg!(target_os = "windows") { + let key = if fbuild_core::platform::host::is_windows() { "windows" - } else if cfg!(target_os = "macos") { + } else if fbuild_core::platform::host::is_macos() { "macos" - } else if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "linux-aarch64" } else { "linux-x86_64" @@ -248,11 +250,7 @@ fn find_bin_root(install_dir: &Path) -> PathBuf { /// Get the tool binary name with .exe extension on Windows. fn tool_name(name: &str) -> String { - if cfg!(windows) { - format!("{}.exe", name) - } else { - name.to_string() - } + fbuild_core::platform::executable::native_name(name) } /// Get the full path to a tool binary. @@ -380,11 +378,10 @@ mod tests { #[test] fn test_tool_name_platform() { let name = tool_name("avr-gcc"); - if cfg!(windows) { - assert_eq!(name, "avr-gcc.exe"); - } else { - assert_eq!(name, "avr-gcc"); - } + assert_eq!( + name, + fbuild_core::platform::executable::native_name("avr-gcc") + ); } #[test] diff --git a/crates/fbuild-toolchain/src/toolchain/clang.rs b/crates/fbuild-toolchain/src/toolchain/clang.rs index c3622525e..a24352b33 100644 --- a/crates/fbuild-toolchain/src/toolchain/clang.rs +++ b/crates/fbuild-toolchain/src/toolchain/clang.rs @@ -106,11 +106,7 @@ impl ClangComponent { /// Calls `ensure_installed()` internally. pub async fn get_binary(&self, name: &str) -> fbuild_core::Result { let install_dir = self.ensure_installed().await?; - let binary_name = if cfg!(windows) { - format!("{}.exe", name) - } else { - name.to_string() - }; + let binary_name = fbuild_core::platform::executable::native_name(name); find_binary_in_dir(&install_dir, &binary_name).ok_or_else(|| { fbuild_core::FbuildError::Other(format!( "'{}' not found in {} installation at {}", @@ -244,11 +240,7 @@ impl ClangComponent { fn validate(kind: ClangComponentKind, dir: &Path) -> fbuild_core::Result<()> { for name in kind.required_binaries() { - let binary_name = if cfg!(windows) { - format!("{}.exe", name) - } else { - (*name).to_string() - }; + let binary_name = fbuild_core::platform::executable::native_name(name); if find_binary_in_dir(dir, &binary_name).is_none() { return Err(fbuild_core::FbuildError::PackageError(format!( "'{}' not found in extracted {} archive", @@ -346,9 +338,9 @@ fn find_gcc_includes_recursive(dir: &Path, depth: u32, out: &mut Vec) { } fn platform() -> &'static str { - if cfg!(target_os = "windows") { + if fbuild_core::platform::host::is_windows() { "win" - } else if cfg!(target_os = "macos") { + } else if fbuild_core::platform::host::is_macos() { "darwin" } else { "linux" @@ -356,7 +348,9 @@ fn platform() -> &'static str { } fn arch() -> &'static str { - if cfg!(target_arch = "aarch64") { + if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "arm64" } else { "x86_64" @@ -417,12 +411,8 @@ mod tests { let dir = tempfile::tempdir().unwrap(); let bin_dir = dir.path().join("bin"); std::fs::create_dir_all(&bin_dir).unwrap(); - let name = if cfg!(windows) { - "clang-tidy.exe" - } else { - "clang-tidy" - }; - std::fs::write(bin_dir.join(name), b"fake").unwrap(); + let name = fbuild_core::platform::executable::native_name("clang-tidy"); + std::fs::write(bin_dir.join(&name), b"fake").unwrap(); let result = ClangComponent::validate(ClangComponentKind::ClangExtra, dir.path()); assert!(result.is_ok()); } @@ -432,13 +422,9 @@ mod tests { let dir = tempfile::tempdir().unwrap(); let nested = dir.path().join("llvm-21.1.5").join("bin"); std::fs::create_dir_all(&nested).unwrap(); - let name = if cfg!(windows) { - "clang-tidy.exe" - } else { - "clang-tidy" - }; - std::fs::write(nested.join(name), b"fake").unwrap(); - assert!(find_binary_in_dir(dir.path(), name).is_some()); + let name = fbuild_core::platform::executable::native_name("clang-tidy"); + std::fs::write(nested.join(&name), b"fake").unwrap(); + assert!(find_binary_in_dir(dir.path(), &name).is_some()); } #[test] diff --git a/crates/fbuild-toolchain/src/toolchain/esp32.rs b/crates/fbuild-toolchain/src/toolchain/esp32.rs index c552a4ebd..ba402e626 100644 --- a/crates/fbuild-toolchain/src/toolchain/esp32.rs +++ b/crates/fbuild-toolchain/src/toolchain/esp32.rs @@ -293,15 +293,19 @@ fn platform_package(is_riscv: bool) -> (String, Option) { "xtensa-esp-elf" }; - let key = if cfg!(target_os = "windows") { + let key = if fbuild_core::platform::host::is_windows() { "windows" - } else if cfg!(target_os = "macos") { - if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::is_macos() { + if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "macos-arm64" } else { "macos-x86_64" } - } else if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "linux-aarch64" } else { "linux-x86_64" @@ -366,11 +370,7 @@ fn find_bin_root(install_dir: &Path) -> PathBuf { /// Get the tool binary name with .exe extension on Windows. fn tool_name(name: &str) -> String { - if cfg!(windows) { - format!("{}.exe", name) - } else { - name.to_string() - } + fbuild_core::platform::executable::native_name(name) } /// Get the full path to a tool binary. @@ -400,11 +400,10 @@ mod tests { #[test] fn test_tool_name_platform() { let name = tool_name("riscv32-esp-elf-gcc"); - if cfg!(windows) { - assert_eq!(name, "riscv32-esp-elf-gcc.exe"); - } else { - assert_eq!(name, "riscv32-esp-elf-gcc"); - } + assert_eq!( + name, + fbuild_core::platform::executable::native_name("riscv32-esp-elf-gcc") + ); } #[test] diff --git a/crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs b/crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs index a8bfa693a..56f234f82 100644 --- a/crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs +++ b/crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs @@ -38,15 +38,19 @@ pub struct ResolvedToolchain { /// Returns a key matching the platform entries in tools.json: /// `"win64"`, `"linux-amd64"`, `"linux-arm64"`, `"macos"`, `"macos-arm64"` pub fn detect_platform() -> &'static str { - if cfg!(target_os = "windows") { + if fbuild_core::platform::host::is_windows() { "win64" - } else if cfg!(target_os = "macos") { - if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::is_macos() { + if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "macos-arm64" } else { "macos" } - } else if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "linux-arm64" } else { "linux-amd64" diff --git a/crates/fbuild-toolchain/src/toolchain/esp8266.rs b/crates/fbuild-toolchain/src/toolchain/esp8266.rs index 8fafd3b91..16c06d6d8 100644 --- a/crates/fbuild-toolchain/src/toolchain/esp8266.rs +++ b/crates/fbuild-toolchain/src/toolchain/esp8266.rs @@ -191,15 +191,19 @@ fn all_platform_packages() -> [(&'static str, PlatformPackage); 5] { } fn platform_package() -> (String, Option) { - let key = if cfg!(target_os = "windows") { + let key = if fbuild_core::platform::host::is_windows() { "windows" - } else if cfg!(target_os = "macos") { - if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::is_macos() { + if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "macos-arm64" } else { "macos-x86_64" } - } else if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "linux-aarch64" } else { "linux-x86_64" @@ -239,11 +243,7 @@ fn find_bin_root(install_dir: &Path) -> PathBuf { } fn tool_name(name: &str) -> String { - if cfg!(windows) { - format!("{name}.exe") - } else { - name.to_string() - } + fbuild_core::platform::executable::native_name(name) } fn tool_binary(bin_dir: &Path, name: &str) -> PathBuf { @@ -265,11 +265,10 @@ mod tests { #[test] fn test_tool_name_platform() { let name = tool_name("xtensa-lx106-elf-gcc"); - if cfg!(windows) { - assert_eq!(name, "xtensa-lx106-elf-gcc.exe"); - } else { - assert_eq!(name, "xtensa-lx106-elf-gcc"); - } + assert_eq!( + name, + fbuild_core::platform::executable::native_name("xtensa-lx106-elf-gcc") + ); } #[test] diff --git a/crates/fbuild-toolchain/src/toolchain/esp_qemu.rs b/crates/fbuild-toolchain/src/toolchain/esp_qemu.rs index c278847c1..47f8269cb 100644 --- a/crates/fbuild-toolchain/src/toolchain/esp_qemu.rs +++ b/crates/fbuild-toolchain/src/toolchain/esp_qemu.rs @@ -14,6 +14,7 @@ use std::path::{Path, PathBuf}; +use fbuild_core::platform::host::{self, HostArch, HostPlatform}; use fbuild_core::{FbuildError, Result}; use crate::{CacheSubdir, Package, PackageBase, PackageInfo}; @@ -71,11 +72,15 @@ impl EspQemuArch { } fn binary_name(self) -> &'static str { - match (self, cfg!(windows)) { - (Self::Xtensa, true) => "qemu-system-xtensa.exe", - (Self::Xtensa, false) => "qemu-system-xtensa", - (Self::Riscv32, true) => "qemu-system-riscv32.exe", - (Self::Riscv32, false) => "qemu-system-riscv32", + match self { + Self::Xtensa => fbuild_core::platform::executable::name( + "qemu-system-xtensa", + "qemu-system-xtensa.exe", + ), + Self::Riscv32 => fbuild_core::platform::executable::name( + "qemu-system-riscv32", + "qemu-system-riscv32.exe", + ), } } } @@ -357,34 +362,38 @@ struct PlatformPackage { } fn platform_package(arch: EspQemuArch) -> Result { + platform_package_for(host::current(), arch) +} + +fn platform_package_for(host: HostPlatform, arch: EspQemuArch) -> Result { match arch { - EspQemuArch::Xtensa => xtensa_platform_package(), - EspQemuArch::Riscv32 => riscv32_platform_package(), + EspQemuArch::Xtensa => xtensa_platform_package(host), + EspQemuArch::Riscv32 => riscv32_platform_package(host), } } -fn xtensa_platform_package() -> Result { - if cfg!(target_os = "windows") && cfg!(target_arch = "x86_64") { +fn xtensa_platform_package(host: HostPlatform) -> Result { + if host.is_windows() && host.arch() == HostArch::X86_64 { Ok(PlatformPackage { archive_suffix: "x86_64-w64-mingw32", sha256: "ef550b912726997f3c1ff4a4fb13c1569e2b692efdc5c9f9c3c926a8f7c540fa", }) - } else if cfg!(target_os = "linux") && cfg!(target_arch = "x86_64") { + } else if host.is_linux() && host.arch() == HostArch::X86_64 { Ok(PlatformPackage { archive_suffix: "x86_64-linux-gnu", sha256: "588bfaccd0f929650655d10a580f020c6ba9c131712d8fa519280081b8d126eb", }) - } else if cfg!(target_os = "linux") && cfg!(target_arch = "aarch64") { + } else if host.is_linux() && host.arch() == HostArch::Aarch64 { Ok(PlatformPackage { archive_suffix: "aarch64-linux-gnu", sha256: "317f6e0fd1dba0886d8110709823d909593ef29438822a14f81ebe19d72ce7cd", }) - } else if cfg!(target_os = "macos") && cfg!(target_arch = "x86_64") { + } else if host.is_macos() && host.arch() == HostArch::X86_64 { Ok(PlatformPackage { archive_suffix: "x86_64-apple-darwin", sha256: "00b9dbc2124cf7633cb86f264fbc524226ad4001bce68bbdba43c9bdc4eb026e", }) - } else if cfg!(target_os = "macos") && cfg!(target_arch = "aarch64") { + } else if host.is_macos() && host.arch() == HostArch::Aarch64 { Ok(PlatformPackage { archive_suffix: "aarch64-apple-darwin", sha256: "aa92e337461d482f5d9f31cd8efc0bd67b3de8fcfcfb567289cb43a59c184651", @@ -392,34 +401,34 @@ fn xtensa_platform_package() -> Result { } else { Err(FbuildError::PackageError(format!( "native QEMU (xtensa) is not supported on {}-{}", - std::env::consts::OS, - std::env::consts::ARCH + host.os_name(), + host.arch_name() ))) } } -fn riscv32_platform_package() -> Result { - if cfg!(target_os = "windows") && cfg!(target_arch = "x86_64") { +fn riscv32_platform_package(host: HostPlatform) -> Result { + if host.is_windows() && host.arch() == HostArch::X86_64 { Ok(PlatformPackage { archive_suffix: "x86_64-w64-mingw32", sha256: "9474015f24d27acb7516955ec932e5307226bd9d6652cdc870793ed36010ab73", }) - } else if cfg!(target_os = "linux") && cfg!(target_arch = "x86_64") { + } else if host.is_linux() && host.arch() == HostArch::X86_64 { Ok(PlatformPackage { archive_suffix: "x86_64-linux-gnu", sha256: "373b37a68bae3ef441ead24a7bfc950fcbfc274cbdd2b628fc6915f179eb1d8e", }) - } else if cfg!(target_os = "linux") && cfg!(target_arch = "aarch64") { + } else if host.is_linux() && host.arch() == HostArch::Aarch64 { Ok(PlatformPackage { archive_suffix: "aarch64-linux-gnu", sha256: "f907a54313058f8a9681d2f48257d518950ff98bcd5a319194b4bee7c10cf223", }) - } else if cfg!(target_os = "macos") && cfg!(target_arch = "x86_64") { + } else if host.is_macos() && host.arch() == HostArch::X86_64 { Ok(PlatformPackage { archive_suffix: "x86_64-apple-darwin", sha256: "820028ee7cd2dd8fe8cd8ca5519ab6e792d15fea9367c4525cf63c0f707c0b1f", }) - } else if cfg!(target_os = "macos") && cfg!(target_arch = "aarch64") { + } else if host.is_macos() && host.arch() == HostArch::Aarch64 { Ok(PlatformPackage { archive_suffix: "aarch64-apple-darwin", sha256: "234690b6fa7c1d5dfe3dbb2bdd0c2810755e7c98999a9f21c389a6046b7eb76d", @@ -427,8 +436,8 @@ fn riscv32_platform_package() -> Result { } else { Err(FbuildError::PackageError(format!( "native QEMU (riscv32) is not supported on {}-{}", - std::env::consts::OS, - std::env::consts::ARCH + host.os_name(), + host.arch_name() ))) } } @@ -707,6 +716,17 @@ mod tests { assert_eq!(EspQemuArch::for_mcu("stm32"), None); } + #[test] + fn linux_host_selects_linux_artifacts_for_both_embedded_qemu_targets() { + let linux = HostPlatform::new(host::HostOs::Linux, HostArch::X86_64); + + let xtensa = platform_package_for(linux, EspQemuArch::Xtensa).unwrap(); + let riscv = platform_package_for(linux, EspQemuArch::Riscv32).unwrap(); + + assert_eq!(xtensa.archive_suffix, "x86_64-linux-gnu"); + assert_eq!(riscv.archive_suffix, "x86_64-linux-gnu"); + } + #[test] fn find_qemu_binary_direct_bin_xtensa() { let tmp = tempfile::TempDir::new().unwrap(); @@ -876,7 +896,7 @@ mod tests { // so the probe succeeds cross-platform. let tmp = tempfile::TempDir::new().unwrap(); let probe = tmp.path().join("probe_qemu"); - if cfg!(windows) { + if fbuild_core::platform::host::is_windows() { std::fs::write(&probe, b"@echo off\r\nexit /b 0\r\n").unwrap(); } else { std::fs::write(&probe, b"#!/bin/sh\nexit 0\n").unwrap(); diff --git a/crates/fbuild-toolchain/src/toolchain/riscv.rs b/crates/fbuild-toolchain/src/toolchain/riscv.rs index 1755b7516..95f767c97 100644 --- a/crates/fbuild-toolchain/src/toolchain/riscv.rs +++ b/crates/fbuild-toolchain/src/toolchain/riscv.rs @@ -292,11 +292,13 @@ fn all_platform_packages() -> [(&'static str, RiscvPlatformPackage); 4] { /// Get the platform-specific download URL and optional checksum for the current host. fn platform_package() -> (String, Option) { - let key = if cfg!(target_os = "windows") { + let key = if fbuild_core::platform::host::is_windows() { "windows" - } else if cfg!(target_os = "macos") { + } else if fbuild_core::platform::host::is_macos() { "macos" - } else if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "linux-aarch64" } else { "linux-x86_64" @@ -340,11 +342,7 @@ fn find_bin_root(install_dir: &Path) -> PathBuf { /// Get the tool binary name with .exe extension on Windows. fn tool_name(name: &str) -> String { - if cfg!(windows) { - format!("{}.exe", name) - } else { - name.to_string() - } + fbuild_core::platform::executable::native_name(name) } /// Get the full path to a tool binary. @@ -368,11 +366,10 @@ mod tests { #[test] fn test_tool_name_platform() { let name = tool_name("riscv-none-elf-gcc"); - if cfg!(windows) { - assert_eq!(name, "riscv-none-elf-gcc.exe"); - } else { - assert_eq!(name, "riscv-none-elf-gcc"); - } + assert_eq!( + name, + fbuild_core::platform::executable::native_name("riscv-none-elf-gcc") + ); } #[test] diff --git a/crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs b/crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs index 1a5f0d58b..56d234906 100644 --- a/crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs +++ b/crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs @@ -151,15 +151,19 @@ fn supported_hosts() -> String { } fn platform_package() -> PlatformPackage { - let key = if cfg!(target_os = "windows") { + let key = if fbuild_core::platform::host::is_windows() { "windows" - } else if cfg!(target_os = "macos") { - if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::is_macos() { + if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "macos-arm64" } else { "macos-x86_64" } - } else if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "linux-aarch64" } else { "linux-x86_64" @@ -184,11 +188,7 @@ fn find_picotool_root(install_dir: &Path) -> PathBuf { } fn picotool_name() -> &'static str { - if cfg!(windows) { - "picotool.exe" - } else { - "picotool" - } + fbuild_core::platform::executable::name("picotool", "picotool.exe") } #[cfg(test)] diff --git a/crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs b/crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs index 081baec72..ca3a4f1fe 100644 --- a/crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs +++ b/crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs @@ -191,15 +191,19 @@ fn all_platform_packages() -> [(&'static str, PlatformPackage); 5] { } fn platform_package() -> (String, Option) { - let key = if cfg!(target_os = "windows") { + let key = if fbuild_core::platform::host::is_windows() { "windows" - } else if cfg!(target_os = "macos") { - if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::is_macos() { + if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "macos-arm64" } else { "macos-x86_64" } - } else if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "linux-aarch64" } else { "linux-x86_64" @@ -235,11 +239,7 @@ fn find_bin_root(install_dir: &Path) -> PathBuf { } fn tool_name(name: &str) -> String { - if cfg!(windows) { - format!("{name}.exe") - } else { - name.to_string() - } + fbuild_core::platform::executable::native_name(name) } fn tool_binary(bin_dir: &Path, name: &str) -> PathBuf { @@ -261,11 +261,10 @@ mod tests { #[test] fn test_tool_name_platform() { let name = tool_name("arm-none-eabi-gcc"); - if cfg!(windows) { - assert_eq!(name, "arm-none-eabi-gcc.exe"); - } else { - assert_eq!(name, "arm-none-eabi-gcc"); - } + assert_eq!( + name, + fbuild_core::platform::executable::native_name("arm-none-eabi-gcc") + ); } #[test] diff --git a/crates/fbuild-toolchain/src/toolchain/teensy_arm.rs b/crates/fbuild-toolchain/src/toolchain/teensy_arm.rs index c08799a3f..8f8c423e8 100644 --- a/crates/fbuild-toolchain/src/toolchain/teensy_arm.rs +++ b/crates/fbuild-toolchain/src/toolchain/teensy_arm.rs @@ -188,15 +188,21 @@ fn all_platform_packages() -> [TeensyArmPlatformPackage; 6] { } fn platform_package() -> TeensyArmPlatformPackage { - let key = if cfg!(target_os = "windows") { + let key = if fbuild_core::platform::host::is_windows() { "windows" - } else if cfg!(target_os = "macos") { + } else if fbuild_core::platform::host::is_macos() { "macos" - } else if cfg!(target_arch = "aarch64") { + } else if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Aarch64 + { "linux-aarch64" - } else if cfg!(target_arch = "arm") { + } else if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::Arm + { "linux-arm" - } else if cfg!(target_arch = "x86") { + } else if fbuild_core::platform::host::current().arch() + == fbuild_core::platform::host::HostArch::X86 + { "linux-i686" } else { "linux-x86_64" @@ -232,11 +238,7 @@ fn find_bin_root(install_dir: &Path) -> PathBuf { } fn tool_name(name: &str) -> String { - if cfg!(windows) { - format!("{}.exe", name) - } else { - name.to_string() - } + fbuild_core::platform::executable::native_name(name) } fn tool_binary(bin_dir: &Path, name: &str) -> PathBuf { @@ -261,11 +263,10 @@ mod tests { #[test] fn test_tool_name_platform() { let name = tool_name("arm-none-eabi-gcc"); - if cfg!(windows) { - assert_eq!(name, "arm-none-eabi-gcc.exe"); - } else { - assert_eq!(name, "arm-none-eabi-gcc"); - } + assert_eq!( + name, + fbuild_core::platform::executable::native_name("arm-none-eabi-gcc") + ); } #[test] diff --git a/docs/architecture/portability.md b/docs/architecture/portability.md index 484780c6b..a46cab4e8 100644 --- a/docs/architecture/portability.md +++ b/docs/architecture/portability.md @@ -12,6 +12,14 @@ Host mechanics are distinct from the embedded board/compiler target. A Linux host that builds Windows-hosted tool artifacts or firmware for another MCU must still use Linux process, filesystem, IPC, and device mechanics. +Shared code reads the current machine through +`fbuild_core::platform::host::current()`, which returns a `HostPlatform` +containing `HostOs` and `HostArch`. Path-list separation comes from the same +value. Executable and command-script spelling uses +`fbuild_core::platform::executable`; product crates retain their artifact +tables and embedded-target policy. Raw `cfg!` OS/architecture reads are not +permitted outside the private platform implementation. + ## Windows (MSYS2/Git Bash) ### USB-CDC Serial diff --git a/docs/platform-boundary-research-inventory.md b/docs/platform-boundary-research-inventory.md index b9d2e6fe0..e269cc43b 100644 --- a/docs/platform-boundary-research-inventory.md +++ b/docs/platform-boundary-research-inventory.md @@ -39,8 +39,8 @@ not included; the same reconciliation also added concrete removed 25 false positives where local modules named `linux`, `macos`, or `unix` had been mistaken for native crates. Eight host-cfg occurrences added to `fbuild-paths` on `main` before the phase 2 baseline was merged were then -reconciled into the ledger. The corrected, authoritative union contains **504 -rows**: +reconciled into the ledger. The phase-2 bootstrap's corrected, authoritative +union contained **504 rows**: | Kind | Rows | | --- | ---: | @@ -67,7 +67,7 @@ rows**: | `fs` | 43 | | `ipc` | 12 | -## Distribution by crate +## Phase-2 distribution by crate | Crate | Rows | | --- | ---: | @@ -92,6 +92,46 @@ this scan also records compile-time host facts, native paths/dependencies, and target-specific dependency tables and treats multiple constructs on a line as separate findings. +## Phase-3 host-fact contraction + +Phase 3 replaced every raw `cfg!` OS/architecture query and compile-time host +fact outside the boundary with `fbuild_core::platform::{host,executable}`. +Product owners retain embedded-target and artifact-table policy; they now +consume an explicit neutral `HostPlatform`. The exact enforcement ledger fell +from **504 to 271 rows**, deleting 233 migrated occurrences. Its current shape +is: + +| Kind | Rows | +| --- | ---: | +| `attr_cfg` | 181 | +| `native_path` | 77 | +| `native_dependency` | 7 | +| `target_dependency_table` | 6 | +| `cfg_macro` | 0 | +| `compile_host_fact` | 0 | + +| Classification | Rows | +| --- | ---: | +| Host mechanic | 262 | +| Host artifact policy | 9 | + +| Capability | Rows | +| --- | ---: | +| `process` | 95 | +| `device` | 76 | +| `host` | 36 | +| `fs` | 39 | +| `host_executable` | 20 | +| `ipc` | 5 | + +The host-independent research inventory contains 275 rows because it also +records the three authorized `std::env::consts::ARCH` reads in the private +Windows, Linux, and macOS implementations and the single authorized +`std::env::current_exe` read inside the executable facade. Those rows are +intentionally absent from the enforcement ledger and Dylint baseline; +regression tests verify that boundary implementation findings cannot be +grandfathered while direct shared-caller current-image reads are rejected. + ## Manifest findings Target-specific native ownership currently exists in: diff --git a/docs/platform-boundary-research.md b/docs/platform-boundary-research.md index 479dc2df5..ea7a24d66 100644 --- a/docs/platform-boundary-research.md +++ b/docs/platform-boundary-research.md @@ -159,3 +159,22 @@ private, inline-test, integration-test, example, bench, and build-script source; the Dylint covers every construct in the current host's compiled sources, including arbitrary unexpanded macro tokens. CI compares actual Dylint observations with the scanner projection so a skipped compiler traversal fails. + +## Phase-3 host and executable facts + +Phase 3 introduced the value-type `HostPlatform` and neutral executable naming +helpers. RED characterization failed on the absent `HostPlatform`, `current`, +`name_for`, and `native_name_for` APIs. The same focused test is GREEN for +Windows, Linux, and macOS values, including architecture identity and path-list +separation. A product-owner test also proves that a Linux host selects Linux +QEMU artifacts for both Xtensa and RISC-V embedded targets. + +The migration removed every raw `cfg!` host query and compile-time host fact +outside the private boundary. Artifact URL/checksum tables, embedded-target +selection, retry policy, and diagnostics remain in their existing product +owners. The exact ledger contracted from 504 to 271 rows; the independent +research inventory is 275 because it also records three authorized architecture +reads inside the private selected modules and the single authorized current-image +read inside the executable facade. Focused enforcement permanently asserts zero +`cfg_macro` and `compile_host_fact` rows outside the boundary, while both +detectors reject direct current-image discovery in shared callers. diff --git a/dylints/enforce_platform_boundary/src/baseline.txt b/dylints/enforce_platform_boundary/src/baseline.txt index dd28ca697..493a960c8 100644 --- a/dylints/enforce_platform_boundary/src/baseline.txt +++ b/dylints/enforce_platform_boundary/src/baseline.txt @@ -1,51 +1,15 @@ # pathkindnormalizedordinal -crates/fbuild-build-arm/src/generic_arm/arm_linker.rs cfg_macro windows 0 -crates/fbuild-build-arm/src/teensy/teensy_linker.rs cfg_macro windows 0 -crates/fbuild-build-arm/src/teensy/teensy_linker.rs cfg_macro windows 1 -crates/fbuild-build-engine/src/compiler_tests.rs cfg_macro windows 0 -crates/fbuild-build-engine/src/linker.rs cfg_macro windows 0 -crates/fbuild-build-engine/src/script_runtime.rs cfg_macro windows 0 crates/fbuild-build-engine/src/script_runtime_tests.rs attr_cfg windows 0 -crates/fbuild-build-esp/src/esp32/esp32_compiler.rs cfg_macro windows 0 -crates/fbuild-build-esp/src/esp32/esp32_linker.rs cfg_macro windows 0 crates/fbuild-build/tests/avr_build.rs attr_cfg windows 0 crates/fbuild-build/tests/avr_build.rs attr_cfg windows 1 -crates/fbuild-build/tests/cache_survives_tar_extract.rs cfg_macro windows 0 -crates/fbuild-build/tests/cache_survives_tar_extract.rs cfg_macro windows 1 -crates/fbuild-build/tests/clangd_check_parity.rs cfg_macro windows 0 crates/fbuild-build/tests/esp32_build.rs attr_cfg windows 0 crates/fbuild-build/tests/esp32_build.rs attr_cfg windows 1 -crates/fbuild-build/tests/lite_scons_acceptance.rs cfg_macro windows 0 -crates/fbuild-build/tests/zccache_embedded_smoke.rs cfg_macro windows 0 -crates/fbuild-build/tests/zccache_embedded_smoke.rs cfg_macro windows 1 -crates/fbuild-cli/src/cli/build.rs cfg_macro target_os 0 -crates/fbuild-cli/src/cli/build.rs cfg_macro target_os 1 -crates/fbuild-cli/src/cli/build.rs cfg_macro windows 0 -crates/fbuild-cli/src/cli/compile_many.rs cfg_macro windows 0 -crates/fbuild-cli/src/cli/daemon_cmd.rs cfg_macro windows 0 -crates/fbuild-cli/src/cli/daemon_cmd.rs cfg_macro windows 1 crates/fbuild-cli/src/cli/debug.rs attr_cfg windows 0 crates/fbuild-cli/src/cli/debug.rs attr_cfg windows 1 -crates/fbuild-cli/src/cli/debug.rs cfg_macro windows 0 -crates/fbuild-cli/src/cli/debug.rs cfg_macro windows 1 crates/fbuild-cli/src/cli/deploy.rs attr_cfg windows 0 crates/fbuild-cli/src/cli/deploy.rs attr_cfg windows 1 -crates/fbuild-cli/src/cli/deploy.rs cfg_macro windows 0 crates/fbuild-cli/src/cli/ide.rs attr_cfg windows 0 -crates/fbuild-cli/src/cli/ide.rs cfg_macro target_os 0 -crates/fbuild-cli/src/cli/ide.rs cfg_macro windows 0 -crates/fbuild-cli/src/cli/ide.rs cfg_macro windows 1 -crates/fbuild-cli/src/cli/ide.rs cfg_macro windows 2 -crates/fbuild-cli/src/cli/ide.rs cfg_macro windows 3 crates/fbuild-cli/src/cli/ide.rs native_import std::os::windows 0 -crates/fbuild-cli/src/cli/pio.rs cfg_macro windows 0 -crates/fbuild-cli/src/cli/pio.rs cfg_macro windows 1 -crates/fbuild-cli/src/cli/port_doctor.rs cfg_macro windows 0 -crates/fbuild-cli/src/cli/port_doctor.rs cfg_macro windows 1 -crates/fbuild-cli/src/cli/port_doctor.rs cfg_macro windows 2 -crates/fbuild-cli/src/cli/port_doctor_fix.rs cfg_macro windows 0 -crates/fbuild-cli/src/cli/symbols_cmd.rs cfg_macro windows 0 -crates/fbuild-cli/src/cli/tests.rs cfg_macro windows 0 crates/fbuild-cli/src/cli/usb_recovery.rs attr_cfg windows 0 crates/fbuild-cli/src/cli/usb_recovery.rs attr_cfg windows 1 crates/fbuild-cli/src/cli/usb_recovery.rs attr_cfg windows 2 @@ -60,13 +24,8 @@ crates/fbuild-cli/src/cli/usb_recovery.rs native_import windows_sys 4 crates/fbuild-cli/src/daemon_client.rs attr_cfg windows 0 crates/fbuild-cli/src/daemon_client.rs attr_cfg windows 1 crates/fbuild-cli/src/daemon_client.rs attr_cfg windows 2 -crates/fbuild-cli/src/daemon_client/identity.rs cfg_macro windows 0 -crates/fbuild-cli/tests/daemon_crash_recovery.rs cfg_macro windows 0 -crates/fbuild-cli/tests/daemon_crash_recovery.rs cfg_macro windows 1 crates/fbuild-config/src/bin/enrich_boards.rs attr_cfg windows 0 crates/fbuild-config/src/bin/enrich_boards.rs attr_cfg windows 1 -crates/fbuild-config/src/ini_parser/tests.rs cfg_macro windows 0 -crates/fbuild-config/src/ini_parser/values.rs cfg_macro windows 0 crates/fbuild-core/src/containment.rs attr_cfg target_os 0 crates/fbuild-core/src/containment.rs attr_cfg target_os 1 crates/fbuild-core/src/containment.rs attr_cfg unix 0 @@ -80,8 +39,6 @@ crates/fbuild-core/src/containment.rs attr_cfg windows 1 crates/fbuild-core/src/containment.rs attr_cfg windows 2 crates/fbuild-core/src/containment.rs attr_cfg windows 3 crates/fbuild-core/src/containment.rs attr_cfg windows 4 -crates/fbuild-core/src/containment.rs cfg_macro windows 0 -crates/fbuild-core/src/containment.rs cfg_macro windows 1 crates/fbuild-core/src/containment.rs native_import libc 0 crates/fbuild-core/src/containment.rs native_import libc 1 crates/fbuild-core/src/containment.rs native_import libc 2 @@ -118,7 +75,6 @@ crates/fbuild-core/src/path.rs attr_cfg windows 11 crates/fbuild-core/src/path.rs attr_cfg windows 12 crates/fbuild-core/src/path.rs attr_cfg windows 13 crates/fbuild-core/src/path.rs attr_cfg windows 14 -crates/fbuild-core/src/path.rs cfg_macro windows 0 crates/fbuild-core/src/path.rs native_import std::os::unix 0 crates/fbuild-core/src/process_identity.rs attr_cfg target_os 0 crates/fbuild-core/src/process_identity.rs attr_cfg target_os 1 @@ -134,7 +90,6 @@ crates/fbuild-core/src/process_identity.rs attr_cfg windows 2 crates/fbuild-core/src/process_identity.rs attr_cfg windows 3 crates/fbuild-core/src/process_identity.rs attr_cfg windows 4 crates/fbuild-core/src/process_identity.rs attr_cfg windows 5 -crates/fbuild-core/src/process_identity.rs cfg_macro windows 0 crates/fbuild-core/src/process_identity.rs native_import libc 0 crates/fbuild-core/src/process_identity.rs native_import libc 1 crates/fbuild-core/src/process_identity.rs native_import libc 2 @@ -146,7 +101,6 @@ crates/fbuild-core/src/process_identity.rs native_import libc 7 crates/fbuild-core/src/process_identity.rs native_import std::os::windows 0 crates/fbuild-core/src/process_identity.rs native_import std::os::windows 1 crates/fbuild-core/src/process_identity.rs native_import std::os::windows 2 -crates/fbuild-core/src/response_file.rs cfg_macro windows 0 crates/fbuild-core/src/subprocess.rs attr_cfg unix 0 crates/fbuild-core/src/subprocess.rs attr_cfg unix 1 crates/fbuild-core/src/subprocess.rs attr_cfg unix 2 @@ -158,18 +112,6 @@ crates/fbuild-core/src/subprocess.rs attr_cfg windows 4 crates/fbuild-core/src/subprocess.rs attr_cfg windows 5 crates/fbuild-core/src/subprocess.rs attr_cfg windows 6 crates/fbuild-core/src/subprocess.rs attr_cfg windows 7 -crates/fbuild-core/src/subprocess.rs cfg_macro windows 0 -crates/fbuild-core/src/subprocess.rs cfg_macro windows 1 -crates/fbuild-core/src/subprocess.rs cfg_macro windows 2 -crates/fbuild-core/src/subprocess.rs cfg_macro windows 3 -crates/fbuild-core/src/subprocess.rs cfg_macro windows 4 -crates/fbuild-core/src/subprocess.rs cfg_macro windows 5 -crates/fbuild-core/src/subprocess.rs cfg_macro windows 6 -crates/fbuild-core/src/subprocess.rs cfg_macro windows 7 -crates/fbuild-core/src/subprocess.rs cfg_macro windows 8 -crates/fbuild-core/src/subprocess.rs cfg_macro windows 9 -crates/fbuild-core/src/subprocess.rs cfg_macro windows 10 -crates/fbuild-core/src/subprocess.rs cfg_macro windows 11 crates/fbuild-core/src/subprocess.rs native_import std::os::unix 0 crates/fbuild-core/src/subprocess.rs native_import std::os::unix 1 crates/fbuild-core/src/subprocess.rs native_import std::os::windows 0 @@ -178,22 +120,9 @@ crates/fbuild-daemon/src/broker/backend.rs attr_cfg windows 0 crates/fbuild-daemon/src/broker/backend.rs native_import interprocess 0 crates/fbuild-daemon/src/broker/backend.rs native_import interprocess 1 crates/fbuild-daemon/src/broker/backend.rs native_import interprocess 2 -crates/fbuild-daemon/src/broker/service.rs cfg_macro windows 0 -crates/fbuild-daemon/src/broker/service.rs cfg_macro windows 1 -crates/fbuild-daemon/src/broker/service.rs cfg_macro windows 2 -crates/fbuild-daemon/src/broker/service.rs cfg_macro windows 3 -crates/fbuild-daemon/src/broker/service.rs cfg_macro windows 4 -crates/fbuild-daemon/src/broker/session.rs cfg_macro windows 0 crates/fbuild-daemon/src/handlers/emulator/avr8js_headless.rs attr_cfg windows 0 -crates/fbuild-daemon/src/handlers/emulator/avr8js_npm.rs cfg_macro windows 0 -crates/fbuild-daemon/src/handlers/emulator/avr8js_npm.rs cfg_macro windows 1 -crates/fbuild-daemon/src/handlers/emulator/runners.rs cfg_macro target_os 0 -crates/fbuild-daemon/src/handlers/emulator/runners.rs cfg_macro target_os 1 -crates/fbuild-daemon/src/handlers/emulator/runners.rs cfg_macro windows 0 crates/fbuild-daemon/src/handlers/emulator/shared.rs attr_cfg windows 0 crates/fbuild-daemon/src/handlers/emulator/shared.rs attr_cfg windows 1 -crates/fbuild-daemon/src/handlers/emulator/shared.rs cfg_macro target_os 0 -crates/fbuild-daemon/src/handlers/emulator/shared.rs cfg_macro target_os 1 crates/fbuild-daemon/src/handlers/emulator/tests_npm_cache.rs attr_cfg windows 0 crates/fbuild-daemon/src/handlers/emulator/tests_process.rs attr_cfg windows 0 crates/fbuild-daemon/src/handlers/emulator/tests_process.rs attr_cfg windows 1 @@ -201,15 +130,8 @@ crates/fbuild-daemon/src/handlers/locks.rs attr_cfg unix 0 crates/fbuild-daemon/src/handlers/locks.rs attr_cfg unix 1 crates/fbuild-daemon/src/handlers/locks.rs attr_cfg windows 0 crates/fbuild-daemon/src/handlers/locks.rs attr_cfg windows 1 -crates/fbuild-daemon/src/handlers/locks.rs cfg_macro target_os 0 -crates/fbuild-daemon/src/handlers/locks.rs cfg_macro windows 0 -crates/fbuild-daemon/src/handlers/locks.rs cfg_macro windows 1 crates/fbuild-daemon/src/handlers/locks.rs native_import libc 0 crates/fbuild-daemon/src/handlers/locks.rs native_import libc 1 -crates/fbuild-daemon/src/handlers/operations/deploy.rs cfg_macro windows 0 -crates/fbuild-daemon/src/handlers/operations/deploy.rs cfg_macro windows 1 -crates/fbuild-daemon/src/handlers/operations/deploy.rs cfg_macro windows 2 -crates/fbuild-daemon/src/handlers/operations/deploy.rs cfg_macro windows 3 crates/fbuild-daemon/src/main.rs attr_cfg unix 0 crates/fbuild-daemon/src/main.rs attr_cfg unix 1 crates/fbuild-daemon/src/main.rs attr_cfg windows 0 @@ -223,7 +145,6 @@ crates/fbuild-daemon/src/main.rs native_import libc 0 crates/fbuild-daemon/src/main.rs native_import std::os::windows 0 crates/fbuild-daemon/tests/legacy_daemon_transition.rs attr_cfg unix 0 crates/fbuild-daemon/tests/legacy_daemon_transition.rs attr_cfg windows 0 -crates/fbuild-daemon/tests/legacy_daemon_transition.rs cfg_macro windows 0 crates/fbuild-daemon/tests/legacy_daemon_transition.rs native_import libc 0 crates/fbuild-daemon/tests/legacy_daemon_transition.rs native_import libc 1 crates/fbuild-daemon/tests/port_recovery.rs attr_cfg unix 0 @@ -241,23 +162,9 @@ crates/fbuild-deploy/src/lpc.rs attr_cfg target_os 0 crates/fbuild-deploy/src/lpc.rs attr_cfg target_os 1 crates/fbuild-deploy/src/lpc.rs attr_cfg windows 0 crates/fbuild-deploy/src/lpc.rs attr_cfg windows 1 -crates/fbuild-deploy/src/lpc.rs cfg_macro windows 0 -crates/fbuild-deploy/src/lpc.rs cfg_macro windows 1 -crates/fbuild-deploy/src/lpc.rs cfg_macro windows 2 -crates/fbuild-deploy/src/lpc.rs cfg_macro windows 3 crates/fbuild-deploy/src/lpc_debugger_reflash.rs attr_cfg target_os 0 -crates/fbuild-deploy/src/lpc_debugger_reflash.rs cfg_macro target_os 0 -crates/fbuild-deploy/src/lpc_debugger_reflash.rs cfg_macro target_os 1 -crates/fbuild-deploy/src/lpc_debugger_reflash.rs cfg_macro windows 0 -crates/fbuild-deploy/src/lpc_debugger_reflash.rs cfg_macro windows 1 crates/fbuild-deploy/src/probe_rs.rs attr_cfg unix 0 crates/fbuild-deploy/src/probe_rs.rs attr_cfg windows 0 -crates/fbuild-deploy/src/probe_rs.rs cfg_macro windows 0 -crates/fbuild-deploy/src/probe_rs.rs cfg_macro windows 1 -crates/fbuild-deploy/src/probe_rs.rs cfg_macro windows 2 -crates/fbuild-deploy/src/probe_rs.rs cfg_macro windows 3 -crates/fbuild-deploy/src/probe_rs.rs compile_host_fact std::env::consts::ARCH 0 -crates/fbuild-deploy/src/probe_rs.rs compile_host_fact std::env::consts::OS 0 crates/fbuild-deploy/src/probe_rs.rs native_import std::os::unix 0 crates/fbuild-deploy/src/rp2040.rs attr_cfg windows 0 crates/fbuild-deploy/src/rp2040.rs attr_cfg windows 1 @@ -265,12 +172,6 @@ crates/fbuild-deploy/src/rp2040.rs attr_cfg windows 2 crates/fbuild-deploy/src/rp2040.rs attr_cfg windows 3 crates/fbuild-deploy/src/rp2040.rs attr_cfg windows 4 crates/fbuild-deploy/src/rp2040.rs attr_cfg windows 5 -crates/fbuild-deploy/src/rp2040.rs cfg_macro target_os 0 -crates/fbuild-deploy/src/rp2040.rs cfg_macro target_os 1 -crates/fbuild-deploy/src/rp2040.rs cfg_macro windows 0 -crates/fbuild-deploy/src/rp2040.rs cfg_macro windows 1 -crates/fbuild-deploy/src/rp2040.rs cfg_macro windows 2 -crates/fbuild-deploy/src/rp2040.rs cfg_macro windows 3 crates/fbuild-deploy/src/rp2040.rs native_import std::os::windows 0 crates/fbuild-deploy/src/rp2040.rs native_import std::os::windows 1 crates/fbuild-deploy/src/rp2040.rs native_import std::os::windows 2 @@ -279,9 +180,6 @@ crates/fbuild-deploy/src/rp2040_mount.rs attr_cfg target_os 0 crates/fbuild-deploy/src/rp2040_mount.rs attr_cfg target_os 1 crates/fbuild-deploy/src/rp2040_mount.rs attr_cfg target_os 2 crates/fbuild-deploy/src/rp2040_mount.rs attr_cfg target_os 3 -crates/fbuild-deploy/src/rp2040_picotool.rs cfg_macro windows 0 -crates/fbuild-deploy/src/rp2040_picotool.rs cfg_macro windows 1 -crates/fbuild-deploy/src/rp2040_picotool.rs cfg_macro windows 2 crates/fbuild-deploy/src/rp2040_topology.rs attr_cfg windows 0 crates/fbuild-deploy/src/rp2040_topology.rs attr_cfg windows 1 crates/fbuild-deploy/src/rp2040_topology.rs attr_cfg windows 2 @@ -294,36 +192,15 @@ crates/fbuild-deploy/src/rp2040_topology.rs attr_cfg windows 8 crates/fbuild-deploy/src/rp2040_topology.rs attr_cfg windows 9 crates/fbuild-deploy/src/rp2040_topology.rs attr_cfg windows 10 crates/fbuild-deploy/src/rp2040_topology.rs native_import std::os::windows 0 -crates/fbuild-deploy/src/teensy/soft_reboot.rs cfg_macro windows 0 crates/fbuild-deploy/src/wchisp.rs attr_cfg unix 0 -crates/fbuild-deploy/src/wchisp.rs cfg_macro windows 0 -crates/fbuild-deploy/src/wchisp.rs cfg_macro windows 1 -crates/fbuild-deploy/src/wchisp.rs cfg_macro windows 2 -crates/fbuild-deploy/src/wchisp.rs cfg_macro windows 3 -crates/fbuild-deploy/src/wchisp.rs compile_host_fact std::env::consts::ARCH 0 -crates/fbuild-deploy/src/wchisp.rs compile_host_fact std::env::consts::OS 0 crates/fbuild-deploy/src/wchisp.rs native_import std::os::unix 0 crates/fbuild-deploy/src/wlink.rs attr_cfg unix 0 -crates/fbuild-deploy/src/wlink.rs cfg_macro windows 0 -crates/fbuild-deploy/src/wlink.rs cfg_macro windows 1 -crates/fbuild-deploy/src/wlink.rs cfg_macro windows 2 -crates/fbuild-deploy/src/wlink.rs cfg_macro windows 3 -crates/fbuild-deploy/src/wlink.rs compile_host_fact std::env::consts::ARCH 0 -crates/fbuild-deploy/src/wlink.rs compile_host_fact std::env::consts::OS 0 crates/fbuild-deploy/src/wlink.rs native_import std::os::unix 0 crates/fbuild-library/src/library/esptool.rs attr_cfg unix 0 crates/fbuild-library/src/library/esptool.rs attr_cfg unix 1 -crates/fbuild-library/src/library/esptool.rs cfg_macro windows 0 -crates/fbuild-library/src/library/esptool.rs compile_host_fact std::env::consts::ARCH 0 -crates/fbuild-library/src/library/esptool.rs compile_host_fact std::env::consts::ARCH 1 -crates/fbuild-library/src/library/esptool.rs compile_host_fact std::env::consts::OS 0 -crates/fbuild-library/src/library/esptool.rs compile_host_fact std::env::consts::OS 1 crates/fbuild-library/src/library/esptool.rs native_import std::os::unix 0 crates/fbuild-library/src/library/esptool.rs native_import std::os::unix 1 -crates/fbuild-library/src/library/library_compiler.rs cfg_macro windows 0 -crates/fbuild-library/src/library/library_compiler.rs cfg_macro windows 1 crates/fbuild-library/src/library/library_spec.rs attr_cfg windows 0 -crates/fbuild-library/src/library/library_spec.rs cfg_macro windows 0 crates/fbuild-packages-fetch/src/disk_cache/budget.rs attr_cfg unix 0 crates/fbuild-packages-fetch/src/disk_cache/budget.rs attr_cfg unix 1 crates/fbuild-packages-fetch/src/disk_cache/budget.rs attr_cfg unix 2 @@ -334,37 +211,6 @@ crates/fbuild-packages-fetch/src/disk_cache/index/pid.rs attr_cfg unix 0 crates/fbuild-packages-fetch/src/disk_cache/index/pid.rs attr_cfg unix 1 crates/fbuild-packages-fetch/src/disk_cache/index/pid.rs attr_cfg windows 0 crates/fbuild-packages-fetch/src/disk_cache/index/pid.rs attr_cfg windows 1 -crates/fbuild-packages-fetch/src/install_lock.rs cfg_macro windows 0 -crates/fbuild-paths/src/lib.rs attr_cfg target_os 0 -crates/fbuild-paths/src/lib.rs attr_cfg target_os 1 -crates/fbuild-paths/src/lib.rs attr_cfg windows 0 -crates/fbuild-paths/src/lib.rs attr_cfg windows 1 -crates/fbuild-paths/src/lib.rs attr_cfg windows 2 -crates/fbuild-paths/src/lib.rs attr_cfg windows 3 -crates/fbuild-paths/src/lib.rs attr_cfg windows 4 -crates/fbuild-paths/src/lib.rs attr_cfg windows 5 -crates/fbuild-paths/src/lib.rs attr_cfg windows 6 -crates/fbuild-paths/src/lib.rs attr_cfg windows 7 -crates/fbuild-paths/src/running_process.rs attr_cfg target_os 0 -crates/fbuild-paths/src/running_process.rs attr_cfg target_os 1 -crates/fbuild-paths/src/running_process.rs attr_cfg target_os 2 -crates/fbuild-paths/src/running_process.rs attr_cfg target_os 3 -crates/fbuild-paths/src/running_process.rs attr_cfg target_os 4 -crates/fbuild-paths/src/running_process.rs attr_cfg unix 0 -crates/fbuild-paths/src/running_process.rs attr_cfg unix 1 -crates/fbuild-paths/src/running_process.rs attr_cfg unix 2 -crates/fbuild-paths/src/running_process.rs attr_cfg windows 0 -crates/fbuild-paths/src/running_process.rs attr_cfg windows 1 -crates/fbuild-paths/src/running_process.rs attr_cfg windows 2 -crates/fbuild-python/src/daemon.rs attr_cfg windows 0 -crates/fbuild-python/src/daemon.rs attr_cfg windows 1 -crates/fbuild-python/src/daemon.rs attr_cfg windows 2 -crates/fbuild-python/src/daemon.rs attr_cfg windows 3 -crates/fbuild-serial/src/boards.rs cfg_macro windows 0 -crates/fbuild-serial/src/crash_decoder.rs cfg_macro windows 0 -crates/fbuild-serial/src/crash_decoder.rs cfg_macro windows 1 -crates/fbuild-serial/src/manager.rs cfg_macro windows 0 -crates/fbuild-serial/src/manager.rs cfg_macro windows 1 crates/fbuild-serial/src/port_class.rs attr_cfg target_os 0 crates/fbuild-serial/src/port_class.rs attr_cfg target_os 1 crates/fbuild-serial/src/port_class.rs attr_cfg target_os 2 @@ -407,42 +253,6 @@ crates/fbuild-serial/src/usb_recovery.rs attr_cfg windows 2 crates/fbuild-serial/src/usb_recovery.rs native_import windows 0 crates/fbuild-serial/src/usb_recovery.rs native_import windows_sys 0 crates/fbuild-serial/src/usb_recovery.rs native_import windows_sys 1 -crates/fbuild-toolchain/src/toolchain/arm.rs cfg_macro target_arch 0 -crates/fbuild-toolchain/src/toolchain/arm.rs cfg_macro target_os 0 -crates/fbuild-toolchain/src/toolchain/arm.rs cfg_macro target_os 1 -crates/fbuild-toolchain/src/toolchain/arm.rs cfg_macro windows 0 -crates/fbuild-toolchain/src/toolchain/arm.rs cfg_macro windows 1 -crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs cfg_macro target_os 0 -crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs cfg_macro target_os 1 -crates/fbuild-toolchain/src/toolchain/arm_gcc8.rs cfg_macro windows 0 -crates/fbuild-toolchain/src/toolchain/avr.rs cfg_macro target_arch 0 -crates/fbuild-toolchain/src/toolchain/avr.rs cfg_macro target_os 0 -crates/fbuild-toolchain/src/toolchain/avr.rs cfg_macro target_os 1 -crates/fbuild-toolchain/src/toolchain/avr.rs cfg_macro windows 0 -crates/fbuild-toolchain/src/toolchain/avr.rs cfg_macro windows 1 -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro target_arch 0 -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro target_os 0 -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro target_os 1 -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro windows 0 -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro windows 1 -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro windows 2 -crates/fbuild-toolchain/src/toolchain/clang.rs cfg_macro windows 3 -crates/fbuild-toolchain/src/toolchain/esp32.rs cfg_macro target_arch 0 -crates/fbuild-toolchain/src/toolchain/esp32.rs cfg_macro target_arch 1 -crates/fbuild-toolchain/src/toolchain/esp32.rs cfg_macro target_os 0 -crates/fbuild-toolchain/src/toolchain/esp32.rs cfg_macro target_os 1 -crates/fbuild-toolchain/src/toolchain/esp32.rs cfg_macro windows 0 -crates/fbuild-toolchain/src/toolchain/esp32.rs cfg_macro windows 1 -crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs cfg_macro target_arch 0 -crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs cfg_macro target_arch 1 -crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs cfg_macro target_os 0 -crates/fbuild-toolchain/src/toolchain/esp32_metadata.rs cfg_macro target_os 1 -crates/fbuild-toolchain/src/toolchain/esp8266.rs cfg_macro target_arch 0 -crates/fbuild-toolchain/src/toolchain/esp8266.rs cfg_macro target_arch 1 -crates/fbuild-toolchain/src/toolchain/esp8266.rs cfg_macro target_os 0 -crates/fbuild-toolchain/src/toolchain/esp8266.rs cfg_macro target_os 1 -crates/fbuild-toolchain/src/toolchain/esp8266.rs cfg_macro windows 0 -crates/fbuild-toolchain/src/toolchain/esp8266.rs cfg_macro windows 1 crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg target_os 0 crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg target_os 1 crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg target_os 2 @@ -456,55 +266,6 @@ crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg windows 5 crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg windows 6 crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg windows 7 crates/fbuild-toolchain/src/toolchain/esp_qemu.rs attr_cfg windows 8 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_arch 0 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_arch 1 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_arch 2 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_arch 3 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_arch 4 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_arch 5 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_arch 6 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_arch 7 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_arch 8 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_arch 9 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_os 0 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_os 1 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_os 2 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_os 3 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_os 4 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_os 5 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_os 6 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_os 7 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_os 8 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro target_os 9 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro windows 0 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs cfg_macro windows 1 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs compile_host_fact std::env::consts::ARCH 0 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs compile_host_fact std::env::consts::ARCH 1 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs compile_host_fact std::env::consts::OS 0 -crates/fbuild-toolchain/src/toolchain/esp_qemu.rs compile_host_fact std::env::consts::OS 1 crates/fbuild-toolchain/src/toolchain/esp_qemu.rs native_import std::os::unix 0 crates/fbuild-toolchain/src/toolchain/esp_qemu.rs native_import std::os::unix 1 crates/fbuild-toolchain/src/toolchain/mod.rs attr_cfg windows 0 -crates/fbuild-toolchain/src/toolchain/riscv.rs cfg_macro target_arch 0 -crates/fbuild-toolchain/src/toolchain/riscv.rs cfg_macro target_os 0 -crates/fbuild-toolchain/src/toolchain/riscv.rs cfg_macro target_os 1 -crates/fbuild-toolchain/src/toolchain/riscv.rs cfg_macro windows 0 -crates/fbuild-toolchain/src/toolchain/riscv.rs cfg_macro windows 1 -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs cfg_macro target_arch 0 -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs cfg_macro target_arch 1 -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs cfg_macro target_os 0 -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs cfg_macro target_os 1 -crates/fbuild-toolchain/src/toolchain/rp2040_picotool.rs cfg_macro windows 0 -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs cfg_macro target_arch 0 -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs cfg_macro target_arch 1 -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs cfg_macro target_os 0 -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs cfg_macro target_os 1 -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs cfg_macro windows 0 -crates/fbuild-toolchain/src/toolchain/rp2040_pqt.rs cfg_macro windows 1 -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro target_arch 0 -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro target_arch 1 -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro target_arch 2 -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro target_os 0 -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro target_os 1 -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro windows 0 -crates/fbuild-toolchain/src/toolchain/teensy_arm.rs cfg_macro windows 1 diff --git a/dylints/enforce_platform_boundary/src/lib.rs b/dylints/enforce_platform_boundary/src/lib.rs index 994f45ad9..e649b8b1f 100644 --- a/dylints/enforce_platform_boundary/src/lib.rs +++ b/dylints/enforce_platform_boundary/src/lib.rs @@ -233,6 +233,13 @@ fn record(context: &EarlyContext<'_>, span: Span, kind: Kind, normalized: &str) }; match classify(&path) { Scope::Selector | Scope::Concrete | Scope::OutOfScope => return, + Scope::Facade + if path == "crates/fbuild-core/src/platform/executable.rs" + && kind == Kind::NativeImport + && normalized == "std::env::current_exe" => + { + return; + } Scope::Facade | Scope::Ui => { emit(context, span, kind, normalized); return; @@ -377,6 +384,15 @@ impl State<'_> { } fn check_path_segments(&self, span: Span, segments: &[String]) { + if segments.len() >= 3 && segments[..3] == ["std", "env", "current_exe"] { + record( + self.context, + span, + Kind::NativeImport, + "std::env::current_exe", + ); + return; + } if segments.len() >= 4 && segments[..3] == ["std", "env", "consts"] && matches!(segments[3].as_str(), "OS" | "ARCH") diff --git a/dylints/enforce_platform_boundary/ui/disallowed.rs b/dylints/enforce_platform_boundary/ui/disallowed.rs index 3483a4057..631ebb49a 100644 --- a/dylints/enforce_platform_boundary/ui/disallowed.rs +++ b/dylints/enforce_platform_boundary/ui/disallowed.rs @@ -20,6 +20,7 @@ fn main() { let _backend = platform_windows::Backend; let _nested_host = format!("{}", cfg!(target_os = "linux")); let _nested_os = format!("{}", std::env::consts::OS); + let _current_image = std::env::current_exe(); } #[cfg(test)] diff --git a/dylints/enforce_platform_boundary/ui/disallowed.stderr b/dylints/enforce_platform_boundary/ui/disallowed.stderr index 008c3d089..2c259296e 100644 --- a/dylints/enforce_platform_boundary/ui/disallowed.stderr +++ b/dylints/enforce_platform_boundary/ui/disallowed.stderr @@ -30,6 +30,12 @@ error: module ref `platform_windows` is outside fbuild_core::platform; use a neu LL | let _backend = platform_windows::Backend; | ^^^^^^^^^^^^^^^^^^^^^^^^^ +error: native import `std::env::current_exe` is outside fbuild_core::platform; use a neutral facade + --> $DIR/disallowed.rs:23:26 + | +LL | let _current_image = std::env::current_exe(); + | ^^^^^^^^^^^^^^^^^^^^^ + error: cfg macro `target_os` is outside fbuild_core::platform; use a neutral facade --> $DIR/disallowed.rs:17:17 | @@ -61,10 +67,9 @@ LL | let _nested_os = format!("{}", std::env::consts::OS); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cfg macro `unix` is outside fbuild_core::platform; use a neutral facade - --> $DIR/disallowed.rs:29:9 + --> $DIR/disallowed.rs:30:9 | LL | assert!(cfg!(unix)); | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 11 previous errors - +error: aborting due to 12 previous errors From 1d253ec523ab7e10138b871e71367128034fe944 Mon Sep 17 00:00:00 2001 From: zackees Date: Thu, 20 Aug 2026 07:20:42 -0700 Subject: [PATCH 2/5] test: match Dylint UI output terminator --- dylints/enforce_platform_boundary/ui/disallowed.stderr | 1 + 1 file changed, 1 insertion(+) diff --git a/dylints/enforce_platform_boundary/ui/disallowed.stderr b/dylints/enforce_platform_boundary/ui/disallowed.stderr index 2c259296e..d20802314 100644 --- a/dylints/enforce_platform_boundary/ui/disallowed.stderr +++ b/dylints/enforce_platform_boundary/ui/disallowed.stderr @@ -73,3 +73,4 @@ LL | assert!(cfg!(unix)); | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 12 previous errors + From 8e205a684322e54188f73ac903a578cfa863e6b1 Mon Sep 17 00:00:00 2001 From: zackees Date: Thu, 20 Aug 2026 07:48:19 -0700 Subject: [PATCH 3/5] fix: normalize executable facade paths --- ci/platform_boundary_research.tsv | 2 +- crates/fbuild-cli/src/cli/daemon_cmd.rs | 1 + crates/fbuild-core/src/platform/executable.rs | 15 ++++++++------- crates/fbuild-daemon/src/main.rs | 4 ++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/ci/platform_boundary_research.tsv b/ci/platform_boundary_research.tsv index 8bc56dbae..f963832e6 100644 --- a/ci/platform_boundary_research.tsv +++ b/ci/platform_boundary_research.tsv @@ -77,7 +77,7 @@ crates/fbuild-core/src/path.rs 739 attr_cfg #[cfg(windows)] fs host_mechanic crates/fbuild-core/src/path.rs 814 attr_cfg #[cfg(unix)] fs host_mechanic crates/fbuild-core/src/path.rs 822 native_path std::os::unix::fs::symlink fs host_mechanic crates/fbuild-core/src/path.rs 829 attr_cfg #[cfg(windows)] fs host_mechanic -crates/fbuild-core/src/platform/executable.rs 55 native_path std::env::current_exe host_executable host_mechanic +crates/fbuild-core/src/platform/executable.rs 56 native_path std::env::current_exe host_executable host_mechanic crates/fbuild-core/src/platform/linux/mod.rs 6 compile_host_fact std::env::consts::ARCH host host_mechanic crates/fbuild-core/src/platform/macos/mod.rs 6 compile_host_fact std::env::consts::ARCH host host_mechanic crates/fbuild-core/src/platform/windows/mod.rs 6 compile_host_fact std::env::consts::ARCH host host_mechanic diff --git a/crates/fbuild-cli/src/cli/daemon_cmd.rs b/crates/fbuild-cli/src/cli/daemon_cmd.rs index 61f9f64a7..3a1734c49 100644 --- a/crates/fbuild-cli/src/cli/daemon_cmd.rs +++ b/crates/fbuild-cli/src/cli/daemon_cmd.rs @@ -309,6 +309,7 @@ fn daemon_executable_candidate() -> std::path::PathBuf { fbuild_core::platform::executable::current_image_sibling( fbuild_paths::running_process::DAEMON_BINARY_NAME, ) + .map(fbuild_core::path::NormalizedPath::into_path_buf) .unwrap_or_else(|_| std::path::PathBuf::from(fbuild_paths::running_process::DAEMON_BINARY_NAME)) } diff --git a/crates/fbuild-core/src/platform/executable.rs b/crates/fbuild-core/src/platform/executable.rs index d49f11930..af7b522cf 100644 --- a/crates/fbuild-core/src/platform/executable.rs +++ b/crates/fbuild-core/src/platform/executable.rs @@ -1,8 +1,9 @@ //! Neutral executable naming, discovery, and materialization APIs. use super::host::{self, HostArch, HostPlatform}; +use crate::path::NormalizedPath; use std::io; -use std::path::{Path, PathBuf}; +use std::path::Path; /// Select the spelling of an executable or command script for an explicit host. pub const fn name_for<'a>(host: HostPlatform, non_windows: &'a str, windows: &'a str) -> &'a str { @@ -51,12 +52,12 @@ pub fn path_candidate_names(stem: &str) -> Vec { } /// Discover the path of the currently running executable image. -pub fn current_image() -> io::Result { - std::env::current_exe() +pub fn current_image() -> io::Result { + std::env::current_exe().map(NormalizedPath::from) } /// Return a path next to the current executable image. -pub fn current_image_sibling(name: impl AsRef) -> io::Result { +pub fn current_image_sibling(name: impl AsRef) -> io::Result { let image = current_image()?; let parent = image.parent().ok_or_else(|| { io::Error::new( @@ -64,16 +65,16 @@ pub fn current_image_sibling(name: impl AsRef) -> io::Result { "current executable image has no parent directory", ) })?; - Ok(parent.join(name)) + Ok(parent.join(name).into()) } /// Return the conventional unsuffixed and `.exe` sibling candidates. /// /// Probing both preserves compatibility with archives that carry an explicit /// Windows suffix even when inspected from another host. -pub fn current_image_sibling_candidates(stem: &str) -> io::Result<[PathBuf; 2]> { +pub fn current_image_sibling_candidates(stem: &str) -> io::Result<[NormalizedPath; 2]> { let unsuffixed = current_image_sibling(stem)?; - let explicit_exe = unsuffixed.with_extension("exe"); + let explicit_exe = NormalizedPath::from(unsuffixed.with_extension("exe")); Ok([unsuffixed, explicit_exe]) } diff --git a/crates/fbuild-daemon/src/main.rs b/crates/fbuild-daemon/src/main.rs index e8bfe97d4..a5014ab19 100644 --- a/crates/fbuild-daemon/src/main.rs +++ b/crates/fbuild-daemon/src/main.rs @@ -263,7 +263,7 @@ async fn main() { let identity = fbuild_paths::running_process::DaemonCacheIdentity::discover(); let claim = fbuild_paths::daemon_ownership::OwnerClaim { pid: std::process::id(), - exe: exe.into(), + exe, version: env!("CARGO_PKG_VERSION").to_string(), mode: identity.mode.to_string(), cache_root_key: identity.cache_root_key.clone(), @@ -292,7 +292,7 @@ async fn main() { let daemon_binary = this_exe .parent() .map(|d| d.join(fbuild_paths::running_process::DAEMON_BINARY_NAME)) - .unwrap_or(this_exe); + .unwrap_or_else(|| this_exe.into_path_buf()); match fbuild_daemon::broker::install_fbuild_service_definition(&daemon_binary) { Ok(written) => tracing::info!( "installed running-process service definition: {}", From a60e0787d80eb2ad43503397e76812b94b6a2d36 Mon Sep 17 00:00:00 2001 From: zackees Date: Thu, 20 Aug 2026 08:13:36 -0700 Subject: [PATCH 4/5] test: normalize host path fixture --- crates/fbuild-core/src/subprocess.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fbuild-core/src/subprocess.rs b/crates/fbuild-core/src/subprocess.rs index 30a8a59ad..cfda884a6 100644 --- a/crates/fbuild-core/src/subprocess.rs +++ b/crates/fbuild-core/src/subprocess.rs @@ -825,9 +825,9 @@ mod tests { assert_eq!(bare_name_path_overlay("esptool", None), None); // Absolute and relative paths never trigger a PATH lookup. let absolute = if crate::platform::host::is_windows() { - std::path::PathBuf::from(r"C:\tools\esptool") + crate::path::NormalizedPath::from(r"C:\tools\esptool") } else { - std::path::PathBuf::from("/usr/local/bin") + crate::path::NormalizedPath::from("/usr/local/bin") } .join(crate::platform::executable::native_name("esptool")); assert_eq!( From 5bd8bb1b7e19494c014216c185417bada3ea64fd Mon Sep 17 00:00:00 2001 From: zackees Date: Thu, 20 Aug 2026 08:50:50 -0700 Subject: [PATCH 5/5] fix: address platform facade review --- .../fbuild-build/tests/flag_escaping_lint.rs | 23 +++++++++-------- crates/fbuild-core/src/platform/executable.rs | 25 ++++++++++++++++++- crates/fbuild-python/src/daemon.rs | 2 +- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/crates/fbuild-build/tests/flag_escaping_lint.rs b/crates/fbuild-build/tests/flag_escaping_lint.rs index ee7a96f80..833c8e1c9 100644 --- a/crates/fbuild-build/tests/flag_escaping_lint.rs +++ b/crates/fbuild-build/tests/flag_escaping_lint.rs @@ -38,20 +38,21 @@ fn collect_rs_files(dir: &Path) -> Vec { /// Check that a compiler file that has a non-Windows `run_command` path /// also calls `prepare_flags_for_exec` in that path. /// -/// Heuristic: if a file contains both `run_command` and `fbuild_core::platform::host::is_windows()` (the -/// response-file branch pattern), it MUST also contain `prepare_flags_for_exec`. +/// Heuristic: if a file contains both `run_command` and an `is_windows` +/// reference (the response-file branch pattern), it MUST also contain +/// `prepare_flags_for_exec`. Matching the symbol reference also covers direct, +/// imported, and aliased calls because the import still names `is_windows`. #[test] fn compiler_backends_must_sanitize_flags_for_exec() { let src = crate_src_dir(); let mut rs_files = collect_rs_files(&src); - // Also scan fbuild-packages which has its own library compiler. - let packages_src = Path::new(env!("CARGO_MANIFEST_DIR")) - .parent() - .unwrap() - .join("fbuild-packages") - .join("src"); - rs_files.extend(collect_rs_files(&packages_src)); + // Also scan the packages and library crates, which own direct compiler + // backends outside this crate's source tree. + let crates_dir = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap(); + for crate_name in ["fbuild-packages", "fbuild-library"] { + rs_files.extend(collect_rs_files(&crates_dir.join(crate_name).join("src"))); + } let mut violations = Vec::new(); @@ -63,7 +64,7 @@ fn compiler_backends_must_sanitize_flags_for_exec() { let has_run_command = content.contains("run_command"); let has_response_file = content.contains("write_response_file") || content.contains("@response"); - let has_cfg_windows = content.contains("fbuild_core::platform::host::is_windows()"); + let has_windows_host_branch = content.contains("is_windows"); // Linker files use response files for link flags (not -D defines), // so they don't need prepare_flags_for_exec. @@ -75,7 +76,7 @@ fn compiler_backends_must_sanitize_flags_for_exec() { // compiler backend that must sanitize flags on the non-Windows path. if has_run_command && has_response_file - && has_cfg_windows + && has_windows_host_branch && !is_linker && !content.contains("prepare_flags_for_exec") { diff --git a/crates/fbuild-core/src/platform/executable.rs b/crates/fbuild-core/src/platform/executable.rs index af7b522cf..6f39ce032 100644 --- a/crates/fbuild-core/src/platform/executable.rs +++ b/crates/fbuild-core/src/platform/executable.rs @@ -3,7 +3,7 @@ use super::host::{self, HostArch, HostPlatform}; use crate::path::NormalizedPath; use std::io; -use std::path::Path; +use std::path::{Component, Path}; /// Select the spelling of an executable or command script for an explicit host. pub const fn name_for<'a>(host: HostPlatform, non_windows: &'a str, windows: &'a str) -> &'a str { @@ -58,6 +58,18 @@ pub fn current_image() -> io::Result { /// Return a path next to the current executable image. pub fn current_image_sibling(name: impl AsRef) -> io::Result { + let name = name.as_ref(); + let mut components = name.components(); + if !matches!( + (components.next(), components.next()), + (Some(Component::Normal(_)), None) + ) { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "current executable sibling name must be exactly one file-name component", + )); + } + let image = current_image()?; let parent = image.parent().ok_or_else(|| { io::Error::new( @@ -120,4 +132,15 @@ mod tests { Some("fbuild-daemon.exe") ); } + + #[test] + fn current_image_sibling_rejects_paths_that_can_escape_the_image_directory() { + for invalid in [ + std::path::Path::new("/tmp/other"), + std::path::Path::new("../other"), + ] { + let error = super::current_image_sibling(invalid).expect_err("reject non-sibling path"); + assert_eq!(error.kind(), std::io::ErrorKind::InvalidInput); + } + } } diff --git a/crates/fbuild-python/src/daemon.rs b/crates/fbuild-python/src/daemon.rs index 8c25f056a..d30a7797a 100644 --- a/crates/fbuild-python/src/daemon.rs +++ b/crates/fbuild-python/src/daemon.rs @@ -475,7 +475,7 @@ mod tests { // Unix it is unsuffixed. assert_eq!( DAEMON_BIN_NAME, - fbuild_core::platform::executable::name("fbuild-daemon", "fbuild-daemon.exe") + fbuild_core::platform::executable::native_name("fbuild-daemon") ); }