summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2017-04-21 15:45:12 -0700
committerGitHub <noreply@github.com>2017-04-21 15:45:12 -0700
commitc67f8e4aa1d0d19c4c83d366d153d99428fcfb16 (patch)
tree37d93b8cb38f6eaabd0322c754e72f2a4bd73763 /lib
parent63c341037033f683221a7ede9d6b24e86ddf0951 (diff)
downloadspack-c67f8e4aa1d0d19c4c83d366d153d99428fcfb16.tar.gz
spack-c67f8e4aa1d0d19c4c83d366d153d99428fcfb16.tar.bz2
spack-c67f8e4aa1d0d19c4c83d366d153d99428fcfb16.tar.xz
spack-c67f8e4aa1d0d19c4c83d366d153d99428fcfb16.zip
Fix ABI detection issues with macOS gcc. (#3854)
- gcc on macOS says it's version 4.2.1, but it's really clang, and it's actually the *same* clang as the system clang. - It also doesn't respond with a full path when called with --print-file-name=libstdc++.dylib, which is expected from gcc in abi.py. Instead, it gives a relative path and _gcc_compiler_compare doesn't understand what to do with it. This results in errors like: ``` lib/spack/spack/abi.py, line 71, in _gcc_get_libstdcxx_version libpath = os.readlink(output.strip()) OSError: [Errno 2] No such file or directory: 'libstdc++.dylib' ``` - This commit does two things: 1. Ignore any gcc that's actually clang in abi.py. We can probably do better than this, but it's not clear there is a need to, since we should handle the compiler as clang, not gcc. 2. Don't auto-detect any "gcc" that is actually clang anymore. Ignore it and expect people to use clang (which is the default macOS compiler anyway). Users can still add fake gccs to their compilers.yaml if they want, but it's discouraged.
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/abi.py9
-rw-r--r--lib/spack/spack/compiler.py7
-rw-r--r--lib/spack/spack/compilers/gcc.py10
-rw-r--r--lib/spack/spack/test/cmd/test_compiler_cmd.py4
4 files changed, 23 insertions, 7 deletions
diff --git a/lib/spack/spack/abi.py b/lib/spack/spack/abi.py
index b3b1dd6d27..ad3cae6ee2 100644
--- a/lib/spack/spack/abi.py
+++ b/lib/spack/spack/abi.py
@@ -29,6 +29,7 @@ import spack.spec
from spack.build_environment import dso_suffix
from spack.spec import CompilerSpec
from spack.util.executable import Executable, ProcessError
+from spack.compilers.clang import Clang
from llnl.util.lang import memoized
@@ -44,7 +45,7 @@ class ABI(object):
@memoized
def _gcc_get_libstdcxx_version(self, version):
"""Returns gcc ABI compatibility info by getting the library version of
- a compiler's libstdc++.so or libgcc_s.so"""
+ a compiler's libstdc++ or libgcc_s"""
spec = CompilerSpec("gcc", version)
compilers = spack.compilers.compilers_for_spec(spec)
if not compilers:
@@ -62,6 +63,12 @@ class ABI(object):
else:
return None
try:
+ # Some gcc's are actually clang and don't respond properly to
+ # --print-file-name (they just print the filename, not the
+ # full path). Ignore these and expect them to be handled as clang.
+ if Clang.default_version(rungcc.exe[0]) != 'unknown':
+ return None
+
output = rungcc("--print-file-name=%s" % libname,
return_output=True)
except ProcessError:
diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py
index 90af900d0d..bfce31a9a3 100644
--- a/lib/spack/spack/compiler.py
+++ b/lib/spack/spack/compiler.py
@@ -49,14 +49,15 @@ _version_cache = {}
def get_compiler_version(compiler_path, version_arg, regex='(.*)'):
- if compiler_path not in _version_cache:
+ key = (compiler_path, version_arg, regex)
+ if key not in _version_cache:
compiler = Executable(compiler_path)
output = compiler(version_arg, output=str, error=str)
match = re.search(regex, output)
- _version_cache[compiler_path] = match.group(1) if match else 'unknown'
+ _version_cache[key] = match.group(1) if match else 'unknown'
- return _version_cache[compiler_path]
+ return _version_cache[key]
def dumpversion(compiler_path):
diff --git a/lib/spack/spack/compilers/gcc.py b/lib/spack/spack/compilers/gcc.py
index 304f82a492..826ddbf432 100644
--- a/lib/spack/spack/compilers/gcc.py
+++ b/lib/spack/spack/compilers/gcc.py
@@ -88,6 +88,16 @@ class Gcc(Compiler):
return "-fPIC"
@classmethod
+ def default_version(cls, cc):
+ # Skip any gcc versions that are actually clang, like Apple's gcc.
+ # Returning "unknown" makes them not detected by default.
+ # Users can add these manually to compilers.yaml at their own risk.
+ if spack.compilers.clang.Clang.default_version(cc) != 'unknown':
+ return 'unknown'
+
+ return super(Gcc, cls).default_version(cc)
+
+ @classmethod
def fc_version(cls, fc):
return get_compiler_version(
fc, '-dumpversion',
diff --git a/lib/spack/spack/test/cmd/test_compiler_cmd.py b/lib/spack/spack/test/cmd/test_compiler_cmd.py
index 842b64039e..b046cdb922 100644
--- a/lib/spack/spack/test/cmd/test_compiler_cmd.py
+++ b/lib/spack/spack/test/cmd/test_compiler_cmd.py
@@ -89,6 +89,4 @@ class TestCompilerCommand(object):
# Ensure new compiler is in there
new_compilers = set(spack.compilers.all_compiler_specs())
new_compiler = new_compilers - old_compilers
- assert new_compiler
- assert sum(1 for c in new_compiler if
- c.version == Version(test_version)) > 0
+ assert any(c.version == Version(test_version) for c in new_compiler)