mirror of
https://github.com/esphome/esphome.git
synced 2026-09-11 15:27:33 +00:00
Match the pch source TU by resolved path so symlinked build dirs keep the pch
This commit is contained in:
@@ -212,6 +212,18 @@ _PCH_STRIP_FLAGS_WITH_ARG = frozenset({"-o", "-c", "-MT", "-MF", "-MQ"})
|
||||
_PCH_STRIP_FLAGS = frozenset({"-MD", "-MMD", "-MP", "-MM", "-M"})
|
||||
|
||||
|
||||
def _db_source_path(entry: dict, build_dir: Path) -> Path:
|
||||
"""A compile database entry's source file as a resolved absolute path."""
|
||||
path = Path(entry["file"])
|
||||
if not path.is_absolute():
|
||||
directory = entry.get("directory")
|
||||
base = (
|
||||
Path(directory) if isinstance(directory, str) and directory else build_dir
|
||||
)
|
||||
path = base / path
|
||||
return path.resolve()
|
||||
|
||||
|
||||
def pch_compile_command(
|
||||
build_dir: Path, header: Path, gch: Path
|
||||
) -> tuple[list[str], Path] | None:
|
||||
@@ -232,16 +244,17 @@ def pch_compile_command(
|
||||
if not isinstance(entries, list):
|
||||
_LOGGER.warning("Malformed compile database, skipping pch")
|
||||
return None
|
||||
# Windows compile DBs use backslashes; normalize both sides
|
||||
src_prefix = str(CORE.relative_src_path()).replace("\\", "/")
|
||||
# CMake may spell paths through a symlink differently than CORE does
|
||||
# (macOS /tmp vs /private/tmp), so compare resolved paths
|
||||
src_root = Path(CORE.relative_src_path()).resolve()
|
||||
entry = next(
|
||||
(
|
||||
e
|
||||
for e in entries
|
||||
if isinstance(e, dict)
|
||||
and isinstance(e.get("file"), str)
|
||||
and e["file"].replace("\\", "/").startswith(src_prefix)
|
||||
and e["file"].endswith(CXX_SOURCE_SUFFIXES)
|
||||
and _db_source_path(e, build_dir).is_relative_to(src_root)
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
||||
@@ -657,6 +657,31 @@ def test_pch_compile_command_variants(tmp_path: Path) -> None:
|
||||
assert cmd_dir == build
|
||||
|
||||
|
||||
@pytest.mark.skipif(os.name == "nt", reason="symlinks need privileges on Windows")
|
||||
def test_pch_compile_command_matches_src_through_symlink(tmp_path: Path) -> None:
|
||||
"""Find the src TU when CMake spells paths through a different symlink (macOS /tmp)."""
|
||||
from esphome.build_helpers.pch import pch_compile_command
|
||||
|
||||
real = tmp_path / "real"
|
||||
(real / "src" / "esphome").mkdir(parents=True)
|
||||
link = tmp_path / "link"
|
||||
link.symlink_to(real, target_is_directory=True)
|
||||
CORE.build_path = str(real)
|
||||
build = real / "build"
|
||||
build.mkdir()
|
||||
header = build / "esphome_pch.h"
|
||||
gch = build / "esphome_pch.h.gch"
|
||||
src_file = str(link / "src" / "esphome" / "a.cpp")
|
||||
(build / "compile_commands.json").write_text(
|
||||
json.dumps([{"command": f"g++ -DX=1 -o a.obj -c {src_file}", "file": src_file}])
|
||||
)
|
||||
|
||||
cmd, cmd_dir = pch_compile_command(build, header, gch)
|
||||
|
||||
assert cmd[:2] == ["g++", "-DX=1"]
|
||||
assert cmd_dir == build
|
||||
|
||||
|
||||
def test_pch_compile_command_rejects_unusable_entries(tmp_path: Path) -> None:
|
||||
"""Malformed DB shapes and command-less entries skip cleanly instead of
|
||||
producing a compiler-less argv retried every build."""
|
||||
|
||||
Reference in New Issue
Block a user