From cb8c131519d638b0eeb4e386f976e44c9f18efcc Mon Sep 17 00:00:00 2001 From: zackees Date: Wed, 19 Aug 2026 23:26:43 -0700 Subject: [PATCH 1/2] refactor(platform): record phase 1 research gate (#1307) --- .github/workflows/README.md | 1 + .../workflows/platform-boundary-research.yml | 39 ++ ci/README.md | 1 + ci/fixtures/platform_boundary/README.md | 6 + .../platform_boundary/research_red_pass.rs | 18 + ci/platform_boundary_research.py | 412 +++++++++++++++ ci/platform_boundary_research.tsv | 491 ++++++++++++++++++ ci/test_platform_boundary_research.py | 95 ++++ docs/INDEX.md | 1 + docs/README.md | 2 + docs/architecture/portability.md | 12 + docs/platform-boundary-research-inventory.md | 109 ++++ docs/platform-boundary-research.md | 144 +++++ 13 files changed, 1331 insertions(+) create mode 100644 .github/workflows/platform-boundary-research.yml create mode 100644 ci/fixtures/platform_boundary/README.md create mode 100644 ci/fixtures/platform_boundary/research_red_pass.rs create mode 100644 ci/platform_boundary_research.py create mode 100644 ci/platform_boundary_research.tsv create mode 100644 ci/test_platform_boundary_research.py create mode 100644 docs/platform-boundary-research-inventory.md create mode 100644 docs/platform-boundary-research.md diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 042fda61b..d327f1583 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -7,6 +7,7 @@ CI/CD workflows for the fbuild project, covering lint, test, documentation, and - **`check-{macos,ubuntu,windows}.yml`** -- Clippy + tests per platform - **`fmt.yml`** -- Rustfmt check | **`docs.yml`** -- Doc build with `-D warnings` - **`msrv.yml`** -- MSRV 1.94.1 verification | **`validate-boards.yml`** -- Board JSON validation +- **`platform-boundary-research.yml`** -- Windows/Linux/macOS reconciliation of the #1307 research inventory and RED fixture - **`loc-gate.yml`** -- Reject `.rs` files over 1000 LOC | **`lint-subprocess.yml`** -- Forbid direct subprocess spawns - **`crate-gate.yml`** -- Reject new workspace crates (monocrate policy, `ci/check_workspace_crates.py`) diff --git a/.github/workflows/platform-boundary-research.yml b/.github/workflows/platform-boundary-research.yml new file mode 100644 index 000000000..2a126e830 --- /dev/null +++ b/.github/workflows/platform-boundary-research.yml @@ -0,0 +1,39 @@ +name: Platform Boundary Research + +on: + workflow_dispatch: {} + pull_request: + branches: [main] + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" + +jobs: + inventory: + name: Inventory (${{ matrix.host }}) + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + host: linux + - os: windows-latest + host: windows + - os: macos-latest + host: macos + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v6 + - uses: astral-sh/setup-uv@v3 + - uses: zackees/setup-soldr@v0 + with: + version: 0.8.23 + cache: true + toolchain: 1.94.1 + prebuild-deps: none + - name: Check deterministic inventory + run: uv run --no-project python ci/platform_boundary_research.py --check --host-label ${{ matrix.host }} + - name: Run research scanner tests + run: uv run --no-project python -m unittest ci.test_platform_boundary_research + - name: Preserve RED compile evidence + run: soldr rustc --crate-type lib --emit metadata ci/fixtures/platform_boundary/research_red_pass.rs diff --git a/ci/README.md b/ci/README.md index 0c672c66f..6b9da9c67 100644 --- a/ci/README.md +++ b/ci/README.md @@ -9,6 +9,7 @@ Python scripts for CI, packaging, and development tooling. All invoked via `uv r - **`env.py`** -- Centralized PATH activation ensuring `.cargo/bin` is on PATH before invoking Rust tools - **`extract_pio_build_flags.py`** -- Extracts compiler/linker flags from PlatformIO for each board and writes reference JSONs - **`lint.py`** -- Workspace linting (rustfmt + clippy), supports single-file and auto-fix modes +- **`platform_boundary_research.py`** -- Host-independent phase-1 inventory and cross-host drift check for FastLED/fbuild#1307 - **`render_workflows.py`** -- Re-renders the `on:` blocks of `.github/workflows/build-*.yml` and the full `nightly-platforms.yml` from `board_families.json` + `ci_common_paths.txt`. CI invokes `--check` to enforce no drift. See [docs/DEVELOPMENT.md](../docs/DEVELOPMENT.md#ci-per-board-build-triggers) and FastLED/fbuild#835. - **`board_families.json`** -- SOT: per-board metadata (workflow / test_dir / env_name / family) plus the family → crate-path mapping consumed by `render_workflows.py`. - **`ci_common_paths.txt`** -- SOT: paths whose changes force-run *every* per-board build workflow. diff --git a/ci/fixtures/platform_boundary/README.md b/ci/fixtures/platform_boundary/README.md new file mode 100644 index 000000000..6487b21d2 --- /dev/null +++ b/ci/fixtures/platform_boundary/README.md @@ -0,0 +1,6 @@ +# Platform-boundary fixtures + +`research_red_pass.rs` preserves phase-1 evidence for FastLED/fbuild#1307: the +current workspace has no host-platform boundary lint, so representative private, +inactive, native-import, compile-host-fact, and `cfg!` constructs compile on each +supported host. Phase 2 converts these constructs into negative Dylint fixtures. diff --git a/ci/fixtures/platform_boundary/research_red_pass.rs b/ci/fixtures/platform_boundary/research_red_pass.rs new file mode 100644 index 000000000..396dcadac --- /dev/null +++ b/ci/fixtures/platform_boundary/research_red_pass.rs @@ -0,0 +1,18 @@ +#![allow(dead_code, unused_imports)] + +// Phase-1 RED evidence: all of these constructs compile before the boundary +// from #1306 exists. Phase 2 converts them into negative Dylint fixtures. +#[cfg(windows)] +fn private_windows_only() {} + +#[cfg(unix)] +use std::os::unix::ffi::OsStrExt as _; + +#[cfg(windows)] +use std::os::windows::ffi::OsStrExt as _; + +pub fn research_red_evidence() { + let _is_windows = cfg!(windows); + let _host_os = std::env::consts::OS; + let _target_os = option_env!("CARGO_CFG_TARGET_OS"); +} diff --git a/ci/platform_boundary_research.py b/ci/platform_boundary_research.py new file mode 100644 index 000000000..db91eb44e --- /dev/null +++ b/ci/platform_boundary_research.py @@ -0,0 +1,412 @@ +"""Generate the phase-1 host-platform boundary research inventory. + +This source walker is deliberately host independent: it scans every handwritten +Rust file under ``crates/`` without relying on cfg expansion, so Windows, Linux, +and macOS observe the same inactive branches. Phase 2 replaces this research +inventory with the authoritative Dylint/parser ledger; this file provides the +reviewed input and a cross-host drift check for FastLED/fbuild#1307. +""" + +from __future__ import annotations + +import argparse +import dataclasses +import re +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent +INVENTORY = ROOT / "ci/platform_boundary_research.tsv" + +HOST_KEYS = { + "unix", + "windows", + "target_abi", + "target_arch", + "target_endian", + "target_env", + "target_family", + "target_feature", + "target_os", + "target_pointer_width", + "target_vendor", +} +NATIVE_ROOTS = { + "interprocess", + "libc", + "mach2", + "nix", + "portable_pty", + "winapi", + "windows", + "windows_sys", +} + +CFG_ATTRIBUTE_START = re.compile(r"#\s*!?\s*\[\s*cfg(?:_attr)?\s*\(") +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*os\s*::\s*(?:windows|unix|linux|macos)\b" + r"(?:\s*::\s*[A-Za-z_][A-Za-z0-9_]*)*" + ), + re.compile(r"\b(?:windows_sys|winapi|libc|mach2|nix|portable_pty)\s*::"), + re.compile(r"\bwindows\s*::\s*Win32\b"), + re.compile(r"\binterprocess\s*::\s*os\s*::\s*(?:windows|unix)\b"), + re.compile(r"\btokio\s*::\s*net\s*::\s*(?:windows|UnixListener|UnixStream)\b"), +) +COMPILE_HOST_CONST = re.compile( + r"\bstd\s*::\s*env\s*::\s*consts\s*::\s*(?:OS|ARCH)\b" +) +COMPILE_HOST_MACRO = re.compile( + r"\b(?:env|option_env)\s*!\s*\(\s*\"CARGO_CFG_TARGET_[A-Z_]+\"" +) +CONCRETE_MODULE = re.compile( + r"\b(?:platform_imp|platform_win|platform_windows|platform_linux|platform_macos)\b" +) +TARGET_TABLE = re.compile( + r"^\s*\[target\.(.+)\.(?:build-|dev-)?dependencies\]\s*$" +) +DEPENDENCY = re.compile(r"^\s*([A-Za-z0-9_-]+)\s*=") + + +@dataclasses.dataclass(frozen=True, order=True) +class Finding: + path: str + line: int + kind: str + normalized: str + capability: str + classification: str + + def tsv(self) -> str: + return "\t".join( + ( + self.path, + str(self.line), + self.kind, + self.normalized, + self.capability, + self.classification, + ) + ) + + +def code_only(text: str) -> str: + """Blank Rust comments and string contents while preserving offsets/newlines.""" + out = list(text) + index = 0 + block_depth = 0 + while index < len(text): + pair = text[index : index + 2] + if block_depth: + if pair == "/*": + block_depth += 1 + out[index] = out[index + 1] = " " + index += 2 + elif pair == "*/": + block_depth -= 1 + out[index] = out[index + 1] = " " + index += 2 + else: + if text[index] != "\n": + out[index] = " " + index += 1 + continue + raw = re.match(r'(?:b)?r(#{0,255})"', text[index:]) + if raw: + terminator = '"' + raw.group(1) + cursor = text.find(terminator, index + raw.end()) + cursor = len(text) if cursor < 0 else cursor + len(terminator) + for position in range(index, cursor): + if text[position] != "\n": + out[position] = " " + index = cursor + continue + if pair == "//": + end = text.find("\n", index) + end = len(text) if end < 0 else end + for cursor in range(index, end): + out[cursor] = " " + index = end + continue + if pair == "/*": + block_depth = 1 + out[index] = out[index + 1] = " " + index += 2 + continue + if text[index] == '"': + cursor = index + 1 + while cursor < len(text): + if text[cursor] == "\\": + cursor += 2 + continue + if text[cursor] == '"': + cursor += 1 + break + cursor += 1 + for position in range(index, min(cursor, len(text))): + if text[position] != "\n": + out[position] = " " + index = cursor + continue + index += 1 + return "".join(out) + + +def matching_delimiter(text: str, opening: int, left: str, right: str) -> int: + depth = 0 + for index in range(opening, len(text)): + if text[index] == left: + depth += 1 + elif text[index] == right: + depth -= 1 + if depth == 0: + return index + return len(text) - 1 + + +def normalized_construct(text: str) -> str: + return re.sub(r"\s+", "", text) + + +def line_at(text: str, offset: int) -> int: + return text.count("\n", 0, offset) + 1 + + +def classify(path: str, kind: str, normalized: str = "", line: int = 0) -> 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 "::fs" in normalized or "permissions" in normalized.lower(): + return "fs", "host_mechanic" + if "/fbuild-serial/" in f"/{path}/" or "/fbuild-deploy/" in f"/{path}/": + return "device", "host_mechanic" + return "process", "host_mechanic" + if "/fbuild-toolchain/" in f"/{path}/": + # esp_qemu mixes artifact selection with concrete host runtime and + # test-fixture mechanics. Review these occurrences individually instead + # of granting the whole file the artifact-policy classification. + if path.endswith("/esp_qemu.rs") and kind == "attr_cfg": + return ("fs" if line >= 850 else "host_executable"), "host_mechanic" + if path.endswith("/esp_qemu.rs") and line >= 850: + return "fs", "host_mechanic" + return "host_executable", "host_artifact_policy" + if "/fbuild-serial/" in f"/{path}/" or "/fbuild-deploy/" in f"/{path}/": + return "device", "host_mechanic" + if "/fbuild-daemon/src/broker/" in f"/{path}/" or "daemon_client" in path: + return "ipc", "host_mechanic" + if any(token in path for token in ("containment", "subprocess", "process_identity")): + return "process", "host_mechanic" + if any(token in path for token in ("path.rs", "response_file", "disk_cache", "install_lock")): + return "fs", "host_mechanic" + if any(token in path for token in ("emulator", "esptool", "library_compiler")): + return "host_executable", "host_artifact_policy" + return "host", "host_mechanic" + + +def source_files(root: Path = ROOT) -> list[Path]: + return sorted( + path + for path in (root / "crates").rglob("*.rs") + if "target" not in path.parts and not any(part.startswith(".") for part in path.parts) + ) + + +def scan_rust(path: Path, root: Path = ROOT) -> list[Finding]: + relative = path.relative_to(root).as_posix() + original = path.read_text(encoding="utf-8") + code = code_only(original) + findings: list[Finding] = [] + + for start_pattern, kind, closing in ( + (CFG_ATTRIBUTE_START, "attr_cfg", "]"), + (CFG_MACRO_START, "cfg_macro", ")"), + ): + for match in start_pattern.finditer(code): + opening = code.find("[" if closing == "]" else "(", match.start()) + end = matching_delimiter(code, opening, "[" if closing == "]" else "(", closing) + construct = code[match.start() : end + 1] + if not (HOST_KEYS & set(IDENTIFIER.findall(construct))): + continue + normalized = normalized_construct(construct) + line = line_at(original, match.start()) + capability, classification = classify(relative, kind, normalized, line) + findings.append( + Finding( + relative, + line, + kind, + normalized, + capability, + classification, + ) + ) + + for pattern in NATIVE_PATHS: + for match in pattern.finditer(code): + normalized = normalized_construct(match.group(0)) + line = line_at(original, match.start()) + capability, classification = classify( + relative, "native_path", normalized, line + ) + findings.append( + Finding( + relative, + line, + "native_path", + normalized, + capability, + classification, + ) + ) + compile_host_matches = list(COMPILE_HOST_CONST.finditer(code)) + compile_host_matches.extend( + match + for match in COMPILE_HOST_MACRO.finditer(original) + if code[match.start() : match.start() + len(match.group(0).split("!", 1)[0])].strip() + ) + for match in sorted(compile_host_matches, key=lambda item: item.start()): + normalized = normalized_construct(match.group(0)) + line = line_at(original, match.start()) + capability, classification = classify( + relative, "compile_host_fact", normalized, line + ) + findings.append( + Finding( + relative, + line, + "compile_host_fact", + normalized, + capability, + classification, + ) + ) + for match in CONCRETE_MODULE.finditer(code): + line = line_at(original, match.start()) + capability, classification = classify( + relative, "concrete_module_ref", match.group(0), line + ) + findings.append( + Finding( + relative, + line_at(original, match.start()), + "concrete_module_ref", + match.group(0), + capability, + classification, + ) + ) + return findings + + +def scan_manifests(root: Path = ROOT) -> list[Finding]: + findings: list[Finding] = [] + for manifest in sorted((root / "crates").glob("*/Cargo.toml")): + relative = manifest.relative_to(root).as_posix() + current_target = False + for line_number, line in enumerate(manifest.read_text(encoding="utf-8").splitlines(), 1): + table = TARGET_TABLE.match(line) + if table: + current_target = True + normalized = normalized_construct(table.group(0)) + capability, classification = classify( + relative, "target_dependency_table", normalized, line_number + ) + findings.append( + Finding( + relative, + line_number, + "target_dependency_table", + normalized, + capability, + classification, + ) + ) + continue + if line.lstrip().startswith("["): + current_target = False + dependency = DEPENDENCY.match(line) + if dependency and dependency.group(1).replace("-", "_") in NATIVE_ROOTS: + capability, classification = classify( + relative, "native_dependency", dependency.group(1), line_number + ) + findings.append( + Finding( + relative, + line_number, + "native_dependency", + dependency.group(1), + capability, + classification, + ) + ) + elif current_target and dependency: + # The table itself is inventoried once; ordinary dependencies inside it + # are not native-boundary findings unless named above. + continue + return findings + + +def inventory(root: Path = ROOT) -> list[Finding]: + findings = [finding for path in source_files(root) for finding in scan_rust(path, root)] + findings.extend(scan_manifests(root)) + return sorted(findings) + + +def render(findings: list[Finding]) -> str: + header = "path\tline\tkind\tnormalized\tcapability\tclassification" + return header + "\n" + "\n".join(finding.tsv() for finding in findings) + "\n" + + +def totals(findings: list[Finding]) -> str: + from collections import Counter + + kinds = Counter(finding.kind for finding in findings) + capabilities = Counter(finding.capability for finding in findings) + classifications = Counter(finding.classification for finding in findings) + return "; ".join( + ( + f"rows={len(findings)}", + "kinds=" + ",".join(f"{key}:{kinds[key]}" for key in sorted(kinds)), + "capabilities=" + + ",".join(f"{key}:{capabilities[key]}" for key in sorted(capabilities)), + "classifications=" + + ",".join( + f"{key}:{classifications[key]}" for key in sorted(classifications) + ), + ) + ) + + +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--check", action="store_true", help="fail if the committed inventory drifts") + parser.add_argument("--write", action="store_true", help="rewrite the research inventory") + parser.add_argument("--host-label", help="label printed for cross-host CI evidence") + parser.add_argument("--print-totals", action="store_true") + args = parser.parse_args(argv) + findings = inventory() + rendered = render(findings) + if args.write: + INVENTORY.write_text(rendered, encoding="utf-8", newline="\n") + if args.check: + try: + committed = INVENTORY.read_text(encoding="utf-8") + except OSError as error: + print(f"platform-boundary-research: {error}", file=sys.stderr) + return 1 + if committed != rendered: + print( + "platform-boundary-research: committed inventory is stale; run " + "`uv run --no-project python ci/platform_boundary_research.py --write`", + file=sys.stderr, + ) + return 1 + if args.print_totals or args.host_label: + prefix = f"host={args.host_label}; " if args.host_label else "" + print(prefix + totals(findings)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/ci/platform_boundary_research.tsv b/ci/platform_boundary_research.tsv new file mode 100644 index 000000000..2473ca71c --- /dev/null +++ b/ci/platform_boundary_research.tsv @@ -0,0 +1,491 @@ +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/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 501 cfg_macro cfg!(windows) host host_mechanic +crates/fbuild-cli/src/cli/port_doctor.rs 538 cfg_macro cfg!(windows) host host_mechanic +crates/fbuild-cli/src/cli/port_doctor.rs 565 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 +crates/fbuild-cli/src/cli/usb_recovery.rs 253 native_path windows_sys:: process host_mechanic +crates/fbuild-cli/src/cli/usb_recovery.rs 256 native_path windows_sys:: process host_mechanic +crates/fbuild-cli/src/cli/usb_recovery.rs 259 native_path windows_sys:: process host_mechanic +crates/fbuild-cli/src/cli/usb_recovery.rs 262 native_path std::os::windows::ffi::OsStrExt process host_mechanic +crates/fbuild-cli/src/cli/usb_recovery.rs 424 attr_cfg #[cfg(windows)] host host_mechanic +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 33 cfg_macro cfg!(windows) host host_mechanic +crates/fbuild-cli/tests/daemon_crash_recovery.rs 103 cfg_macro cfg!(windows) host 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-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 +crates/fbuild-core/src/containment.rs 127 native_path std::os::windows::io::AsRawHandle process host_mechanic +crates/fbuild-core/src/containment.rs 139 attr_cfg #[cfg(unix)] process host_mechanic +crates/fbuild-core/src/containment.rs 154 attr_cfg #[cfg(windows)] process host_mechanic +crates/fbuild-core/src/containment.rs 164 attr_cfg #[cfg(unix)] process host_mechanic +crates/fbuild-core/src/containment.rs 196 attr_cfg #[cfg(unix)] process host_mechanic +crates/fbuild-core/src/containment.rs 198 native_path std::os::unix::process::CommandExt process host_mechanic +crates/fbuild-core/src/containment.rs 203 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 206 attr_cfg #[cfg(target_os=)] process host_mechanic +crates/fbuild-core/src/containment.rs 208 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 208 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 208 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 211 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 214 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 222 attr_cfg #[cfg(unix)] process host_mechanic +crates/fbuild-core/src/containment.rs 224 native_path std::os::unix::process::CommandExt process host_mechanic +crates/fbuild-core/src/containment.rs 228 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 291 attr_cfg #[cfg(unix)] process host_mechanic +crates/fbuild-core/src/containment.rs 301 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 304 attr_cfg #[cfg(target_os=)] process host_mechanic +crates/fbuild-core/src/containment.rs 306 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 306 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 306 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 309 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 312 native_path libc:: process host_mechanic +crates/fbuild-core/src/containment.rs 319 attr_cfg #[cfg(not(unix))] process host_mechanic +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 +crates/fbuild-core/src/path.rs 336 attr_cfg #[cfg(target_os=)] fs host_mechanic +crates/fbuild-core/src/path.rs 341 attr_cfg #[cfg(not(any(windows,target_os=)))] fs host_mechanic +crates/fbuild-core/src/path.rs 509 attr_cfg #[cfg(windows)] fs host_mechanic +crates/fbuild-core/src/path.rs 536 attr_cfg #[cfg(any(windows,target_os=))] fs host_mechanic +crates/fbuild-core/src/path.rs 546 attr_cfg #[cfg(not(any(windows,target_os=)))] fs host_mechanic +crates/fbuild-core/src/path.rs 613 attr_cfg #[cfg(windows)] fs host_mechanic +crates/fbuild-core/src/path.rs 627 attr_cfg #[cfg(not(windows))] fs host_mechanic +crates/fbuild-core/src/path.rs 644 attr_cfg #[cfg(windows)] fs host_mechanic +crates/fbuild-core/src/path.rs 658 attr_cfg #[cfg(windows)] fs host_mechanic +crates/fbuild-core/src/path.rs 719 attr_cfg #[cfg(not(windows))] fs host_mechanic +crates/fbuild-core/src/path.rs 729 attr_cfg #[cfg(windows)] fs host_mechanic +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/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 +crates/fbuild-core/src/process_identity.rs 40 attr_cfg #[cfg(windows)] process host_mechanic +crates/fbuild-core/src/process_identity.rs 43 native_path std::os::windows::raw::HANDLE process host_mechanic +crates/fbuild-core/src/process_identity.rs 65 attr_cfg #[cfg(not(any(unix,windows)))] process host_mechanic +crates/fbuild-core/src/process_identity.rs 76 attr_cfg #[cfg(target_os=)] process host_mechanic +crates/fbuild-core/src/process_identity.rs 83 attr_cfg #[cfg(all(unix,not(target_os=)))] process host_mechanic +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 +crates/fbuild-core/src/process_identity.rs 169 native_path libc:: process host_mechanic +crates/fbuild-core/src/process_identity.rs 175 native_path libc:: process host_mechanic +crates/fbuild-core/src/process_identity.rs 175 native_path libc:: process host_mechanic +crates/fbuild-core/src/process_identity.rs 175 native_path libc:: process host_mechanic +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 +crates/fbuild-core/src/subprocess.rs 520 attr_cfg #[cfg(not(unix))] process host_mechanic +crates/fbuild-core/src/subprocess.rs 574 attr_cfg #[cfg(windows)] process host_mechanic +crates/fbuild-core/src/subprocess.rs 576 native_path std::os::windows::process::CommandExt process host_mechanic +crates/fbuild-core/src/subprocess.rs 658 attr_cfg #[cfg(windows)] process host_mechanic +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-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 +crates/fbuild-daemon/Cargo.toml 88 target_dependency_table [target.'cfg(unix)'.dev-dependencies] host host_mechanic +crates/fbuild-daemon/Cargo.toml 89 native_dependency libc process host_mechanic +crates/fbuild-daemon/src/broker/backend.rs 189 attr_cfg #[cfg(unix)] ipc host_mechanic +crates/fbuild-daemon/src/broker/backend.rs 200 attr_cfg #[cfg(windows)] ipc 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 +crates/fbuild-daemon/src/main.rs 589 attr_cfg #[cfg(windows)] host host_mechanic +crates/fbuild-daemon/src/main.rs 612 attr_cfg #[cfg(not(any(unix,windows)))] host host_mechanic +crates/fbuild-daemon/src/main.rs 680 attr_cfg #[cfg(windows)] host host_mechanic +crates/fbuild-daemon/src/main.rs 686 attr_cfg #[cfg(not(windows))] host host_mechanic +crates/fbuild-daemon/src/main.rs 763 attr_cfg #[cfg(windows)] host host_mechanic +crates/fbuild-daemon/src/main.rs 765 native_path std::os::windows::io::AsRawSocket process host_mechanic +crates/fbuild-daemon/src/main.rs 810 attr_cfg #[cfg(windows)] host host_mechanic +crates/fbuild-daemon/tests/legacy_daemon_transition.rs 54 attr_cfg #[cfg(unix)] host 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 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 +crates/fbuild-daemon/tests/port_recovery.rs 88 attr_cfg #[cfg(windows)] host host_mechanic +crates/fbuild-daemon/tests/process_containment.rs 154 attr_cfg #[cfg(unix)] process host_mechanic +crates/fbuild-daemon/tests/process_containment.rs 158 native_path libc:: process host_mechanic +crates/fbuild-daemon/tests/process_containment.rs 161 attr_cfg #[cfg(windows)] process host_mechanic +crates/fbuild-daemon/tests/process_containment.rs 188 attr_cfg #[cfg(unix)] process host_mechanic +crates/fbuild-daemon/tests/process_containment.rs 190 native_path libc:: process host_mechanic +crates/fbuild-daemon/tests/process_containment.rs 190 native_path libc:: process host_mechanic +crates/fbuild-daemon/tests/process_containment.rs 198 attr_cfg #[cfg(windows)] process host_mechanic +crates/fbuild-deploy/Cargo.toml 47 target_dependency_table [target.'cfg(windows)'.dependencies] device host_mechanic +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/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 1777 cfg_macro cfg!(windows) device host_mechanic +crates/fbuild-deploy/src/rp2040.rs 2005 cfg_macro cfg!(windows) device host_mechanic +crates/fbuild-deploy/src/rp2040.rs 2232 cfg_macro cfg!(windows) device host_mechanic +crates/fbuild-deploy/src/rp2040.rs 2251 cfg_macro cfg!(windows) device host_mechanic +crates/fbuild-deploy/src/rp2040.rs 3791 attr_cfg #[cfg(windows)] device host_mechanic +crates/fbuild-deploy/src/rp2040.rs 3794 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 +crates/fbuild-deploy/src/rp2040_topology.rs 30 attr_cfg #[cfg(any(windows,test))] device host_mechanic +crates/fbuild-deploy/src/rp2040_topology.rs 41 attr_cfg #[cfg(any(windows,test))] device host_mechanic +crates/fbuild-deploy/src/rp2040_topology.rs 81 attr_cfg #[cfg(any(windows,test))] device host_mechanic +crates/fbuild-deploy/src/rp2040_topology.rs 91 attr_cfg #[cfg(any(windows,test))] device host_mechanic +crates/fbuild-deploy/src/rp2040_topology.rs 98 attr_cfg #[cfg(any(windows,test))] device host_mechanic +crates/fbuild-deploy/src/rp2040_topology.rs 109 attr_cfg #[cfg(any(windows,test))] device host_mechanic +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-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/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 +crates/fbuild-packages-fetch/src/disk_cache/budget.rs 112 attr_cfg #[cfg(not(any(unix,windows)))] fs host_mechanic +crates/fbuild-packages-fetch/src/disk_cache/budget.rs 120 attr_cfg #[cfg(windows)] fs host_mechanic +crates/fbuild-packages-fetch/src/disk_cache/budget.rs 148 attr_cfg #[cfg(unix)] fs host_mechanic +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 440 attr_cfg #[cfg(target_os=)] host host_mechanic +crates/fbuild-paths/src/lib.rs 444 attr_cfg #[cfg(not(target_os=))] 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 +crates/fbuild-serial/src/port_class.rs 122 attr_cfg #[cfg(not(any(target_os=,target_os=,target_os=)))] device host_mechanic +crates/fbuild-serial/src/port_class.rs 129 attr_cfg #[cfg(target_os=)] device host_mechanic +crates/fbuild-serial/src/port_class.rs 224 attr_cfg #[cfg(target_os=)] device host_mechanic +crates/fbuild-serial/src/port_class.rs 281 attr_cfg #[cfg(target_os=)] device host_mechanic +crates/fbuild-serial/src/port_class.rs 285 native_path std::os::unix::fs::symlink fs host_mechanic +crates/fbuild-serial/src/port_class.rs 419 attr_cfg #[cfg(target_os=)] device host_mechanic +crates/fbuild-serial/src/port_class.rs 495 attr_cfg #[cfg(target_os=)] device host_mechanic +crates/fbuild-serial/src/ports.rs 129 attr_cfg #[cfg_attr(not(windows),allow(dead_code))] device host_mechanic +crates/fbuild-serial/src/ports.rs 137 attr_cfg #[cfg_attr(not(windows),allow(dead_code))] device host_mechanic +crates/fbuild-serial/src/ports.rs 159 attr_cfg #[cfg_attr(not(windows),allow(dead_code))] device host_mechanic +crates/fbuild-serial/src/ports.rs 182 attr_cfg #[cfg(windows)] device host_mechanic +crates/fbuild-serial/src/ports.rs 186 attr_cfg #[cfg(not(windows))] device host_mechanic +crates/fbuild-serial/src/ports.rs 195 attr_cfg #[cfg(target_os=)] device host_mechanic +crates/fbuild-serial/src/ports.rs 208 attr_cfg #[cfg(target_os=)] device host_mechanic +crates/fbuild-serial/src/ports.rs 270 attr_cfg #[cfg(any(windows,test))] device host_mechanic +crates/fbuild-serial/src/ports.rs 281 attr_cfg #[cfg(windows)] device host_mechanic +crates/fbuild-serial/src/ports.rs 285 attr_cfg #[cfg(not(windows))] device host_mechanic +crates/fbuild-serial/src/ports.rs 299 attr_cfg #[cfg(windows)] device host_mechanic +crates/fbuild-serial/src/ports.rs 303 attr_cfg #[cfg(not(windows))] device host_mechanic +crates/fbuild-serial/src/ports.rs 326 attr_cfg #[cfg(windows)] device host_mechanic +crates/fbuild-serial/src/ports.rs 330 attr_cfg #[cfg(not(windows))] device host_mechanic +crates/fbuild-serial/src/ports.rs 341 attr_cfg #[cfg(target_os=)] device host_mechanic +crates/fbuild-serial/src/ports.rs 471 attr_cfg #[cfg(windows)] device host_mechanic +crates/fbuild-serial/src/ports.rs 482 native_path windows_sys:: device host_mechanic +crates/fbuild-serial/src/ports.rs 492 native_path windows_sys:: device host_mechanic +crates/fbuild-serial/src/ports.rs 495 native_path windows_sys:: device host_mechanic +crates/fbuild-serial/src/ports.rs 499 native_path windows_sys:: device host_mechanic +crates/fbuild-serial/src/ports.rs 502 native_path windows_sys:: device host_mechanic +crates/fbuild-serial/src/ports.rs 507 native_path windows_sys:: device host_mechanic +crates/fbuild-serial/src/ports.rs 511 native_path windows_sys:: device host_mechanic +crates/fbuild-serial/src/sysfs_usb.rs 461 attr_cfg #[cfg(target_os=)] device host_mechanic +crates/fbuild-serial/src/usb_recovery.rs 258 attr_cfg #[cfg(windows)] device host_mechanic +crates/fbuild-serial/src/usb_recovery.rs 263 attr_cfg #[cfg(not(windows))] device host_mechanic +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/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_platform_boundary_research.py b/ci/test_platform_boundary_research.py new file mode 100644 index 000000000..8ce467fef --- /dev/null +++ b/ci/test_platform_boundary_research.py @@ -0,0 +1,95 @@ +from __future__ import annotations + +import unittest +from pathlib import Path +from tempfile import TemporaryDirectory + +from ci import platform_boundary_research + + +class PlatformBoundaryResearchTests(unittest.TestCase): + def test_red_fixture_contains_every_representative_violation(self) -> None: + fixture = Path(__file__).parent / "fixtures/platform_boundary/research_red_pass.rs" + findings = platform_boundary_research.scan_rust(fixture, platform_boundary_research.ROOT) + kinds = {finding.kind for finding in findings} + + self.assertIn("attr_cfg", kinds) + self.assertIn("cfg_macro", kinds) + self.assertIn("native_path", kinds) + self.assertIn("compile_host_fact", kinds) + + def test_comments_and_strings_are_not_findings(self) -> None: + source = ( + '// cfg!(windows)\n' + 'const TEXT: &str = "std::os::unix";\n' + 'const RAW: &str = r#"cfg!(windows); libc::kill(1, 1)"#;\n' + ) + code = platform_boundary_research.code_only(source) + + self.assertNotRegex(code, r"cfg\s*!|std\s*::\s*os") + + def test_compile_host_macros_are_found_but_quoted_text_is_not(self) -> None: + with TemporaryDirectory(dir=platform_boundary_research.ROOT) as directory: + path = Path(directory) / "compile_facts.rs" + path.write_text( + 'const A: Option<&str> = option_env!("CARGO_CFG_TARGET_OS");\n' + 'const B: &str = env!("CARGO_CFG_TARGET_ARCH");\n' + 'const TEXT: &str = r#"env!(\\"CARGO_CFG_TARGET_ENV\\")"#;\n', + encoding="utf-8", + ) + findings = platform_boundary_research.scan_rust( + path, platform_boundary_research.ROOT + ) + + macros = [ + finding + for finding in findings + if finding.kind == "compile_host_fact" + ] + self.assertEqual(len(macros), 2) + + def test_all_target_dependency_table_forms_are_recognized(self) -> None: + for suffix in ("dependencies", "dev-dependencies", "build-dependencies"): + with self.subTest(suffix=suffix): + self.assertIsNotNone( + platform_boundary_research.TARGET_TABLE.match( + f"[target.'cfg(unix)'.{suffix}]" + ) + ) + + def test_mixed_qemu_file_classifies_permissions_as_filesystem_mechanics(self) -> None: + path = ( + platform_boundary_research.ROOT + / "crates/fbuild-toolchain/src/toolchain/esp_qemu.rs" + ) + findings = platform_boundary_research.scan_rust( + path, platform_boundary_research.ROOT + ) + permission_findings = [ + finding + for finding in findings + if finding.line in {884, 886, 899, 901} + and finding.kind in {"attr_cfg", "native_path"} + ] + + self.assertTrue(permission_findings) + self.assertTrue( + all( + finding.capability == "fs" + and finding.classification == "host_mechanic" + for finding in permission_findings + ) + ) + + def test_inventory_is_sorted_and_matches_committed_file(self) -> None: + findings = platform_boundary_research.inventory() + + self.assertEqual(findings, sorted(findings)) + self.assertEqual( + platform_boundary_research.INVENTORY.read_text(encoding="utf-8"), + platform_boundary_research.render(findings), + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/docs/INDEX.md b/docs/INDEX.md index e2323f603..2d83411bc 100644 --- a/docs/INDEX.md +++ b/docs/INDEX.md @@ -27,6 +27,7 @@ fbuild docs. | How do the PyO3 Python bindings work? | [architecture/pyo3-bindings.md](architecture/pyo3-bindings.md) | | How does deploy preemption work? | [architecture/deploy-preemption.md](architecture/deploy-preemption.md) | | What are the cross-platform portability constraints? | [architecture/portability.md](architecture/portability.md) | +| How is host-platform code being centralized and inventoried? | [platform-boundary-research.md](platform-boundary-research.md) | | How does library selection (LDF) work in fbuild? | [architecture/library-selection.md](architecture/library-selection.md) | | Why was my library wrongly compiled (#204) / not found (#202)? | [architecture/library-selection.md](architecture/library-selection.md#why) | | Why did we choose X over Y? | [DESIGN_DECISIONS.md](DESIGN_DECISIONS.md) | diff --git a/docs/README.md b/docs/README.md index d2b9bcef7..a300f1894 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,6 +18,8 @@ Documentation is organized by reader intent. Start with - **`DEVELOPMENT.md`** -- testing, troubleshooting, local development setup - **`ARCHITECTURE.md`** -- index of all architecture documents - **`architecture/`** -- subsystem-specific architecture documents +- **`platform-boundary-research.md`** -- host-platform boundary decision and migration ordering for #1306 +- **`platform-boundary-research-inventory.md`** -- reproducible phase-1 host/native source inventory - **`CLAUDE.md`** -- guide mapping crates to relevant architecture docs - **`DESIGN_DECISIONS.md`** -- ADR-style decisions with rationale - **`ROADMAP.md`** -- implementation phases for the Rust port diff --git a/docs/architecture/portability.md b/docs/architecture/portability.md index 8e3c6a276..484780c6b 100644 --- a/docs/architecture/portability.md +++ b/docs/architecture/portability.md @@ -1,5 +1,17 @@ # Platform Portability +## Host-platform architecture + +FastLED/fbuild#1306 is centralizing host mechanics behind a single +`fbuild_core::platform` selector. The phase-1 decision and source inventory are +documented in [platform-boundary-research.md](../platform-boundary-research.md) +and +[platform-boundary-research-inventory.md](../platform-boundary-research-inventory.md). + +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. + ## Windows (MSYS2/Git Bash) ### USB-CDC Serial diff --git a/docs/platform-boundary-research-inventory.md b/docs/platform-boundary-research-inventory.md new file mode 100644 index 000000000..4eafaa3ea --- /dev/null +++ b/docs/platform-boundary-research-inventory.md @@ -0,0 +1,109 @@ +# Phase-1 host-platform research inventory + +This document records the reproducible inventory for +[FastLED/fbuild#1307](https://github.com/FastLED/fbuild/issues/1307). The rows in +`ci/platform_boundary_research.tsv` are reviewed input to phase 2, not a +grandfathering baseline. + +## Scope and method + +The scanner walks every handwritten `.rs` file below `crates/`, including crate +roots, inline tests, integration tests, examples, benches, and otherwise +inactive module files. It strips comments and quoted string contents while +preserving offsets, then records host cfg attributes/macros, compile-time host +facts, native paths, concrete platform references, target dependency tables, +and native dependencies. Generated output, `target/`, Dylint fixtures, and +external/vendor sources are outside this research union. + +Because the scanner walks source rather than expanded modules, the same checkout +produces the same union on every host. `.github/workflows/platform-boundary-research.yml` +runs the drift check and fixture tests on Windows, Linux, and macOS and prints a +host-labelled total. Phase 2 must still reconcile the three raw parser/Dylint +inventories before it freezes its authoritative ledger; compiler hooks alone +cannot see wrong-host or orphaned module files. + +Reproduce locally with: + +```powershell +uv run --no-project python ci/platform_boundary_research.py --check --print-totals +uv run --no-project python -m unittest ci.test_platform_boundary_research +``` + +## Reconciled union + +The committed union contains **490 rows**: + +| Kind | Rows | +| --- | ---: | +| `attr_cfg` | 194 | +| `cfg_macro` | 197 | +| `compile_host_fact` | 14 | +| `native_path` | 72 | +| `native_dependency` | 7 | +| `target_dependency_table` | 6 | + +| Classification | Rows | +| --- | ---: | +| Host mechanic | 384 | +| Host artifact policy | 106 | +| Embedded build-target policy | 0 | +| Specialized artifact | 0 | + +| Capability | Rows | +| --- | ---: | +| `host_executable` | 117 | +| `device` | 116 | +| `process` | 106 | +| `host` | 96 | +| `fs` | 43 | +| `ipc` | 12 | + +## Distribution by crate + +| Crate | Rows | +| --- | ---: | +| `fbuild-core` | 101 | +| `fbuild-toolchain` | 101 | +| `fbuild-deploy` | 76 | +| `fbuild-daemon` | 62 | +| `fbuild-serial` | 46 | +| `fbuild-cli` | 47 | +| `fbuild-library` | 13 | +| `fbuild-build` | 10 | +| `fbuild-paths` | 9 | +| `fbuild-packages-fetch` | 9 | +| `fbuild-python` | 4 | +| `fbuild-build-engine` | 4 | +| `fbuild-config` | 3 | +| `fbuild-build-arm` | 3 | +| `fbuild-build-esp` | 2 | + +The 490-row count is larger than #1306's preliminary 386 matching lines because +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. + +## Manifest findings + +Target-specific native ownership currently exists in: + +- `fbuild-core`: Unix `libc`; +- `fbuild-cli`: Windows `windows-sys`; +- `fbuild-deploy`: Windows `windows-sys`; +- `fbuild-serial`: Windows `windows-sys`; +- `fbuild-daemon`: Unix `libc`, including a dev dependency, plus + cross-platform `interprocess`. + +Phase 2's manifest checker must freeze exact occurrences. Later capability +phases move native dependency ownership into `fbuild-core`'s private concrete +platform implementation and remove caller target tables when their final use is +migrated. + +## Classification limits + +Phase 1 classifies by source ownership and reviewed subsystem responsibility. +It intentionally does not claim that a lightweight source walker is an AST +authority. In particular, phase 2 must normalize nested cfg token trees, +aliases, raw strings, grouped/glob imports, raw handle/fd traits, and repeated +identical occurrences with stable ordinals. If the phase-2 union differs, its PR +must explain every delta instead of regenerating a baseline to make CI pass. diff --git a/docs/platform-boundary-research.md b/docs/platform-boundary-research.md new file mode 100644 index 000000000..205fd4b8e --- /dev/null +++ b/docs/platform-boundary-research.md @@ -0,0 +1,144 @@ +# Host-platform boundary: phase 1 research gate + +This note is the phase-1 architecture decision for +[FastLED/fbuild#1306](https://github.com/FastLED/fbuild/issues/1306) and +[#1307](https://github.com/FastLED/fbuild/issues/1307). It deliberately changes +no production ownership or toolchain pin. Phase 2 consumes this decision and +the companion inventory before freezing a migration ledger. + +## Decision + +Add the host-platform boundary as `fbuild_core::platform`; do not add a +workspace crate. `fbuild-core` has no local workspace dependencies, every +current host-sensitive product crate already depends on it directly or can add +that leaf dependency without a cycle, and the repository's monocrate rule +reserves new crates for compile-parallelism splits backed by timings. + +The module root will contain the only production host selector. It uses +`std::cfg_select!` with exactly `target_os = "windows"`, +`target_os = "linux"`, and `target_os = "macos"` arms and no fallback. Linux +and macOS have separate private concrete trees; there is no permanent generic +Unix implementation. Unsupported hosts fail to compile at the selector. + +The initial neutral facade is: + +| Namespace | Owns | Callers retain | +| --- | --- | --- | +| `platform::host` | Host OS/architecture facts, path-list separator, home/runtime facts | Embedded target and package/tool selection policy | +| `platform::executable` | Native/sibling executable names, PATH/PATHEXT candidates, current image | Which compiler/deployer/emulator to select and diagnostics | +| `platform::process` | Native command setup, containment, termination, PID/image inspection, exit interpretation | Programs, arguments, retry policy, lifecycle state | +| `platform::fs` | File identity, links/reparse points, permissions, replacement, volume facts, native error normalization | `NormalizedPath`, cache/archive policy, authorization and retries | +| `platform::ipc` | fbuild-owned endpoint/listener/peer primitives not already abstracted upstream | Broker/HTTP framing, routing, protocol and lifecycle policy | +| `platform::device` | Serial/USB/PnP/sysfs/IOKit/removable-volume/topology primitives | Board selection, VID/PID registry data, deploy and recovery policy | + +Facade APIs exchange standard-library values or facade-owned neutral types. +Raw handles/file descriptors, Win32/libc structs and error codes, concrete +sockets/pipes, native extension traits, and concrete OS modules do not cross +the boundary. + +Existing libraries remain the preferred implementation. In particular, +`running-process`, `serialport`, and `interprocess` are delegated to when their +neutral surface already owns a primitive. This project does not fork or +duplicate their platform implementations. + +## Host, host artifact, and embedded target + +The inventory uses three distinct concepts: + +```text +HOST MECHANICS +"What OS is this fbuild executable running on?" + -> fbuild_core::platform + +HOST ARTIFACT POLICY +"Which compiler/emulator/deployer package runs on this host?" + -> product owner consumes platform::host/executable facts + +EMBEDDED BUILD TARGET +"Which board/MCU/framework is being compiled or flashed?" + -> fbuild_core::Platform, board data, toolchain/orchestrator policy +``` + +A Linux host selecting a Windows or macOS compiler artifact or embedded target +still uses Linux filesystem, process, IPC, and device mechanics. Compile-time +host cfg must never stand in for the board/compiler target. The phase-1 scan +found no legitimate embedded-target occurrence expressed as Rust host cfg; +such an occurrence would be a bug, not a permanent exception. + +## Toolchain proof and pin audit + +`std::cfg_select!` is stable in Rust 1.95.0. The current workspace MSRV and +toolchain are 1.94.1, so phase 2 raises all declarations that build fbuild +itself to one reviewed 1.95.x patch release. + +The fbuild-owned pin set is: + +- root workspace manifest, `rust-toolchain.toml`, `CLAUDE.md`, and + `docs/DEVELOPMENT.md`; +- `.github/workflows/{msrv,fmt,dylint,template_native_build,platform-boundary-research}.yml` + and `.github/workflows/README.md`; +- `ci/docker-test-serial/run-test.sh` and + `ci/docker-mac-cross/README.md`; +- `dylints/README.md` (the stable workspace description only). + +The separately pinned Dylint nightly remains independent. Historical measured +data in `docs/SOLDR_BUILD_PERF.md` and `tasks/baseline-205.md` records the +compiler actually used for those measurements and is not rewritten. Phase 2 +adds a drift test so future build pins cannot diverge. + +## Inventory result and dependency order + +The host-independent source walker in `ci/platform_boundary_research.py` +reports 490 candidate occurrences. The checked-in rows and reproducible +three-host protocol are described in +`platform-boundary-research-inventory.md`. This is reviewed research input, not +the phase-2 exact-occurrence baseline. + +The dependency edges confirm the issue breakdown: + +1. `host` and `executable` facts first, because artifact/tool selection consumes + them across toolchain, deploy, CLI, and emulator code. +2. `process` next, because daemon lifecycle and device tooling depend on native + spawn/containment/inspection primitives. +3. `fs` before IPC, because owner-private endpoint paths and retirement consume + filesystem primitives. +4. daemon IPC/lifecycle after process and fs. +5. serial/USB/device before deploy and emulator exceptions, because deployers + consume topology, PnP, port, and removable-volume primitives. +6. resolve all domain-specific callers, then consolidate at a zero baseline. + +## Exceptional-component decisions + +No current fbuild component needs a permanent specialized-artifact zone. + +| Candidate | Decision | Reason | +| --- | --- | --- | +| `fbuild-python` PyO3 cdylib | Migrate ordinary callers | Binding/package identity does not require native host APIs outside the facade. | +| running-process broker integration | Delegate and migrate fbuild seams | Broker/session transport remains upstream; fbuild endpoint/lifecycle policy stays neutral. | +| RP2040/probe-rs/WCH/WLink deployers | Migrate to `device`/`process` | Their native USB, volume, and process operations can use neutral primitives. | +| QEMU/avr8js emulator runners | Migrate to `host`/`executable`/`process` | Host artifact and launch behavior needs no special binary ABI zone. | +| build/test fixtures | Generic or concrete-facade tests | Tests are not an exemption from the source boundary. | + +Phase 2 must revalidate this decision against its parser-derived three-host +union. If it discovers a genuine artifact ABI constraint, the exception must be +named and narrowly linted; a file/directory wildcard is not acceptable. + +## RED evidence + +`ci/fixtures/platform_boundary/research_red_pass.rs` contains a private host +attribute, active-host native import, `cfg!` expression, and compile-time host +fact. It compiles on Windows, Linux, and macOS today because fbuild has no +host-platform boundary lint. The phase-1 workflow preserves that positive +compile result on all three hosts. Phase 2 converts the same constructs into +negative Dylint/scanner fixtures whose expected result is a boundary error. + +Existing production and test sources provide additional RED evidence: the +research inventory includes private/inactive attributes, 72 native paths, and +host cfg in integration and inline-test sources without a boundary diagnostic. + +## Phase-2 entry requirements + +Phase 2 must use the committed union as input, replace research scanning with +syntax-aware pre-expansion Dylint plus an independent whole-tree parser, freeze +the exact-occurrence ledger, add the selector skeleton, and update the toolchain. +No capability migration begins until those gates pass. From 5d41fea22934aa73cd7bd5c11c72325b929e046a Mon Sep 17 00:00:00 2001 From: zackees Date: Wed, 19 Aug 2026 23:39:33 -0700 Subject: [PATCH 2/2] fix(ci): stabilize platform research classification --- .../workflows/platform-boundary-research.yml | 4 +- ci/platform_boundary_research.py | 59 +++++++++++++++---- ci/test_platform_boundary_research.py | 41 ++++++++++++- 3 files changed, 91 insertions(+), 13 deletions(-) diff --git a/.github/workflows/platform-boundary-research.yml b/.github/workflows/platform-boundary-research.yml index 2a126e830..98dbf369a 100644 --- a/.github/workflows/platform-boundary-research.yml +++ b/.github/workflows/platform-boundary-research.yml @@ -24,6 +24,8 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v6 + with: + persist-credentials: false - uses: astral-sh/setup-uv@v3 - uses: zackees/setup-soldr@v0 with: @@ -36,4 +38,4 @@ jobs: - name: Run research scanner tests run: uv run --no-project python -m unittest ci.test_platform_boundary_research - name: Preserve RED compile evidence - run: soldr rustc --crate-type lib --emit metadata ci/fixtures/platform_boundary/research_red_pass.rs + run: soldr rustc --edition 2021 -D warnings --crate-type lib --emit metadata ci/fixtures/platform_boundary/research_red_pass.rs diff --git a/ci/platform_boundary_research.py b/ci/platform_boundary_research.py index db91eb44e..d3211b6f1 100644 --- a/ci/platform_boundary_research.py +++ b/ci/platform_boundary_research.py @@ -68,6 +68,12 @@ r"^\s*\[target\.(.+)\.(?:build-|dev-)?dependencies\]\s*$" ) DEPENDENCY = re.compile(r"^\s*([A-Za-z0-9_-]+)\s*=") +FUNCTION_START = re.compile(r"\b(?:async\s+)?fn\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(") + +ESP_QEMU_FS_CONTEXTS = { + "preflight_ok_when_binary_runs_version_successfully", + "preflight_linux_detects_missing_shared_library_exit_127", +} @dataclasses.dataclass(frozen=True, order=True) @@ -174,7 +180,29 @@ def line_at(text: str, offset: int) -> int: return text.count("\n", 0, offset) + 1 -def classify(path: str, kind: str, normalized: str = "", line: int = 0) -> tuple[str, str]: +def enclosing_function(text: str, offset: int) -> str: + """Return the function owning an offset, including an attribute on that function.""" + starts = list(FUNCTION_START.finditer(text)) + for match in reversed(starts): + if match.start() > offset: + continue + opening = text.find("{", match.end()) + if opening >= 0 and offset <= matching_delimiter(text, opening, "{", "}"): + return match.group(1) + + for match in starts: + if match.start() <= offset: + continue + prefix = text[offset : match.start()] + if len(prefix) <= 256 and "{" not in prefix and ";" not in prefix: + return match.group(1) + break + return "" + + +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 "::fs" in normalized or "permissions" in normalized.lower(): @@ -186,10 +214,10 @@ def classify(path: str, kind: str, normalized: str = "", line: int = 0) -> tuple # esp_qemu mixes artifact selection with concrete host runtime and # test-fixture mechanics. Review these occurrences individually instead # of granting the whole file the artifact-policy classification. - if path.endswith("/esp_qemu.rs") and kind == "attr_cfg": - return ("fs" if line >= 850 else "host_executable"), "host_mechanic" - if path.endswith("/esp_qemu.rs") and line >= 850: + if path.endswith("/esp_qemu.rs") and context in ESP_QEMU_FS_CONTEXTS: return "fs", "host_mechanic" + if path.endswith("/esp_qemu.rs") and kind == "attr_cfg": + return "host_executable", "host_mechanic" return "host_executable", "host_artifact_policy" if "/fbuild-serial/" in f"/{path}/" or "/fbuild-deploy/" in f"/{path}/": return "device", "host_mechanic" @@ -230,7 +258,9 @@ def scan_rust(path: Path, root: Path = ROOT) -> list[Finding]: continue normalized = normalized_construct(construct) line = line_at(original, match.start()) - capability, classification = classify(relative, kind, normalized, line) + capability, classification = classify( + relative, kind, normalized, enclosing_function(code, match.start()) + ) findings.append( Finding( relative, @@ -247,7 +277,10 @@ def scan_rust(path: Path, root: Path = ROOT) -> list[Finding]: normalized = normalized_construct(match.group(0)) line = line_at(original, match.start()) capability, classification = classify( - relative, "native_path", normalized, line + relative, + "native_path", + normalized, + enclosing_function(code, match.start()), ) findings.append( Finding( @@ -269,7 +302,10 @@ def scan_rust(path: Path, root: Path = ROOT) -> list[Finding]: normalized = normalized_construct(match.group(0)) line = line_at(original, match.start()) capability, classification = classify( - relative, "compile_host_fact", normalized, line + relative, + "compile_host_fact", + normalized, + enclosing_function(code, match.start()), ) findings.append( Finding( @@ -284,7 +320,10 @@ def scan_rust(path: Path, root: Path = ROOT) -> list[Finding]: for match in CONCRETE_MODULE.finditer(code): line = line_at(original, match.start()) capability, classification = classify( - relative, "concrete_module_ref", match.group(0), line + relative, + "concrete_module_ref", + match.group(0), + enclosing_function(code, match.start()), ) findings.append( Finding( @@ -310,7 +349,7 @@ def scan_manifests(root: Path = ROOT) -> list[Finding]: current_target = True normalized = normalized_construct(table.group(0)) capability, classification = classify( - relative, "target_dependency_table", normalized, line_number + relative, "target_dependency_table", normalized ) findings.append( Finding( @@ -328,7 +367,7 @@ def scan_manifests(root: Path = ROOT) -> list[Finding]: dependency = DEPENDENCY.match(line) if dependency and dependency.group(1).replace("-", "_") in NATIVE_ROOTS: capability, classification = classify( - relative, "native_dependency", dependency.group(1), line_number + relative, "native_dependency", dependency.group(1) ) findings.append( Finding( diff --git a/ci/test_platform_boundary_research.py b/ci/test_platform_boundary_research.py index 8ce467fef..bb17cfc04 100644 --- a/ci/test_platform_boundary_research.py +++ b/ci/test_platform_boundary_research.py @@ -68,8 +68,8 @@ def test_mixed_qemu_file_classifies_permissions_as_filesystem_mechanics(self) -> permission_findings = [ finding for finding in findings - if finding.line in {884, 886, 899, 901} - and finding.kind in {"attr_cfg", "native_path"} + if finding.capability == "fs" + and finding.kind in {"attr_cfg", "cfg_macro", "native_path"} ] self.assertTrue(permission_findings) @@ -81,6 +81,43 @@ def test_mixed_qemu_file_classifies_permissions_as_filesystem_mechanics(self) -> ) ) + for context in platform_boundary_research.ESP_QEMU_FS_CONTEXTS: + with self.subTest(context=context): + self.assertEqual( + platform_boundary_research.classify( + "crates/fbuild-toolchain/src/toolchain/esp_qemu.rs", + "attr_cfg", + "#[cfg(unix)]", + context, + ), + ("fs", "host_mechanic"), + ) + + def test_function_context_handles_inner_and_attached_cfg_attributes(self) -> None: + source = """ +fn outer() { + #[cfg(unix)] + let enabled = true; +} + +#[cfg(target_os = "linux")] +fn attached() {} +""" + code = platform_boundary_research.code_only(source) + + self.assertEqual( + platform_boundary_research.enclosing_function( + code, code.index("#[cfg(unix)]") + ), + "outer", + ) + self.assertEqual( + platform_boundary_research.enclosing_function( + code, code.index("#[cfg(target_os") + ), + "attached", + ) + def test_inventory_is_sorted_and_matches_committed_file(self) -> None: findings = platform_boundary_research.inventory()