From 2af06e3b5359dfdfdb2697f01c8eaaef419ed7bf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 22 Aug 2026 19:16:50 -0500 Subject: [PATCH] Use the exported consumed-options set, guard the analyze-memory ELF, trigger on the cache action --- esphome/__main__.py | 12 ++++++++++-- esphome/arduino8266/toolchain.py | 10 +++++----- esphome/components/esp32/__init__.py | 5 +++-- script/determine-jobs.py | 1 + tests/script/test_determine_jobs.py | 4 +++- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index acb7370bab..91ade1570d 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -2029,10 +2029,11 @@ def command_analyze_memory(args: ArgsProtocol, config: ConfigType) -> int: ): if not tool.is_file(): # The analyzer would silently fall back to host binutils, - # which cannot read the target ELF + # which cannot read the target ELF. clean-all is heavy for + # ESP-IDF, so suggest a recompile first. _LOGGER.error( "%s is missing; the toolchain install may be incomplete " - "(run 'esphome clean-all')", + "(recompile, or run 'esphome clean-all' if it persists)", tool, ) return 1 @@ -2040,6 +2041,13 @@ def command_analyze_memory(args: ArgsProtocol, config: ConfigType) -> int: readelf_path = str(native_toolchain.get_readelf_path()) firmware_elf = native_toolchain.get_elf_path() + if not firmware_elf.is_file(): + # The analyzer swallows tool failures, so a missing ELF would + # produce an exit-0 zeroed report + _LOGGER.error( + "%s is missing; compile the configuration first", firmware_elf + ) + return 1 else: from esphome.platformio import toolchain diff --git a/esphome/arduino8266/toolchain.py b/esphome/arduino8266/toolchain.py index 947f75985f..6513bbe866 100644 --- a/esphome/arduino8266/toolchain.py +++ b/esphome/arduino8266/toolchain.py @@ -27,13 +27,13 @@ _MAX_RAM_SIZE = 81920 def _warn_ignored_platformio_options() -> None: """Warn for component-added platformio options the native build drops. - The consumed set derives from NATIVE_ARDUINO_PIO_OPTIONS so the two - lists cannot drift; YAML upload_speed never reaches - CORE.platformio_options here. + The consumed set is exported by core/config.py next to the routing that + stores these options, so the two cannot drift; YAML upload_speed never + reaches CORE.platformio_options here. """ - from esphome.core.config import NATIVE_ARDUINO_PIO_OPTIONS + from esphome.core.config import NATIVE_ARDUINO_CONSUMED_PIO_OPTIONS - consumed = NATIVE_ARDUINO_PIO_OPTIONS | {"lib_ignore"} + consumed = NATIVE_ARDUINO_CONSUMED_PIO_OPTIONS for key in sorted(CORE.platformio_options or {}): if key not in consumed: _LOGGER.warning( diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 70b24e0372..5e010319bb 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -3447,8 +3447,9 @@ def process_stacktrace(config, line, backtrace_state): def native_toolchain_module(): """The native build backend for the resolved toolchain, if any. - Hook for ``__main__``'s shared dispatch (idedata, analyze_memory, - decode); same seam the esp8266 component provides. + Hook for ``__main__``'s shared dispatch (idedata, analyze_memory); + esp32's crash decode still branches inline in _decode_pc. Same seam + the esp8266 component provides. """ if not CORE.using_toolchain_esp_idf: return None diff --git a/script/determine-jobs.py b/script/determine-jobs.py index 3dc7737d9a..946fb88a5b 100755 --- a/script/determine-jobs.py +++ b/script/determine-jobs.py @@ -670,6 +670,7 @@ ESP8266_NATIVE_TRIGGER_FILES = frozenset( "esphome/platformio/toolchain.py", "script/test_build_components.py", ".github/workflows/ci.yml", + ".github/actions/cache-arduino8266/action.yml", } ) diff --git a/tests/script/test_determine_jobs.py b/tests/script/test_determine_jobs.py index f1f2ead81a..395a1ef539 100644 --- a/tests/script/test_determine_jobs.py +++ b/tests/script/test_determine_jobs.py @@ -3111,8 +3111,10 @@ def test_esp8266_native_components_full_list_on_infra_change() -> None: # Top-level esphome/*.py modules the backend imports directly ["esphome/framework_helpers.py"], ["esphome/writer.py"], - # ccache_path imports from platformio/toolchain.py + # esp8266/__init__.py imports copy_ccache_script from it ["esphome/platformio/toolchain.py"], + # The composite cache action must not ship unexercised + [".github/actions/cache-arduino8266/action.yml"], ): with ( patch.object(determine_jobs, "changed_files", return_value=changed),