espidf: never resolve generic platform headers against user libraries

Reported by a user whose every ESP32 build failed with errors from
libraries he never installed (SoftwareSerial.h, ArduinoBearSSL.h,
Adafruit_GFX.h, AsyncElegantOTA.h) coming out of user_libs_all, in a
project whose file list doesn't even show that folder.

Traced end to end: ESPAsyncWebServer includes <Hash.h> (an ESP8266-core
header, guarded for that platform, so arduino-esp32's tree has no such
file). The global scan then resolved it to stemi-hexapod's src/Hash.h --
a hexapod-robot library -- merged the WHOLE library into user_libs_all,
and its Serial.cpp / Hash.cpp / Server.cpp / BluetoothLowEnergy.cpp /
ExpansionDriver.cpp were compiled, each failing on its own unrelated
includes. Log line: 'Merging "stemihexapod" into user_libs_all for
<Hash.h>'.

Hash.h and friends now join the never-resolve-against-user-libs set.
They cannot be discovered by the core-tree scan (the core genuinely
lacks them) yet their names are generic enough that some installed
library owns a file by that name.
This commit is contained in:
David Montero 2026-08-04 05:23:42 +02:00
parent aa273a56e9
commit 7b5d30791c
2 changed files with 54 additions and 0 deletions

View File

@ -693,6 +693,20 @@ class ESPIDFCompiler:
'Udp.h', 'IPAddress.h', 'Client.h', 'Server.h', 'Stream.h',
'Print.h', 'Printable.h', 'WiFiUdp.h', 'WiFiClient.h',
'WiFiServer.h', 'WiFiType.h', 'esp_wifi.h',
# Platform headers that do NOT exist in the arduino-esp32 core, so
# the core-tree scan can't discover them, yet carry names generic
# enough that some random installed library owns a file by that
# name. Resolving one drags that whole library into user_libs_all
# and its sources then fail on THEIR own missing includes.
#
# Reported 2026-08-03 (nikas79): ESPAsyncWebServer includes <Hash.h>
# (an ESP8266-core header, guarded for that platform) and the global
# scan resolved it to `stemihexapod/src/Hash.h` — a hexapod-robot
# library — whose Serial.cpp / Hash.cpp / Server.cpp /
# BluetoothLowEnergy.cpp / ExpansionDriver.cpp then broke every
# ESP32 build with errors naming libraries the user never installed.
'Hash.h', 'Serial.h', 'HardwareSerial.h', 'WString.h',
'WCharacter.h', 'binary.h', 'pins_arduino.h', 'Esp.h',
})
# arduino-esp32 uses a single library architecture id ("esp32") across

View File

@ -171,3 +171,43 @@ class TestManifestScope(unittest.TestCase):
if __name__ == "__main__":
unittest.main()
class TestGenericHeaderCollision(unittest.TestCase):
"""Issue reported 2026-08-03 (nikas79): ESPAsyncWebServer includes
<Hash.h> (an ESP8266-core header) and the global scan resolved it to a
hexapod-robot library that happens to ship src/Hash.h. The whole library
was merged and its unrelated sources broke every ESP32 build with
'fatal error: SoftwareSerial.h' and friends."""
def setUp(self) -> None:
self.tmp = Path(tempfile.mkdtemp())
def tearDown(self) -> None:
shutil.rmtree(self.tmp, ignore_errors=True)
def test_generic_platform_header_never_resolves_to_a_user_lib(self):
ulibs = self.tmp / "Arduino" / "libraries"
# A library with a generic Hash.h, exactly like stemi-hexapod.
_mk(ulibs / "stemihexapod" / "library.properties",
"name=stemi-hexapod\narchitectures=esp32\n")
_mk(ulibs / "stemihexapod" / "src" / "Hash.h")
_mk(ulibs / "stemihexapod" / "src" / "Serial.cpp",
'#include <SoftwareSerial.h>\n')
c = ESPIDFCompiler()
c.arduino_path = ""
c._core_headers_cache = None
out = self.tmp / "project" / "user_libs"
out.mkdir(parents=True)
_names, hdr2comp = c._resolve_library_components(
["Hash.h", "Server.h", "Serial.h"],
arduino_libs=ulibs, esp32_libs=None,
arduino_comp_name="arduino-esp32", user_libs_dir=out,
)
for header in ("Hash.h", "Server.h", "Serial.h"):
self.assertNotIn(header, hdr2comp, f"{header} must stay core-provided")
copied = [p.name for p in out.rglob("*") if p.is_file()]
self.assertNotIn("Serial.cpp", copied,
"the unrelated library must NOT be merged")