diff --git a/esphome/build_gen/arduino8266.py b/esphome/build_gen/arduino8266.py index d8ebf92a53..d93c1b7943 100644 --- a/esphome/build_gen/arduino8266.py +++ b/esphome/build_gen/arduino8266.py @@ -28,6 +28,7 @@ from typing import TYPE_CHECKING, NamedTuple from esphome.arduino8266.framework import toolchain_tool from esphome.build_helpers.ccache import effective_ccache_basedir +from esphome.build_helpers.idedata import is_joined_include from esphome.build_helpers.ninja import ( escape as _e, quote_path as _q, @@ -1211,9 +1212,9 @@ 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") and not tok.startswith("-include-"): - # Joined spelling; left in src_other it would precede the pch - # include and silently defeat the .gch + elif is_joined_include(tok): + # 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)) diff --git a/esphome/build_helpers/idedata.py b/esphome/build_helpers/idedata.py index 4f6b7f36fc..930fe983a6 100644 --- a/esphome/build_helpers/idedata.py +++ b/esphome/build_helpers/idedata.py @@ -161,6 +161,15 @@ def is_launcher(token: str) -> bool: return Path(token).stem.lower() in _LAUNCHER_STEMS +def is_joined_include(tok: str) -> bool: + """The joined ``-includefoo.h`` spelling; excludes clang's -include-pch.""" + return ( + tok.startswith("-include") + and tok != "-include" + and not tok.startswith("-include-") + ) + + def parse_entry( entry: dict, launcher: str | None = None ) -> tuple[str, list[str], list[str], list[str]]: @@ -201,9 +210,7 @@ def parse_entry( for tok in it: if tok in ("-c", "-o"): next(it, None) # drop the flag and its argument (input/output) - elif tok == "-include" or ( - tok.startswith("-include") and not tok.startswith("-include-") - ): + elif tok == "-include" or is_joined_include(tok): # Re-anchor only names next to the compile (the pch); a name # meant for the -I chain must stay untouched raw = next(it, "") if tok == "-include" else tok[len("-include") :] diff --git a/tests/unit_tests/build_helpers/test_pch.py b/tests/unit_tests/build_helpers/test_pch.py index 0fc2378288..010c93bb66 100644 --- a/tests/unit_tests/build_helpers/test_pch.py +++ b/tests/unit_tests/build_helpers/test_pch.py @@ -205,3 +205,14 @@ def test_include_closure_walks_angle_includes_under_src(tmp_path: Path) -> None: (tmp_path / "local.h").write_text("") closure = pch._include_closure(tmp_path, ["a.h"]) assert set(closure) == {"a.h", "local.h"} + + +def test_ccache_pch_env_warns_on_falsy_extsum( + caplog: pytest.LogCaptureFixture, +) -> None: + """A user CCACHE_PCH_EXTSUM=false makes ccache hash the .gch bytes.""" + pch.mark_pch_emitted() + with patch.dict(os.environ, {"CCACHE_PCH_EXTSUM": "false"}, clear=True): + env = pch.ccache_pch_env() + assert "CCACHE_PCH_EXTSUM" not in env + assert "disables pch caching" in caplog.text