mirror of
https://github.com/esphome/esphome.git
synced 2026-08-25 07:36:19 +00:00
Merge branch 'esp8266-native-build-infra' into esp8266-native-framework-installer
This commit is contained in:
@@ -39,11 +39,13 @@ ZEPHYR_FRAMEWORK = "zephyr"
|
||||
|
||||
|
||||
def _escape(p: PathType) -> str:
|
||||
# In CMakeLists.txt, backslashes need to be escaped (mirrors the ESP-IDF
|
||||
# backend's escape_entry). Doubling -- rather than rewriting '\' -> '/' --
|
||||
# preserves content, so it's safe for arbitrary build flags (e.g. a -D value
|
||||
# containing a backslash) as well as Windows paths.
|
||||
return f'"{str(p)}"'.replace("\\", "\\\\")
|
||||
# In CMakeLists.txt, backslashes and embedded quotes need escaping
|
||||
# (mirrors the ESP-IDF backend's escape_entry; the lex round-trip makes
|
||||
# a literal quote in a -D value reachable). Doubling backslashes --
|
||||
# rather than rewriting '\' -> '/' -- preserves content, so it's safe
|
||||
# for arbitrary build flags as well as Windows paths.
|
||||
escaped = str(p).replace("\\", "\\\\").replace('"', '\\"')
|
||||
return f'"{escaped}"'
|
||||
|
||||
|
||||
def generate_module_yml(component: ConvertedLibrary) -> str:
|
||||
|
||||
@@ -714,6 +714,10 @@ def normalize_dependencies(
|
||||
list, and a plain (possibly comma-separated) string; normalize them all
|
||||
so callers see a uniform list. ``manifest_name`` names the manifest in the
|
||||
warning for entries that cannot be normalized.
|
||||
|
||||
Bare-name spellings carry no version; the dependency walk later drops
|
||||
version-less entries at DEBUG, since they are usually names of bundled
|
||||
framework libraries (Wire, SPI) that need no registry install.
|
||||
"""
|
||||
if dependencies is None:
|
||||
return []
|
||||
@@ -1133,15 +1137,25 @@ def convert_libraries(
|
||||
malformed = not isinstance(component.data, dict)
|
||||
if not malformed:
|
||||
build = component.data.get("build", {})
|
||||
esphome_data = component.data.get(ESPHOME_DATA_KEY, {})
|
||||
malformed = (
|
||||
not isinstance(build, dict)
|
||||
or not isinstance(component.data.get(ESPHOME_DATA_KEY, {}), dict)
|
||||
or not isinstance(esphome_data, dict)
|
||||
or not isinstance(
|
||||
esphome_data.get(ESPHOME_DATA_LINK_FLAGS_KEY, []), list
|
||||
)
|
||||
or not isinstance(build.get("srcDir", ""), str)
|
||||
or not isinstance(build.get("includeDir", ""), str)
|
||||
or not isinstance(build.get("srcFilter", ""), (str, list))
|
||||
)
|
||||
if malformed:
|
||||
raise EsphomeError(f"Library {key} has a malformed manifest")
|
||||
# Fail fast only for a library the user asked for; a defect
|
||||
# in an unrequested corner of the graph must not block the
|
||||
# build
|
||||
if key in top_level_keys:
|
||||
raise EsphomeError(f"Library {key} has a malformed manifest")
|
||||
_LOGGER.warning("Skipping dependency %s: malformed manifest", key)
|
||||
continue
|
||||
warn_properties_depends(component.name, component.data)
|
||||
|
||||
try:
|
||||
|
||||
@@ -826,6 +826,7 @@ def test_normalize_dependencies_forms(caplog) -> None:
|
||||
{"name": "A", "build": {"srcDir": 123}},
|
||||
{"name": "A", "build": {"includeDir": ["inc"]}},
|
||||
{"name": "A", "build": {"srcFilter": {"+": "src"}}},
|
||||
{"name": "A", "ESPHOME": {"LINK_FLAGS": "-Wl,-x"}},
|
||||
],
|
||||
)
|
||||
def test_convert_libraries_malformed_manifest_raises(
|
||||
@@ -838,6 +839,29 @@ def test_convert_libraries_malformed_manifest_raises(
|
||||
convert_libraries([Library("esphome/A", None, None)], _backend())
|
||||
|
||||
|
||||
def test_convert_libraries_malformed_transitive_dep_skips(
|
||||
tmp_path, monkeypatch, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""A malformed manifest on a dependency the user never asked for warns
|
||||
and skips; only a top-level library fails the build."""
|
||||
_patch_download_with_manifests(
|
||||
monkeypatch,
|
||||
tmp_path,
|
||||
{
|
||||
"esphome/A": {
|
||||
"name": "A",
|
||||
"dependencies": [{"name": "B", "owner": "esphome", "version": "1.0"}],
|
||||
},
|
||||
"esphome/B": {"name": "B", "build": {"srcDir": 123}},
|
||||
},
|
||||
)
|
||||
components = convert_libraries([Library("esphome/A", None, None)], _backend())
|
||||
names = [c.name for c in components]
|
||||
assert "esphome/A" in names
|
||||
assert "esphome/B" not in names
|
||||
assert "Skipping dependency esphome/B: malformed manifest" in caplog.text
|
||||
|
||||
|
||||
def test_walk_warns_for_properties_only_depends(
|
||||
tmp_path, monkeypatch, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
|
||||
@@ -66,6 +66,18 @@ def test_generate_cmakelists_txt_flags_and_includes(tmp_path):
|
||||
assert "-lm" in out
|
||||
|
||||
|
||||
def test_generate_cmakelists_txt_escapes_embedded_quotes(tmp_path):
|
||||
"""A define value carrying a literal quote (reachable via the lex
|
||||
round-trip) survives as an escaped quote, not a broken CMake string."""
|
||||
c = _make_component(tmp_path)
|
||||
(tmp_path / "src").mkdir()
|
||||
(tmp_path / "src" / "a.c").write_text("")
|
||||
c.data = {"build": {"flags": ['-DMSG=\\"hi\\"']}}
|
||||
|
||||
out = generate_cmakelists_txt(c)
|
||||
assert '"-DMSG=\\"hi\\""' in out
|
||||
|
||||
|
||||
def test_generate_cmakelists_txt_lexes_spaced_flags(tmp_path):
|
||||
"""A spaced -I entry routes to include dirs instead of landing verbatim
|
||||
in compile options; same shared lexer as the espidf emitter."""
|
||||
|
||||
Reference in New Issue
Block a user