Check the elf2bin inputs at generation, quote cxx flags, add d1_wroom_02 to BOARDS

elf2bin.py and eboot.elf join the existence checks so a half-extracted
package fails by name before the compile instead of at the
second-to-last edge. get_project_cxx_compile_flags() values go through
_shell_token like every other flag source. d1_wroom_02 (2 MB, in
ESP8266_BOARD_BUILD and buildable under PlatformIO) joins BOARDS so the
native board guard stops rejecting it, and the guard comment states
what config validation actually checks.
This commit is contained in:
J. Nick Koston
2026-08-21 12:57:36 -05:00
parent 523150a4c9
commit debfff005b
3 changed files with 38 additions and 3 deletions
+13 -3
View File
@@ -551,8 +551,8 @@ def write_project(paths: InstalledPaths) -> bool:
config = _resolve_build_config(flag_defines)
esp8266_data = CORE.data[KEY_ESP8266]
board = esp8266_data[KEY_BOARD]
# Config-time validation rejects unsupported boards before this runs;
# guard anyway so a bypassing caller fails by name, not KeyError
# Config validation accepts the board as a bare string, so this is the
# first place an unknown board can fail by name instead of a KeyError
if board not in BOARDS or board not in ESP8266_BOARD_BUILD:
raise EsphomeError(f"Board '{board}' is not supported by the native toolchain")
board_build = ESP8266_BOARD_BUILD[board]
@@ -590,6 +590,16 @@ def write_project(paths: InstalledPaths) -> bool:
raise EsphomeError(
f"{_INCOMPLETE_INSTALL}: missing {required}; {_CLEAN_HINT}"
)
# The elf2bin edge runs after the full compile and link; a
# half-extracted package must fail here, not an hour of wall-clock later
for required_file in (
framework / "tools" / "elf2bin.py",
framework / "bootloaders" / "eboot" / "eboot.elf",
):
if not required_file.is_file():
raise EsphomeError(
f"{_INCOMPLETE_INSTALL}: missing {required_file}; {_CLEAN_HINT}"
)
for lib in libraries:
include_dirs += lib.include_dirs
@@ -611,7 +621,7 @@ def write_project(paths: InstalledPaths) -> bool:
["-fno-rtti", f"-std={cpp_standard}"]
+ ["-fexceptions" if config.exceptions else "-fno-exceptions"]
+ common
+ get_project_cxx_compile_flags()
+ [_shell_token(f) for f in get_project_cxx_compile_flags()]
)
# PlatformIO's ASPPCOM carries defines and includes but not CCFLAGS,
# so only -D/-I user flags reach assembly there; match it. The tokens
+4
View File
@@ -199,6 +199,10 @@ BOARDS = {
"name": "WeMos D1 mini Pro",
"flash_size": FLASH_SIZE_16_MB,
},
"d1_wroom_02": {
"name": "WeMos D1 ESP-WROOM-02",
"flash_size": FLASH_SIZE_2_MB,
},
"d1": {
"name": "WEMOS D1 R1",
"flash_size": FLASH_SIZE_4_MB,
@@ -185,6 +185,10 @@ def _make_framework(tmp_path: Path) -> InstalledPaths:
for sub in ("include", "ld", "lwip2/include", "lib"):
(framework / "tools" / "sdk" / sub).mkdir(parents=True)
(framework / "libraries").mkdir()
(framework / "tools" / "elf2bin.py").write_text("")
eboot = framework / "bootloaders" / "eboot"
eboot.mkdir(parents=True)
(eboot / "eboot.elf").write_text("")
toolchain = tmp_path / "toolchain"
(toolchain / "bin").mkdir(parents=True)
(toolchain / "include").mkdir()
@@ -722,6 +726,23 @@ def test_write_project_returns_changed(tmp_path: Path) -> None:
assert arduino8266.write_project(paths) is False
def test_write_project_missing_elf2bin_raises(tmp_path: Path) -> None:
"""A half-extracted package must fail by name at generation, not after
the full compile at the elf2bin edge."""
paths = _make_framework(tmp_path)
(paths.framework / "tools" / "elf2bin.py").unlink()
_set_flags()
src = CORE.relative_src_path()
(src / "main.cpp").parent.mkdir(parents=True, exist_ok=True)
(src / "main.cpp").write_text("")
with (
patch.object(arduino8266, "generate_ld_scripts"),
patch("esphome.arduino.library.resolve_libraries", return_value=[]),
pytest.raises(EsphomeError, match="elf2bin"),
):
arduino8266.write_project(paths)
def test_write_project_missing_src_dir_raises(tmp_path: Path) -> None:
"""A missing generated source tree is its own error, not an install one."""
paths = _make_framework(tmp_path)