diff --git a/esphome/arduino8266/toolchain.py b/esphome/arduino8266/toolchain.py index 18b2e612e6..a2f61ce49c 100644 --- a/esphome/arduino8266/toolchain.py +++ b/esphome/arduino8266/toolchain.py @@ -3,6 +3,7 @@ from __future__ import annotations import logging +import os from pathlib import Path import subprocess @@ -34,8 +35,14 @@ def get_elf_path() -> Path: return get_build_dir() / "firmware.elf" +# Windows binutils carry the executable suffix; is_file() checks need it +_EXE_SUFFIX = ".exe" if os.name == "nt" else "" + + def _toolchain_tool(name: str) -> Path: - return framework.get_toolchain_path() / "bin" / f"xtensa-lx106-elf-{name}" + return ( + framework.get_toolchain_path() / "bin" / f"xtensa-lx106-elf-{name}{_EXE_SUFFIX}" + ) def get_addr2line_path() -> Path: @@ -126,7 +133,7 @@ def _print_size_summary(build_dir: Path, toolchain_path: Path) -> None: """ from esphome.espidf.size_summary import format_bar - size_tool = toolchain_path / "bin" / "xtensa-lx106-elf-size" + size_tool = _toolchain_tool("size") result = subprocess.run( [str(size_tool), "-A", "-d", str(get_elf_path())], capture_output=True, diff --git a/esphome/build_gen/arduino8266.py b/esphome/build_gen/arduino8266.py index ca7a4f2617..cfcc643e32 100644 --- a/esphome/build_gen/arduino8266.py +++ b/esphome/build_gen/arduino8266.py @@ -489,6 +489,13 @@ def write_project(paths: dict[str, Path]) -> bool: ) asflags = _ASFLAGS + defines + includes + project_compile_flags + # build_unflags applies to the framework flag sets too, as it does under + # PlatformIO (a silently ignored ``build_unflags: -Os`` would diverge). + if unflags := set(CORE.build_unflags): + cflags = [f for f in cflags if f not in unflags] + cxxflags = [f for f in cxxflags if f not in unflags] + asflags = [f for f in asflags if f not in unflags] + link_flags = list(_LINKFLAGS) if esp8266_data.get(KEY_SCANF_FLOAT): link_flags += ["-u", "_scanf_float"] diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index 6c1cd584bf..dbb071b87a 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -596,7 +596,10 @@ def _decode_pc(config, addr): addr2line = native_toolchain.get_addr2line_path() elf = native_toolchain.get_elf_path() if not addr2line.is_file() or not elf.is_file(): - _LOGGER.debug("decode_pc no addr2line") + _LOGGER.warning( + "Cannot decode crash addresses: %s missing", + addr2line if not addr2line.is_file() else elf, + ) return addr2line, elf = str(addr2line), str(elf) else: diff --git a/tests/unit_tests/build_gen/test_arduino8266.py b/tests/unit_tests/build_gen/test_arduino8266.py index 653482f2a2..d9844baf4a 100644 --- a/tests/unit_tests/build_gen/test_arduino8266.py +++ b/tests/unit_tests/build_gen/test_arduino8266.py @@ -539,3 +539,14 @@ def test_build_config_nonosdk_precedence() -> None: "-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221", ) assert _resolve_build_config(_flag_defines()).nonosdk == "NONOSDK221" + + +def test_write_project_build_unflags_apply_to_framework_flags(tmp_path: Path) -> None: + """build_unflags removes flags from the framework sets, as PlatformIO does.""" + paths = _make_framework(tmp_path) + _set_flags() + CORE.build_unflags = {"-fipa-pta"} + content = _write_ninja(paths) + for line in content.splitlines(): + if line.split(" = ")[0] in ("cflags", "cxxflags", "asflags"): + assert "-fipa-pta" not in line diff --git a/tests/unit_tests/test_arduino8266_toolchain.py b/tests/unit_tests/test_arduino8266_toolchain.py index 16d0dc2f13..ec6135a8e1 100644 --- a/tests/unit_tests/test_arduino8266_toolchain.py +++ b/tests/unit_tests/test_arduino8266_toolchain.py @@ -53,6 +53,9 @@ def test_path_getters(tmp_path: Path) -> None: assert toolchain.get_addr2line_path().name == "xtensa-lx106-elf-addr2line" assert toolchain.get_objdump_path().name == "xtensa-lx106-elf-objdump" assert toolchain.get_readelf_path().name == "xtensa-lx106-elf-readelf" + # Windows binutils carry the executable suffix + with patch.object(toolchain, "_EXE_SUFFIX", ".exe"): + assert toolchain.get_addr2line_path().name == "xtensa-lx106-elf-addr2line.exe" def test_run_compile_build_failure(tmp_path: Path) -> None: