summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGreg Becker <becker33@llnl.gov>2020-08-19 21:56:06 -0700
committerGitHub <noreply@github.com>2020-08-19 21:56:06 -0700
commitccf94ded67e688770dc8d0388d8f75d0d6641e1e (patch)
treeb3430021092769154cc24d662853d2239c120386 /lib
parent1650824ef5886a12715bd0004e95ab3bf4dc5dfd (diff)
downloadspack-ccf94ded67e688770dc8d0388d8f75d0d6641e1e.tar.gz
spack-ccf94ded67e688770dc8d0388d8f75d0d6641e1e.tar.bz2
spack-ccf94ded67e688770dc8d0388d8f75d0d6641e1e.tar.xz
spack-ccf94ded67e688770dc8d0388d8f75d0d6641e1e.zip
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
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/architecture.py2
-rw-r--r--lib/spack/spack/compiler.py25
-rw-r--r--lib/spack/spack/compilers/apple_clang.py8
-rw-r--r--lib/spack/spack/compilers/cce.py8
-rw-r--r--lib/spack/spack/compilers/clang.py12
-rw-r--r--lib/spack/spack/compilers/gcc.py20
-rw-r--r--lib/spack/spack/compilers/intel.py14
-rw-r--r--lib/spack/spack/compilers/pgi.py4
-rw-r--r--lib/spack/spack/compilers/xl.py10
-rw-r--r--lib/spack/spack/test/compilers/basics.py35
10 files changed, 95 insertions, 43 deletions
diff --git a/lib/spack/spack/architecture.py b/lib/spack/spack/architecture.py
index e4a20759cf..15561d436c 100644
--- a/lib/spack/spack/architecture.py
+++ b/lib/spack/spack/architecture.py
@@ -217,7 +217,7 @@ class Target(object):
if isinstance(compiler, spack.spec.CompilerSpec):
compiler = spack.compilers.compilers_for_spec(compiler).pop()
try:
- compiler_version = compiler.get_real_version()
+ compiler_version = compiler.real_version
except spack.util.executable.ProcessError as e:
# log this and just return compiler.version instead
tty.debug(str(e))
diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py
index f1a9263c76..d498803633 100644
--- a/lib/spack/spack/compiler.py
+++ b/lib/spack/spack/compiler.py
@@ -18,6 +18,7 @@ import llnl.util.tty as tty
import spack.error
import spack.spec
+import spack.version
import spack.architecture
import spack.util.executable
import spack.util.module_cmd
@@ -278,7 +279,8 @@ class Compiler(object):
self.target = target
self.modules = modules or []
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.cc = paths[0]
@@ -292,9 +294,6 @@ class Compiler(object):
else:
self.fc = paths[3]
- self.environment = environment
- self.extra_rpaths = extra_rpaths or []
-
# Unfortunately have to make sure these params are accepted
# in the same order they are returned by sorted(flags)
# in compilers/__init__.py
@@ -304,6 +303,10 @@ class Compiler(object):
if value is not None:
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):
"""Raise an error if any of the compiler executables is not valid.
@@ -333,6 +336,20 @@ class Compiler(object):
def version(self):
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):
if self.enable_implicit_rpaths is False:
return []
diff --git a/lib/spack/spack/compilers/apple_clang.py b/lib/spack/spack/compilers/apple_clang.py
index 63e0a9c42f..e03117ae05 100644
--- a/lib/spack/spack/compilers/apple_clang.py
+++ b/lib/spack/spack/compilers/apple_clang.py
@@ -38,7 +38,7 @@ class AppleClang(spack.compilers.clang.Clang):
def cxx11_flag(self):
# Adapted from CMake's AppleClang-CXX rules
# 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(
self, "the C++11 standard", "cxx11_flag", "Xcode < 4.0.0"
)
@@ -47,11 +47,11 @@ class AppleClang(spack.compilers.clang.Clang):
@property
def cxx14_flag(self):
# 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(
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++14"
@@ -59,7 +59,7 @@ class AppleClang(spack.compilers.clang.Clang):
@property
def cxx17_flag(self):
# 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(
self, "the C++17 standard", "cxx17_flag", "Xcode < 6.1.0"
)
diff --git a/lib/spack/spack/compilers/cce.py b/lib/spack/spack/compilers/cce.py
index 55718c292a..a325bf3a45 100644
--- a/lib/spack/spack/compilers/cce.py
+++ b/lib/spack/spack/compilers/cce.py
@@ -34,7 +34,7 @@ class Cce(Compiler):
@property
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)
@property
@@ -69,9 +69,9 @@ class Cce(Compiler):
def c99_flag(self):
if self.is_clang_based:
return '-std=c99'
- elif self.version >= ver('8.4'):
+ elif self.real_version >= ver('8.4'):
return '-h std=c99,noconform,gnu'
- elif self.version >= ver('8.1'):
+ elif self.real_version >= ver('8.1'):
return '-h c99,noconform,gnu'
raise UnsupportedCompilerFlag(self,
'the C99 standard',
@@ -82,7 +82,7 @@ class Cce(Compiler):
def c11_flag(self):
if self.is_clang_based:
return '-std=c11'
- elif self.version >= ver('8.5'):
+ elif self.real_version >= ver('8.5'):
return '-h std=c11,noconform,gnu'
raise UnsupportedCompilerFlag(self,
'the C11 standard',
diff --git a/lib/spack/spack/compilers/clang.py b/lib/spack/spack/compilers/clang.py
index f158ff3276..2f8c7d43e3 100644
--- a/lib/spack/spack/compilers/clang.py
+++ b/lib/spack/spack/compilers/clang.py
@@ -90,7 +90,7 @@ class Clang(Compiler):
@property
def cxx11_flag(self):
- if self.version < ver('3.3'):
+ if self.real_version < ver('3.3'):
raise UnsupportedCompilerFlag(
self, "the C++11 standard", "cxx11_flag", "< 3.3"
)
@@ -98,22 +98,22 @@ class Clang(Compiler):
@property
def cxx14_flag(self):
- if self.version < ver('3.4'):
+ if self.real_version < ver('3.4'):
raise UnsupportedCompilerFlag(
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++14"
@property
def cxx17_flag(self):
- if self.version < ver('3.5'):
+ if self.real_version < ver('3.5'):
raise UnsupportedCompilerFlag(
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++17"
@@ -124,7 +124,7 @@ class Clang(Compiler):
@property
def c11_flag(self):
- if self.version < ver('6.1.0'):
+ if self.real_version < ver('6.1.0'):
raise UnsupportedCompilerFlag(self,
"the C11 standard",
"c11_flag",
diff --git a/lib/spack/spack/compilers/gcc.py b/lib/spack/spack/compilers/gcc.py
index 8a19e7d1b5..02ee3e5db9 100644
--- a/lib/spack/spack/compilers/gcc.py
+++ b/lib/spack/spack/compilers/gcc.py
@@ -56,53 +56,53 @@ class Gcc(spack.compiler.Compiler):
@property
def cxx98_flag(self):
- if self.version < ver('6.0'):
+ if self.real_version < ver('6.0'):
return ""
else:
return "-std=c++98"
@property
def cxx11_flag(self):
- if self.version < ver('4.3'):
+ if self.real_version < ver('4.3'):
raise spack.compiler.UnsupportedCompilerFlag(
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"
else:
return "-std=c++11"
@property
def cxx14_flag(self):
- if self.version < ver('4.8'):
+ if self.real_version < ver('4.8'):
raise spack.compiler.UnsupportedCompilerFlag(
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"
- elif self.version < ver('6.0'):
+ elif self.real_version < ver('6.0'):
return "-std=c++14"
else:
return ""
@property
def cxx17_flag(self):
- if self.version < ver('5.0'):
+ if self.real_version < ver('5.0'):
raise spack.compiler.UnsupportedCompilerFlag(
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"
else:
return "-std=c++17"
@property
def c99_flag(self):
- if self.version < ver('4.5'):
+ if self.real_version < ver('4.5'):
raise spack.compiler.UnsupportedCompilerFlag(
self, "the C99 standard", "c99_flag", "< 4.5")
return "-std=c99"
@property
def c11_flag(self):
- if self.version < ver('4.7'):
+ if self.real_version < ver('4.7'):
raise spack.compiler.UnsupportedCompilerFlag(
self, "the C11 standard", "c11_flag", "< 4.7")
return "-std=c11"
diff --git a/lib/spack/spack/compilers/intel.py b/lib/spack/spack/compilers/intel.py
index b44ed73d6f..5e64a1439e 100644
--- a/lib/spack/spack/compilers/intel.py
+++ b/lib/spack/spack/compilers/intel.py
@@ -48,20 +48,20 @@ class Intel(Compiler):
@property
def openmp_flag(self):
- if self.version < ver('16.0'):
+ if self.real_version < ver('16.0'):
return "-openmp"
else:
return "-qopenmp"
@property
def cxx11_flag(self):
- if self.version < ver('11.1'):
+ if self.real_version < ver('11.1'):
raise UnsupportedCompilerFlag(self,
"the C++11 standard",
"cxx11_flag",
"< 11.1")
- elif self.version < ver('13'):
+ elif self.real_version < ver('13'):
return "-std=c++0x"
else:
return "-std=c++11"
@@ -69,19 +69,19 @@ class Intel(Compiler):
@property
def cxx14_flag(self):
# Adapted from CMake's Intel-CXX rules.
- if self.version < ver('15'):
+ if self.real_version < ver('15'):
raise UnsupportedCompilerFlag(self,
"the C++14 standard",
"cxx14_flag",
"< 15")
- elif self.version < ver('15.0.2'):
+ elif self.real_version < ver('15.0.2'):
return "-std=c++1y"
else:
return "-std=c++14"
@property
def c99_flag(self):
- if self.version < ver('12'):
+ if self.real_version < ver('12'):
raise UnsupportedCompilerFlag(self,
"the C99 standard",
"c99_flag",
@@ -91,7 +91,7 @@ class Intel(Compiler):
@property
def c11_flag(self):
- if self.version < ver('16'):
+ if self.real_version < ver('16'):
raise UnsupportedCompilerFlag(self,
"the C11 standard",
"c11_flag",
diff --git a/lib/spack/spack/compilers/pgi.py b/lib/spack/spack/compilers/pgi.py
index f782e1fc86..383281a9f4 100644
--- a/lib/spack/spack/compilers/pgi.py
+++ b/lib/spack/spack/compilers/pgi.py
@@ -73,7 +73,7 @@ class Pgi(Compiler):
@property
def c99_flag(self):
- if self.version >= ver('12.10'):
+ if self.real_version >= ver('12.10'):
return '-c99'
raise UnsupportedCompilerFlag(self,
'the C99 standard',
@@ -82,7 +82,7 @@ class Pgi(Compiler):
@property
def c11_flag(self):
- if self.version >= ver('15.3'):
+ if self.real_version >= ver('15.3'):
return '-c11'
raise UnsupportedCompilerFlag(self,
'the C11 standard',
diff --git a/lib/spack/spack/compilers/xl.py b/lib/spack/spack/compilers/xl.py
index ce74ec47c1..66009646e3 100644
--- a/lib/spack/spack/compilers/xl.py
+++ b/lib/spack/spack/compilers/xl.py
@@ -47,7 +47,7 @@ class Xl(Compiler):
@property
def cxx11_flag(self):
- if self.version < ver('13.1'):
+ if self.real_version < ver('13.1'):
raise UnsupportedCompilerFlag(self,
"the C++11 standard",
"cxx11_flag",
@@ -57,9 +57,9 @@ class Xl(Compiler):
@property
def c99_flag(self):
- if self.version >= ver('13.1.1'):
+ if self.real_version >= ver('13.1.1'):
return '-std=gnu99'
- if self.version >= ver('10.1'):
+ if self.real_version >= ver('10.1'):
return '-qlanglvl=extc99'
raise UnsupportedCompilerFlag(self,
'the C99 standard',
@@ -68,9 +68,9 @@ class Xl(Compiler):
@property
def c11_flag(self):
- if self.version >= ver('13.1.2'):
+ if self.real_version >= ver('13.1.2'):
return '-std=gnu11'
- if self.version >= ver('12.1'):
+ if self.real_version >= ver('12.1'):
return '-qlanglvl=extc1x'
raise UnsupportedCompilerFlag(self,
'the C11 standard',
diff --git a/lib/spack/spack/test/compilers/basics.py b/lib/spack/spack/test/compilers/basics.py
index acc7c7e5f0..762a2e67aa 100644
--- a/lib/spack/spack/test/compilers/basics.py
+++ b/lib/spack/spack/test/compilers/basics.py
@@ -739,6 +739,41 @@ fi
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):
"""Test a code path that is taken only if the package uses
Xcode on MacOS.