Skip to content

research(esp32): genuine bare-IDF / CMake component builds — options, cost, and a no-false-coverage gate #1761

Open

Description

@zackees

Why

Follow-up to #1664 and #1730. #1730 closed the reject half of "honor or reject": a bare framework = espidf project now fails before compilation instead of silently producing an Arduino-only build.

The honor half — actually running a bare-IDF / CMake-component project — has no home. This issue is the research placeholder for it, deliberately deferred: investigation and design only, no implementation in this pass.

What exists today (evidence)

  • The ESP32 path resolves pioarduino: platform-espressif32 + framework-arduinoespressif32 (crates/fbuild-build-esp/src/esp32/orchestrator/packages.rs:1-37), then compiles the sketch, Arduino cores and library sources itself.
  • It consumes ESP-IDF artifacts as 100+ precompiled .a libraries linked with fbuild's own recipe (crates/fbuild-build-esp/src/esp32/esp32_linker.rs:4).
  • There is no CMake and no idf.py: stated verbatim at crates/fbuild-build-esp/src/esp32/orchestrator/helpers.rs:76 ("precompiled ESP-IDF libraries; it has no CMake/idf.py component build"), and a grep for cmake/ninja across the ESP crates returns only those helper comments.
  • Consequence to keep honest: framework = arduino, espidf is honored, but it is not component coverage — it links IDF through the Arduino core. FastLED's ci/boards.py claim that ESP32DEV_IDF5_COMPONENT exercises idf_component_register() is therefore not proven under fbuild (noted in fix(esp32): reject framework = espidf instead of silently building Arduino (#1664) #1730).

Research questions

  1. Demand. What fraction of real FastLED/third-party ESP32 projects are genuinely CMake-component builds versus Arduino-on-IDF with extra components? This decides whether delegation (option 1) pays for itself.
  2. Minimum viable inputs. What must fbuild read to build a component project correctly: the CMakeLists.txt/idf_component_register() graph, sdkconfig/Kconfig (sdkconfig.projbuild), IDF linker fragments, partition table, bootloader?
  3. Hermetic delegation + caching. If a delegated idf.py/CMake build is used, what replaces the zccache and framework-libs caches, where do artifacts land, and how is compile_commands.json merged for the daemon and indexers?
  4. Metadata. What must be recorded (requested framework vs effective framework + integration mode) so that CMake/IDF coverage can never be claimed without artifacts?
  5. Toolchain cost. What does the package set have to grow by (cmake, ninja, python, IDF component manager) and what is the install/disk cost — ties into feat(esp32): make ESP builds survive low-disk hosts — pre-flight free-space check, on-demand cache reclaim, actionable ENOSPC #1750.

Design options (to evaluate, not choose now)

  1. Delegate to idf.py/CMake. Fastest route to correctness: run the project's own build, ingest elf/bin, compile_commands.json, sdkconfig, partition table. Cost: a second foreign build system to install and supervise, a separate caching story, new CI prerequisites.
  2. Native IDF component model in Rust. Parse the component graph, implement Kconfig/sdkconfig, emit IDF linker fragments, generate bootloader and partitions. Best integration with fbuild's caches and diagnostics, but essentially re-implements IDF's build layer and would perpetually lag upstream IDF releases.
  3. Hybrid (preferred shape). Keep the natively-supported shape (Arduino-on-IDF plus extra components — what arduino, espidf already is) and route genuine CMake-component projects through option 1, with artifacts as proof.

Non-goals / guardrails

Acceptance criteria (for the research task, not the feature)

  • A written design note in-repo comparing the three options, grounded in measured evidence — including at least one spike that actually builds a real component project under option 1 and captures the artifacts.
  • A recommendation with explicit cost/risk, plus a proposed breakdown of follow-up implementation issues.
  • Confirmation that the framework-dispatch metadata from fix(esp32): reject framework = espidf instead of silently building Arduino (#1664) #1730 is sufficient to prevent false coverage claims.

Related

#1664 (honor-or-reject parent), #1730 (the reject half, merged), #205 (precedent for Rust-native scanning), #952 (framework libs cache), #1750 (disk cost of a second toolchain).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    deferredInvestigation cannot be safely completed in the current burn-down passenhancementNew feature or request

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions