mirror of
https://github.com/esphome/esphome.git
synced 2026-09-11 15:27:33 +00:00
Merge branch 'esp8266-native-pch' into esp32-idf-pch
This commit is contained in:
@@ -24,7 +24,7 @@ PCH_CORE_HEADER = "esphome/core/defines.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 components/esp8266/pch.py.script.
|
||||
# Keep in sync with the literals in platformio/pch.py.script.
|
||||
_CCACHE_PCH_ENV = {
|
||||
"CCACHE_SLOPPINESS": "pch_defines,time_macros",
|
||||
"CCACHE_PCH_EXTSUM": "true",
|
||||
|
||||
@@ -35,7 +35,7 @@ from esphome.core import (
|
||||
)
|
||||
from esphome.core.config import BOARD_MAX_LENGTH
|
||||
from esphome.helpers import IS_MACOS, copy_file_if_changed
|
||||
from esphome.platformio.toolchain import copy_ccache_script
|
||||
from esphome.platformio.toolchain import copy_ccache_script, copy_pch_script
|
||||
from esphome.storage_json import StorageJSON
|
||||
from esphome.types import ConfigType
|
||||
|
||||
@@ -579,7 +579,6 @@ def copy_files() -> None:
|
||||
dir = Path(__file__).parent
|
||||
for script in (
|
||||
"post_build",
|
||||
"pch",
|
||||
"testing_mode",
|
||||
"exclude_updater",
|
||||
"exclude_waveform",
|
||||
@@ -591,6 +590,7 @@ def copy_files() -> None:
|
||||
CORE.relative_build_path(f"{script}.py"),
|
||||
)
|
||||
copy_ccache_script()
|
||||
copy_pch_script()
|
||||
|
||||
|
||||
# ESP logs stack trace decoder, based on https://github.com/me-no-dev/EspExceptionDecoder
|
||||
|
||||
@@ -10,12 +10,13 @@ import subprocess
|
||||
Import("env", "projenv") # noqa: F821
|
||||
|
||||
# Precompile the src force-includes plus defines.h (which pulls in
|
||||
# Arduino.h) and force-include the result into C++ src compiles only; those
|
||||
# TUs already include this content first, so their preprocessed output is
|
||||
# unchanged. Post script: the final src flags exist, nothing compiled yet.
|
||||
# Registration is gated host-side (esp8266/__init__.py, pch_enabled()).
|
||||
# Keep the header tail, ccache values, include-closure recipe, and the
|
||||
# checksum/failed-marker stamp flow in sync with build_helpers/pch.py.
|
||||
# Arduino.h on Arduino platforms) and force-include the result into C++ src
|
||||
# compiles only; those TUs already include this content first, so their
|
||||
# preprocessed output is unchanged. Post script: the final src flags exist,
|
||||
# nothing compiled yet. Registration is gated host-side (the platform's
|
||||
# __init__.py, pch_enabled()). Keep the header tail, ccache values,
|
||||
# include-closure recipe, and the checksum/failed-marker stamp flow in sync
|
||||
# with build_helpers/pch.py.
|
||||
|
||||
_INCLUDE_RE = re.compile(rb'^\s*#\s*include\s+"([^"]+)"', re.MULTILINE)
|
||||
_CORE_HEADER = "esphome/core/defines.h"
|
||||
@@ -46,7 +47,16 @@ def _include_closure(src_dir: Path, roots: list) -> dict:
|
||||
return seen
|
||||
|
||||
|
||||
def _esp8266_setup_pch() -> None:
|
||||
def _shell_arg(element) -> str:
|
||||
"""One compiler argv from one SCons element, matching the real spawn:
|
||||
SCons whole-quotes spaced elements, the shell unquotes the rest."""
|
||||
arg = str(element)
|
||||
if " " in arg:
|
||||
return arg.replace('\\"', '"')
|
||||
return shlex.split(arg)[0] if arg else arg
|
||||
|
||||
|
||||
def _setup_pch() -> None:
|
||||
# Project root, not $BUILD_DIR: SCons compiles run with the project dir
|
||||
# as cwd, so "-include esphome_pch.h" resolves here as a relative path.
|
||||
# An absolute path would put the per-device build path on every compile
|
||||
@@ -62,7 +72,10 @@ def _esp8266_setup_pch() -> None:
|
||||
# not see them; consumers keep theirs, which the .gch then satisfies.
|
||||
flags = []
|
||||
include_headers = []
|
||||
flag_it = iter(shlex.split(projenv.subst("$CXXFLAGS $CCFLAGS $_CCCOMCOM"))) # noqa: F821
|
||||
flag_it = iter(
|
||||
_shell_arg(element)
|
||||
for element in projenv.subst_list("$CXXFLAGS $CCFLAGS $_CCCOMCOM")[0] # noqa: F821
|
||||
)
|
||||
for tok in flag_it:
|
||||
if tok == "-include":
|
||||
include_headers.append(next(flag_it, ""))
|
||||
@@ -82,10 +95,14 @@ def _esp8266_setup_pch() -> None:
|
||||
flags_id = flags_id.replace(basedir, "")
|
||||
digest.update(flags_id.encode())
|
||||
# GCC never validates a .gch against its source headers, and PlatformIO
|
||||
# package paths carry no version, so a platform bump must invalidate here
|
||||
# package paths carry no version, so a package bump must invalidate here
|
||||
platform = env.PioPlatform() # noqa: F821
|
||||
for package in ("framework-arduinoespressif8266", "toolchain-xtensa"):
|
||||
digest.update(str(platform.get_package_version(package)).encode())
|
||||
for package in sorted(platform.packages):
|
||||
try:
|
||||
version = platform.get_package_version(package)
|
||||
except Exception: # noqa: BLE001 -- absent optional package
|
||||
version = None
|
||||
digest.update(f"{package}={version}".encode())
|
||||
digest.update(b"\0")
|
||||
closure = _include_closure(src_dir, [*include_headers, _CORE_HEADER])
|
||||
for rel in sorted(closure):
|
||||
@@ -142,4 +159,4 @@ def _esp8266_setup_pch() -> None:
|
||||
print("ESPHome: Compiling with precompiled header")
|
||||
|
||||
|
||||
_esp8266_setup_pch()
|
||||
_setup_pch()
|
||||
@@ -289,6 +289,15 @@ def copy_ccache_script() -> None:
|
||||
)
|
||||
|
||||
|
||||
def copy_pch_script() -> None:
|
||||
"""Copy the shared precompiled-header SCons post-script into the build
|
||||
dir; platform components pair it with ``post:pch.py`` in extra_scripts."""
|
||||
copy_file_if_changed(
|
||||
Path(__file__).parent / "pch.py.script",
|
||||
CORE.relative_build_path("pch.py"),
|
||||
)
|
||||
|
||||
|
||||
def run_platformio_cli(*args, **kwargs) -> str | int:
|
||||
# Re-provision the PlatformIO cache if the interpreter's major.minor changed
|
||||
# since it was last built; a stale platform otherwise rejects the new Python
|
||||
|
||||
Reference in New Issue
Block a user