Skip to content

Teensy 4.x: SPI framework library compiled but not linked — undefined references to SPIClass::* at link time #284

Description

@zackees

Summary

On Teensy 4.x (teensy41, very likely teensy40 too), every FastLED example now fails at the link step with undefined references to SPIClass::* and the SPI global, even examples that don't use SPI directly. Compilation succeeds, so this is distinct from the earlier framework-header failure (#163, fixed) and the Arm GNU 15.2 toolchain failure (#176, fixed) — both compile-stage problems. This is a link-stage problem: the SPI library's object files are not being passed to the linker.

This is the active blocker referenced in FastLED/FastLED#2365.

Repro

FastLED master with fbuild==2.2.7:

./compile --no-interactive teensy41 all

Every example fails identically — including pure-clockless examples like examples/AnalogOutput, examples/Animartrix, examples/Apa102, examples/Async, examples/Audio, examples/AnimartrixRing, etc. The breakage is universal because FastLED's Teensy 4.x platform headers reference SPI transitively.

Failure excerpt

Board: Teensy 4.1 / IMXRT1062 @ 600MHz
Toolchain: arm-none-eabi-gcc 11.3.1
Compiled 138/138 files
Compiled 1/1 files
Compiled 25/25 files
Linking firmware.elf
<artificial>:(.text+0x3e46): undefined reference to `SPIClass::transfer(void const*, void*, unsigned int)'
<artificial>:(.text+0x406a): undefined reference to `SPIClass::transfer(void const*, void*, unsigned int)'
<artificial>:(.text+0x5e26): undefined reference to `SPIClass::begin()'
ld: <artificial>:(.text+0x5ec0): undefined reference to `SPI'
<artificial>:(.text+0x3e08): undefined reference to `SPIClass::end()'
<artificial>:(.text+0x1104): undefined reference to `SPIClass::setSCK(unsigned char)'
<artificial>:(.text+0x1114): undefined reference to `SPIClass::setMOSI(unsigned char)'
collect2: error: ld returned 1 exit status
build error: build failed: arm-none-eabi-gcc link failed

Toolchain used now (good — matches PlatformIO):

/home/runner/work/_temp/fbuild-cache/toolchains/toolchain-gccarmnoneeabi-teensy/f10975e5515d77b9/1.110301.0/bin/../lib/gcc/arm-none-eabi/11.3.1/...

Recent failing CI run

FastLED/FastLED#2537, job 78578752067, run 26659643188 (2026-05-29). Master itself has not had a single passing teensy41 run since at least 2026-05-12 — over two weeks of red CI; verified by walking 100 master runs of .github/workflows/build_teensy41.yml.

Diagnosis

The included headers resolve (#include <SPI.h> no longer fails), and the FastLED translation units compile fine. The linker invocation is finding the libgcc/newlib search path but is missing the compiled SPI library archive. This points at fbuild's Teensy orchestrator: it appears to be adding the framework library's include path (fix from #163) but not adding the framework library's compiled objects/archive to the link line.

Suggested files to look at (same orchestrator referenced in #163):

  • crates/fbuild-build/src/teensy/orchestrator.rs
  • crates/fbuild-packages/src/library/teensy_core.rs

Specifically, the place where framework libraries are added to link inputs (as opposed to compile inputs / include paths) — that's the path missing for the SPI library on Teensy 4.x.

Expected behavior

For teensy41 / teensy40 builds, framework libraries that the project's translation units reference must contribute their compiled object files to the link, not just their headers to the include path. At minimum: SPI. The previously-required OctoWS2811 (from #163) is presumably already being linked since I do not see undefined references for it, but the same fix should ensure it stays that way.

Workaround for FastLED CI

Per FastLED/FastLED#2365, the documented short-term workaround is to remove teensy40/teensy41 from ci/compiler/fbuild_boards.py so they fall back to PlatformIO. That is a workaround, not a fix.

🤖 Filed by Claude Code after investigating FastLED/FastLED#2537 CI failure.

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