Merge branch 'esp8266-native-ninja-emission' into esp8266-arduino-toolchain

# Conflicts:
#	esphome/components/esp8266/__init__.py
This commit is contained in:
J. Nick Koston
2026-08-23 16:43:20 -05:00
4 changed files with 27 additions and 20 deletions
+11 -5
View File
@@ -37,9 +37,9 @@ from esphome.components.esp8266.boards import (
board_ld_script,
)
from esphome.components.esp8266.const import (
BUILD_FLASH_MODES,
KEY_BOARD,
KEY_ESP8266,
KEY_FLASH_MODE,
KEY_FLASH_SIZE,
KEY_SCANF_FLOAT,
)
@@ -107,8 +107,8 @@ def _apply_surgery(fn, *args: object) -> str:
# Every supported board's f_flash is 40 MHz; re-check on a platform bump
# board_flash_mode's closed set (cv.one_of in esp8266/__init__.py)
_FLASH_MODES = frozenset({"qio", "qout", "dio", "dout"})
# board_flash_mode's closed set, shared with cv.one_of's validation
_FLASH_MODES = frozenset(BUILD_FLASH_MODES)
_FLASH_FREQ_MHZ = 40
# From platformio-build.py. Knob suffix -> SDK define; the first entry is
@@ -851,7 +851,8 @@ def write_project(paths: InstalledPaths, ccache: str | None) -> bool:
if board not in ESP8266_BOARD_BUILD:
raise EsphomeError(f"Board '{board}' is not supported by the native toolchain")
board_build = ESP8266_BOARD_BUILD[board]
flash_mode = esp8266_data[KEY_FLASH_MODE]
# From the same producer the PlatformIO path reads (one source)
flash_mode = _pio_option("board_build.flash_mode", "dout")
if flash_mode not in _FLASH_MODES:
# Lands unquoted in the elf2bin command and a -D body; validation
# (cv.one_of on board_flash_mode) already gates it, defense-in-depth
@@ -1102,7 +1103,12 @@ def write_project(paths: InstalledPaths, ccache: str | None) -> bool:
)
for tok in src_it:
if tok == "-include":
src_parts.append(f"-include {_q(src_dir / next(src_it, ''))}")
header = next(src_it, "")
if not header:
raise EsphomeError(
"build_src_flags has a trailing '-include' with no header"
)
src_parts.append(f"-include {_q(src_dir / header)}")
else:
src_parts.append(_shell_token(tok))
src_extra = " ".join(src_parts)
+2 -5
View File
@@ -40,13 +40,13 @@ from esphome.types import ConfigType
from .boards import BOARDS, ESP8266_BOARD_BUILD, ESP8266_LD_SCRIPTS, board_ld_script
from .const import (
BUILD_FLASH_MODES,
CONF_EARLY_PIN_INIT,
CONF_ENABLE_SERIAL,
CONF_ENABLE_SERIAL1,
CONF_RESTORE_FROM_FLASH,
KEY_BOARD,
KEY_ESP8266,
KEY_FLASH_MODE,
KEY_FLASH_SIZE,
KEY_LDSCRIPT,
KEY_PIN_INITIAL_STATES,
@@ -104,7 +104,6 @@ def set_core_data(config: ConfigType) -> ConfigType:
config[CONF_FRAMEWORK][CONF_VERSION]
)
CORE.data[KEY_ESP8266][KEY_BOARD] = config[CONF_BOARD]
CORE.data[KEY_ESP8266][KEY_FLASH_MODE] = config[CONF_BOARD_FLASH_MODE]
CORE.data[KEY_ESP8266][KEY_PIN_INITIAL_STATES] = [
PinInitialState() for _ in range(16)
]
@@ -294,7 +293,6 @@ ARDUINO_FRAMEWORK_SCHEMA = cv.All(
)
BUILD_FLASH_MODES = ["qio", "qout", "dio", "dout"]
CONFIG_SCHEMA = cv.All(
cv.Schema(
{
@@ -384,8 +382,7 @@ async def to_code(config: ConfigType) -> None:
"enabling scanf float support (~8KB flash)"
)
# The native toolchain reads this decision from CORE.data instead of the
# remove_float_scanf extra script.
# The native generator reads the same decision (KEY_SCANF_FLOAT)
CORE.data[KEY_ESP8266][KEY_SCANF_FLOAT] = bool(enable_scanf_float)
if use_platformio:
extra_scripts = [
+1
View File
@@ -74,3 +74,4 @@ def enable_serial1() -> None:
KEY_LDSCRIPT = "ldscript"
BUILD_FLASH_MODES = ("qio", "qout", "dio", "dout")
+13 -10
View File
@@ -28,12 +28,7 @@ from esphome.build_gen.arduino8266 import (
)
from esphome.components.esp8266.boards import BOARDS, ESP8266_BOARD_BUILD
from esphome.components.esp8266.build_surgery import RATETABLE_RULE
from esphome.components.esp8266.const import (
KEY_BOARD,
KEY_ESP8266,
KEY_FLASH_MODE,
KEY_SCANF_FLOAT,
)
from esphome.components.esp8266.const import KEY_BOARD, KEY_ESP8266, KEY_SCANF_FLOAT
import esphome.config_validation as cv
from esphome.const import KEY_CORE, KEY_FRAMEWORK_VERSION
from esphome.core import CORE, EsphomeError
@@ -48,12 +43,12 @@ def _setup_core(tmp_path: Path) -> Generator[None]:
CORE.data[KEY_CORE] = {KEY_FRAMEWORK_VERSION: cv.Version(3, 1, 2)}
CORE.data[KEY_ESP8266] = {
KEY_BOARD: "nodemcuv2",
KEY_FLASH_MODE: "dout",
KEY_SCANF_FLOAT: False,
}
# The producer esp8266/__init__ pins unconditionally
# The producers esp8266/__init__ pins unconditionally
CORE.platformio_options = {
"build_src_flags": "-include esphome/components/esp8266/throw_stubs.h"
"board_build.flash_mode": "dout",
"build_src_flags": "-include esphome/components/esp8266/throw_stubs.h",
}
yield
# CORE.reset() (the suite-wide autouse fixture) does not clear this flag
@@ -245,11 +240,19 @@ def test_write_project_rejects_bad_flash_mode(tmp_path: Path) -> None:
"""A flash mode outside the closed set fails by name before landing
unquoted in the elf2bin command."""
paths = _make_framework(tmp_path)
CORE.data[KEY_ESP8266][KEY_FLASH_MODE] = "dout; rm -rf /"
CORE.platformio_options["board_build.flash_mode"] = "dout; rm -rf /"
with pytest.raises(EsphomeError, match="Invalid flash mode"):
_write_ninja(paths)
def test_write_project_trailing_include_raises(tmp_path: Path) -> None:
"""A dangling -include must fail by name, not become -include <src_dir>."""
paths = _make_framework(tmp_path)
CORE.platformio_options["build_src_flags"] = "-include"
with pytest.raises(EsphomeError, match="trailing '-include'"):
_write_ninja(paths)
def test_write_project_passes_other_src_flags_through(tmp_path: Path) -> None:
"""Non-include build_src_flags tokens are requoted onto the src edges."""
paths = _make_framework(tmp_path)