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)
This commit is contained in:
Massimiliano Culpo 2019-03-11 19:15:34 +01:00 committed by Peter Scheibel
parent 1fd01af773
commit a42fd7f276
2 changed files with 48 additions and 13 deletions

View File

@ -178,22 +178,33 @@ def default_version(cls, comp):
if comp not in _version_cache:
compiler = Executable(comp)
output = compiler('--version', output=str, error=str)
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)
_version_cache[comp] = ver
_version_cache[comp] = cls.detect_version_from_str(output)
return _version_cache[comp]
@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'.
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):
# We could map from gcc/gfortran version to clang version, but on macOS

View File

@ -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