[core] Resolve GCC multilib include dirs for clang-tidy (#18111)

This commit is contained in:
J. Nick Koston
2026-08-05 19:09:13 -05:00
committed by GitHub
parent 524b278811
commit f971e404c7
2 changed files with 36 additions and 0 deletions
+35
View File
@@ -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
+1
View File
@@ -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",