From a69f2c8f66c662e4cf494f935690e81847e9ea52 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 26 Aug 2026 09:57:44 -0500 Subject: [PATCH] Fold the joined src force-include spelling, export ccache settings after the flags land --- esphome/build_gen/arduino8266.py | 4 ++++ esphome/platformio/pch.py.script | 20 +++++++++---------- .../unit_tests/build_gen/test_arduino8266.py | 14 +++++++++++++ 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/esphome/build_gen/arduino8266.py b/esphome/build_gen/arduino8266.py index 38f488efea..ee5bfb1871 100644 --- a/esphome/build_gen/arduino8266.py +++ b/esphome/build_gen/arduino8266.py @@ -1210,6 +1210,10 @@ def write_project(paths: InstalledPaths, ccache: str | None) -> bool: "build_src_flags has a trailing '-include' with no header" ) src_includes.append(header) + elif tok.startswith("-include"): + # Joined spelling; left in src_other it would precede the pch + # include and silently defeat the .gch + src_includes.append(tok[len("-include") :]) else: src_other.append(_shell_token(tok)) include_flags = [f"-include {_q(src_dir / h)}" for h in src_includes] diff --git a/esphome/platformio/pch.py.script b/esphome/platformio/pch.py.script index d8f2980747..b631897e29 100644 --- a/esphome/platformio/pch.py.script +++ b/esphome/platformio/pch.py.script @@ -279,8 +279,16 @@ def _setup_pch() -> None: failed_marker.unlink(missing_ok=True) sum_path.write_text(checksum + "\n", encoding="utf-8") - # projenv["ENV"] aliases os.environ, so these reach all TUs; only - # time_macros affects non-pch TUs. User-set values win. + # Prepended: GCC only uses a .gch while no other tokens precede it. + # The relative name also reaches "pio run -t idedata" output. + # -Wno-error: the per-process probe can pass while a later cc1plus + # rejects the .gch; that must stay a warning under user -Werror. + projenv.Prepend( # noqa: F821 + CXXFLAGS=["-Winvalid-pch", "-Wno-error=invalid-pch", "-include", header.name] + ) + # Exported last so a raise above cannot leave the relaxed settings with + # no pch in the build. projenv["ENV"] aliases os.environ, so these + # reach all TUs; only time_macros affects non-pch TUs. User values win. for key, value in ( ("CCACHE_SLOPPINESS", "pch_defines,time_macros"), ("CCACHE_PCH_EXTSUM", "true"), @@ -295,14 +303,6 @@ def _setup_pch() -> None: # Without these ccache declines every pch-consuming compile projenv["ENV"]["CCACHE_SLOPPINESS"] = ",".join((sloppiness, *missing)) # noqa: F821 print(f"ESPHome: adding {','.join(missing)} to CCACHE_SLOPPINESS for the pch") - - # Prepended: GCC only uses a .gch while no other tokens precede it. - # The relative name also reaches "pio run -t idedata" output. - # -Wno-error: the per-process probe can pass while a later cc1plus - # rejects the .gch; that must stay a warning under user -Werror. - projenv.Prepend( # noqa: F821 - CXXFLAGS=["-Winvalid-pch", "-Wno-error=invalid-pch", "-include", header.name] - ) print("ESPHome: Compiling with precompiled header") diff --git a/tests/unit_tests/build_gen/test_arduino8266.py b/tests/unit_tests/build_gen/test_arduino8266.py index 7c822195e4..4009e91f01 100644 --- a/tests/unit_tests/build_gen/test_arduino8266.py +++ b/tests/unit_tests/build_gen/test_arduino8266.py @@ -416,6 +416,20 @@ def test_write_project_pch_identity_unknown_skips_pch( assert "Could not establish the pch identity" in caplog.text +def test_write_project_pch_folds_joined_src_force_include( + tmp_path: Path, +) -> None: + """-includefoo.h in build_src_flags must fold into the pch like the + separated spelling, not precede and defeat it.""" + paths = _make_framework(tmp_path) + _set_flags("-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH") + CORE.platformio_options["build_src_flags"] = "-includeesphome/core/defines.h" + content = _write_ninja(paths, ccache="/usr/bin/ccache") + assert "build esphome_pch.h.gch: pch" in content + assert "srccxxflags" in content + assert "-includeesphome" not in content + + def test_write_project_pch_skipped_for_joined_force_include_spelling( tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: