Merge branch 'platformio-pch-rp2' into platformio-pch-libretiny

This commit is contained in:
J. Nick Koston
2026-08-25 18:05:34 -05:00
3 changed files with 31 additions and 31 deletions
+4 -23
View File
@@ -6,7 +6,7 @@ from pathlib import Path
from esphome.build_helpers import pch
from esphome.build_helpers.pch import (
PCH_CORE_HEADER,
PCH_DEFAULT_HEADERS,
PCH_HEADER_NAME,
pch_enabled,
pch_header_text,
@@ -29,26 +29,6 @@ from esphome.helpers import mkdir_p, write_file_if_changed
_LOGGER = logging.getLogger(__name__)
# Prefix-header contents, defines.h first so USE_* macros exist for the
# rest. Deliberately hard-coded: frequency-derived sets measured no better
# and kept selecting headers that cannot compile standalone (X-macro,
# platform-variant). Every entry must be safe to include first in an
# empty TU. Caveat: application.h/automation.h become ambiently visible,
# so a TU missing those #includes still builds here but not on other
# platforms; ESPHOME_PCH_ENABLE=0 restores the strict view.
_PCH_HEADERS = (
PCH_CORE_HEADER,
"esphome/core/component.h",
"esphome/core/helpers.h",
"esphome/core/log.h",
"esphome/core/application.h",
"esphome/core/automation.h",
)
# Header and .gch/.sum sidecars, relative to the device dir; see
# _pch_cmake() and prepare_pch() for the layout rationale
_PCH_BUILD_HEADER = f"build/{PCH_HEADER_NAME}"
# Replaces the IDF default C++ standard (-std=gnu++2b appended to
# CXX_COMPILE_OPTIONS by project.cmake's __build_init) with the one set via
# cg.set_cpp_standard(). Emitted between include(project.cmake) and project(),
@@ -355,7 +335,7 @@ def prepare_pch() -> None:
sdkconfig = f"unreadable:{type(err).__name__}:{err.errno}"
pch.prepare_pch(
CORE.relative_build_path("build"),
_PCH_HEADERS,
PCH_DEFAULT_HEADERS,
(
str(idf_version()),
CORE.cpp_standard or "",
@@ -387,7 +367,8 @@ def write_project(
if pch_enabled():
write_file_if_changed(
CORE.relative_build_path(_PCH_BUILD_HEADER), pch_header_text(_PCH_HEADERS)
CORE.relative_build_path("build", PCH_HEADER_NAME),
pch_header_text(PCH_DEFAULT_HEADERS),
)
# Snapshot the exclusion set so has_outdated_files() can trigger a
+17
View File
@@ -43,6 +43,23 @@ PCH_ARTIFACT_NAMES = (
# The core defines header every backend anchors its prefix on.
PCH_CORE_HEADER = "esphome/core/defines.h"
# Prefix-header contents for backends that inject a curated set (rather
# than mirroring the TUs' own force-includes), defines.h first so USE_*
# macros exist for the rest. Deliberately hard-coded: frequency-derived
# sets measured no better and kept selecting headers that cannot compile
# standalone (X-macro, platform-variant). Every entry must be safe to
# include first in an empty TU. Caveat: application.h/automation.h become
# ambiently visible, so a TU missing those #includes still builds on such
# backends; ESPHOME_PCH_ENABLE=0 restores the strict view.
PCH_DEFAULT_HEADERS = (
PCH_CORE_HEADER,
"esphome/core/component.h",
"esphome/core/helpers.h",
"esphome/core/log.h",
"esphome/core/application.h",
"esphome/core/automation.h",
)
# ccache cannot hash through a .gch; CCACHE_PCH_EXTSUM makes it hash the
# .sum sidecar instead of the .gch bytes, which are not reproducible.
# Keep in sync with the literals in platformio/pch.py.script.
+10 -8
View File
@@ -494,10 +494,10 @@ def test_get_component_cmakelists_no_compile_features() -> None:
def _make_pch_device(tmp_path: Path, name: str) -> Path:
"""A device dir with the pch source headers and a stub compile_commands."""
from esphome.build_gen.espidf import _PCH_HEADERS
from esphome.build_helpers.pch import PCH_DEFAULT_HEADERS
dev = tmp_path / name
for header in _PCH_HEADERS:
for header in PCH_DEFAULT_HEADERS:
path = dev / "src" / header
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("")
@@ -512,7 +512,7 @@ def _make_pch_device(tmp_path: Path, name: str) -> Path:
build.mkdir(exist_ok=True)
from esphome.build_helpers.pch import pch_header_text
(build / "esphome_pch.h").write_text(pch_header_text(_PCH_HEADERS))
(build / "esphome_pch.h").write_text(pch_header_text(PCH_DEFAULT_HEADERS))
# Native separators: mixed f-string paths break the src-prefix match
# on Windows
src_file = str(dev / "src" / "a.cpp")
@@ -674,7 +674,7 @@ def test_pch_compile_command_rejects_unusable_entries(tmp_path: Path) -> None:
def test_pch_header_list_order_is_in_checksum(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
"""Reordering _PCH_HEADERS keeps the include closure identical, but the
"""Reordering PCH_DEFAULT_HEADERS keeps the include closure identical, but the
generated header text differs, so the .gch must rebuild."""
import esphome.build_gen.espidf as espidf_mod
@@ -693,7 +693,9 @@ def test_pch_header_list_order_is_in_checksum(
espidf_mod.prepare_pch()
first = (dev / "build" / "esphome_pch.h.gch.sum").read_text()
monkeypatch.setattr(
espidf_mod, "_PCH_HEADERS", tuple(reversed(espidf_mod._PCH_HEADERS))
espidf_mod,
"PCH_DEFAULT_HEADERS",
tuple(reversed(espidf_mod.PCH_DEFAULT_HEADERS)),
)
espidf_mod.prepare_pch()
assert (dev / "build" / "esphome_pch.h.gch.sum").read_text() != first
@@ -818,8 +820,8 @@ def test_write_project_pch_disabled_writes_no_header(
def test_write_project_writes_pch_header(tmp_path: Path) -> None:
"""The header write_project emits is what _pch_cmake() force-includes;
this pairing is the one non-fail-safe path in the design."""
from esphome.build_gen.espidf import _PCH_HEADERS, write_project
from esphome.build_helpers.pch import pch_header_text
from esphome.build_gen.espidf import write_project
from esphome.build_helpers.pch import PCH_DEFAULT_HEADERS, pch_header_text
_write_project_description(tmp_path, {})
CORE.build_path = tmp_path
@@ -829,7 +831,7 @@ def test_write_project_writes_pch_header(tmp_path: Path) -> None:
):
write_project()
assert (tmp_path / "build" / "esphome_pch.h").read_text() == pch_header_text(
_PCH_HEADERS
PCH_DEFAULT_HEADERS
)