From d4b0b3d82234168d6d3ceacd7c8872dd0c5c317f Mon Sep 17 00:00:00 2001 From: David Montero Date: Fri, 31 Jul 2026 22:04:49 +0200 Subject: [PATCH] espidf: fix architecture guard skipping usable libraries (issue #257) Two-tier rule replacing the blanket skip: - 'all' now counts as wildcard ('*'): LiquidCrystal_I2C 2.0.0 declares architectures=all and was skipped on every ESP32 build, breaking the most popular I2C LCD library with a bare 'No such file or directory'. - Headers the SKETCH includes directly merge even when the library declares a foreign-only architecture (many avr-declared libs are pure Wire/SPI code that compiles fine; a truthful compile error beats a missing-header one). Transitive pulls keep the HARD guard, which is the path that dragged SAMD-only Adafruit_ZeroDMA into ESP32 builds. --- backend/app/services/espidf_compiler.py | 32 ++++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/backend/app/services/espidf_compiler.py b/backend/app/services/espidf_compiler.py index 0dcc8d80..b5fe2b9b 100644 --- a/backend/app/services/espidf_compiler.py +++ b/backend/app/services/espidf_compiler.py @@ -766,7 +766,10 @@ class ESPIDFCompiler: if not arch: return True arches = {a.strip().lower() for a in arch.split(',') if a.strip()} - return '*' in arches or self._ESP32_LIB_ARCH in arches + # 'all' is a common non-spec synonym for '*' (e.g. LiquidCrystal_I2C + # 2.0.0 declares architectures=all) — treating it as unknown skipped + # the most popular I2C LCD library on every ESP32 build (issue #257). + return '*' in arches or 'all' in arches or self._ESP32_LIB_ARCH in arches @staticmethod def _norm_lib_name(name: str) -> str: @@ -928,6 +931,14 @@ class ESPIDFCompiler: found_any = False headers_to_resolve: list[str] = list(ext_headers) + # Headers the SKETCH itself includes (vs transitive pulls found by + # re-scanning copied library headers). The architecture guard is + # advisory for these: the user explicitly asked for the library, and + # many AVR-declared libs are pure Wire/SPI code that compiles fine on + # ESP32 — skipping them produced a bare "No such file or directory" + # (issue #257). Transitive pulls keep the HARD guard: that is the + # path that dragged SAMD-only Adafruit_ZeroDMA into ESP32 builds. + direct_headers: set[str] = set(ext_headers) resolved_headers: set[str] = set() while headers_to_resolve: @@ -974,11 +985,20 @@ class ESPIDFCompiler: if src_root is not None: _lib_root = src_root.parent if src_root.name == 'src' else src_root if not self._library_supports_esp32(_lib_root): - logger.warning( - f'[espidf] <{header}> resolved to "{_lib_root.name}" but its ' - f'library.properties architectures exclude esp32 — skipping' - ) - src_root = None + if header in direct_headers: + logger.warning( + f'[espidf] <{header}> resolved to "{_lib_root.name}" whose ' + f'library.properties architectures exclude esp32 — merging ' + f'anyway because the sketch includes it directly (a real ' + f'compile error beats "No such file")' + ) + else: + logger.warning( + f'[espidf] <{header}> resolved to "{_lib_root.name}" but its ' + f'library.properties architectures exclude esp32 — skipping ' + f'(transitive pull, not included by the sketch)' + ) + src_root = None # Tracks the "resolved to a core lib that's already compiled into # the arduino-esp32 component" case, so we don't fall through to