Compilers: use Compiler._real_version for flag version checks (#18179)
Compilers can have strange versions, as the version is provided by the user. We know the real version internally, (by querying the compiler) so expose it as a property and use it in places we don't trust the user. Eventually we'll refactor this with compilers as dependencies, but this is the best fix we've got for now. - [x] Make `real_version` a property and cache the version returned by the compiler - [x] Use `real_version` to make C++ language level flags work
This commit is contained in:
parent
1650824ef5
commit
ccf94ded67
@ -217,7 +217,7 @@ def optimization_flags(self, compiler):
|
|||||||
if isinstance(compiler, spack.spec.CompilerSpec):
|
if isinstance(compiler, spack.spec.CompilerSpec):
|
||||||
compiler = spack.compilers.compilers_for_spec(compiler).pop()
|
compiler = spack.compilers.compilers_for_spec(compiler).pop()
|
||||||
try:
|
try:
|
||||||
compiler_version = compiler.get_real_version()
|
compiler_version = compiler.real_version
|
||||||
except spack.util.executable.ProcessError as e:
|
except spack.util.executable.ProcessError as e:
|
||||||
# log this and just return compiler.version instead
|
# log this and just return compiler.version instead
|
||||||
tty.debug(str(e))
|
tty.debug(str(e))
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
import spack.error
|
import spack.error
|
||||||
import spack.spec
|
import spack.spec
|
||||||
|
import spack.version
|
||||||
import spack.architecture
|
import spack.architecture
|
||||||
import spack.util.executable
|
import spack.util.executable
|
||||||
import spack.util.module_cmd
|
import spack.util.module_cmd
|
||||||
@ -278,7 +279,8 @@ def __init__(self, cspec, operating_system, target,
|
|||||||
self.target = target
|
self.target = target
|
||||||
self.modules = modules or []
|
self.modules = modules or []
|
||||||
self.alias = alias
|
self.alias = alias
|
||||||
self.extra_rpaths = extra_rpaths
|
self.environment = environment or {}
|
||||||
|
self.extra_rpaths = extra_rpaths or []
|
||||||
self.enable_implicit_rpaths = enable_implicit_rpaths
|
self.enable_implicit_rpaths = enable_implicit_rpaths
|
||||||
|
|
||||||
self.cc = paths[0]
|
self.cc = paths[0]
|
||||||
@ -292,9 +294,6 @@ def __init__(self, cspec, operating_system, target,
|
|||||||
else:
|
else:
|
||||||
self.fc = paths[3]
|
self.fc = paths[3]
|
||||||
|
|
||||||
self.environment = environment
|
|
||||||
self.extra_rpaths = extra_rpaths or []
|
|
||||||
|
|
||||||
# Unfortunately have to make sure these params are accepted
|
# Unfortunately have to make sure these params are accepted
|
||||||
# in the same order they are returned by sorted(flags)
|
# in the same order they are returned by sorted(flags)
|
||||||
# in compilers/__init__.py
|
# in compilers/__init__.py
|
||||||
@ -304,6 +303,10 @@ def __init__(self, cspec, operating_system, target,
|
|||||||
if value is not None:
|
if value is not None:
|
||||||
self.flags[flag] = tokenize_flags(value)
|
self.flags[flag] = tokenize_flags(value)
|
||||||
|
|
||||||
|
# caching value for compiler reported version
|
||||||
|
# used for version checks for API, e.g. C++11 flag
|
||||||
|
self._real_version = None
|
||||||
|
|
||||||
def verify_executables(self):
|
def verify_executables(self):
|
||||||
"""Raise an error if any of the compiler executables is not valid.
|
"""Raise an error if any of the compiler executables is not valid.
|
||||||
|
|
||||||
@ -333,6 +336,20 @@ def accessible_exe(exe):
|
|||||||
def version(self):
|
def version(self):
|
||||||
return self.spec.version
|
return self.spec.version
|
||||||
|
|
||||||
|
@property
|
||||||
|
def real_version(self):
|
||||||
|
"""Executable reported compiler version used for API-determinations
|
||||||
|
|
||||||
|
E.g. C++11 flag checks.
|
||||||
|
"""
|
||||||
|
if not self._real_version:
|
||||||
|
try:
|
||||||
|
self._real_version = spack.version.Version(
|
||||||
|
self.get_real_version())
|
||||||
|
except spack.util.executable.ProcessError:
|
||||||
|
self._real_version = self.version
|
||||||
|
return self._real_version
|
||||||
|
|
||||||
def implicit_rpaths(self):
|
def implicit_rpaths(self):
|
||||||
if self.enable_implicit_rpaths is False:
|
if self.enable_implicit_rpaths is False:
|
||||||
return []
|
return []
|
||||||
|
@ -38,7 +38,7 @@ def extract_version_from_output(cls, output):
|
|||||||
def cxx11_flag(self):
|
def cxx11_flag(self):
|
||||||
# Adapted from CMake's AppleClang-CXX rules
|
# Adapted from CMake's AppleClang-CXX rules
|
||||||
# Spack's AppleClang detection only valid from Xcode >= 4.6
|
# Spack's AppleClang detection only valid from Xcode >= 4.6
|
||||||
if self.version < spack.version.ver('4.0.0'):
|
if self.real_version < spack.version.ver('4.0.0'):
|
||||||
raise spack.compiler.UnsupportedCompilerFlag(
|
raise spack.compiler.UnsupportedCompilerFlag(
|
||||||
self, "the C++11 standard", "cxx11_flag", "Xcode < 4.0.0"
|
self, "the C++11 standard", "cxx11_flag", "Xcode < 4.0.0"
|
||||||
)
|
)
|
||||||
@ -47,11 +47,11 @@ def cxx11_flag(self):
|
|||||||
@property
|
@property
|
||||||
def cxx14_flag(self):
|
def cxx14_flag(self):
|
||||||
# Adapted from CMake's rules for AppleClang
|
# Adapted from CMake's rules for AppleClang
|
||||||
if self.version < spack.version.ver('5.1.0'):
|
if self.real_version < spack.version.ver('5.1.0'):
|
||||||
raise spack.compiler.UnsupportedCompilerFlag(
|
raise spack.compiler.UnsupportedCompilerFlag(
|
||||||
self, "the C++14 standard", "cxx14_flag", "Xcode < 5.1.0"
|
self, "the C++14 standard", "cxx14_flag", "Xcode < 5.1.0"
|
||||||
)
|
)
|
||||||
elif self.version < spack.version.ver('6.1.0'):
|
elif self.real_version < spack.version.ver('6.1.0'):
|
||||||
return "-std=c++1y"
|
return "-std=c++1y"
|
||||||
|
|
||||||
return "-std=c++14"
|
return "-std=c++14"
|
||||||
@ -59,7 +59,7 @@ def cxx14_flag(self):
|
|||||||
@property
|
@property
|
||||||
def cxx17_flag(self):
|
def cxx17_flag(self):
|
||||||
# Adapted from CMake's rules for AppleClang
|
# Adapted from CMake's rules for AppleClang
|
||||||
if self.version < spack.version.ver('6.1.0'):
|
if self.real_version < spack.version.ver('6.1.0'):
|
||||||
raise spack.compiler.UnsupportedCompilerFlag(
|
raise spack.compiler.UnsupportedCompilerFlag(
|
||||||
self, "the C++17 standard", "cxx17_flag", "Xcode < 6.1.0"
|
self, "the C++17 standard", "cxx17_flag", "Xcode < 6.1.0"
|
||||||
)
|
)
|
||||||
|
@ -34,7 +34,7 @@ class Cce(Compiler):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def is_clang_based(self):
|
def is_clang_based(self):
|
||||||
version = self.version
|
version = self._real_version or self.version
|
||||||
return version >= ver('9.0') and 'classic' not in str(version)
|
return version >= ver('9.0') and 'classic' not in str(version)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -69,9 +69,9 @@ def cxx11_flag(self):
|
|||||||
def c99_flag(self):
|
def c99_flag(self):
|
||||||
if self.is_clang_based:
|
if self.is_clang_based:
|
||||||
return '-std=c99'
|
return '-std=c99'
|
||||||
elif self.version >= ver('8.4'):
|
elif self.real_version >= ver('8.4'):
|
||||||
return '-h std=c99,noconform,gnu'
|
return '-h std=c99,noconform,gnu'
|
||||||
elif self.version >= ver('8.1'):
|
elif self.real_version >= ver('8.1'):
|
||||||
return '-h c99,noconform,gnu'
|
return '-h c99,noconform,gnu'
|
||||||
raise UnsupportedCompilerFlag(self,
|
raise UnsupportedCompilerFlag(self,
|
||||||
'the C99 standard',
|
'the C99 standard',
|
||||||
@ -82,7 +82,7 @@ def c99_flag(self):
|
|||||||
def c11_flag(self):
|
def c11_flag(self):
|
||||||
if self.is_clang_based:
|
if self.is_clang_based:
|
||||||
return '-std=c11'
|
return '-std=c11'
|
||||||
elif self.version >= ver('8.5'):
|
elif self.real_version >= ver('8.5'):
|
||||||
return '-h std=c11,noconform,gnu'
|
return '-h std=c11,noconform,gnu'
|
||||||
raise UnsupportedCompilerFlag(self,
|
raise UnsupportedCompilerFlag(self,
|
||||||
'the C11 standard',
|
'the C11 standard',
|
||||||
|
@ -90,7 +90,7 @@ def verbose_flag(self):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def cxx11_flag(self):
|
def cxx11_flag(self):
|
||||||
if self.version < ver('3.3'):
|
if self.real_version < ver('3.3'):
|
||||||
raise UnsupportedCompilerFlag(
|
raise UnsupportedCompilerFlag(
|
||||||
self, "the C++11 standard", "cxx11_flag", "< 3.3"
|
self, "the C++11 standard", "cxx11_flag", "< 3.3"
|
||||||
)
|
)
|
||||||
@ -98,22 +98,22 @@ def cxx11_flag(self):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def cxx14_flag(self):
|
def cxx14_flag(self):
|
||||||
if self.version < ver('3.4'):
|
if self.real_version < ver('3.4'):
|
||||||
raise UnsupportedCompilerFlag(
|
raise UnsupportedCompilerFlag(
|
||||||
self, "the C++14 standard", "cxx14_flag", "< 3.5"
|
self, "the C++14 standard", "cxx14_flag", "< 3.5"
|
||||||
)
|
)
|
||||||
elif self.version < ver('3.5'):
|
elif self.real_version < ver('3.5'):
|
||||||
return "-std=c++1y"
|
return "-std=c++1y"
|
||||||
|
|
||||||
return "-std=c++14"
|
return "-std=c++14"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cxx17_flag(self):
|
def cxx17_flag(self):
|
||||||
if self.version < ver('3.5'):
|
if self.real_version < ver('3.5'):
|
||||||
raise UnsupportedCompilerFlag(
|
raise UnsupportedCompilerFlag(
|
||||||
self, "the C++17 standard", "cxx17_flag", "< 3.5"
|
self, "the C++17 standard", "cxx17_flag", "< 3.5"
|
||||||
)
|
)
|
||||||
elif self.version < ver('5.0'):
|
elif self.real_version < ver('5.0'):
|
||||||
return "-std=c++1z"
|
return "-std=c++1z"
|
||||||
|
|
||||||
return "-std=c++17"
|
return "-std=c++17"
|
||||||
@ -124,7 +124,7 @@ def c99_flag(self):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def c11_flag(self):
|
def c11_flag(self):
|
||||||
if self.version < ver('6.1.0'):
|
if self.real_version < ver('6.1.0'):
|
||||||
raise UnsupportedCompilerFlag(self,
|
raise UnsupportedCompilerFlag(self,
|
||||||
"the C11 standard",
|
"the C11 standard",
|
||||||
"c11_flag",
|
"c11_flag",
|
||||||
|
@ -56,53 +56,53 @@ def openmp_flag(self):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def cxx98_flag(self):
|
def cxx98_flag(self):
|
||||||
if self.version < ver('6.0'):
|
if self.real_version < ver('6.0'):
|
||||||
return ""
|
return ""
|
||||||
else:
|
else:
|
||||||
return "-std=c++98"
|
return "-std=c++98"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cxx11_flag(self):
|
def cxx11_flag(self):
|
||||||
if self.version < ver('4.3'):
|
if self.real_version < ver('4.3'):
|
||||||
raise spack.compiler.UnsupportedCompilerFlag(
|
raise spack.compiler.UnsupportedCompilerFlag(
|
||||||
self, "the C++11 standard", "cxx11_flag", " < 4.3")
|
self, "the C++11 standard", "cxx11_flag", " < 4.3")
|
||||||
elif self.version < ver('4.7'):
|
elif self.real_version < ver('4.7'):
|
||||||
return "-std=c++0x"
|
return "-std=c++0x"
|
||||||
else:
|
else:
|
||||||
return "-std=c++11"
|
return "-std=c++11"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cxx14_flag(self):
|
def cxx14_flag(self):
|
||||||
if self.version < ver('4.8'):
|
if self.real_version < ver('4.8'):
|
||||||
raise spack.compiler.UnsupportedCompilerFlag(
|
raise spack.compiler.UnsupportedCompilerFlag(
|
||||||
self, "the C++14 standard", "cxx14_flag", "< 4.8")
|
self, "the C++14 standard", "cxx14_flag", "< 4.8")
|
||||||
elif self.version < ver('4.9'):
|
elif self.real_version < ver('4.9'):
|
||||||
return "-std=c++1y"
|
return "-std=c++1y"
|
||||||
elif self.version < ver('6.0'):
|
elif self.real_version < ver('6.0'):
|
||||||
return "-std=c++14"
|
return "-std=c++14"
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cxx17_flag(self):
|
def cxx17_flag(self):
|
||||||
if self.version < ver('5.0'):
|
if self.real_version < ver('5.0'):
|
||||||
raise spack.compiler.UnsupportedCompilerFlag(
|
raise spack.compiler.UnsupportedCompilerFlag(
|
||||||
self, "the C++17 standard", "cxx17_flag", "< 5.0")
|
self, "the C++17 standard", "cxx17_flag", "< 5.0")
|
||||||
elif self.version < ver('6.0'):
|
elif self.real_version < ver('6.0'):
|
||||||
return "-std=c++1z"
|
return "-std=c++1z"
|
||||||
else:
|
else:
|
||||||
return "-std=c++17"
|
return "-std=c++17"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def c99_flag(self):
|
def c99_flag(self):
|
||||||
if self.version < ver('4.5'):
|
if self.real_version < ver('4.5'):
|
||||||
raise spack.compiler.UnsupportedCompilerFlag(
|
raise spack.compiler.UnsupportedCompilerFlag(
|
||||||
self, "the C99 standard", "c99_flag", "< 4.5")
|
self, "the C99 standard", "c99_flag", "< 4.5")
|
||||||
return "-std=c99"
|
return "-std=c99"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def c11_flag(self):
|
def c11_flag(self):
|
||||||
if self.version < ver('4.7'):
|
if self.real_version < ver('4.7'):
|
||||||
raise spack.compiler.UnsupportedCompilerFlag(
|
raise spack.compiler.UnsupportedCompilerFlag(
|
||||||
self, "the C11 standard", "c11_flag", "< 4.7")
|
self, "the C11 standard", "c11_flag", "< 4.7")
|
||||||
return "-std=c11"
|
return "-std=c11"
|
||||||
|
@ -48,20 +48,20 @@ def opt_flags(self):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def openmp_flag(self):
|
def openmp_flag(self):
|
||||||
if self.version < ver('16.0'):
|
if self.real_version < ver('16.0'):
|
||||||
return "-openmp"
|
return "-openmp"
|
||||||
else:
|
else:
|
||||||
return "-qopenmp"
|
return "-qopenmp"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cxx11_flag(self):
|
def cxx11_flag(self):
|
||||||
if self.version < ver('11.1'):
|
if self.real_version < ver('11.1'):
|
||||||
raise UnsupportedCompilerFlag(self,
|
raise UnsupportedCompilerFlag(self,
|
||||||
"the C++11 standard",
|
"the C++11 standard",
|
||||||
"cxx11_flag",
|
"cxx11_flag",
|
||||||
"< 11.1")
|
"< 11.1")
|
||||||
|
|
||||||
elif self.version < ver('13'):
|
elif self.real_version < ver('13'):
|
||||||
return "-std=c++0x"
|
return "-std=c++0x"
|
||||||
else:
|
else:
|
||||||
return "-std=c++11"
|
return "-std=c++11"
|
||||||
@ -69,19 +69,19 @@ def cxx11_flag(self):
|
|||||||
@property
|
@property
|
||||||
def cxx14_flag(self):
|
def cxx14_flag(self):
|
||||||
# Adapted from CMake's Intel-CXX rules.
|
# Adapted from CMake's Intel-CXX rules.
|
||||||
if self.version < ver('15'):
|
if self.real_version < ver('15'):
|
||||||
raise UnsupportedCompilerFlag(self,
|
raise UnsupportedCompilerFlag(self,
|
||||||
"the C++14 standard",
|
"the C++14 standard",
|
||||||
"cxx14_flag",
|
"cxx14_flag",
|
||||||
"< 15")
|
"< 15")
|
||||||
elif self.version < ver('15.0.2'):
|
elif self.real_version < ver('15.0.2'):
|
||||||
return "-std=c++1y"
|
return "-std=c++1y"
|
||||||
else:
|
else:
|
||||||
return "-std=c++14"
|
return "-std=c++14"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def c99_flag(self):
|
def c99_flag(self):
|
||||||
if self.version < ver('12'):
|
if self.real_version < ver('12'):
|
||||||
raise UnsupportedCompilerFlag(self,
|
raise UnsupportedCompilerFlag(self,
|
||||||
"the C99 standard",
|
"the C99 standard",
|
||||||
"c99_flag",
|
"c99_flag",
|
||||||
@ -91,7 +91,7 @@ def c99_flag(self):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def c11_flag(self):
|
def c11_flag(self):
|
||||||
if self.version < ver('16'):
|
if self.real_version < ver('16'):
|
||||||
raise UnsupportedCompilerFlag(self,
|
raise UnsupportedCompilerFlag(self,
|
||||||
"the C11 standard",
|
"the C11 standard",
|
||||||
"c11_flag",
|
"c11_flag",
|
||||||
|
@ -73,7 +73,7 @@ def fc_pic_flag(self):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def c99_flag(self):
|
def c99_flag(self):
|
||||||
if self.version >= ver('12.10'):
|
if self.real_version >= ver('12.10'):
|
||||||
return '-c99'
|
return '-c99'
|
||||||
raise UnsupportedCompilerFlag(self,
|
raise UnsupportedCompilerFlag(self,
|
||||||
'the C99 standard',
|
'the C99 standard',
|
||||||
@ -82,7 +82,7 @@ def c99_flag(self):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def c11_flag(self):
|
def c11_flag(self):
|
||||||
if self.version >= ver('15.3'):
|
if self.real_version >= ver('15.3'):
|
||||||
return '-c11'
|
return '-c11'
|
||||||
raise UnsupportedCompilerFlag(self,
|
raise UnsupportedCompilerFlag(self,
|
||||||
'the C11 standard',
|
'the C11 standard',
|
||||||
|
@ -47,7 +47,7 @@ def openmp_flag(self):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def cxx11_flag(self):
|
def cxx11_flag(self):
|
||||||
if self.version < ver('13.1'):
|
if self.real_version < ver('13.1'):
|
||||||
raise UnsupportedCompilerFlag(self,
|
raise UnsupportedCompilerFlag(self,
|
||||||
"the C++11 standard",
|
"the C++11 standard",
|
||||||
"cxx11_flag",
|
"cxx11_flag",
|
||||||
@ -57,9 +57,9 @@ def cxx11_flag(self):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def c99_flag(self):
|
def c99_flag(self):
|
||||||
if self.version >= ver('13.1.1'):
|
if self.real_version >= ver('13.1.1'):
|
||||||
return '-std=gnu99'
|
return '-std=gnu99'
|
||||||
if self.version >= ver('10.1'):
|
if self.real_version >= ver('10.1'):
|
||||||
return '-qlanglvl=extc99'
|
return '-qlanglvl=extc99'
|
||||||
raise UnsupportedCompilerFlag(self,
|
raise UnsupportedCompilerFlag(self,
|
||||||
'the C99 standard',
|
'the C99 standard',
|
||||||
@ -68,9 +68,9 @@ def c99_flag(self):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def c11_flag(self):
|
def c11_flag(self):
|
||||||
if self.version >= ver('13.1.2'):
|
if self.real_version >= ver('13.1.2'):
|
||||||
return '-std=gnu11'
|
return '-std=gnu11'
|
||||||
if self.version >= ver('12.1'):
|
if self.real_version >= ver('12.1'):
|
||||||
return '-qlanglvl=extc1x'
|
return '-qlanglvl=extc1x'
|
||||||
raise UnsupportedCompilerFlag(self,
|
raise UnsupportedCompilerFlag(self,
|
||||||
'the C11 standard',
|
'the C11 standard',
|
||||||
|
@ -739,6 +739,41 @@ def _call(*args, **kwargs):
|
|||||||
assert 'SPACK_TEST_CMP_ON' not in os.environ
|
assert 'SPACK_TEST_CMP_ON' not in os.environ
|
||||||
|
|
||||||
|
|
||||||
|
def test_compiler_flags_use_real_version(working_env, monkeypatch, tmpdir):
|
||||||
|
# Create compiler
|
||||||
|
gcc = str(tmpdir.join('gcc'))
|
||||||
|
with open(gcc, 'w') as f:
|
||||||
|
f.write("""#!/bin/bash
|
||||||
|
echo "4.4.4"
|
||||||
|
""") # Version for which c++11 flag is -std=c++0x
|
||||||
|
fs.set_executable(gcc)
|
||||||
|
|
||||||
|
# Add compiler to config
|
||||||
|
compiler_info = {
|
||||||
|
'spec': 'gcc@foo',
|
||||||
|
'paths': {
|
||||||
|
'cc': gcc,
|
||||||
|
'cxx': None,
|
||||||
|
'f77': None,
|
||||||
|
'fc': None,
|
||||||
|
},
|
||||||
|
'flags': {},
|
||||||
|
'operating_system': 'fake',
|
||||||
|
'target': 'fake',
|
||||||
|
'modules': ['turn_on'],
|
||||||
|
'environment': {},
|
||||||
|
'extra_rpaths': [],
|
||||||
|
}
|
||||||
|
compiler_dict = {'compiler': compiler_info}
|
||||||
|
|
||||||
|
# Run and confirm output
|
||||||
|
compilers = spack.compilers.get_compilers([compiler_dict])
|
||||||
|
assert len(compilers) == 1
|
||||||
|
compiler = compilers[0]
|
||||||
|
flag = compiler.cxx11_flag
|
||||||
|
assert flag == '-std=c++0x'
|
||||||
|
|
||||||
|
|
||||||
def test_apple_clang_setup_environment(mock_executable, monkeypatch):
|
def test_apple_clang_setup_environment(mock_executable, monkeypatch):
|
||||||
"""Test a code path that is taken only if the package uses
|
"""Test a code path that is taken only if the package uses
|
||||||
Xcode on MacOS.
|
Xcode on MacOS.
|
||||||
|
Loading…
Reference in New Issue
Block a user