From ba5bb9dfa747d41aff9d222d7f5c6147e546cad5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 2 Jul 2025 09:02:06 -0500 Subject: [PATCH] wip --- esphome/analyze_memory.py | 11 +++++++++-- esphome/platformio_api.py | 27 ++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/esphome/analyze_memory.py b/esphome/analyze_memory.py index cff1209624..0329013cdf 100644 --- a/esphome/analyze_memory.py +++ b/esphome/analyze_memory.py @@ -926,6 +926,7 @@ class MemoryAnalyzer: elf_path: str, objdump_path: str | None = None, readelf_path: str | None = None, + external_components: set[str] | None = None, ): self.elf_path = Path(elf_path) if not self.elf_path.exists(): @@ -933,6 +934,7 @@ class MemoryAnalyzer: self.objdump_path = objdump_path or "objdump" self.readelf_path = readelf_path or "readelf" + self.external_components = external_components or set() self.sections: dict[str, MemorySection] = {} self.components: dict[str, ComponentMemory] = defaultdict( @@ -1120,10 +1122,14 @@ class MemoryAnalyzer: # Strip trailing underscore if present (e.g., switch_ -> switch) component_name = component_name.rstrip("_") - # Check if this is an actual component or core + # Check if this is an actual component in the components directory if component_name in ESPHOME_COMPONENTS: return f"[esphome]{component_name}" + # Check if this is a known external component from the config + elif component_name in self.external_components: + return f"[external]{component_name}" else: + # Everything else in esphome:: namespace is core return "[esphome]core" # Check for esphome core namespace (no component namespace) @@ -1501,9 +1507,10 @@ def analyze_elf( objdump_path: str | None = None, readelf_path: str | None = None, detailed: bool = False, + external_components: set[str] | None = None, ) -> str: """Analyze an ELF file and return a memory report.""" - analyzer = MemoryAnalyzer(elf_path, objdump_path, readelf_path) + analyzer = MemoryAnalyzer(elf_path, objdump_path, readelf_path, external_components) analyzer.analyze() return analyzer.generate_report(detailed) diff --git a/esphome/platformio_api.py b/esphome/platformio_api.py index 96e746fa8d..7f474a1fc4 100644 --- a/esphome/platformio_api.py +++ b/esphome/platformio_api.py @@ -389,8 +389,33 @@ def analyze_memory_usage(config: dict[str, Any]) -> None: _LOGGER.warning("ELF file not found at %s or %s", elf_path, alt_path) return + # Extract external components from config + external_components = set() + + # Get the list of built-in ESPHome components + from esphome.analyze_memory import get_esphome_components + + builtin_components = get_esphome_components() + + # Special non-component keys that appear in configs + NON_COMPONENT_KEYS = { + CONF_ESPHOME, + "substitutions", + "packages", + "globals", + "<<", + } + + # Check all top-level keys in config + for key in config: + if key not in builtin_components and key not in NON_COMPONENT_KEYS: + # This is an external component + external_components.add(key) + + _LOGGER.debug("Detected external components: %s", external_components) + # Create analyzer and run analysis - analyzer = MemoryAnalyzer(elf_path, objdump_path, readelf_path) + analyzer = MemoryAnalyzer(elf_path, objdump_path, readelf_path, external_components) analyzer.analyze() # Generate and print report