fix(espidf): treat C++ stdlib headers as built-in in user_libs bundler

The user_libs_all bundler in _resolve_library_components does BFS over the
sketch's external includes, copying each matching Arduino library into
one merged IDF component.  Anything not in _BUILTIN_HEADERS is treated as
an external library to resolve, and the lookup just scans
/root/Arduino/libraries/ for a directory whose `src/` (or root) holds a
matching header file.

_BUILTIN_HEADERS only listed C headers (stdint.h, stdio.h, …).  The C++
wrappers (cstdint, cstdio, cmath, …) and the STL containers (vector,
complex, string, …) were absent.  Result: any library transitively
#including <cstdint> or <vector> caused the bundler to "resolve" the
header against /root/Arduino/libraries/ArduinoSTL/ — an AVR-only
uClibc++ port that ships every C++ stdlib header as plain files. Once
ArduinoSTL was matched the bundler dragged in ALL of it, including
complex.cpp:

    template class _UCXXEXPORT complex<float>;

which fails on the ESP-IDF Xtensa toolchain because _UCXXEXPORT isn't
defined in that compile context AND the symbol already exists in the
real libstdc++ pulled in by <complex>.  Net effect: every ESP32 sketch
whose deps transitively include a C++ stdlib header (e.g. ESP32Servo
includes <cstdint>) blew up with 66+ errors before the servo example
even reached the link step.

Fix: extend _BUILTIN_HEADERS to cover the full set of C++ stdlib
wrappers and STL headers so the bundler never treats them as installable
libraries.  The Xtensa GCC + libstdc++ shipped by ESP-IDF provides them
natively; ArduinoSTL never has any business being part of an ESP32 build.

Verified end-to-end on /example/esp32-servo: compile now succeeds, sketch
boots, moving the potentiometer drives the wokwi-servo angle (Pot=2801 →
Angle=123 deg, servo arm rotates).
This commit is contained in:
David Montero 2026-05-22 18:48:14 +02:00
parent cf4af79414
commit dccb70aacd
1 changed files with 22 additions and 1 deletions

View File

@ -581,9 +581,30 @@ class ESPIDFCompiler:
# dynamically: user-installed libs → IDF component; arduino-esp32 bundled
# libs → skip (already compiled in); not found → warning.
_BUILTIN_HEADERS = frozenset({
# C/C++ standard library
# C standard library
'math.h', 'stdint.h', 'stdio.h', 'stdlib.h', 'string.h', 'stdarg.h',
'stddef.h', 'stdbool.h', 'float.h', 'limits.h', 'assert.h',
'ctype.h', 'errno.h', 'inttypes.h', 'locale.h', 'setjmp.h',
'signal.h', 'time.h', 'wchar.h', 'wctype.h',
# C++ standard library wrappers and STL.
# MUST be marked built-in — otherwise the user_libs bundler resolves
# them against /root/Arduino/libraries/ArduinoSTL (an AVR-only
# uClibc++ port) and drags in complex.cpp / vector.cpp / …, none of
# which compile against ESP-IDF's libstdc++.
'cstdint', 'cstddef', 'cstdio', 'cstdlib', 'cstring', 'cmath',
'cassert', 'cctype', 'cerrno', 'cfloat', 'climits', 'clocale',
'csetjmp', 'csignal', 'cstdarg', 'ctime', 'cwchar', 'cwctype',
'cinttypes',
'algorithm', 'array', 'atomic', 'bitset', 'chrono', 'codecvt',
'complex', 'condition_variable', 'deque', 'exception', 'fstream',
'functional', 'future', 'initializer_list', 'iomanip', 'ios',
'iosfwd', 'iostream', 'istream', 'iterator', 'limits', 'list',
'locale', 'map', 'memory', 'mutex', 'new', 'numeric', 'optional',
'ostream', 'queue', 'random', 'ratio', 'regex', 'set', 'sstream',
'stack', 'stdexcept', 'streambuf', 'string', 'string_view',
'system_error', 'thread', 'tuple', 'type_traits', 'typeindex',
'typeinfo', 'unordered_map', 'unordered_set', 'utility', 'valarray',
'variant', 'vector', 'any',
# Arduino core types — part of arduino-esp32 source, not installable libraries
'Arduino.h', 'HardwareSerial.h', 'Stream.h', 'Print.h', 'WString.h',
'pgmspace.h', 'IPAddress.h',