Skip to content

fbuild should resolve project-local boards/*.json like PlatformIO does #515

Description

@zackees

Problem

fbuild's board database is baked in at compile time and there is no runtime fallback to project-local boards/<id>.json, so a well-formed platformio.ini that builds cleanly under PlatformIO fails under fbuild with:

build error: config error: unknown board 'lpc845brk' (no built-in defaults)

Reproducible failure from a real CI run:
https://github.com/zackees/ArduinoCore-LPC8xx/actions/runs/27172681316/job/80214987717

Where the gap is in the code

crates/fbuild-config/src/board/db.rs:

static BOARDS_DIR: include_dir::Dir =
    include_dir::include_dir!(\"$CARGO_MANIFEST_DIR/assets/boards/json\");

The board DB is a compile-time include_dir! snapshot of crates/fbuild-config/assets/boards/json/. There is no code path that reads <project>/boards/*.json, ~/.platformio/boards/*.json, or the resolved platform package's boards/ directory. crates/fbuild-config/src/board/loaders.rs calls get_board_defaults(board_id); when that returns None, the build aborts with the message above.

How PlatformIO solves the same problem

PlatformIO's board resolution is dynamic and cascades:

  1. <project>/boards/<id>.json (project-local override — this is what makes the failing case work in pio)
  2. ~/.platformio/boards/<id>.json (user override)
  3. <installed_platform>/boards/<id>.json (platform-provided)

A board JSON sitting next to platformio.ini is automatically picked up; no special config required.

Proposed feature

Add a runtime loader to fbuild-config that scans <project>/boards/*.json (the dir containing the resolved platformio.ini) and merges those entries into the lookup BEFORE falling through to the "unknown board" error. Optionally also resolve ~/.platformio/boards/ and the installed-platform boards/ for full PIO parity, but project-local alone closes the most common case.

Sketch:

// pseudo
pub(super) fn get_board_defaults(board_id: &str) -> Option<HashMap<String, String>> {
    if let Some(v) = get_board_db().get(board_id) {
        return Some(flatten(v));
    }
    if let Some(v) = load_project_local_board(board_id) {  // NEW
        return Some(flatten(v));
    }
    None
}

load_project_local_board would look in <project_dir>/boards/<board_id>.json using whatever already locates the active platformio.ini (e.g., the same path the build is being invoked against — fbuild build <dir> -e <env>).

Why this matters

  • Generalizes. Every new board for any platform works the moment its JSON exists in the project. No per-board upstream PR + fbuild release cycle.
  • PIO parity. The fbuild marketing line is "directly compatible with platformio.ini". Project-local board JSONs are a documented part of PIO's platformio.ini story; not honoring them is a divergence users will hit again and again.
  • Unblocks LPC8xx today without waiting on a full Stage 2 LPC8xx orchestrator (Native support for NXP LPC8xx (LPC845-BRK, LPCXpresso804, LPCXpresso845-MAX) #513). LPC8xx is just the first reproducer — anyone using a custom or pre-release board will hit the same wall.

Context: the failing platformio.ini

For reference, the (working under pio, failing under fbuild) config is:

[platformio]
src_dir = examples/Blink

[env]
platform = https://github.com/zackees/platform-nxplpc-arduino.git
framework = arduino

[env:lpc845brk]
board = lpc845brk
board_build.ldscript = \${platformio.packages_dir}/framework-arduino-lpc8xx/linker_scripts/gcc/lpc845_flash.ld

with boards/lpc845brk.json sitting at the project root. PlatformIO finds it; fbuild doesn't.

Related

cc @zackees

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions