libraries: guard TinyUSB include under PlatformIO so SAMD builds compile - #396
Open
tyeth-ai-assisted wants to merge 1 commit into
Open
Conversation
Member
|
Hey @hathach could you have a review of this please? This rectifies the include error that occurs otherwise. |
Member
|
Oops, failing CI on untested path, will fix |
tyeth-ai-assisted
force-pushed
the
platformio-tinyusb-include-guards
branch
from
August 28, 2026 12:56
8904a30 to
a9a2c20
Compare
tyeth-ai-assisted
force-pushed
the
platformio-tinyusb-include-guards
branch
from
August 28, 2026 13:06
a9a2c20 to
26c39c0
Compare
tyeth-ai-assisted
force-pushed
the
platformio-tinyusb-include-guards
branch
2 times, most recently
from
August 28, 2026 13:16
00da71d to
06da1e0
Compare
Under PlatformIO, framework-bundled libraries do not receive lib_deps include paths, so the unguarded #include <Adafruit_TinyUSB.h> hard-fails every SAMD build with USE_TINYUSB. Adafruit_TinyUSB.h lives in the library's src/, and only src/arduino is ever added to the include path (platform.txt does this for arduino-cli; PlatformIO's atmelsam builder does the same), so the header is unreachable from these five sources. Skip the include under PlatformIO when it is unreachable, keeping it plain and unconditional everywhere else. The nesting is deliberate: the include is what the Arduino builder discovers the TinyUSB library from, and its dependency-detection pass cannot parse a __has_include() expression -- it then finds no dependency, TinyUSB is never linked, and the usbstack=tinyusb examples fail with undefined references to Serial and Adafruit_USBD_CDC::begin. Putting __has_include() inside #ifdef PLATFORMIO leaves it in a branch arduino-cli skips without evaluating, so arduino-cli behaviour is unchanged. Verified both ways in CI. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TJa4WYfEHBFUhnJVRLja7A
tyeth-ai-assisted
force-pushed
the
platformio-tinyusb-include-guards
branch
from
August 28, 2026 13:25
06da1e0 to
c63ec86
Compare
tyeth
approved these changes
Aug 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Every PlatformIO SAMD build with
USE_TINYUSBfails to compile:arduino-cliis unaffected, which is why this has gone unnoticed.Why
Adafruit_TinyUSB.hlives in the library'ssrc/, and onlysrc/arduinois ever put on the include path — by both toolchains:platform.txt(line 80) forarduino-cli:"-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"atmelsamplatform appends that same.../Adafruit_TinyUSB_Arduino/src/arduinoto the globalCPPPATHfor the Adafruit vendor core (builder/frameworks/arduino/arduino-samd.py).So
Adafruit_USBD_CDC.hresolves everywhere, while<Adafruit_TinyUSB.h>resolves from neither.Under
arduino-cliit works anyway, because that unresolved include is itself what drives the Arduino builder's library discovery: it findsAdafruit_TinyUSB_Arduino, adds itssrc/to the include path, and links the library — the side effect the existing comment refers to. PlatformIO has no equivalent step for framework-bundled libraries (they never receivelib_depsinclude paths), so there the include is simply a hard error.Fix
Skip the include under PlatformIO when the header is unreachable, and leave it plain and unconditional everywhere else:
The nesting is load-bearing, and this repo's CI is what proved it. A flat guard —
#if !defined(__has_include) || __has_include(<Adafruit_TinyUSB.h>)around the include, with or without a!defined(PLATFORMIO)clause — turns bothusbstack=tinyusblegs red withundefined reference to 'Serial'andAdafruit_USBD_CDC::begin(unsigned long)in theWireandSAMD_AnalogCorrectionexamples. The failures are link-time only, never compile errors: the Arduino builder's dependency-detection pass cannot parse a__has_include()expression, so it finds no dependency and TinyUSB is never linked, while the real compile (GCC 9, which does support__has_include) goes through fine. Short-circuiting does not help, because the expression still has to be parsed. Nesting it inside#ifdef PLATFORMIOputs it in a brancharduino-cliskips without evaluating, leaving that toolchain untouched.Servo.cppis the only file that actually fails in the configuration I tested; the other four carry the identical unguarded include and the identical hazard, so they get the same treatment rather than surfacing one at a time.Testing
PlatformIO — Adafruit WipperSnapper (TinyUSB + SPI + Wire + ~60 sensor libraries), env
adafruit_pyportal_m4, PlatformIO 6,USE_TINYUSB=1. Each tree was built from the installedplatformio/framework-arduino-samd-adafruit@1.10716.0package (= this repo at 1.7.16) consumed viaplatform_packages = framework-arduino-samd-adafruit@symlink://<tree>, so these five files are the only variable. They are byte-identical betweenmasterand 1.7.16, so the result applies directly to this branch.Servo.cpp:26: fatal error: Adafruit_TinyUSB.h: No such file or directoryarduino-cli — this repo's own matrix, run three times on this PR:
__has_includeguardSerial)The PlatformIO firmware is byte-for-byte the same size across every guard variant, confirming the guard only ever removes an include PlatformIO could not resolve in the first place.
Note
This supersedes a Copilot-authored attempt (
tyeth/adafruit_ArduinoCore-samd#1) that rerouted theAdafruit_USBD_CDC.hinclude to"arduino/Adafruit_USBD_CDC.h"underPLATFORMIO. That rested on the inverted premise that PlatformIO exposessrcbut notsrc/arduino; it breaks every translation unit that includesArduino.h, and it was never compiled. Closed.