Name dropped requests and non-platform dependency rejections, correct the dot_a_linkage attribution

This commit is contained in:
J. Nick Koston
2026-08-20 23:55:38 -05:00
parent e6bf3e0e8f
commit 662978c402
2 changed files with 80 additions and 12 deletions
+31 -12
View File
@@ -8,10 +8,11 @@ resolution/download pipeline in ``esphome.platformio.library``. Nothing here
is core-specific: the caller names the PlatformIO platform, MCU, and cache
key of the Arduino core it builds.
Known deviation: flat-layout (``library.properties``, no ``src/``) libraries
get the recursive default source filter rather than PlatformIO's root-only
Arduino-1.0 filter; no bundled library is affected, only user-supplied ones
carrying sources in unusual subdirectories.
Known deviations: flat-layout (``library.properties``, no ``src/``)
libraries get the recursive default source filter rather than PlatformIO's
root-only Arduino-1.0 filter (no bundled library is affected), and the
Arduino ``dot_a_linkage`` property is honored even though PlatformIO
ignores it.
Mirrors PlatformIO's ``lib_ldf_mode=off`` behavior: each library builds into
its own static archive and every library's include dir joins one global
@@ -87,8 +88,9 @@ def _library_info(name: str, read_path: Path, data: dict) -> ArduinoLibrary:
# PlatformIO shell-lexes each build.flags entry
flag_tokens = lex_build_flags(build.get("flags", []), f"library {name}")
# PIO precedence: build.libArchive, else the Arduino-format
# dot_a_linkage property, else archive (PlatformIO's default)
# build.libArchive is PIO behavior; dot_a_linkage is honored as a
# deliberate extra (Arduino IDE's property, which PIO ignores) so
# properties-only libraries can opt out of archiving too
if "libArchive" in build:
lib_archive = bool(build["libArchive"])
elif "dot_a_linkage" in data:
@@ -245,11 +247,19 @@ def resolve_libraries(
try:
check_library_data(dep, pio_platform, "arduino")
except InvalidLibrary as err:
# check_library_data's only raise is the platform filter, and
# rejecting another platform's dependency of a cross-platform
# manifest is routine (every ESPAsyncWebServer build hits it);
# a warning here would be noise, and the reason is in the log.
_LOGGER.debug("Skipping bundled dependency %s: %s", name, err)
# Rejecting another platform's dependency of a cross-platform
# manifest is routine (every ESPAsyncWebServer build hits
# it), so the platform filter stays at debug; any other
# cause means a dropped dependency and must be visible
if "platform" in str(err).lower():
_LOGGER.debug("Skipping bundled dependency %s: %s", name, err)
else:
_LOGGER.warning(
"Skipping bundled dependency %s of %s: %s",
name,
component.name,
err,
)
continue
bundled_names.add(name)
bundled.append(_bundled_library(framework_path, name))
@@ -266,7 +276,7 @@ def resolve_libraries(
_add_bundled_dependencies(component)
if external:
convert_libraries(
resolved = convert_libraries(
external,
LibraryBackend(
platform=pio_platform,
@@ -275,5 +285,14 @@ def resolve_libraries(
cache_key=cache_key,
),
)
if len(resolved) < len(external):
# A requested library the converter dropped would otherwise
# surface only as link errors far from the cause
_LOGGER.warning(
"%d of %d requested libraries were not resolved (resolved: %s)",
len(external) - len(resolved),
len(external),
", ".join(sorted(c.name for c in resolved)) or "none",
)
return bundled + converted
+49
View File
@@ -409,3 +409,52 @@ def test_resolve_libraries_dep_warnings(
assert "malformed dependency entry" in caplog.text
assert "Orphan" in caplog.text
assert "owner but no version" in caplog.text
def test_resolve_libraries_warns_when_converter_drops_a_request(
tmp_path: Path, caplog: pytest.LogCaptureFixture
) -> None:
"""A requested external library the converter drops is named, not lost."""
framework = _make_framework(tmp_path)
_add_library("pngle", "1.0.0")
with patch.object(component, "convert_libraries", return_value=[]):
component.resolve_libraries(
framework,
pio_platform="espressif8266",
board_mcu="esp8266",
cache_key="arduino8266",
)
assert "1 of 1 requested libraries were not resolved" in caplog.text
def test_bundled_dependency_nonplatform_rejection_warns(
tmp_path: Path, caplog: pytest.LogCaptureFixture
) -> None:
"""An InvalidLibrary whose cause is not the platform filter is visible."""
from esphome.platformio.library import InvalidLibrary
framework = _make_framework(tmp_path)
_add_library("ESP32Async/ESPAsyncWebServer", "3.9.6")
lib_dir = tmp_path / "converted" / "webserver"
(lib_dir / "src").mkdir(parents=True)
converted = _converted(
"esp32async__ESPAsyncWebServer",
lib_dir,
{"build": {}, "dependencies": [{"name": "Wire"}]},
)
with (
_emitting_converter(converted),
patch.object(
component,
"check_library_data",
side_effect=InvalidLibrary("manifest is corrupt"),
),
):
component.resolve_libraries(
framework,
pio_platform="espressif8266",
board_mcu="esp8266",
cache_key="arduino8266",
)
assert "Skipping bundled dependency Wire" in caplog.text
assert "manifest is corrupt" in caplog.text