Skip to content

nxplpc: framework-arduino-lpc8xx pin is hardcoded — platform_packages override in platformio.ini is silently ignored (blocks FastLED#3325 bisection) #663

Description

@zackees

TL;DR

ArduinoCoreLpc8xx (and by symmetry any other framework package whose source we may need to override per-build) pins its URL + commit SHA + sha256 as const &str in the Rust source. There is no platform_packages lookup. The orchestrator already has env_config in scope but throws away any consumer-provided framework override.

This breaks LPC8xx bisection on the fbuild backend — currently blocking FastLED/FastLED#3325 (LPC845-BRK JSON-RPC echo regression bisection, root issue FastLED/FastLED#3300). PlatformIO honors platform_packages = framework-arduino-lpc8xx@<URL>#<sha> and re-clones per pin; fbuild silently ignores the same line.

Repro / evidence

crates/fbuild-packages/src/library/arduino_core_lpc8xx.rs (HEAD e165ea4f, v2.2.31):

const ACLPC_COMMIT: &str   = "195a2eddd31eba8472ceaffa6a1a1902f72439ae";
const ACLPC_VERSION: &str  = "0.1.0+g195a2ed";
const ACLPC_URL: &str      = "https://github.com/zackees/ArduinoCore-LPC8xx/archive/195a2eddd31eba8472ceaffa6a1a1902f72439ae.tar.gz";
const ACLPC_CHECKSUM: &str = "366de74b93179ba4b5e8ac9e527f15f189d9e26bcedd030fe11c11a2c907f3e4";

impl ArduinoCoreLpc8xx {
    pub fn new(project_dir: &Path) -> Self { /* uses the 4 consts unconditionally */ }
}

Both call sites pass only project_dir, never an override:

crates/fbuild-build/src/nxplpc/orchestrator.rs:121:
    let core = fbuild_packages::library::ArduinoCoreLpc8xx::new(&params.project_dir);
crates/fbuild-build/src/nxplpc/mod.rs:39:
    let core = fbuild_packages::library::ArduinoCoreLpc8xx::new(project_dir);

Meanwhile the orchestrator already parses platformio.ini and has env_config in scope (orchestrator.rs:78–89). The platform_packages key is just not read.

By contrast PlatformIO's nxplpc-arduino platform.json:

"framework-arduino-lpc8xx": {
    "type": "framework",
    "optional": true,
    "version": "https://github.com/zackees/ArduinoCore-LPC8xx.git"
}

— bare URL, no SHA. Whatever's on the consumer's platformio.ini platform_packages line wins.

Impact: this blocks downstream bisection workflows

FastLED/FastLED#3325 needs to bisect 7+ ArduinoCore-LPC8xx commits (4560e6c41d..da8f2b8b42) to find a JSON-RPC bring-up regression. On the PIO backend the bisect step is one platformio.ini edit + one bash compile lpc845brk --platformio (~60s). On the fbuild backend the equivalent step requires:

  1. Edit arduino_core_lpc8xx.rs to swap ACLPC_COMMIT / ACLPC_VERSION / ACLPC_URL.
  2. Download the new tarball, compute sha256, update ACLPC_CHECKSUM.
  3. Rebuild fbuild from source (cargo build --release, ~minutes).
  4. Re-run bash compile lpc845brk (~60s).
  5. Test the device.

That makes the fbuild backend effectively unbisectable. And because fbuild's currently-pinned commit 195a2eddd3 is one of the top regression suspects in #3325 (ArduinoCore-LPC8xx #29, the pre-CRP linker pack), the asymmetry is actively biting right now.

The cache structure already supports per-pin caches (.fbuild/prod/cache/platforms/zackees-ArduinoCore-LPC8xx/<url-hash>/<version>+g<short-sha>/). Only the input wiring is missing.

Proposed fix

1. Plumb a URL+SHA override through ArduinoCoreLpc8xx

Add an opt-in constructor that takes the override:

impl ArduinoCoreLpc8xx {
    pub fn new(project_dir: &Path) -> Self { /* keep default consts */ }

    /// Consumer-overridden core source. URL must be a downloadable
    /// `archive/<sha>.tar.gz` (or `.zip`) — i.e. resolvable to a single
    /// commit. Checksum is None because the consumer is responsible for
    /// trusting the pin.
    pub fn with_override(project_dir: &Path, url: &str, version: &str) -> Self { /* … */ }
}

version is needed because the cache subdir is <version>+g<short-sha>/ and otherwise the override would collide with the default-pinned cache.

2. Read platform_packages in the nxplpc orchestrator

In orchestrator.rs after env_config is resolved, look up the framework override:

let core_override = env_config
    .get("platform_packages")
    .and_then(parse_platform_packages_entry("framework-arduino-lpc8xx"));

let core = match core_override {
    Some((url, sha)) => ArduinoCoreLpc8xx::with_override(
        &params.project_dir, &url, &format!("0.1.0+g{}", &sha[..7])),
    None => ArduinoCoreLpc8xx::new(&params.project_dir),
};

A small parse_platform_packages_entry helper that handles the PIO syntax — name@<URL>#<sha> and name@<owner/repo>#<sha> — would also let the same plumbing serve any future ARM/Arduino framework package we vendor (e.g. nrf52, samd, sam if/when they land).

3. Checksum behavior with override

Two reasonable choices, prefer (a):

(a) Skip the sha256 check when an override is set and log a warning. The consumer is explicitly overriding for development / bisection; demanding they recompute sha256 per step defeats the point.

(b) Auto-compute sha256 on first fetch and cache it locally (per cache-subdir manifest). Slightly more work but stays content-addressed.

4. Surface the override in fbuild's build log

One INFO line at the start of compile so it's obvious from terminal scrollback when a non-default core is in use:

ArduinoCore-LPC8xx OVERRIDE: https://github.com/zackees/ArduinoCore-LPC8xx/archive/<sha>.tar.gz (default pinned: 195a2eddd3)

Out of scope (but worth noting)

  • Same gap likely exists for any other framework-* package whose source is const-pinned in fbuild-packages. A grep for const .*_URL: &str across crates/fbuild-packages/src/library/ will enumerate them; consider whether to generalize the override plumbing into PackageBase so adding override-support to a new package is one constructor variant rather than a new code path.
  • This issue is not requesting that fbuild start consuming PlatformIO's framework defaults. The platform.json indirection is a separate (larger) discussion. This is just: when the consumer's platformio.ini explicitly says "use this commit," respect it.

Acceptance criteria

  • platform_packages = framework-arduino-lpc8xx@<URL>#<sha> in [env:lpc845brk] causes fbuild to fetch and use the consumer-specified commit.
  • Default behavior (no override) is unchanged — same pin, same checksum, same cache subdir.
  • Cache subdir for an override is distinct from default (no collision).
  • An INFO log line in bash compile lpc845brk makes the override visible at runtime.
  • Per-step bisection (edit platformio.ini, re-compile, test) completes in seconds, not minutes.

Refs

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