fix(espidf): scan all project files for external #includes, not just the .ino

When a sketch's external library headers were only referenced from
project headers (e.g. esp32-eyes.ino includes Common.h, Common.h
includes <ESP32Servo.h>), the compile failed with
  fatal error: ESP32Servo.h: No such file or directory
because _detect_external_includes was only called on main_content
(the processed .ino). Project .h/.cpp files were never scanned, so
ESP32Servo / DHT / Adafruit_Sensor referenced only transitively
through user code never reached _resolve_library_components and
never landed in user_libs_all/.

Fix: collect ext_headers from main_content PLUS every uploaded
.h/.hpp/.ino/.c/.cpp file before resolving libraries. Lib resolver
already walks transitive includes inside the lib bundle once it's
copied; this just makes sure the first-level set covers user
project headers too.

Repro: open https://velxio.dev/example/robot-desktop-eyes, click
Compile. Before this commit: 13 errors starting at ESP32Servo.h.
After: ext_headers includes ESP32Servo.h on the first pass and the
build proceeds.
This commit is contained in:
David Montero 2026-05-23 09:00:22 +02:00
parent 1a6e2a23a7
commit f4b7776cd6
1 changed files with 16 additions and 1 deletions

View File

@ -1614,7 +1614,22 @@ class ESPIDFCompiler:
# proper ESP-IDF component with its own CMakeLists.txt and # proper ESP-IDF component with its own CMakeLists.txt and
# INCLUDE_DIRS. The root CMakeLists.txt (template) adds user_libs # INCLUDE_DIRS. The root CMakeLists.txt (template) adds user_libs
# to EXTRA_COMPONENT_DIRS so ESP-IDF discovers them automatically. # to EXTRA_COMPONENT_DIRS so ESP-IDF discovers them automatically.
ext_headers = self._detect_external_includes(main_content) #
# Scan the .ino AND every user-supplied .h/.hpp/.c/.cpp so
# transitive includes inside project headers (e.g. Common.h
# → <ESP32Servo.h>) are picked up. Previously only main_content
# was scanned, so libs only referenced from project headers
# never reached _resolve_library_components and the build
# died with "fatal error: ESP32Servo.h: No such file".
ext_headers_set: set[str] = set(
self._detect_external_includes(main_content)
)
for _f in files:
if _f.get('name', '').endswith(('.h', '.hpp', '.ino', '.c', '.cpp')):
ext_headers_set.update(
self._detect_external_includes(_f.get('content', ''))
)
ext_headers = list(ext_headers_set)
component_names: list[str] = [] component_names: list[str] = []
# arduino-esp32 component name (directory basename of ARDUINO_ESP32_PATH) # arduino-esp32 component name (directory basename of ARDUINO_ESP32_PATH)
arduino_comp_name = Path(self.arduino_path).name if self.arduino_path else 'arduino-esp32' arduino_comp_name = Path(self.arduino_path).name if self.arduino_path else 'arduino-esp32'