diff options
author | Todd Gamblin <tgamblin@llnl.gov> | 2017-04-21 15:45:12 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-21 15:45:12 -0700 |
commit | c67f8e4aa1d0d19c4c83d366d153d99428fcfb16 (patch) | |
tree | 37d93b8cb38f6eaabd0322c754e72f2a4bd73763 | |
parent | 63c341037033f683221a7ede9d6b24e86ddf0951 (diff) | |
download | spack-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.
-rw-r--r-- | lib/spack/spack/abi.py | 9 | ||||
-rw-r--r-- | lib/spack/spack/compiler.py | 7 | ||||
-rw-r--r-- | lib/spack/spack/compilers/gcc.py | 10 | ||||
-rw-r--r-- | lib/spack/spack/test/cmd/test_compiler_cmd.py | 4 |
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) |