mirror of
https://github.com/esphome/esphome.git
synced 2026-09-11 15:27:33 +00:00
Merge branch 'esp32-idf-pch' into platformio-pch-rp2
This commit is contained in:
@@ -36,6 +36,7 @@ from esphome.build_helpers.ninja import (
|
||||
from esphome.build_helpers.pch import (
|
||||
PCH_CORE_HEADER,
|
||||
PCH_HEADER_NAME,
|
||||
mark_pch_emitted,
|
||||
pch_checksum,
|
||||
pch_enabled,
|
||||
pch_header_text,
|
||||
@@ -1284,6 +1285,7 @@ def write_project(paths: InstalledPaths, ccache: str | None) -> bool:
|
||||
]
|
||||
lines.append(f"srccxxflags = {' '.join(cxx_parts)}")
|
||||
src_cxx_override = ("$srccxxflags", gch)
|
||||
mark_pch_emitted()
|
||||
src_objs = _ninja_compile_edges(
|
||||
lines,
|
||||
_collect_sources(src_dir),
|
||||
|
||||
@@ -8,6 +8,7 @@ from esphome.build_helpers import pch
|
||||
from esphome.build_helpers.pch import (
|
||||
PCH_DEFAULT_HEADERS,
|
||||
PCH_HEADER_NAME,
|
||||
mark_pch_emitted,
|
||||
pch_enabled,
|
||||
pch_header_text,
|
||||
)
|
||||
@@ -371,6 +372,8 @@ def write_project(
|
||||
CORE.relative_build_path("build", PCH_HEADER_NAME),
|
||||
pch_header_text(PCH_DEFAULT_HEADERS),
|
||||
)
|
||||
# Consumers carry the -include; gate the ccache relaxation on it
|
||||
mark_pch_emitted()
|
||||
|
||||
# Snapshot the exclusion set so has_outdated_files() can trigger a
|
||||
# discovery reconfigure when it changes. Excluded components never
|
||||
|
||||
@@ -8,6 +8,7 @@ it too; Arduino.h visibility there is intended (esphome#8693).
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterable
|
||||
from dataclasses import dataclass
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
@@ -25,6 +26,27 @@ from esphome.build_helpers.idedata import (
|
||||
split_command,
|
||||
)
|
||||
|
||||
_DOMAIN = "pch"
|
||||
|
||||
|
||||
@dataclass
|
||||
class _PCHData:
|
||||
emitted: bool = False
|
||||
|
||||
|
||||
def _pch_data() -> _PCHData:
|
||||
from esphome.core import CORE
|
||||
|
||||
if _DOMAIN not in CORE.data:
|
||||
CORE.data[_DOMAIN] = _PCHData()
|
||||
return CORE.data[_DOMAIN]
|
||||
|
||||
|
||||
def mark_pch_emitted() -> None:
|
||||
"""Record that this build's consumers reference the pch."""
|
||||
_pch_data().emitted = True
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
# The header and its .gch/.sum sidecars live in the build directory.
|
||||
@@ -81,9 +103,10 @@ def pch_enabled() -> bool:
|
||||
|
||||
def ccache_pch_env() -> dict[str, str]:
|
||||
"""Settings ccache needs to cache compiles that consume the .gch;
|
||||
empty when the pch is disabled. User-set values win. Native backends
|
||||
export these process-wide; only time_macros affects non-pch TUs."""
|
||||
if not pch_enabled():
|
||||
empty unless this build actually emitted one. User-set values win.
|
||||
Native backends export these process-wide; only time_macros affects
|
||||
non-pch TUs."""
|
||||
if not (pch_enabled() and _pch_data().emitted):
|
||||
return {}
|
||||
env = {k: v for k, v in _CCACHE_PCH_ENV.items() if k not in os.environ}
|
||||
user_sloppiness = os.environ.get("CCACHE_SLOPPINESS")
|
||||
|
||||
@@ -386,6 +386,10 @@ def test_write_project_pch(tmp_path: Path) -> None:
|
||||
'#include "esphome/core/defines.h"',
|
||||
]
|
||||
assert (build_dir / "esphome_pch.h.gch.sum").read_text().strip()
|
||||
# Emission recorded so the framework env exports the ccache settings
|
||||
from esphome.build_helpers.pch import ccache_pch_env
|
||||
|
||||
assert "CCACHE_PCH_EXTSUM" in ccache_pch_env()
|
||||
|
||||
|
||||
def test_write_project_pch_sum_only_with_ccache(tmp_path: Path) -> None:
|
||||
@@ -456,6 +460,10 @@ def test_write_project_pch_skipped_when_user_force_include_precedes(
|
||||
assert "esphome_pch" not in content
|
||||
assert "srccxxflags" not in content
|
||||
assert "prevents the precompiled header" in caplog.text
|
||||
# No pch emitted: the ccache relaxation must stay off
|
||||
from esphome.build_helpers.pch import ccache_pch_env
|
||||
|
||||
assert ccache_pch_env() == {}
|
||||
|
||||
|
||||
def test_write_project_pch_disabled(
|
||||
|
||||
@@ -33,7 +33,14 @@ def test_pch_enabled(value: str | None, expected: bool) -> None:
|
||||
assert pch.pch_enabled() is expected
|
||||
|
||||
|
||||
def test_ccache_pch_env_empty_until_emitted() -> None:
|
||||
"""No sloppiness relaxation for a build that skipped the pch."""
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
assert pch.ccache_pch_env() == {}
|
||||
|
||||
|
||||
def test_ccache_pch_env_enabled() -> None:
|
||||
pch.mark_pch_emitted()
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
env = pch.ccache_pch_env()
|
||||
assert env["CCACHE_SLOPPINESS"] == "pch_defines,time_macros"
|
||||
@@ -48,6 +55,7 @@ def test_ccache_pch_env_disabled() -> None:
|
||||
def test_ccache_pch_env_token_check_is_membership_not_substring(
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
pch.mark_pch_emitted()
|
||||
"""A token merely containing ours must not suppress the union."""
|
||||
with patch.dict(os.environ, {"CCACHE_SLOPPINESS": "pch_defines_extra"}, clear=True):
|
||||
env = pch.ccache_pch_env()
|
||||
@@ -57,6 +65,7 @@ def test_ccache_pch_env_token_check_is_membership_not_substring(
|
||||
def test_ccache_pch_env_unions_user_sloppiness(
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
pch.mark_pch_emitted()
|
||||
"""Without pch_defines/time_macros ccache declines every pch-consuming
|
||||
compile, so missing tokens are unioned onto the user's value."""
|
||||
with patch.dict(os.environ, {"CCACHE_SLOPPINESS": "locale"}, clear=True):
|
||||
|
||||
@@ -9,6 +9,7 @@ from unittest.mock import MagicMock, patch
|
||||
import pytest
|
||||
|
||||
from esphome.arduino8266 import framework, toolchain
|
||||
from esphome.build_helpers.pch import mark_pch_emitted
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_COMPILE_PROCESS_LIMIT,
|
||||
@@ -632,6 +633,7 @@ def test_get_idedata_accepts_preresolved_ccache() -> None:
|
||||
|
||||
|
||||
def test_ccache_env_includes_pch_settings() -> None:
|
||||
mark_pch_emitted()
|
||||
"""The native build exports the ccache settings the pch needs."""
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
env = framework.ccache_env("/usr/bin/ccache")
|
||||
@@ -647,6 +649,7 @@ def test_ccache_env_pch_disabled() -> None:
|
||||
|
||||
|
||||
def test_ccache_env_respects_user_sloppiness() -> None:
|
||||
mark_pch_emitted()
|
||||
with patch.dict(os.environ, {"CCACHE_SLOPPINESS": "locale"}, clear=True):
|
||||
env = framework.ccache_env("/usr/bin/ccache")
|
||||
# The user's tokens survive; the ones the pch needs are unioned on
|
||||
|
||||
@@ -19,6 +19,7 @@ from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome.build_helpers.pch import _PCHData
|
||||
from esphome.espidf.framework import (
|
||||
ESPHOME_STAMP_FILE,
|
||||
STAMP_SCHEMA_VERSION,
|
||||
@@ -1565,10 +1566,14 @@ def _ccache_patches(tmp_path: Path, which: str | None, build_path: Path | None):
|
||||
"esphome.espidf.framework.get_idf_tools_path",
|
||||
return_value=tmp_path / "tools",
|
||||
),
|
||||
# ccache_defaults_env (build_helpers.ccache) reads CORE at call time
|
||||
# ccache_defaults_env and the pch emission flag read CORE at call time
|
||||
patch(
|
||||
"esphome.core.CORE",
|
||||
SimpleNamespace(build_path=build_path),
|
||||
SimpleNamespace(
|
||||
build_path=build_path,
|
||||
# Pre-marked: these env tests model a pch-emitting build
|
||||
data={"pch": _PCHData(emitted=True)},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user