You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to PR #241 (merged): the new fbuild compile-many primitive does the same job as PlatformIO's pio ci — compile one or more sketches against a board for CI. Today the two commands have the same intent but different surfaces, so any existing pio ci invocation in a library's CI scripts has to be rewritten to switch backends. We can make that switch a no-op.
What pio ci looks like
pio ci --board uno --lib . examples/Blink/Blink.ino [examples/Fire2012/Fire2012.ino ...]
Key shape:
--board <board> (-b) — required, repeatable across pio ci for multi-board, single-board per invocation otherwise.
Positional args — sketch source files or directories. Globs work in the shell, pio ci itself accepts paths.
--lib <path> (-l) — extra library roots to include in the build. Repeatable.
--project-conf <path> (-c) — point at a platformio.ini for build flags.
Add fbuild ci as the canonical CI command and treat compile-many as its in-tree backend. The two-stage execution model already shipped in #241; this issue is purely about the CLI surface.
Minimum surface to claim PlatformIO compatibility:
pio ci flag
fbuild ci equivalent
Notes
--board <b> / -b <b>
--board <b> / -b <b>
Already supported in compile-many.
positional sketch paths
positional sketch paths
Already supported.
--lib <path> / -l <path>
--lib <path> (repeatable)
Maps to extra include / library roots routed through the orchestrator. Today compile-many has no equivalent flag — needs wiring.
--project-conf <path> / -c <path>
--project-conf <path> / -c <path>
Points at platformio.ini. fbuild already parses platformio.ini in non-CI paths; route the same parser.
--keep-build-dir, --build-dir <path>
same
Optional. Useful for inspecting firmware.elf / firmware.hex after a CI run.
Two parallelism flags from #241 (--framework-jobs, --sketch-jobs) stay as fbuild-only extensions — they have no PIO equivalent and are fine to be additive.
Behavior decisions to pin down in the issue:
Should fbuild ci and fbuild compile-many both exist? Recommendation: yes. ci is the canonical name (matches PIO + matches what most consumers will type); compile-many becomes a hidden alias or is documented as the fbuild-native name. Either way the underlying code path is one.
Default behavior on flag absence.pio ci errors out if --board is missing; matching that errors-early behavior is safer than picking a default.
--lib resolution semantics. PIO interprets --lib . as "include the current dir as a library root". The shape that matches today is to feed the path into the orchestrator's extra_include_dirs and let the existing LDF pick it up; document if there's a difference.
Why this matters
Every library currently running pio ci in GitHub Actions today is a near-zero-cost candidate for fbuild adoption — if the command swap is a one-line s/pio ci/fbuild ci/ in the workflow. If the surface diverges (different flag names, different positional semantics), each library has to rewrite its CI, which is friction we don't need given the primitive is already identical.
This is the same normalization story as fbuild deploy matching pio run --target upload semantically: drop-in switching is the path to broad adoption.
Acceptance
fbuild ci --board <b> [--lib <path>...] [--project-conf <path>] <sketch...> works end-to-end, producing the same artifacts as fbuild compile-many for the same inputs.
pio ci --board <b> examples/*/*.ino and fbuild ci --board <b> examples/*/*.ino produce equivalent firmware.elf/.hex outputs for at least one canonical FastLED-style library on uno (smoke test in crates/fbuild-cli/tests/).
A 1-paragraph doc section in docs/ (or crates/fbuild-cli/README.md) maps pio ci flags to fbuild ci flags so library maintainers know what to expect.
Exit codes match PIO convention: 0 on all-pass, non-zero on any-sketch-fail.
pio ci's --exclude filter and other low-traffic flags. Add them if a real consumer needs them; otherwise the four flags above cover the canonical shape.
Adopting pio ci's build directory layout. fbuild's .fbuild/build/... tree is fine; the build-dir flag governs where, not how.
Follow-up to PR #241 (merged): the new
fbuild compile-manyprimitive does the same job as PlatformIO'spio ci— compile one or more sketches against a board for CI. Today the two commands have the same intent but different surfaces, so any existingpio ciinvocation in a library's CI scripts has to be rewritten to switch backends. We can make that switch a no-op.What
pio cilooks likeKey shape:
--board <board>(-b) — required, repeatable acrosspio cifor multi-board, single-board per invocation otherwise.pio ciitself accepts paths.--lib <path>(-l) — extra library roots to include in the build. Repeatable.--project-conf <path>(-c) — point at aplatformio.inifor build flags.--keep-build-dir/--build-dir <path>— preserve / locate the build outputs.Proposal
Add
fbuild cias the canonical CI command and treatcompile-manyas its in-tree backend. The two-stage execution model already shipped in #241; this issue is purely about the CLI surface.Minimum surface to claim PlatformIO compatibility:
pio ciflagfbuild ciequivalent--board <b>/-b <b>--board <b>/-b <b>compile-many.--lib <path>/-l <path>--lib <path>(repeatable)compile-manyhas no equivalent flag — needs wiring.--project-conf <path>/-c <path>--project-conf <path>/-c <path>platformio.ini. fbuild already parses platformio.ini in non-CI paths; route the same parser.--keep-build-dir,--build-dir <path>firmware.elf/firmware.hexafter a CI run.Two parallelism flags from #241 (
--framework-jobs,--sketch-jobs) stay as fbuild-only extensions — they have no PIO equivalent and are fine to be additive.Behavior decisions to pin down in the issue:
fbuild ciandfbuild compile-manyboth exist? Recommendation: yes.ciis the canonical name (matches PIO + matches what most consumers will type);compile-manybecomes a hidden alias or is documented as the fbuild-native name. Either way the underlying code path is one.pio cierrors out if--boardis missing; matching that errors-early behavior is safer than picking a default.--libresolution semantics. PIO interprets--lib .as "include the current dir as a library root". The shape that matches today is to feed the path into the orchestrator'sextra_include_dirsand let the existing LDF pick it up; document if there's a difference.Why this matters
Every library currently running
pio ciin GitHub Actions today is a near-zero-cost candidate for fbuild adoption — if the command swap is a one-lines/pio ci/fbuild ci/in the workflow. If the surface diverges (different flag names, different positional semantics), each library has to rewrite its CI, which is friction we don't need given the primitive is already identical.This is the same normalization story as
fbuild deploymatchingpio run --target uploadsemantically: drop-in switching is the path to broad adoption.Acceptance
fbuild ci --board <b> [--lib <path>...] [--project-conf <path>] <sketch...>works end-to-end, producing the same artifacts asfbuild compile-manyfor the same inputs.pio ci --board <b> examples/*/*.inoandfbuild ci --board <b> examples/*/*.inoproduce equivalentfirmware.elf/.hexoutputs for at least one canonical FastLED-style library onuno(smoke test incrates/fbuild-cli/tests/).docs/(orcrates/fbuild-cli/README.md) mapspio ciflags tofbuild ciflags so library maintainers know what to expect.Out of scope
pio ci's--excludefilter and other low-traffic flags. Add them if a real consumer needs them; otherwise the four flags above cover the canonical shape.pio ci's build directory layout. fbuild's.fbuild/build/...tree is fine; the build-dir flag governs where, not how.Related
compile-manyprimitive (merged).fbuild cirather thanfbuild compile-manyonce the canonical name is settled.