Merge branch 'esp8266-native-library-backend' into esp8266-native-build-spec

This commit is contained in:
J. Nick Koston
2026-08-22 21:42:13 -05:00
6 changed files with 65 additions and 5 deletions
+5 -1
View File
@@ -865,7 +865,11 @@ def compile_program(args: ArgsProtocol, config: ConfigType) -> int:
except IDEDATA_BEST_EFFORT_ERRORS as err:
# The firmware already built; an idedata failure must not fail
# a successful build.
_LOGGER.warning("Could not generate idedata: %s", err)
_LOGGER.warning(
"Could not generate idedata: %s (IDE, clang-tidy, and "
"memory-analysis data will be unavailable for this build)",
err,
)
_LOGGER.debug("Idedata failure detail", exc_info=True)
else:
from esphome.platformio import toolchain
+8
View File
@@ -337,6 +337,14 @@ def idedata_from_build(compile_commands: Path, launcher: str | None = None) -> d
for inc in parse_entry(entry, launcher)[2]:
build_includes.setdefault(inc, None)
if not build_includes:
# No ESPHome translation unit contributed includes: idedata with an
# empty build include set breaks clang-tidy/IDE consumers silently
_LOGGER.warning(
"No ESPHome source includes found in %s; idedata will be incomplete",
compile_commands,
)
return {
"cc_path": _cc_path_from_cxx(cxx_path),
"cxx_path": cxx_path,
+4 -2
View File
@@ -215,8 +215,10 @@ def tool_version_runs(binary: str, warning: str) -> bool:
# Repo-wide convention (posix_spawn fast path)
close_fds=False,
)
except (OSError, subprocess.SubprocessError):
_LOGGER.warning(warning, binary)
except (OSError, subprocess.SubprocessError) as err:
# The cause (permission denied, missing DLL, timeout) is the one
# detail the user needs to fix it
_LOGGER.warning("%s (%s)", warning % binary, err)
return False
return True
+6 -2
View File
@@ -240,10 +240,14 @@ def captured_as_build_flags(
flags.append(f"-L{resolved}")
flags.extend(f"-l{lib}" for lib in result.libs)
for define in result.cppdefines:
if isinstance(define, tuple) and len(define) == 2:
# SCons also accepts dict/list CPPDEFINES; formatting those blind
# would hand the compiler garbage like -D{'FOO': '1'}
if isinstance(define, (tuple, list)) and len(define) == 2:
flags.append(f"-D{define[0]}={define[1]}")
else:
elif isinstance(define, str):
flags.append(f"-D{define}")
else:
_LOGGER.warning("Ignoring unsupported CPPDEFINES entry %r", define)
flags.extend(result.linkflags)
flags.extend(result.cppflags)
return flags
@@ -151,6 +151,29 @@ def test_is_esphome_src_handles_backslash_paths() -> None:
assert not idedata._is_esphome_src(r"C:\b\src\esphome\core\app.h")
def test_idedata_from_build_empty_includes_warns(
tmp_path: Path, caplog: pytest.LogCaptureFixture
) -> None:
"""A compile DB with no ESPHome TU yields no build includes; that is
never a usable idedata, so it must be diagnosable."""
compile_commands = tmp_path / "compile_commands.json"
compile_commands.write_text(
json.dumps(
[
_entry(
f"{ABS}build",
f"{ABS}build/other/lib.cpp",
"/tools/g++ -c other/lib.cpp -o lib.o",
)
]
)
)
with patch.object(idedata, "get_toolchain_includes", return_value=[]):
data = idedata.idedata_from_build(compile_commands)
assert data["includes"]["build"] == []
assert "idedata will be incomplete" in caplog.text
def test_idedata_from_build_dedupes_identical_command_shapes(
tmp_path: Path,
) -> None:
@@ -169,6 +169,25 @@ def test_apply_extra_script_callable_target_and_str_flags(tmp_path) -> None:
assert c.data["build"]["flags"] == ["-DBASE=1", "-lesp8266"]
def test_captured_dict_cppdefines_warn_and_skip(tmp_path, caplog) -> None:
"""A dict CPPDEFINES entry (legal SCons) must warn and skip; formatting
it blind would hand the compiler -D{'FOO': '1'} garbage."""
(tmp_path / "src").mkdir()
script = tmp_path / "extra.py"
script.write_text(
"env.Append(CPPDEFINES=[{'FOO': '1'}, ('BAR', 2), ['BAZ', 3], 'PLAIN'])\n"
)
c = IDFComponent("owner/name", "1.0", source=URLSource("http://dummy"))
c.path = tmp_path
c.data = {"build": {"extraScript": "extra.py"}}
apply_extra_script(c, board_mcu=lambda: "esp8266", pio_platform="espressif8266")
assert c.data["build"]["flags"] == ["-DBAR=2", "-DBAZ=3", "-DPLAIN"]
assert "Ignoring unsupported CPPDEFINES entry" in caplog.text
def test_apply_extra_script_subscript_env_read(tmp_path) -> None:
"""Scripts also read env["BOARD_MCU"]; the subscript form must work or
the broad handler discards every flag the script captured."""