Symptom
FastLED's size-check pipeline (ci/ci-check-compiled-size.py ↓ ci/compiled_size.py) needs a per-build build_info.json (or build_info_<example>.json) at .build/pio/<board>/. The file is the canonical project-metadata blob produced by:
pio project metadata --json-output
When the build is driven by fbuild (which became the default backend in FastLED's ci-compile.py after commit f215b56b8 ci: make fbuild the default for board builds), no build_info.json is emitted, and every consumer that calls _find_build_info(board) fails with:
FileNotFoundError: build_info.json not found for board '<board>'
(tried build_info_<example>.json and build_info.json in .build/pio/<board> and .build/<board>)
Master CI impact
Every binary-size guard on FastLED master is failing because of this:
check_uno_size, check_attiny85, attiny85_binary_size
check_teensy30_size, check_teensy31_size, check_teensy32_size, check_teensy35_size, check_teensy36_size, check_teensy41_size, check_teensylc_size
check_stm32f103c8_bluepill_size
esp32dev_binary_size
teensy41_binary_size
(~10 README-visible workflows.) These are pure cascade — the build itself succeeded; only the post-build metadata is missing.
What PlatformIO provides
pio project metadata --json-output returns a single JSON blob keyed by env name with at least:
prog_path — absolute path to the linked ELF (or HEX on AVR)
cc_path, cxx_path, ar_path, objcopy_path, ... — full toolchain binaries
cc_flags, cxx_flags, link_flags, libs, defines, includes
extra_flags, srcs, frameworks, platform, board
FastLED's ci/compiler/build_config.py::insert_tool_aliases then injects friendlier aliases on top.
Downstream FastLED scripts that consume this blob:
ci/compiled_size.py — prog_path + build dir
ci/inspect_binary.py, ci/inspect_elf.py, ci/symbol_analysis_runner.py, ci/optimization_report.py — toolchain paths + ELF path
ci/decode_esp32_backtrace.py — objdump_path, addr2line_path
All of these silently no-op or hard-fail under fbuild today.
Proposed shape for fbuild
Add a post-link emitter that writes <project>/.build/pio/<board>/build_info_<example>.json (mirror PIO's exact layout) populated from values fbuild already knows internally:
prog_path → fbuild's link target output path
cc_path / cxx_path / ar_path / objcopy_path / objdump_path / addr2line_path / size_path — resolved at toolchain probe time
cc_flags / cxx_flags / link_flags / libs / defines / includes — already in the build graph
frameworks / platform / board / extra_flags — from BoardConfig
srcs — list of compiled units
Wrap that in a key matching the env name (PIO's convention) so the FastLED scripts work without any consumer-side changes.
Suggested entry point: a new EmitBuildInfoJson post-link step in crates/fbuild-build/ (or wherever the artifact-staging code lives), gated on a per-invocation flag like --emit-build-info so non-CI users don't pay the cost.
Workaround being applied immediately to FastLED
While this lands in fbuild, I'm patching FastLED's .github/workflows/build_template_binary_size.yml to force --backend=platformio for the size-check step. That restores PIO's build_info.json emission and reopens all 10 workflows. The workaround can be reverted in one line once fbuild ships the emitter.
Test plan
- Unit:
cargo test -p fbuild-<crate> covering the new emitter (write a JSON blob to a tempdir, assert keys present + parseable, assert it deserializes via the same struct PIO's output does).
- Integration: pop fastled's PIO workaround, rebuild, confirm
.build/pio/<board>/build_info_<example>.json lands and ci/compiled_size.py succeeds.
Filed during a coordinated CI-green sweep on FastLED master. Companion unblocking PR coming to FastLED in parallel.
Symptom
FastLED's size-check pipeline (
ci/ci-check-compiled-size.py↓ci/compiled_size.py) needs a per-buildbuild_info.json(orbuild_info_<example>.json) at.build/pio/<board>/. The file is the canonical project-metadata blob produced by:When the build is driven by fbuild (which became the default backend in FastLED's
ci-compile.pyafter commitf215b56b8 ci: make fbuild the default for board builds), nobuild_info.jsonis emitted, and every consumer that calls_find_build_info(board)fails with:Master CI impact
Every binary-size guard on FastLED master is failing because of this:
check_uno_size,check_attiny85,attiny85_binary_sizecheck_teensy30_size,check_teensy31_size,check_teensy32_size,check_teensy35_size,check_teensy36_size,check_teensy41_size,check_teensylc_sizecheck_stm32f103c8_bluepill_sizeesp32dev_binary_sizeteensy41_binary_size(~10 README-visible workflows.) These are pure cascade — the build itself succeeded; only the post-build metadata is missing.
What PlatformIO provides
pio project metadata --json-outputreturns a single JSON blob keyed by env name with at least:prog_path— absolute path to the linked ELF (or HEX on AVR)cc_path,cxx_path,ar_path,objcopy_path, ... — full toolchain binariescc_flags,cxx_flags,link_flags,libs,defines,includesextra_flags,srcs,frameworks,platform,boardFastLED's
ci/compiler/build_config.py::insert_tool_aliasesthen injects friendlier aliases on top.Downstream FastLED scripts that consume this blob:
ci/compiled_size.py—prog_path+ build dirci/inspect_binary.py,ci/inspect_elf.py,ci/symbol_analysis_runner.py,ci/optimization_report.py— toolchain paths + ELF pathci/decode_esp32_backtrace.py—objdump_path,addr2line_pathAll of these silently no-op or hard-fail under fbuild today.
Proposed shape for fbuild
Add a post-link emitter that writes
<project>/.build/pio/<board>/build_info_<example>.json(mirror PIO's exact layout) populated from values fbuild already knows internally:prog_path→ fbuild's link target output pathcc_path/cxx_path/ar_path/objcopy_path/objdump_path/addr2line_path/size_path— resolved at toolchain probe timecc_flags/cxx_flags/link_flags/libs/defines/includes— already in the build graphframeworks/platform/board/extra_flags— fromBoardConfigsrcs— list of compiled unitsWrap that in a key matching the env name (PIO's convention) so the FastLED scripts work without any consumer-side changes.
Suggested entry point: a new
EmitBuildInfoJsonpost-link step incrates/fbuild-build/(or wherever the artifact-staging code lives), gated on a per-invocation flag like--emit-build-infoso non-CI users don't pay the cost.Workaround being applied immediately to FastLED
While this lands in fbuild, I'm patching FastLED's
.github/workflows/build_template_binary_size.ymlto force--backend=platformiofor the size-check step. That restores PIO's build_info.json emission and reopens all 10 workflows. The workaround can be reverted in one line once fbuild ships the emitter.Test plan
cargo test -p fbuild-<crate>covering the new emitter (write a JSON blob to a tempdir, assert keys present + parseable, assert it deserializes via the same struct PIO's output does)..build/pio/<board>/build_info_<example>.jsonlands andci/compiled_size.pysucceeds.Filed during a coordinated CI-green sweep on FastLED master. Companion unblocking PR coming to FastLED in parallel.