From 1daa616636fb71ca7151a030494d6f53a640b995 Mon Sep 17 00:00:00 2001 From: bruntib Date: Mon, 9 Dec 2024 12:55:46 +0100 Subject: [PATCH] [fix] Don't crash when diagtool is missing For clang-tidy the set of warnings can be queried by a tool named `diagtool`. In some environments `clang` is a symlink to `ccache`. Since CodeChecker tries to find `diagtool` right next to clang, this logic doesn't work, since `diagtool` is usually not next to `ccache`. In this patch CodeChecker searches `diagtool` in the next element of `PATH` environment variable in case `clang` is a symlink to `ccache`, since `ccache` would do the same, too. Fixes #4371 --- .../analyzers/clangtidy/analyzer.py | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/analyzer/codechecker_analyzer/analyzers/clangtidy/analyzer.py b/analyzer/codechecker_analyzer/analyzers/clangtidy/analyzer.py index cbc803edfc..d6aab11f37 100644 --- a/analyzer/codechecker_analyzer/analyzers/clangtidy/analyzer.py +++ b/analyzer/codechecker_analyzer/analyzers/clangtidy/analyzer.py @@ -13,8 +13,10 @@ import ast import json import os +from pathlib import Path import re import shlex +import shutil import subprocess from typing import Iterable, List, Set, Tuple @@ -128,12 +130,28 @@ def get_diagtool_bin(): if not clang_bin: return None + path_env = os.environ['PATH'].split(os.pathsep) + clang_path = Path(clang_bin) + + if clang_path.resolve().name == 'ccache': + for i, path in enumerate(path_env): + if Path(path) == clang_path.parent: + pos = i + break + + clang_bin = shutil.which( + clang_path.name, + path=os.pathsep.join(path_env[pos + 1:])) + + if not clang_bin: + return None + # Resolve symlink. - clang_bin = os.path.realpath(clang_bin) + clang_bin = Path(clang_bin).resolve() # Find diagtool next to the clang binary. - diagtool_bin = os.path.join(os.path.dirname(clang_bin), 'diagtool') - if os.path.exists(diagtool_bin): + diagtool_bin = clang_bin.parent / 'diagtool' + if diagtool_bin.exists(): return diagtool_bin LOG.warning(