mirror of
https://github.com/esphome/esphome.git
synced 2026-09-11 23:37:34 +00:00
Match glob archive specs in the fragment belt and quote the list expansion
This commit is contained in:
@@ -56,7 +56,7 @@ if(COMMAND __ldgen_get_lib_deps_of_target)
|
||||
"nothing; app edits will regenerate sections.ld.")
|
||||
endif()
|
||||
endif()
|
||||
set(${out_list_var} ${${out_list_var}} PARENT_SCOPE)
|
||||
set(${out_list_var} "${${out_list_var}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
else()
|
||||
message(@MISSING@ "ESPHome ldgen override target not found; "
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""ESP-IDF direct build API for ESPHome."""
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
import fnmatch
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
@@ -480,7 +481,21 @@ def _patch_memory_segments():
|
||||
|
||||
|
||||
_LDGEN_FRAGMENTS_RE = re.compile(r'--fragments-list\s+"([^"]+)"')
|
||||
_APP_ARCHIVE_MAPPED_RE = re.compile(r"^\s*archive:\s*libsrc\.a\b", re.MULTILINE)
|
||||
_LDGEN_ARCHIVE_RE = re.compile(r"^\s*archive:\s*(\S+)", re.MULTILINE)
|
||||
|
||||
|
||||
def _fragment_maps_app_archive(text: str) -> bool:
|
||||
"""True when an archive: spec selects libsrc.a, the archive of the src
|
||||
component excluded as idf::src/__idf_src in build_gen/espidf.py.
|
||||
|
||||
The bare * is IDF's stock catch-all; its archive-level entries resolve
|
||||
in the linker against all link inputs, so it stays safe when the
|
||||
archive is excluded from ldgen's own inputs.
|
||||
"""
|
||||
return any(
|
||||
value != "*" and fnmatch.fnmatch("libsrc.a", value)
|
||||
for value in _LDGEN_ARCHIVE_RE.findall(text)
|
||||
)
|
||||
|
||||
|
||||
def _ldgen_check_skip(msg: str, strict: bool) -> None:
|
||||
@@ -512,7 +527,7 @@ def _warn_if_app_archive_mapped() -> None:
|
||||
except OSError as e:
|
||||
_ldgen_check_skip(f"could not read {fragment}: {e}", strict)
|
||||
continue
|
||||
if _APP_ARCHIVE_MAPPED_RE.search(text):
|
||||
if _fragment_maps_app_archive(text):
|
||||
msg = (
|
||||
f"Linker fragment {fragment} maps the app archive; its "
|
||||
"entries may be skipped. Set ESPHOME_LDGEN_FULL_DEPS=1 "
|
||||
|
||||
@@ -173,6 +173,8 @@ def test_get_project_cmakelists_emits_ldgen_override(
|
||||
monkeypatch.delenv("ESPHOME_LDGEN_STRICT", raising=False)
|
||||
content = _render(minimal=minimal)
|
||||
assert "REMOVE_ITEM ${out_list_var} idf::src __idf_src" in content
|
||||
# Quoted so spaced elements survive and an empty list stays defined
|
||||
assert 'set(${out_list_var} "${${out_list_var}}" PARENT_SCOPE)' in content
|
||||
assert 'message(WARNING "ESPHome ldgen app archive exclusion' in content
|
||||
assert 'message(STATUS "ESPHome ldgen override target not found' in content
|
||||
assert 'message(WARNING "ESPHome ldgen override never filtered' in content
|
||||
|
||||
@@ -690,13 +690,28 @@ def test_warn_if_app_archive_mapped_strict_raises(
|
||||
toolchain._warn_if_app_archive_mapped()
|
||||
|
||||
|
||||
def test_warn_if_app_archive_mapped_glob(
|
||||
setup_core: Path, tmp_path: Path, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""A glob archive spec that selects the app archive is also flagged."""
|
||||
_setup_build(setup_core)
|
||||
frag = tmp_path / "linker.lf"
|
||||
frag.write_text("[mapping:evil]\narchive: lib*\n")
|
||||
_write_fragments_build_ninja(tmp_path, [frag])
|
||||
toolchain._warn_if_app_archive_mapped()
|
||||
assert "maps the app archive" in caplog.text
|
||||
|
||||
|
||||
def test_warn_if_app_archive_mapped_clean(
|
||||
setup_core: Path, tmp_path: Path, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""Normal fragments produce no warning."""
|
||||
"""Normal fragments, including IDF's stock archive: * catch-all,
|
||||
produce no warning."""
|
||||
_setup_build(setup_core)
|
||||
frag = tmp_path / "linker.lf"
|
||||
frag.write_text("[mapping:freertos]\narchive: libfreertos.a\n")
|
||||
frag.write_text(
|
||||
"[mapping:freertos]\narchive: libfreertos.a\n[mapping:default]\narchive: *\n"
|
||||
)
|
||||
_write_fragments_build_ninja(tmp_path, [frag])
|
||||
toolchain._warn_if_app_archive_mapped()
|
||||
assert "maps the app archive" not in caplog.text
|
||||
|
||||
Reference in New Issue
Block a user