From 0d794ce6782c94ce215d6c49cce9d51ff9ff37a1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 20 Aug 2026 16:10:02 -0500 Subject: [PATCH] Lex every build flag entry, warn on custom MMU sizes without the knob, note the scanf omission --- esphome/build_gen/arduino8266.py | 23 ++++++++++++------- .../unit_tests/build_gen/test_arduino8266.py | 17 ++++++++++++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/esphome/build_gen/arduino8266.py b/esphome/build_gen/arduino8266.py index f26869b6cc..e6390e7cab 100644 --- a/esphome/build_gen/arduino8266.py +++ b/esphome/build_gen/arduino8266.py @@ -112,6 +112,8 @@ _CCFLAGS = [ "-free", "-fipa-pta", ] +# Upstream's -u _scanf_float is deliberately absent: it is re-added from +# KEY_SCANF_FLOAT at emission (the remove_float_scanf extra script's job). _LINKFLAGS = [ "-Os", "-nostdlib", @@ -166,14 +168,10 @@ def _flag_defines() -> dict[str, str]: """Map define name -> full ``NAME[=VALUE]`` for every -D build flag.""" defines: dict[str, str] = {} for flag in CORE.build_flags: - # Shell-lex multi-token entries the way PlatformIO does, so a knob - # in "-DKNOB -DOTHER" or a spaced "-D KNOB" is still detected; - # single tokens pass verbatim to keep quoting in their bodies intact. - tokens = ( - join_flag_args(split_flag_entry(flag, "esphome"), "esphome") - if " " in flag - else (flag,) - ) + # Shell-lex every entry the way PlatformIO's ParseFlags does, so a + # knob in "-DKNOB -DOTHER", a spaced "-D KNOB", and quoted bodies all + # read identically to _project_flags (and the compile line). + tokens = join_flag_args(split_flag_entry(flag, "esphome"), "esphome") for tok in tokens: if tok.startswith("-D") and len(tok) > 2: body = tok[2:] @@ -225,6 +223,15 @@ def _resolve_build_config(defines: dict[str, str]) -> _BuildConfig: body for name, body in defines.items() if name.startswith("MMU_") ) else: + if "MMU_IRAM_SIZE" in defines or "MMU_ICACHE_SIZE" in defines: + # Same diagnostic the PlatformIO builder prints: without the + # knob the linker script keeps the default layout while the + # compile line carries the custom sizes + _LOGGER.warning( + "Detected custom MMU flags; use " + "-DPIO_FRAMEWORK_ARDUINO_MMU_CUSTOM to disable the " + "default configuration" + ) mmu = list(_MMU_DEFAULT) return _BuildConfig( diff --git a/tests/unit_tests/build_gen/test_arduino8266.py b/tests/unit_tests/build_gen/test_arduino8266.py index d11eafa206..3baa54fa7d 100644 --- a/tests/unit_tests/build_gen/test_arduino8266.py +++ b/tests/unit_tests/build_gen/test_arduino8266.py @@ -422,3 +422,20 @@ def test_flag_defines_joins_spaced_define() -> None: defines = _flag_defines() assert "PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH" in defines assert "" not in defines + + +def test_build_config_custom_mmu_without_knob_warns( + caplog: pytest.LogCaptureFixture, +) -> None: + """Custom MMU sizes without the CUSTOM knob keep the default layout and + warn, as the PlatformIO builder does.""" + _set_flags("-DMMU_IRAM_SIZE=0xC000") + config = _resolve_build_config(_flag_defines()) + assert config.mmu_defines == ["MMU_IRAM_SIZE=0x8000", "MMU_ICACHE_SIZE=0x8000"] + assert "Detected custom MMU flags" in caplog.text + + +def test_flag_defines_lexes_quoted_single_tokens() -> None: + """A quoted single-token define reads the same as on the compile line.""" + _set_flags('-DMMU_SEC_HEAP="0x40108000"') + assert _flag_defines()["MMU_SEC_HEAP"] == "MMU_SEC_HEAP=0x40108000"