Skip to content

Build SAMD51J fails: get_core_dir(adafruit) points at nonexistent cores subdir #319

Description

@zackees

Symptom

Build SAMD51J workflow fails on every main build with:

build error: build failed: compilation failed for
  .fbuild/prod/cache/platforms/adafruit-ArduinoCore-samd/.../1.7.16/ArduinoCore-samd-1.7.16/variants/feather_m4/variant.cpp:
In file included from variants/feather_m4/variant.cpp:19:
variants/feather_m4/variant.h:43:10: fatal error: WVariant.h: No such file or directory
   43 | #include "WVariant.h"

Reproducible: gh run view 26694160364 --log-failed and every recent SAMD51J workflow run on main.

Root cause

The board JSON for adafruit_feather_m4 (and the rest of the Adafruit SAMD family) declares build.core = "adafruit". This matches PlatformIO's upstream board JSON for the same board — so the board-validator agrees.

fbuild's ArduinoCore::get_core_dir(core_name) literally joins cores/<core_name>:

pub fn get_core_dir(&self, core_name: &str) -> PathBuf {
    self.get_cores_dir().join(core_name)
}

So it asks for <framework>/cores/adafruit/. But the adafruit-ArduinoCore-samd repo at v1.7.16 only has cores/arduino/ (verified via GitHub API: GET /repos/adafruit/ArduinoCore-samd/contents/cores?ref=1.7.16 returns one entry, name="arduino"). There is no cores/adafruit/.

PlatformIO works around this in its atmelsam builder by interpreting build.core differently — it doesn't blindly use it as the cores/ subdir name. fbuild just joins.

Result: variant.h is found (it's in variants/feather_m4/), but its #include "WVariant.h" (which lives in cores/arduino/WVariant.h) is unreachable because the include-path entry points at the nonexistent cores/adafruit/ instead.

Proposed fix

In ArduinoCore::get_core_dir(core_name) (or equivalent in the SAM orchestrator's include-path assembly), fall back to cores/arduino/ when cores/<core_name>/ doesn't exist on disk:

pub fn get_core_dir(&self, core_name: &str) -> PathBuf {
    let primary = self.get_cores_dir().join(core_name);
    if primary.is_dir() {
        return primary;
    }
    // Many Arduino-compatible cores declare build.core = "<vendor>" in
    // their board JSON for branding purposes but ship the actual source
    // in cores/arduino/. Mirror PlatformIO's atmelsam builder fallback
    // when the named directory doesn't exist.
    let fallback = self.get_cores_dir().join("arduino");
    if fallback.is_dir() {
        return fallback;
    }
    primary
}

Or, more surgically, do the fallback only in sam/orchestrator.rs since SAM is the only confirmed affected platform.

Affected boards

Likely all Adafruit SAMD boards (feather_m4, itsybitsy_m4, metro_m4, trinket_m0, ...) and any other vendor that uses this branding pattern in build.core.

Test plan

  • Unit test for get_core_dir fallback: given a synthetic framework dir with cores/arduino/ but no cores/adafruit/, get_core_dir("adafruit") should return .../cores/arduino/.
  • Integration: Build SAMD51J workflow turns green on next main push.
  • Spot-check: Build SAMD21, Build SAMD21 Zero, Build SAMD51P workflows (haven't run recently — likely also red).

Filed during a CI-green sweep on fbuild main.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions