From e29accc35e7c7b3656c456c5f98c20e591909e6a Mon Sep 17 00:00:00 2001 From: Zach Vorhies Date: Wed, 2 Sep 2026 16:49:44 -0700 Subject: [PATCH 1/5] ci: drop macOS GitHub runners outside the release path macOS-hosted runners cost the most minutes and are the slowest to schedule, while every shipped macOS artifact is already cross-built from Linux (soldr + cargo-zigbuild + managed Apple SDK) in release-auto.yml. Remove the remaining mac hosts from the push/PR and manual-build lanes: - Delete check-macos.yml (clippy + tests on macos-latest for every push and PR) and its README badge. Only "Dylint" is a required status check on main, so nothing is left waiting on a check that never reports. - platform-boundary-research.yml: drop the macos-latest matrix entry. The scanner walks source rather than expanded modules, so it produces the same union on any host; --host-label is only a print prefix. - build.yml: build aarch64-apple-darwin on ubuntu-latest via the template's mac_cross_linux branch, matching the release matrix, and pass mac_cross_linux through the `with:` block (it was not wired up). release-auto.yml is unchanged -- both apple targets there already run on ubuntu-latest, so no release capability is lost. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CfdhKY6DmrRJ6mzSTzLU58 --- .github/workflows/README.md | 5 +- .github/workflows/build.yml | 16 +++-- .github/workflows/check-macos.yml | 58 ------------------- .../workflows/platform-boundary-research.yml | 2 - README.md | 1 - docs/platform-boundary-research-inventory.md | 10 ++-- docs/platform-boundary-research.md | 10 +++- 7 files changed, 27 insertions(+), 75 deletions(-) delete mode 100644 .github/workflows/check-macos.yml diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 31709aaab..a214d08d7 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -4,10 +4,11 @@ CI/CD workflows for the fbuild project, covering lint, test, documentation, and ## CI Checks (push/PR) -- **`check-{macos,ubuntu,windows}.yml`** -- Clippy + tests per platform +- **`check-{ubuntu,windows}.yml`** -- Clippy + tests per platform (no macOS runner: macOS + binaries are cross-built from Linux in the release matrix, see below) - **`fmt.yml`** -- Rustfmt check | **`docs.yml`** -- Doc build with `-D warnings` - **`msrv.yml`** -- MSRV 1.95.0 verification | **`validate-boards.yml`** -- Board JSON validation -- **`platform-boundary-research.yml`** -- Windows/Linux/macOS reconciliation of the #1307 research inventory and RED fixture +- **`platform-boundary-research.yml`** -- Windows/Linux 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/build.yml b/.github/workflows/build.yml index 11f9f2376..0e6286e7e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,16 +35,21 @@ jobs: linux_cross: true macos_cross: false - # x86_64-apple-darwin removed: Intel Macs use ARM wheel via Rosetta. - # Cross-compiling ring crate ARM→x86 fails; native macos-13 runners - # are perpetually unavailable. Re-enable when ring supports cross or - # GitHub restores Intel runner capacity. + # x86_64-apple-darwin is not built here: Intel Macs install the + # ARM wheel via Rosetta, and the release matrix + # (release-auto.yml) is what produces the Intel archive when a + # release needs one. + # aarch64-apple-darwin cross-compiles from the Linux runner via + # soldr + cargo-zigbuild + soldr's managed Apple SDK, matching the + # release matrix. No macos-latest runner is used anywhere in this + # workflow. - target: aarch64-apple-darwin - runner: macos-latest + runner: ubuntu-latest binary_ext: "" linux_cross: false macos_cross: false + mac_cross_linux: true - target: x86_64-pc-windows-msvc runner: windows-latest @@ -59,4 +64,5 @@ jobs: binary_ext: ${{ matrix.binary_ext }} linux_cross: ${{ matrix.linux_cross }} macos_cross: ${{ matrix.macos_cross }} + mac_cross_linux: ${{ matrix.mac_cross_linux == true }} ref: ${{ github.event.inputs.ref || 'main' }} diff --git a/.github/workflows/check-macos.yml b/.github/workflows/check-macos.yml deleted file mode 100644 index 2419603fc..000000000 --- a/.github/workflows/check-macos.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Check macOS - -on: - workflow_dispatch: {} - push: - branches: [main] - pull_request: - branches: [main] - -# Auto-cancel superseded PR runs: pushing again to a feature branch -# supersedes the in-flight run instead of queueing behind it. Non-PR -# events key on run_id so each gets its own group -- a shared group keeps -# only ONE pending run, which would silently drop queued main SHAs. -concurrency: - group: check-macos.yml-${{ github.event_name == 'pull_request' && github.ref || github.run_id }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -env: - CARGO_TERM_COLOR: always - RUSTFLAGS: "-D warnings" - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" - -jobs: - check: - name: Check (macos-latest) - runs-on: macos-latest - timeout-minutes: 30 - steps: - - uses: actions/checkout@v6 - - name: Setup soldr - id: setup-soldr - uses: zackees/setup-soldr@v0 - with: - version: 0.8.23 - cache: true - build-cache: true - target-cache: true - prebuild-deps: none - # Opt out of the implicit `SOLDR_LINKER=fast` injection so cargo / - # rust-toolchain.toml stays in charge. Silences the routine - # "defaulting SOLDR_LINKER=fast" warning (issue #400 / - # setup-soldr#377). - linker: platform-default - # Realistic zccache payload for the workspace check job is - # ~1.5–2 GiB (issue #400). Raise the soft warn threshold above - # the steady-state size so the action only flags genuinely - # runaway caches. Hard cap stays at the action default (6 GiB). - cache-payload-warn-bytes: 2GiB - - - name: Check - shell: bash - run: soldr cargo check --workspace --all-targets - - name: Clippy - shell: bash - run: soldr cargo clippy --workspace --all-targets -- -D warnings - - name: Test - shell: bash - run: soldr cargo test --workspace diff --git a/.github/workflows/platform-boundary-research.yml b/.github/workflows/platform-boundary-research.yml index 69fd586db..d3347246b 100644 --- a/.github/workflows/platform-boundary-research.yml +++ b/.github/workflows/platform-boundary-research.yml @@ -27,8 +27,6 @@ jobs: host: linux - os: windows-latest host: windows - - os: macos-latest - host: macos runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v6 diff --git a/README.md b/README.md index 72837cb65..1d035cb4e 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ files already used by PlatformIO sketches, but uses a Rust-native, data-driven build pipeline. [![Check Ubuntu](https://github.com/fastled/fbuild/actions/workflows/check-ubuntu.yml/badge.svg)](https://github.com/fastled/fbuild/actions/workflows/check-ubuntu.yml) -[![Check macOS](https://github.com/fastled/fbuild/actions/workflows/check-macos.yml/badge.svg)](https://github.com/fastled/fbuild/actions/workflows/check-macos.yml) [![Check Windows](https://github.com/fastled/fbuild/actions/workflows/check-windows.yml/badge.svg)](https://github.com/fastled/fbuild/actions/workflows/check-windows.yml) [![Formatting](https://github.com/fastled/fbuild/actions/workflows/fmt.yml/badge.svg)](https://github.com/fastled/fbuild/actions/workflows/fmt.yml) [![Documentation](https://github.com/fastled/fbuild/actions/workflows/docs.yml/badge.svg)](https://github.com/fastled/fbuild/actions/workflows/docs.yml) diff --git a/docs/platform-boundary-research-inventory.md b/docs/platform-boundary-research-inventory.md index c2e2a46fa..963e49061 100644 --- a/docs/platform-boundary-research-inventory.md +++ b/docs/platform-boundary-research-inventory.md @@ -17,10 +17,12 @@ 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. +runs the drift check and fixture tests on Windows and Linux and prints a +host-labelled total (the macOS runner lane was dropped from CI; macOS binaries +are cross-built from Linux, and the host-independent scanner reports the same +union there). Phase 2 must still reconcile the raw parser/Dylint inventories +before it freezes its authoritative ledger; compiler hooks alone cannot see +wrong-host or orphaned module files. Reproduce locally with: diff --git a/docs/platform-boundary-research.md b/docs/platform-boundary-research.md index 75bfa2ba5..073ce3fce 100644 --- a/docs/platform-boundary-research.md +++ b/docs/platform-boundary-research.md @@ -123,7 +123,9 @@ No current fbuild component needs a permanent specialized-artifact 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 +union (the scanner is host-independent; CI now runs it on Linux and Windows +only -- the macOS runner lane was dropped and macOS binaries are cross-built +from Linux). 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 @@ -132,8 +134,10 @@ named and narrowly linted; a file/directory wildcard is not acceptable. 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. +compile result on the Linux and Windows CI hosts (the macOS runner lane was +dropped from CI; macOS binaries are cross-built from Linux). 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, 77 native paths, and From 71f68339fa118be3911fb76ca311a237e90c7b08 Mon Sep 17 00:00:00 2001 From: Zach Vorhies Date: Wed, 2 Sep 2026 16:51:18 -0700 Subject: [PATCH 2/5] docs: record that CI has no macOS hosts CLAUDE.md is read at the start of every agent session; leaving "CI: Linux, macOS, Windows" invites the next session to re-add a mac check lane. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CfdhKY6DmrRJ6mzSTzLU58 --- CLAUDE.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index a5f8093d4..a209b930d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -59,7 +59,10 @@ The four rules an agent must internalize before doing anything else (all listed - **Always use a globally-installed `soldr` to execute Rust commands.** Bare cargo/rustc and legacy `uv run cargo` shims are blocked by hook. soldr uses `rustup which` to pick the rustup-managed toolchain from `rust-toolchain.toml`. The standard Cargo path is `soldr cargo ...`, so repo Rust builds get soldr's managed zccache path by default; do not add repo-specific `RUSTC_WRAPPER` wiring for normal builds. Install soldr globally via `uv tool install soldr` (or see https://github.com/zackees/soldr). - **Always use `uv` for Python.** Bare `python`/`pip` are blocked by hook. Use `uv run ...` or `uv pip ...`. - MSRV: 1.95.0 | Edition: 2021 | Toolchain: 1.95.0 pinned in `rust-toolchain.toml` (clippy + rustfmt) -- CI: Linux, macOS, Windows. All warnings denied (`RUSTFLAGS="-D warnings"`) +- CI hosts: Linux, Windows. All warnings denied (`RUSTFLAGS="-D warnings"`). There are + **no macOS runners** — macOS is a build *target*, not a test host: every apple-darwin + binary is cross-built from Linux (soldr + `cargo-zigbuild` + managed Apple SDK) in + `release-auto.yml`. Do not add a `macos-latest` lane back. - Every directory with files must have a README.md (enforced by hook) ## Commands From 5b67f42bcb8fb436d6d400175911babbca03f575 Mon Sep 17 00:00:00 2001 From: Zach Vorhies Date: Thu, 3 Sep 2026 03:35:20 -0700 Subject: [PATCH 3/5] docs(ci): fix Rosetta direction and stale three-host wording CodeRabbit review on #1412: - build.yml repeated an inverted Rosetta claim (Rosetta runs x86_64 on Apple silicon, not the reverse). Drop the rationale and point at the release matrix, which cross-builds the Intel target from Linux. - CLAUDE.md said release-auto.yml was the only workflow producing an Apple binary; build.yml now cross-builds one too. - platform-boundary-research.md still called the protocol "three-host" two paragraphs above the note saying the macOS lane was dropped. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CfdhKY6DmrRJ6mzSTzLU58 --- .github/workflows/build.yml | 8 ++++---- CLAUDE.md | 5 +++-- docs/platform-boundary-research.md | 4 +++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0e6286e7e..cf98df987 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,10 +35,10 @@ jobs: linux_cross: true macos_cross: false - # x86_64-apple-darwin is not built here: Intel Macs install the - # ARM wheel via Rosetta, and the release matrix - # (release-auto.yml) is what produces the Intel archive when a - # release needs one. + # x86_64-apple-darwin is not built here. This workflow builds + # binaries on demand; the release matrix (release-auto.yml) is + # what produces the Intel archive when a release needs one, and + # it cross-builds that target from Linux too. # aarch64-apple-darwin cross-compiles from the Linux runner via # soldr + cargo-zigbuild + soldr's managed Apple SDK, matching the diff --git a/CLAUDE.md b/CLAUDE.md index a209b930d..d0434d327 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -61,8 +61,9 @@ The four rules an agent must internalize before doing anything else (all listed - MSRV: 1.95.0 | Edition: 2021 | Toolchain: 1.95.0 pinned in `rust-toolchain.toml` (clippy + rustfmt) - CI hosts: Linux, Windows. All warnings denied (`RUSTFLAGS="-D warnings"`). There are **no macOS runners** — macOS is a build *target*, not a test host: every apple-darwin - binary is cross-built from Linux (soldr + `cargo-zigbuild` + managed Apple SDK) in - `release-auto.yml`. Do not add a `macos-latest` lane back. + binary is cross-built from Linux (soldr + `cargo-zigbuild` + managed Apple SDK) by the + Linux-hosted native workflows, `release-auto.yml` and `build.yml`. Do not add a + `macos-latest` lane back. - Every directory with files must have a README.md (enforced by hook) ## Commands diff --git a/docs/platform-boundary-research.md b/docs/platform-boundary-research.md index 073ce3fce..792c863ec 100644 --- a/docs/platform-boundary-research.md +++ b/docs/platform-boundary-research.md @@ -93,7 +93,9 @@ initially reported 490 candidate occurrences. Phase 2 Dylint/scanner reconciliation first corrected the union to 496 after adding missed constructs and removing local-module false positives, then incorporated eight host-cfg occurrences added to `fbuild-paths` on `main` before the baseline merged. The -authoritative union is therefore 504. The checked-in rows and reproducible three-host protocol are described in +authoritative union is therefore 504. The checked-in rows and the reproducible +cross-host protocol (three hosts as run for phase 1; the macOS lane has since +been dropped from CI) are described in `platform-boundary-research-inventory.md`. This is reviewed research input, not the phase-2 exact-occurrence baseline. From 814ac6c0260ccc8df5d992ab0a4b9ed0a97b4276 Mon Sep 17 00:00:00 2001 From: Zach Vorhies Date: Wed, 2 Sep 2026 19:43:15 -0700 Subject: [PATCH 4/5] fix(esp32): stop re-downloading the 298MB SDK libs on every S3 build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Esp32Framework::ensure_libs` short-circuits when the per-MCU SDK tree is already installed, and `mcu_sdk_complete` decided that by requiring `/lib/libfreertos.a`. ESP32-S3 is the one MCU that does not ship that archive there: its FreeRTOS build differs per flash/PSRAM mode, so `libfreertos.a` exists only under the memory-type variant dirs (`dio_opi`, `qio_qspi`, `opi_opi`, ...) while `lib/` holds the other 165 archives. Every other MCU in esp32-arduino-libs 3.3.11 (esp32, c3, c5, c6, h2, p4, p4_es, s2) has it in `lib/`. So on ESP32-S3 the check never passed, and every single build — no-op builds included — re-downloaded and re-extracted the 298 MB SDK archive before reaching the fast-path check. Measured on a bare blink sketch for esp32-s3-devkitc-1, no libraries: before: build succeeded in 135.9s pioarduino-resolve=135907 ms after: build succeeded in 0.3s pioarduino-resolve=286 ms which matches the 0.4s no-op the reporter measured for AVR, ESP8266 and STM32 on the same host. An edit to the sketch still rebuilds and relinks normally (14.5s). `has_freertos_archive` now accepts the archive in `lib/` or in any variant dir one level down. The completion check keeps its other two conditions, so the partial ESP32-C2 tree it was written for is still judged incomplete. Also warn when an existing-but-incomplete MCU SDK dir triggers the re-download: the silent form of this bug cost 132s a build and was invisible in the log. Fixes FastLED/fbuild#1411 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CfdhKY6DmrRJ6mzSTzLU58 --- .../src/library/esp32_framework/libs.rs | 76 ++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/crates/fbuild-library/src/library/esp32_framework/libs.rs b/crates/fbuild-library/src/library/esp32_framework/libs.rs index 15ed7b70b..3b3b161b4 100644 --- a/crates/fbuild-library/src/library/esp32_framework/libs.rs +++ b/crates/fbuild-library/src/library/esp32_framework/libs.rs @@ -5,6 +5,10 @@ use std::path::{Path, PathBuf}; use super::Esp32Framework; use super::fs_utils::copy_dir_recursive; +/// Archive whose presence proves a per-MCU SDK tree carries real libraries +/// and not just the partial directory some core archives ship. +const FREERTOS_ARCHIVE: &str = "libfreertos.a"; + const NEW_SDK_LAYOUT: &str = "esp32-arduino-libs"; const OLD_SDK_LAYOUT: &str = "sdk"; @@ -57,7 +61,31 @@ fn mcu_sdk_complete(mcu_dir: &Path) -> bool { .join("FreeRTOS.h") .exists() && mcu_dir.join("flags").join("includes").exists() - && mcu_dir.join("lib").join("libfreertos.a").exists() + && has_freertos_archive(mcu_dir) +} + +/// Locate `libfreertos.a` inside an installed per-MCU SDK tree. +/// +/// Most MCUs put every archive in `lib/`. ESP32-S3 does not: its FreeRTOS +/// build differs per flash/PSRAM mode, so `libfreertos.a` ships **only** +/// under the memory-type variant dirs (`dio_opi`, `qio_qspi`, ...) while +/// `lib/` holds the other 165 archives. Requiring `lib/libfreertos.a` +/// therefore judged a complete S3 install incomplete forever, and +/// [`Esp32Framework::ensure_libs`] re-downloaded and re-extracted the +/// 298 MB SDK archive on *every* build — 132 s of a 136 s no-op +/// (FastLED/fbuild#1411). +fn has_freertos_archive(mcu_dir: &Path) -> bool { + if mcu_dir.join("lib").join(FREERTOS_ARCHIVE).exists() { + return true; + } + // Only one level deep: the variant dirs sit directly under the MCU dir. + std::fs::read_dir(mcu_dir) + .map(|entries| { + entries + .flatten() + .any(|entry| entry.path().join(FREERTOS_ARCHIVE).exists()) + }) + .unwrap_or(false) } /// Merge a requested MCU directory from a skeleton archive, regardless of a @@ -129,6 +157,21 @@ impl Esp32Framework { } } + // A present-but-incomplete MCU tree means the ~300 MB archive is + // about to be fetched and extracted again. That is correct on a + // genuinely partial install and catastrophic when the completion + // check is simply wrong about the layout — the silent form of this + // cost every build 132 s on ESP32-S3 (FastLED/fbuild#1411). Say so. + for mcu_dir in mcu_sdk_dir_candidates(&tools_dir, mcu) { + if mcu_dir.exists() { + tracing::warn!( + "{} SDK dir {} exists but is incomplete; re-downloading the SDK libs archive", + mcu, + mcu_dir.display() + ); + } + } + std::fs::create_dir_all(&tools_dir)?; // Check for already-downloaded archive (skip re-download) @@ -250,6 +293,37 @@ mod tests { write(&mcu_dir.join("lib").join("libfreertos.a"), ""); } + /// ESP32-S3 is the one MCU whose `esp32-arduino-libs` tree ships + /// `libfreertos.a` **only** under the per-memory-type variant dirs + /// (`dio_opi`, `qio_qspi`, ...) — `lib/` holds the other 165 archives + /// but not that one. Requiring `lib/libfreertos.a` therefore judged + /// a fully-installed S3 SDK incomplete on every build, and + /// `ensure_libs` re-downloaded + re-extracted the 298 MB archive each + /// time: 132 s of a 136 s no-op build (FastLED/fbuild#1411). + #[test] + fn mcu_sdk_complete_accepts_memory_type_variant_freertos_lib() { + let tmp = tempfile::TempDir::new().unwrap(); + let mcu_dir = tmp.path().join("esp32s3"); + + write( + &mcu_dir + .join("include") + .join("freertos") + .join("FreeRTOS-Kernel") + .join("include") + .join("freertos") + .join("FreeRTOS.h"), + "", + ); + write(&mcu_dir.join("flags").join("includes"), ""); + // 165 archives land in `lib/`, but not libfreertos.a. + write(&mcu_dir.join("lib").join("libdriver.a"), ""); + assert!(!mcu_sdk_complete(&mcu_dir)); + + write(&mcu_dir.join("qio_qspi").join("libfreertos.a"), ""); + assert!(mcu_sdk_complete(&mcu_dir)); + } + #[test] fn mcu_sdk_complete_requires_freertos_kernel_header() { let tmp = tempfile::TempDir::new().unwrap(); From 4a808e90060df859eff528c7a4783a21a468ef71 Mon Sep 17 00:00:00 2001 From: Zach Vorhies Date: Thu, 3 Sep 2026 03:35:34 -0700 Subject: [PATCH 5/5] =?UTF-8?q?fix(esp32):=20say=20"reinstalling"=20?= =?UTF-8?q?=E2=80=94=20the=20archive=20may=20still=20be=20cached?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeRabbit review on #1413: the warning claimed a re-download, but the check below skips `download_file` when the archive is still in `tools/`, in which case only the extract repeats. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CfdhKY6DmrRJ6mzSTzLU58 --- crates/fbuild-library/src/library/esp32_framework/libs.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/fbuild-library/src/library/esp32_framework/libs.rs b/crates/fbuild-library/src/library/esp32_framework/libs.rs index 3b3b161b4..2a2900242 100644 --- a/crates/fbuild-library/src/library/esp32_framework/libs.rs +++ b/crates/fbuild-library/src/library/esp32_framework/libs.rs @@ -157,15 +157,16 @@ impl Esp32Framework { } } - // A present-but-incomplete MCU tree means the ~300 MB archive is - // about to be fetched and extracted again. That is correct on a + // A present-but-incomplete MCU tree means the ~300 MB SDK is about + // to be installed again — re-extracted, and re-downloaded too + // unless the archive is still cached below. That is correct on a // genuinely partial install and catastrophic when the completion // check is simply wrong about the layout — the silent form of this // cost every build 132 s on ESP32-S3 (FastLED/fbuild#1411). Say so. for mcu_dir in mcu_sdk_dir_candidates(&tools_dir, mcu) { if mcu_dir.exists() { tracing::warn!( - "{} SDK dir {} exists but is incomplete; re-downloading the SDK libs archive", + "{} SDK dir {} exists but is incomplete; reinstalling the SDK libs", mcu, mcu_dir.display() );