Skip to content

fbuild test-emu rebuilds project without picking up lib/FastLED — breaks ESP32 QEMU CI #303

@zackees

Description

@zackees

Symptom

Every FastLED ESP32 QEMU workflow on master fails identically:

All compilations completed successfully in 04m:08s
Running esptool merge_bin: ... merged.bin ...
build error: build failed: compilation failed for .build/pio/esp32dev/src/main.cpp:
In file included from src/main.cpp:5:
src/sketch/BlinkParallel.ino:8:10: fatal error: FastLED.h: No such file or directory
    8 | #include "FastLED.h"
      |          ^~~~~~~~~~~

Reproducible: every recent qemu_esp32dev_test.yml / qemu_esp32s3_test.yml / qemu_esp32c3_test.yml run on master.

Sequence

The workflow runs two steps:

# 1. Build via FastLED's ci-compile.py (defaults to fbuild backend)
uv run ci/ci-compile.py esp32dev --examples BlinkParallel --merged-bin \
    --defines FASTLED_ESP32_IS_QEMU --verbose
# → "All compilations completed successfully in 04m:08s"
# → merge_bin runs, produces merged.bin OK

# 2. Run the merged binary in QEMU
uv run fbuild test-emu --emulator qemu --environment esp32dev \
    .build/pio/esp32dev 2>&1 | tee qemu_output.log
# → fbuild test-emu triggers a project rebuild
# → "fatal error: FastLED.h: No such file or directory"

Step 1's compile succeeded — lib/FastLED/src/FastLED.h is on disk in the build dir, the link succeeded, the merged firmware was produced. Step 2's fbuild test-emu apparently re-validates / rebuilds the project from .build/pio/esp32dev/, and that rebuild can't find FastLED.h.

Root cause hypothesis

fbuild test-emu reads the project's platformio.ini to know which compile args to use, but doesn't replicate ci-compile.py's lib-discovery logic. Specifically:

  • PlatformIO auto-discovers any library under <project>/lib/ and adds its src/ to the include path. This is the implicit lib resolution rule (Library Dependency Finder).
  • fbuild's project-config reader appears to only honor explicit lib_deps entries. The FastLED layout uses lib/FastLED/src/... (no lib_deps entry in the generated platformio.ini — the lib is auto-discovered).
  • So fbuild's rebuild during test-emu produces a compile command without -Ilib/FastLED/src, and #include "FastLED.h" 404s.

That ci-compile.py's first invocation of fbuild succeeded suggests ci-compile.py is augmenting the fbuild call with the FastLED include path explicitly. test-emu doesn't go through ci-compile.py — it goes directly through fbuild's CLI.

Affected workflows

  • ESP32-DEV QEMU Test
  • ESP32-S3 QEMU Test
  • ESP32-C3 QEMU Test

(Any future ESP32 QEMU smoke that uses the same template.)

Proposed fix

In fbuild's project loader (likely crates/fbuild-config/src/ or crates/fbuild-build/src/ — wherever the PlatformIO project ini is read), implement PIO's auto-discovery of <project>/lib/<LibName>/src/:

for d in <project>/lib/*/:
    if (d/src exists) -> add d/src to include path AND compile d/src/**/*.{c,cpp,cpp.hpp}
    elif (d/include exists) -> add d/include + compile d/src or fall back
    else -> add d itself (flat layout)

This matches PlatformIO's LDF "chain" mode default. Without it, every fbuild build of a PIO project that uses lib/FastLED/ (which is FastLED's own CI convention) fails.

Alternative (workaround on FastLED side): have ci-compile.py write an explicit lib_deps = FastLED=symlink://... (or equivalent) into the generated platformio.ini so fbuild test-emu's reader sees it. Heavier than the fbuild-side fix and only papers over the deficiency.

Test plan

  • Unit: BoardConfig or project-loader test: load a synthetic PIO project with lib/Foo/src/foo.h only (no lib_deps), assert the include path contains lib/Foo/src.
  • Integration: re-run FastLED's QEMU workflows after fbuild bump.

Filed during a coordinated CI-green sweep on FastLED master. No immediate FastLED-side workaround attempted — the underlying fbuild gap will surface again for any future PIO consumer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions