mirror of
https://github.com/esphome/esphome.git
synced 2026-08-24 07:06:20 +00:00
Route native dispatch through a platform hook, hoist the pio-options warner, adopt shared toolchain factories
This commit is contained in:
+6
-7
@@ -1920,18 +1920,17 @@ def command_update_all(args: ArgsProtocol) -> int | None:
|
||||
def _native_toolchain_module():
|
||||
"""The native build backend module for the resolved toolchain, if any.
|
||||
|
||||
Platform toolchain validation rejects values a platform cannot serve, so
|
||||
using_toolchain_arduino by itself implies the native ESP8266 build.
|
||||
Platform-owned toolchains resolve through the target platform's
|
||||
``native_toolchain_module`` hook (the same per-platform module seam
|
||||
``compile_program`` uses), so shared dispatch never names a backend.
|
||||
"""
|
||||
if CORE.using_toolchain_esp_idf:
|
||||
from esphome.espidf import toolchain
|
||||
|
||||
return toolchain
|
||||
if CORE.using_toolchain_arduino:
|
||||
from esphome.arduino8266 import toolchain
|
||||
|
||||
return toolchain
|
||||
return None
|
||||
module = importlib.import_module("esphome.components." + CORE.target_platform)
|
||||
get_native = getattr(module, "native_toolchain_module", None)
|
||||
return get_native() if get_native is not None else None
|
||||
|
||||
|
||||
def command_idedata(args: ArgsProtocol, config: ConfigType) -> int:
|
||||
|
||||
@@ -7,6 +7,7 @@ from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
from esphome.arduino8266 import framework
|
||||
from esphome.build_helpers.pio_options import warn_ignored_platformio_options
|
||||
from esphome.const import (
|
||||
CONF_COMPILE_PROCESS_LIMIT,
|
||||
CONF_ESPHOME,
|
||||
@@ -27,23 +28,6 @@ _MAX_RAM_SIZE = 81920
|
||||
_CONSUMED_PIO_OPTIONS = frozenset({"lib_ignore", "upload_speed"})
|
||||
|
||||
|
||||
def _warn_ignored_platformio_options() -> None:
|
||||
"""Warn for component-added platformio options the native build drops.
|
||||
|
||||
YAML ``esphome: platformio_options:`` keys are warned about during code
|
||||
generation and never reach ``CORE.platformio_options`` under the native
|
||||
toolchain, so anything left here came from ``cg.add_platformio_option()``
|
||||
calls (e.g. an external component) and would be silently ignored.
|
||||
"""
|
||||
for key in sorted(CORE.platformio_options or {}):
|
||||
if key not in _CONSUMED_PIO_OPTIONS:
|
||||
_LOGGER.warning(
|
||||
"platformio_options->%s is ignored when building with the "
|
||||
"native 'arduino' toolchain",
|
||||
key,
|
||||
)
|
||||
|
||||
|
||||
_RAM_SECTIONS = (".data", ".rodata", ".bss")
|
||||
_FLASH_SECTIONS = (".irom0.text", ".text", ".text1", ".data", ".rodata")
|
||||
|
||||
@@ -81,21 +65,21 @@ def get_readelf_path() -> Path:
|
||||
def run_compile(config: ConfigType, verbose: bool) -> int:
|
||||
from esphome.build_gen import arduino8266 as build_gen
|
||||
|
||||
_warn_ignored_platformio_options()
|
||||
warn_ignored_platformio_options(_CONSUMED_PIO_OPTIONS, "arduino")
|
||||
paths = framework.check_and_install(CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION])
|
||||
ninja_changed = build_gen.write_project(paths)
|
||||
|
||||
build_dir = get_build_dir()
|
||||
env = framework.get_build_env(paths["toolchain_path"])
|
||||
env = framework.get_build_env(paths.toolchain)
|
||||
|
||||
# The compile database is a pure function of build.ninja (no compilation
|
||||
# involved), so regenerate it before the build: a failed build can then
|
||||
# never leave a stale database behind. Skip the ninja spawn plus MBs of
|
||||
# text on unchanged builds.
|
||||
if ninja_changed or not (build_dir / "compile_commands.json").is_file():
|
||||
_write_compile_commands(paths["ninja_path"], build_dir, env)
|
||||
_write_compile_commands(paths.ninja, build_dir, env)
|
||||
|
||||
cmd = [str(paths["ninja_path"]), "-C", str(build_dir)]
|
||||
cmd = [str(paths.ninja), "-C", str(build_dir)]
|
||||
if verbose:
|
||||
cmd.append("-v")
|
||||
if jobs := config[CONF_ESPHOME].get(CONF_COMPILE_PROCESS_LIMIT):
|
||||
@@ -186,11 +170,9 @@ def _print_size_summary(build_dir: Path) -> None:
|
||||
try:
|
||||
sections[parts[0]] = int(parts[1])
|
||||
except ValueError:
|
||||
# An unparsed RAM/Flash section trips the missing-sections
|
||||
# guard below, so no total is built on a dropped value
|
||||
_LOGGER.warning("Unparsable size output for section %s", parts[0])
|
||||
if parts[0] in _RAM_SECTIONS or parts[0] in _FLASH_SECTIONS:
|
||||
# A confident total built on a dropped section would feed
|
||||
# a wrong number to CI's memory-impact metric
|
||||
return
|
||||
if missing := set(_RAM_SECTIONS + _FLASH_SECTIONS) - set(sections):
|
||||
# A defaulted 0 would print a confidently wrong total for CI's metric
|
||||
_LOGGER.warning(
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
"""Warn about platformio options a native build backend drops."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from esphome.core import CORE
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def warn_ignored_platformio_options(consumed: frozenset[str], toolchain: str) -> None:
|
||||
"""Warn for component-added platformio options the native build drops.
|
||||
|
||||
YAML ``esphome: platformio_options:`` keys are warned about during code
|
||||
generation and never reach ``CORE.platformio_options`` under a native
|
||||
toolchain, so anything left here came from ``cg.add_platformio_option()``
|
||||
calls (e.g. an external component) and would be silently ignored.
|
||||
``consumed`` names the keys the backend honors.
|
||||
"""
|
||||
for key in sorted(CORE.platformio_options or {}):
|
||||
if key not in consumed:
|
||||
_LOGGER.warning(
|
||||
"platformio_options->%s is ignored when building with the "
|
||||
"native '%s' toolchain",
|
||||
key,
|
||||
toolchain,
|
||||
)
|
||||
@@ -109,18 +109,9 @@ def set_core_data(config):
|
||||
return config
|
||||
|
||||
|
||||
def _validate_toolchain(value: str) -> Toolchain:
|
||||
return Toolchain(
|
||||
cv.one_of(Toolchain.PLATFORMIO, Toolchain.ARDUINO, lower=True)(value)
|
||||
)
|
||||
|
||||
|
||||
def _resolve_toolchain(config: ConfigType) -> ConfigType:
|
||||
# Resolve toolchain: CLI (already on CORE.toolchain) > YAML > default.
|
||||
if CORE.toolchain is None:
|
||||
CORE.toolchain = config.get(CONF_TOOLCHAIN, Toolchain.PLATFORMIO)
|
||||
cv.check_supported_toolchain("ESP8266", (Toolchain.PLATFORMIO, Toolchain.ARDUINO))
|
||||
return config
|
||||
_TOOLCHAINS = (Toolchain.PLATFORMIO, Toolchain.ARDUINO)
|
||||
_validate_toolchain = cv.toolchain_enum(_TOOLCHAINS)
|
||||
_resolve_toolchain = cv.resolve_toolchain("ESP8266", _TOOLCHAINS, Toolchain.PLATFORMIO)
|
||||
|
||||
|
||||
def _validate_native_toolchain(config: ConfigType) -> ConfigType:
|
||||
@@ -321,6 +312,18 @@ CONFIG_SCHEMA = cv.All(
|
||||
)
|
||||
|
||||
|
||||
def native_toolchain_module():
|
||||
"""The native build backend for the resolved toolchain, if any.
|
||||
|
||||
Hook for ``__main__``'s shared dispatch (idedata, analyze_memory).
|
||||
"""
|
||||
if not CORE.using_toolchain_arduino:
|
||||
return None
|
||||
from esphome.arduino8266 import toolchain
|
||||
|
||||
return toolchain
|
||||
|
||||
|
||||
def check_rosetta() -> None:
|
||||
"""Fail fast when the x86_64 ESP8266 toolchain cannot run on this Mac.
|
||||
|
||||
@@ -627,12 +630,12 @@ def _decode_pc(config, addr):
|
||||
|
||||
addr2line = native_toolchain.get_addr2line_path()
|
||||
elf = native_toolchain.get_elf_path()
|
||||
missing = addr2line if not addr2line.is_file() else elf
|
||||
if not missing.is_file():
|
||||
_warn_decode_problem(
|
||||
str(missing), "Cannot decode crash addresses: %s missing", missing
|
||||
)
|
||||
return
|
||||
for path in (addr2line, elf):
|
||||
if not path.is_file():
|
||||
_warn_decode_problem(
|
||||
str(path), "Cannot decode crash addresses: %s missing", path
|
||||
)
|
||||
return
|
||||
addr2line, elf = str(addr2line), str(elf)
|
||||
else:
|
||||
from esphome.platformio import toolchain
|
||||
|
||||
@@ -8,6 +8,7 @@ from unittest.mock import MagicMock, patch
|
||||
import pytest
|
||||
|
||||
from esphome.arduino8266 import framework, toolchain
|
||||
from esphome.build_helpers.pio_options import warn_ignored_platformio_options
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_COMPILE_PROCESS_LIMIT,
|
||||
@@ -39,12 +40,12 @@ def _setup_core(tmp_path: Path) -> None:
|
||||
CORE.data[KEY_CORE] = {KEY_FRAMEWORK_VERSION: cv.Version(3, 1, 2)}
|
||||
|
||||
|
||||
def _paths(tmp_path: Path) -> dict[str, Path]:
|
||||
return {
|
||||
"framework_path": tmp_path / "framework",
|
||||
"toolchain_path": tmp_path / "toolchain",
|
||||
"ninja_path": tmp_path / "ninja",
|
||||
}
|
||||
def _paths(tmp_path: Path) -> framework.InstalledPaths:
|
||||
return framework.InstalledPaths(
|
||||
framework=tmp_path / "framework",
|
||||
toolchain=tmp_path / "toolchain",
|
||||
ninja=tmp_path / "ninja",
|
||||
)
|
||||
|
||||
|
||||
def test_path_getters(tmp_path: Path) -> None:
|
||||
@@ -331,7 +332,8 @@ def test_warn_ignored_platformio_options(caplog: pytest.LogCaptureFixture) -> No
|
||||
"lib_ignore": ["Updater"],
|
||||
"upload_speed": "460800",
|
||||
}
|
||||
toolchain._warn_ignored_platformio_options()
|
||||
warn_ignored_platformio_options(toolchain._CONSUMED_PIO_OPTIONS, "arduino")
|
||||
assert "platformio_options->board_build.ldscript is ignored" in caplog.text
|
||||
assert "native 'arduino' toolchain" in caplog.text
|
||||
assert "lib_ignore" not in caplog.text
|
||||
assert "upload_speed" not in caplog.text
|
||||
|
||||
Reference in New Issue
Block a user