mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
[core] Resolve GCC multilib include dirs for clang-tidy (#18111)
This commit is contained in:
@@ -5,11 +5,13 @@ import os
|
||||
from pathlib import Path
|
||||
import queue
|
||||
import re
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
from typing import Any
|
||||
|
||||
import click
|
||||
import colorama
|
||||
@@ -29,6 +31,36 @@ from helpers import (
|
||||
)
|
||||
|
||||
|
||||
def gcc_multilib_directory(idedata: dict[str, Any]) -> str | None:
|
||||
"""The toolchain's active multilib subdirectory (e.g. "thumb"), if any.
|
||||
|
||||
PlatformIO's idedata lists the generic toolchain include directories; GCC
|
||||
resolves the active multilib subdirectory internally while searching them.
|
||||
Toolchains without a default multilib (pico-quick-toolchain 5.0.0+) ship
|
||||
the libstdc++ target config (bits/c++config.h) only inside the multilib
|
||||
subdirectories, so clang needs the resolved directory spelled out.
|
||||
"""
|
||||
machine_flags = [f for f in idedata["cxx_flags"] if f.startswith("-m")]
|
||||
cmd = [idedata["cxx_path"], *machine_flags, "-print-multi-directory"]
|
||||
try:
|
||||
multilib = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
).stdout.strip()
|
||||
except (OSError, subprocess.CalledProcessError) as err:
|
||||
# Without the multilib dir, toolchains lacking a default multilib fail
|
||||
# later with "bits/c++config.h not found"; point at the probe instead.
|
||||
stderr = getattr(err, "stderr", "") or ""
|
||||
print(
|
||||
f"WARNING: multilib probe failed ({shlex.join(cmd)}): {err} {stderr}".strip(),
|
||||
file=sys.stderr,
|
||||
)
|
||||
return None
|
||||
return None if multilib in ("", ".") else multilib
|
||||
|
||||
|
||||
def clang_options(idedata, environment):
|
||||
cmd = []
|
||||
|
||||
@@ -203,9 +235,12 @@ def clang_options(idedata, environment):
|
||||
# toolchain include directories, using -isystem to suppress their errors
|
||||
# idedata contains include directories for all toolchains of this platform, only use those from the one in use
|
||||
toolchain_dir = os.path.normpath(f"{idedata['cxx_path']}/../../")
|
||||
multilib = gcc_multilib_directory(idedata)
|
||||
toolchain_includes = []
|
||||
for directory in idedata["includes"]["toolchain"]:
|
||||
if directory.startswith(toolchain_dir) and "picolibc" not in directory:
|
||||
if multilib and (multilib_dir := Path(directory) / multilib).is_dir():
|
||||
toolchain_includes.extend(["-isystem", str(multilib_dir)])
|
||||
toolchain_includes.extend(["-isystem", directory])
|
||||
|
||||
# library include directories, using -isystem to suppress their errors
|
||||
|
||||
@@ -18,6 +18,7 @@ from pathlib import Path
|
||||
# Root-relative paths whose contents affect clang-tidy results.
|
||||
CLANG_TIDY_GLOBAL_FILES = (
|
||||
".clang-tidy",
|
||||
"script/clang-tidy",
|
||||
"platformio.ini",
|
||||
"requirements_dev.txt",
|
||||
"esphome/idf_component.yml",
|
||||
|
||||
Reference in New Issue
Block a user