From a42fd7f27617db03f2d9d8b4539cec88d03a3949 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Mon, 11 Mar 2019 19:15:34 +0100 Subject: Improved detection of Clang versions (#10316) Fixes #10191 * Add more regular expressions to detect clang versions that were not being picked up * Add a test for parsing versions from the output of Clang (this does not run Clang, but rather uses example outputs from Clang) * Separate Clang version parsing into its own method (to make it easier to test) --- lib/spack/spack/compilers/clang.py | 35 +++++++++++++++++++++++------------ lib/spack/spack/test/compilers.py | 24 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/compilers/clang.py b/lib/spack/spack/compilers/clang.py index cf569cd7a8..c21fc60384 100644 --- a/lib/spack/spack/compilers/clang.py +++ b/lib/spack/spack/compilers/clang.py @@ -178,21 +178,32 @@ class Clang(Compiler): if comp not in _version_cache: compiler = Executable(comp) output = compiler('--version', output=str, error=str) + _version_cache[comp] = cls.detect_version_from_str(output) - ver = 'unknown' - match = re.search(r'^Apple LLVM version ([^ )]+)', output) - if match: - # Apple's LLVM compiler has its own versions, so suffix them. - ver = match.group(1) + '-apple' - else: - # Normal clang compiler versions are left as-is - match = re.search(r'clang version ([^ )]+)', output) - if match: - ver = match.group(1) + return _version_cache[comp] - _version_cache[comp] = ver + @classmethod + def detect_version_from_str(cls, output): + """Returns the version that has been detected from the string + passed as input. If no detection is possible returns the + string 'unknown'. - return _version_cache[comp] + Args: + output (str): string used to detect a compiler version + """ + ver = 'unknown' + match = re.search( + # Apple's LLVM compiler has its own versions, so suffix them. + r'^Apple LLVM version ([^ )]+)|' + # Normal clang compiler versions are left as-is + r'clang version ([^ )]+)-svn[~.\w\d-]*|' + r'clang version ([^ )]+)', + output + ) + if match: + suffix = '-apple' if match.lastindex == 1 else '' + ver = match.group(match.lastindex) + suffix + return ver @classmethod def fc_version(cls, fc): diff --git a/lib/spack/spack/test/compilers.py b/lib/spack/spack/test/compilers.py index 5c46c0b251..0f0742f78e 100644 --- a/lib/spack/spack/test/compilers.py +++ b/lib/spack/spack/test/compilers.py @@ -3,11 +3,15 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) +import pytest + from copy import copy from six import iteritems import spack.spec +import spack.compiler import spack.compilers as compilers +import spack.compilers.clang from spack.compiler import _get_versioned_tuple, Compiler @@ -227,3 +231,23 @@ def test_xl_r_flags(): unsupported_flag_test("cxx11_flag", "xl_r@13.0") supported_flag_test("cxx11_flag", "-qlanglvl=extended0x", "xl_r@13.1") supported_flag_test("pic_flag", "-qpic", "xl_r@1.0") + + +@pytest.mark.regression('10191') +@pytest.mark.parametrize('version_str,expected_version', [ + # macOS clang + ('Apple LLVM version 7.0.2 (clang-700.1.81)\n' + 'Target: x86_64-apple-darwin15.2.0\n' + 'Thread model: posix\n', '7.0.2-apple'), + # Other platforms + ('clang version 6.0.1-svn334776-1~exp1~20181018152737.116 (branches/release_60)\n' # noqa + 'Target: x86_64-pc-linux-gnu\n' + 'Thread model: posix\n' + 'InstalledDir: /usr/bin\n', '6.0.1'), + ('clang version 3.1 (trunk 149096)\n' + 'Target: x86_64-unknown-linux-gnu\n' + 'Thread model: posix\n', '3.1'), +]) +def test_clang_version_detection(version_str, expected_version): + version = spack.compilers.clang.Clang.detect_version_from_str(version_str) + assert version == expected_version -- cgit v1.2.3-70-g09d2