Skip to content

Commit 60ac6f6

Browse files
committed
[NFC] Clean up analyzer version info getter
The version of analyzer binaries can be fetched by `get_binary_version()` function. ClangSA plugin had an extra `version_info()` that returned the version number among some further info in another format. This function is now eliminated. In `log_parser` module it is checked whether the same clang version is used for analysis and the original build. The compiler path was checked by `clang --version` that contains this info. Now we use the clang binary path itself.
1 parent b78d981 commit 60ac6f6

22 files changed

Lines changed: 111 additions & 438 deletions

analyzer/codechecker_analyzer/analyzer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ def perform_analysis(args, skip_handlers, filter_handlers,
282282

283283
version = analyzer_types.supported_analyzers[analyzer] \
284284
.get_binary_version()
285-
metadata_info['analyzer_statistics']['version'] = version
285+
metadata_info['analyzer_statistics']['version'] = str(version)
286286

287287
metadata_tool['analyzers'][analyzer] = metadata_info
288288
LOG.info("Enabled checker list can be found in %s",

analyzer/codechecker_analyzer/analyzers/analyzer_base.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
from abc import ABCMeta, abstractmethod
1414
import os
15+
from semver.version import Version
1516
import signal
1617
import subprocess
1718
import sys
@@ -72,12 +73,10 @@ def resolve_missing_binary(cls, configured_binary, environ):
7273

7374
@classmethod
7475
@abstractmethod
75-
def get_binary_version(cls, details=False) -> str:
76+
def get_binary_version(cls) -> Optional[Version]:
7677
"""
7778
Return the version number of the binary that CodeChecker found, even
78-
if its incompatible. If details is true, additional version information
79-
is provided. If details is false, the return value should be
80-
convertible to a distutils.version.StrictVersion type.
79+
if it's incompatible.
8180
"""
8281
raise NotImplementedError("Subclasses should implement this!")
8382

analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
import re
1616
import subprocess
1717
import sys
18-
from typing import List, Tuple
18+
from typing import List, Optional, Tuple
19+
20+
from semver.version import Version
1921

2022
from codechecker_common import util
2123
from codechecker_common.logger import get_logger
@@ -33,7 +35,6 @@
3335

3436
from . import config_handler
3537
from . import ctu_triple_arch
36-
from . import version
3738
from .result_handler import ClangSAResultHandler
3839

3940
LOG = get_logger('analyzer')
@@ -186,36 +187,30 @@ def __add_plugin_load_flags(cls, analyzer_cmd: List[str]):
186187
analyzer_cmd.extend(["-load", plugin])
187188

188189
@classmethod
189-
def get_binary_version(cls, details=False) -> str:
190+
def get_binary_version(cls) -> Optional[Version]:
190191
# No need to LOG here, we will emit a warning later anyway.
191192
if not cls.analyzer_binary():
192193
return None
193194

194195
environ = analyzer_context.get_context().get_env_for_bin(
195196
cls.analyzer_binary())
196197

197-
if details:
198-
ver = [cls.analyzer_binary(), '--version']
199-
else:
200-
ver = [cls.analyzer_binary(), '-dumpversion']
198+
version = [cls.analyzer_binary(), '-dumpversion']
199+
201200
try:
202-
output = subprocess.check_output(ver,
201+
output = subprocess.check_output(version,
203202
env=environ,
204203
universal_newlines=True,
205204
encoding="utf-8",
206205
errors="ignore")
207-
return output.strip()
206+
return Version.parse(output.strip())
208207
except (subprocess.CalledProcessError, OSError) as oerr:
209208
LOG.warning("Failed to get analyzer version: %s",
210-
' '.join(ver))
209+
' '.join(version))
211210
LOG.warning(oerr)
212211

213212
return None
214213

215-
@classmethod
216-
def version_info(cls):
217-
return version.get(cls.analyzer_binary())
218-
219214
@classmethod
220215
def ctu_mapping(cls):
221216
"""Clang version dependent ctu mapping tool path and mapping file name.
@@ -227,8 +222,8 @@ def ctu_mapping(cls):
227222
default the shorter name is looked up, then if it is not found the
228223
postfixed.
229224
"""
230-
clang_version_info = cls.version_info()
231-
if not clang_version_info:
225+
clang_version = cls.get_binary_version()
226+
if not clang_version:
232227
LOG.debug(
233228
"No clang version information. "
234229
"Can not detect ctu mapping tool.")
@@ -240,9 +235,7 @@ def ctu_mapping(cls):
240235
new_mapping_tool_name = 'clang-extdef-mapping'
241236
new_mapping_file_name = 'externalDefMap.txt'
242237

243-
major_version = clang_version_info.major_version
244-
245-
if major_version > 7:
238+
if clang_version.major > 7:
246239
tool_name = new_mapping_tool_name
247240
mapping_file = new_mapping_file_name
248241
else:
@@ -261,7 +254,7 @@ def ctu_mapping(cls):
261254
"filename...", tool_path, installed_dir)
262255

263256
postfixed_tool_path = ''.join(
264-
[str(tool_path), '-', str(major_version)])
257+
[str(tool_path), '-', str(clang_version.major)])
265258

266259
if os.path.isfile(postfixed_tool_path):
267260
return postfixed_tool_path, mapping_file
@@ -378,12 +371,18 @@ def get_analyzer_checkers(
378371
# The new checker help printig flags are not available there yet.
379372
# If the OSX clang will be updated to based on clang v8
380373
# this early return can be removed.
381-
version_info = cls.version_info()
382-
if version_info and version_info.vendor == "clang":
383-
if alpha and version_info.major_version >= 9:
374+
version_info = cls.get_binary_version()
375+
if version_info:
376+
try:
377+
help_page = clang_command_output([
378+
cls.analyzer_binary(), "-cc1", "--help"])
379+
except (subprocess.CalledProcessError, OSError):
380+
help_page = ""
381+
382+
if alpha and "-analyzer-checker-help-alpha" in help_page:
384383
command.append("-analyzer-checker-help-alpha")
385384

386-
if debug and version_info.major_version >= 9:
385+
if debug and "-analyzer-checker-help-developer" in help_page:
387386
command.append("-analyzer-checker-help-developer")
388387

389388
return parse_clang_help_page(command, 'CHECKERS:')
@@ -402,12 +401,18 @@ def get_checker_config(cls) -> List[analyzer_base.CheckerConfig]:
402401

403402
command.append("-analyzer-checker-option-help")
404403

405-
version_info = ClangSA.version_info()
406-
if version_info.vendor == "clang":
407-
if version_info.major_version >= 9:
404+
version_info = cls.get_binary_version()
405+
if version_info:
406+
try:
407+
help_page = clang_command_output([
408+
cls.analyzer_binary(), "-cc1", "--help"])
409+
except (subprocess.CalledProcessError, OSError):
410+
help_page = ""
411+
412+
if "-analyzer-checker-option-help-alpha" in help_page:
408413
command.append("-analyzer-checker-option-help-alpha")
409414

410-
if version_info.major_version >= 9:
415+
if "-analyzer-checker-option-help-developer" in help_page:
411416
command.append("-analyzer-checker-option-help-developer")
412417

413418
result = []
@@ -534,8 +539,8 @@ def construct_analyzer_cmd(self, result_handler):
534539
'-analyzer-checker=' +
535540
','.join(enabled_checkers)])
536541
# Enable aggressive-binary-operation-simplification option.
537-
version_info = ClangSA.version_info()
538-
if version_info and version_info.major_version >= 8:
542+
version_info = ClangSA.get_binary_version()
543+
if version_info and version_info.major >= 8:
539544
analyzer_cmd.extend([
540545
'-Xclang',
541546
'-analyzer-config',

analyzer/codechecker_analyzer/analyzers/clangsa/version.py

Lines changed: 0 additions & 85 deletions
This file was deleted.

analyzer/codechecker_analyzer/analyzers/clangtidy/analyzer.py

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@
1515
import os
1616
from pathlib import Path
1717
import re
18+
from semver.version import Version
1819
import shutil
1920
import subprocess
2021
import sys
21-
from typing import Iterable, List, Set, Tuple
22+
from typing import Iterable, List, Optional, Set, Tuple
2223

2324
import yaml
2425

@@ -155,12 +156,9 @@ def get_diagtool_bin():
155156

156157
# Sometimes diagtool binary has a version number in its name: diagtool-14.
157158
version = ClangTidy.get_binary_version()
158-
if version:
159-
version = version.split('.')[0]
160159

161-
diagtool_bin = diagtool_bin.with_name(f'diagtool-{version}')
162-
163-
if diagtool_bin.exists():
160+
if version and \
161+
diagtool_bin.with_name(f'diagtool-{version.major}').exists():
164162
return diagtool_bin
165163

166164
LOG.warning(
@@ -238,17 +236,6 @@ def need_asterisk(checker: str) -> bool:
238236
return result
239237

240238

241-
def parse_version(tidy_output):
242-
"""
243-
Parse clang-tidy version output and return the version number.
244-
"""
245-
version_re = re.compile(r'.*version (?P<version>[\d\.]+)', re.S)
246-
match = version_re.match(tidy_output)
247-
if match:
248-
return match.group('version')
249-
return None
250-
251-
252239
class ClangTidy(analyzer_base.SourceAnalyzer):
253240
"""
254241
Constructs the clang tidy analyzer commands.
@@ -279,7 +266,7 @@ def analyzer_binary(cls):
279266
.analyzer_binaries[cls.ANALYZER_NAME]
280267

281268
@classmethod
282-
def get_binary_version(cls, details=False) -> str:
269+
def get_binary_version(cls) -> Optional[Version]:
283270
if not cls.analyzer_binary():
284271
return None
285272
# No need to LOG here, we will emit a warning later anyway.
@@ -293,9 +280,10 @@ def get_binary_version(cls, details=False) -> str:
293280
universal_newlines=True,
294281
encoding="utf-8",
295282
errors="ignore")
296-
if details:
297-
return output.strip()
298-
return parse_version(output)
283+
version_re = re.compile(r'.*version (?P<version>[\d\.]+)', re.S)
284+
match = version_re.match(output)
285+
if match:
286+
return Version.parse(match.group('version'))
299287
except (subprocess.CalledProcessError, OSError) as oerr:
300288
LOG.warning("Failed to get analyzer version: %s",
301289
' '.join(version))

analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111

1212
from collections import defaultdict
1313
import sys
14-
from typing import List
15-
from packaging.version import Version
14+
from typing import List, Optional
1615
from pathlib import Path
1716
import os
1817
import re
18+
from semver.version import Version
1919
import shutil
2020
import subprocess
2121
import xml.etree.ElementTree as ET
@@ -60,14 +60,14 @@ def parse_checkers(cppcheck_output):
6060
return checkers
6161

6262

63-
def parse_version(cppcheck_output):
63+
def parse_version(cppcheck_output) -> Optional[Version]:
6464
"""
6565
Parse cppcheck version output and return the version number.
6666
"""
6767
version_re = re.compile(r'^Cppcheck(.*?)(?P<version>[\d\.]+)')
6868
match = version_re.match(cppcheck_output)
6969
if match:
70-
return match.group('version')
70+
return Version.parse(match.group('version'))
7171
return None
7272

7373

@@ -84,7 +84,7 @@ def analyzer_binary(cls):
8484
.analyzer_binaries[cls.ANALYZER_NAME]
8585

8686
@classmethod
87-
def get_binary_version(cls, details=False) -> str:
87+
def get_binary_version(cls) -> Optional[Version]:
8888
""" Get analyzer version information. """
8989
# No need to LOG here, we will emit a warning later anyway.
9090
if not cls.analyzer_binary():
@@ -98,8 +98,6 @@ def get_binary_version(cls, details=False) -> str:
9898
universal_newlines=True,
9999
encoding="utf-8",
100100
errors="ignore")
101-
if details:
102-
return output.strip()
103101
return parse_version(output)
104102
except (subprocess.CalledProcessError, OSError) as oerr:
105103
LOG.warning("Failed to get analyzer version: %s",
@@ -390,7 +388,7 @@ def is_binary_version_incompatible(cls):
390388

391389
# The analyzer version should be above 1.80 because '--plist-output'
392390
# argument was introduced in this release.
393-
if Version(analyzer_version) >= Version("1.80"):
391+
if analyzer_version and analyzer_version >= Version(1, 80):
394392
return None
395393

396394
return "CppCheck binary found is too old at " \

0 commit comments

Comments
 (0)