diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 16e2e0b040..bfa887f485 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -204,7 +204,7 @@ jobs: - host # Strict by default so a new matrix id cannot silently join in the # degrade-quietly mode the knob exists to catch; the knob is inert - # where no pch code runs (esp32-*-platformio, nrf52). + # where no pch code runs (nrf52). # Opt-outs: libretiny GCC rejects its own pch until a toolchain bump. include: - id: bk72xx-arduino diff --git a/esphome/build_helpers/pch.py b/esphome/build_helpers/pch.py index 4c6e3783ed..e1dfa6dc02 100644 --- a/esphome/build_helpers/pch.py +++ b/esphome/build_helpers/pch.py @@ -64,6 +64,10 @@ PCH_ARTIFACT_NAMES = ( # The core defines header every backend anchors its prefix on. PCH_CORE_HEADER = "esphome/core/defines.h" +# Guarded curated-prefix wrapper for PlatformIO backends without framework +# force-includes (host, esp32); folded by the pch script via build_src_flags. +PCH_PREFIX_HEADER = "esphome/core/pch_prefix.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 diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index bc91f29a42..906562cf30 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -10,6 +10,7 @@ import subprocess from typing import Any from esphome import yaml_util +from esphome.build_helpers.pch import PCH_PREFIX_HEADER, pch_enabled, pch_extra_scripts import esphome.codegen as cg from esphome.components.const import CONF_ENABLE_OTA_DOWNGRADE_PROTECTION from esphome.config_helpers import filter_source_files_from_defines @@ -57,6 +58,7 @@ from esphome.coroutine import CoroPriority, coroutine_with_priority from esphome.espidf.component import generate_idf_components import esphome.final_validate as fv from esphome.helpers import copy_file_if_changed, rmtree, write_file_if_changed +from esphome.platformio.toolchain import copy_pch_script from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor from esphome.types import ConfigType from esphome.writer import clean_build, clean_cmake_cache @@ -2433,6 +2435,11 @@ async def to_code(config): cg.add_platformio_option("lib_ldf_mode", "off") cg.add_platformio_option("lib_compat_mode", "strict") + # CI-speed only: this toolchain is being dropped, so the pch gets + # the same curated prefix as host with no further investment + cg.add_platformio_option("extra_scripts", pch_extra_scripts()) + if pch_enabled(): + cg.add_platformio_option("build_src_flags", f"-include {PCH_PREFIX_HEADER}") cg.add_platformio_option("platform", conf[CONF_PLATFORM_VERSION]) cg.add_platformio_option("board", config[CONF_BOARD]) cg.add_platformio_option("board_upload.flash_size", config[CONF_FLASH_SIZE]) @@ -3350,6 +3357,8 @@ def _write_idf_component_yml(): def copy_files(): _write_sdkconfig() _write_idf_component_yml() + if not CORE.using_toolchain_esp_idf: + copy_pch_script() if "partitions.csv" not in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES]: flash_size = CORE.data[KEY_ESP32][KEY_FLASH_SIZE] diff --git a/esphome/components/host/__init__.py b/esphome/components/host/__init__.py index 4a8fdb98cc..d565201390 100644 --- a/esphome/components/host/__init__.py +++ b/esphome/components/host/__init__.py @@ -1,4 +1,4 @@ -from esphome.build_helpers.pch import pch_enabled, pch_extra_scripts +from esphome.build_helpers.pch import PCH_PREFIX_HEADER, pch_enabled, pch_extra_scripts import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import ( @@ -19,9 +19,6 @@ from .const import KEY_HOST # force import gpio to register pin schema from .gpio import host_pin_to_code # noqa: F401 -# Guarded wrapper: build_src_flags reaches C/assembly edges too -HOST_PCH_PREFIX = "esphome/core/pch_prefix.h" - CODEOWNERS = ["@esphome/core", "@clydebarrow"] AUTO_LOAD = ["network", "preferences"] IS_TARGET_PLATFORM = True @@ -67,7 +64,7 @@ async def to_code(config: ConfigType) -> None: # Gated so ESPHOME_PCH_ENABLE=0 restores the strict view. When the # .gch fails to build or load, the force-include stays and every TU # parses the closure as text: correct, but slower than no pch. - cg.add_platformio_option("build_src_flags", f"-include {HOST_PCH_PREFIX}") + cg.add_platformio_option("build_src_flags", f"-include {PCH_PREFIX_HEADER}") # Called by writer.py diff --git a/tests/unit_tests/test_host_pch_prefix.py b/tests/unit_tests/test_host_pch_prefix.py index ff42ce55a8..c516558b87 100644 --- a/tests/unit_tests/test_host_pch_prefix.py +++ b/tests/unit_tests/test_host_pch_prefix.py @@ -1,16 +1,16 @@ -"""The host pch prefix must keep resolving; a rename would silently +"""The pch prefix must keep resolving; a rename would silently collapse the precompiled set to defines.h with strict CI still green.""" from pathlib import Path import re -from esphome.components.host import HOST_PCH_PREFIX +from esphome.build_helpers.pch import PCH_PREFIX_HEADER REPO = Path(__file__).parents[2] def test_host_pch_prefix_resolves() -> None: - prefix = REPO / HOST_PCH_PREFIX + prefix = REPO / PCH_PREFIX_HEADER assert prefix.is_file() body = prefix.read_text() includes = re.findall(r'#include "([^"]+)"', body)