diff --git a/esphome/build_gen/arduino8266.py b/esphome/build_gen/arduino8266.py index 731f52c2a5..86e4f70ad5 100644 --- a/esphome/build_gen/arduino8266.py +++ b/esphome/build_gen/arduino8266.py @@ -260,7 +260,7 @@ def _flag_defines(unflags: set[str], tokens: list[str]) -> dict[str, str]: """Map define name -> full ``NAME[=VALUE]`` for every -D build flag. ``tokens`` comes from one ``_lexed_build_flags()`` call shared with - ``_project_flags``, which already raised on any bare "-D". + ``_project_flags``, which already warned about and dropped any bare "-D". """ defines: dict[str, str] = {} for tok in tokens: @@ -486,7 +486,7 @@ def _project_flags( for tok in tokens: if tok in unflags: continue - # _lexed_build_flags raised on any bare -I/-D/-L/-l + # _lexed_build_flags warned about and dropped any bare -I/-D/-L/-l if tok.startswith("-Wl,"): link_flags.append(_shell_token(tok)) elif tok.startswith("-L"): @@ -505,6 +505,15 @@ def _project_flags( f"Linker flag {tok} in build_flags is not routed to the " "link line; use the -Wl, form" ) + if tok.startswith("-") and not tok.startswith(_COMPILE_FLAG_PREFIXES): + # The linker deny lists are not exhaustive; an unlisted + # link-only spelling would be inert on the -c compile line, + # so at least surface the odd shape + _LOGGER.warning( + "Build flag %s is not a recognized compile-flag shape; " + "it is passed to the compile line only", + tok, + ) compile_flags.append(_shell_token(tok)) return compile_flags, link_flags, lib_dirs, libs @@ -512,7 +521,19 @@ def _project_flags( # Plain-form linker flags rejected by _project_flags: inert on a -c compile # line, so the firmware would silently lack the requested link behavior # Best-effort, not exhaustive: an unlisted link-only spelling still falls -# through to the compile line +# through to the compile line, with a warning from the shape check +_COMPILE_FLAG_PREFIXES = ( + "-D", + "-I", + "-U", + "-W", + "-f", + "-m", + "-O", + "-g", + "-std=", + "-include", +) _PLAIN_LINKER_FLAGS = ( "-u", "-e", diff --git a/tests/unit_tests/build_gen/test_arduino8266.py b/tests/unit_tests/build_gen/test_arduino8266.py index c98360a2a2..361032dc4c 100644 --- a/tests/unit_tests/build_gen/test_arduino8266.py +++ b/tests/unit_tests/build_gen/test_arduino8266.py @@ -246,6 +246,29 @@ def test_lwip_low_memory_loses_to_listed_knobs() -> None: assert config.lwip_lib == "lwip2-1460" +def test_lwip_ipv6_wins_over_default_knob() -> None: + """The shipping IPv6 config: network emits IPV6_LOW_MEMORY, esp8266 + always emits HIGHER_BANDWIDTH_LOW_FLASH; IPv6 must win exactly as in + platformio-build.py's elif chain.""" + config = _resolve( + "-DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY", + "-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH", + ) + assert config.lwip_lib == "lwip6-536-feat" + assert "LWIP_IPV6=1" in config.knob_defines + + +def test_unrecognized_compile_flag_shape_warns( + caplog: pytest.LogCaptureFixture, +) -> None: + """A link-only spelling missing from the deny lists still reaches the + compile line, but no longer silently.""" + _set_flags("-shared") + compile_flags, _link_flags, _lib_dirs, _libs = _split_flags() + assert "-shared is not a recognized compile-flag shape" in caplog.text + assert "-shared" in compile_flags + + @pytest.mark.parametrize( ("knob", "expected"), [