mirror of
https://github.com/esphome/esphome.git
synced 2026-05-27 11:56:11 +08:00
[analyze_memory] Attribute main.cpp setup()/loop() to esphome core (#16033)
This commit is contained in:
@@ -793,8 +793,11 @@ class MemoryAnalyzer:
|
|||||||
"""Scan ESPHome source object files to map extern "C" symbols to components.
|
"""Scan ESPHome source object files to map extern "C" symbols to components.
|
||||||
|
|
||||||
When no linker map file is available, this uses ``nm`` to scan ``.o`` files
|
When no linker map file is available, this uses ``nm`` to scan ``.o`` files
|
||||||
under ``src/esphome/`` and build a symbol-to-component mapping. This catches
|
under ``src/`` (including ``src/main.cpp.o`` and everything beneath
|
||||||
``extern "C"`` functions and other symbols that lack C++ namespace prefixes.
|
``src/esphome/``) and build a symbol-to-component mapping. This catches
|
||||||
|
``extern "C"`` functions, the ESPHome-generated ``setup()``/``loop()``
|
||||||
|
entry points in ``main.cpp``, and other symbols that lack C++ namespace
|
||||||
|
prefixes.
|
||||||
|
|
||||||
Skips scanning if ``_source_symbol_map`` was already populated by
|
Skips scanning if ``_source_symbol_map`` was already populated by
|
||||||
``_parse_map_file()``.
|
``_parse_map_file()``.
|
||||||
@@ -806,12 +809,12 @@ class MemoryAnalyzer:
|
|||||||
if obj_dir is None:
|
if obj_dir is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Find ESPHome source object files
|
# Scan all ESPHome-owned source object files: src/main.cpp.o and src/esphome/...
|
||||||
esphome_src_dir = obj_dir / "src" / "esphome"
|
src_dir = obj_dir / "src"
|
||||||
if not esphome_src_dir.is_dir():
|
if not src_dir.is_dir():
|
||||||
return
|
return
|
||||||
|
|
||||||
obj_files = sorted(esphome_src_dir.rglob("*.o"))
|
obj_files = sorted(src_dir.rglob("*.o"))
|
||||||
if not obj_files:
|
if not obj_files:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1064,6 +1067,10 @@ class MemoryAnalyzer:
|
|||||||
if component_name in self.external_components:
|
if component_name in self.external_components:
|
||||||
return f"{_COMPONENT_PREFIX_EXTERNAL}{component_name}"
|
return f"{_COMPONENT_PREFIX_EXTERNAL}{component_name}"
|
||||||
|
|
||||||
|
# ESPHome-generated entry point: src/main.cpp.o (contains setup()/loop())
|
||||||
|
if len(parts) >= 2 and parts[-2:] == ("src", "main.cpp.o"):
|
||||||
|
return _COMPONENT_CORE
|
||||||
|
|
||||||
# ESPHome core: src/esphome/core/... or src/esphome/...
|
# ESPHome core: src/esphome/core/... or src/esphome/...
|
||||||
if "core" in parts and "esphome" in parts:
|
if "core" in parts and "esphome" in parts:
|
||||||
return _COMPONENT_CORE
|
return _COMPONENT_CORE
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
"""Tests for source-file-to-component attribution in memory analyzer."""
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from esphome.analyze_memory import MemoryAnalyzer
|
||||||
|
|
||||||
|
|
||||||
|
def _make_analyzer(external_components: set[str] | None = None) -> MemoryAnalyzer:
|
||||||
|
"""Create a MemoryAnalyzer with mocked dependencies."""
|
||||||
|
with patch.object(MemoryAnalyzer, "__init__", lambda self, *a, **kw: None):
|
||||||
|
analyzer = MemoryAnalyzer.__new__(MemoryAnalyzer)
|
||||||
|
analyzer.external_components = external_components or set()
|
||||||
|
analyzer._lib_hash_to_name = {}
|
||||||
|
return analyzer
|
||||||
|
|
||||||
|
|
||||||
|
def test_source_file_to_component_main_cpp_relative() -> None:
|
||||||
|
"""ESPHome-generated src/main.cpp.o (nm path form) attributes to core."""
|
||||||
|
analyzer = _make_analyzer()
|
||||||
|
assert analyzer._source_file_to_component("src/main.cpp.o") == "[esphome]core"
|
||||||
|
|
||||||
|
|
||||||
|
def test_source_file_to_component_main_cpp_pioenvs_path() -> None:
|
||||||
|
"""Linker map paths like .pioenvs/<env>/src/main.cpp.o attribute to core."""
|
||||||
|
analyzer = _make_analyzer()
|
||||||
|
result = analyzer._source_file_to_component(".pioenvs/drivewaygate/src/main.cpp.o")
|
||||||
|
assert result == "[esphome]core"
|
||||||
|
|
||||||
|
|
||||||
|
def test_source_file_to_component_esphome_core() -> None:
|
||||||
|
"""Sources under src/esphome/core/ attribute to core."""
|
||||||
|
analyzer = _make_analyzer()
|
||||||
|
result = analyzer._source_file_to_component("src/esphome/core/application.cpp.o")
|
||||||
|
assert result == "[esphome]core"
|
||||||
|
|
||||||
|
|
||||||
|
def test_source_file_to_component_known_component() -> None:
|
||||||
|
"""Known ESPHome components attribute to their component name."""
|
||||||
|
analyzer = _make_analyzer()
|
||||||
|
result = analyzer._source_file_to_component(
|
||||||
|
"src/esphome/components/wifi/wifi_component.cpp.o"
|
||||||
|
)
|
||||||
|
assert result == "[esphome]wifi"
|
||||||
Reference in New Issue
Block a user