diff --git a/lib/spack/spack/compilers/apple_clang.py b/lib/spack/spack/compilers/apple_clang.py index 8ef58550ea..63e0a9c42f 100644 --- a/lib/spack/spack/compilers/apple_clang.py +++ b/lib/spack/spack/compilers/apple_clang.py @@ -23,7 +23,12 @@ def extract_version_from_output(cls, output): ver = 'unknown' match = re.search( # Apple's LLVM compiler has its own versions, so suffix them. - r'^Apple (?:LLVM|clang) version ([^ )]+)', output + r'^Apple (?:LLVM|clang) version ([^ )]+)', + output, + # Multi-line, since 'Apple clang' may not be on the first line + # in particular, when run as gcc, it seems to output + # "Configured with: --prefix=..." as the first line + re.M, ) if match: ver = match.group(match.lastindex) diff --git a/lib/spack/spack/compilers/gcc.py b/lib/spack/spack/compilers/gcc.py index 98809eea25..8a19e7d1b5 100644 --- a/lib/spack/spack/compilers/gcc.py +++ b/lib/spack/spack/compilers/gcc.py @@ -5,13 +5,13 @@ import re -import spack.compilers.clang +import spack.compiler +import spack.compilers.apple_clang as apple_clang -from spack.compiler import Compiler, UnsupportedCompilerFlag from spack.version import ver -class Gcc(Compiler): +class Gcc(spack.compiler.Compiler): # Subclasses use possible names of C compiler cc_names = ['gcc'] @@ -64,10 +64,8 @@ def cxx98_flag(self): @property def cxx11_flag(self): if self.version < ver('4.3'): - raise UnsupportedCompilerFlag(self, - "the C++11 standard", - "cxx11_flag", - " < 4.3") + raise spack.compiler.UnsupportedCompilerFlag( + self, "the C++11 standard", "cxx11_flag", " < 4.3") elif self.version < ver('4.7'): return "-std=c++0x" else: @@ -76,10 +74,8 @@ def cxx11_flag(self): @property def cxx14_flag(self): if self.version < ver('4.8'): - raise UnsupportedCompilerFlag(self, - "the C++14 standard", - "cxx14_flag", - "< 4.8") + raise spack.compiler.UnsupportedCompilerFlag( + self, "the C++14 standard", "cxx14_flag", "< 4.8") elif self.version < ver('4.9'): return "-std=c++1y" elif self.version < ver('6.0'): @@ -90,10 +86,8 @@ def cxx14_flag(self): @property def cxx17_flag(self): if self.version < ver('5.0'): - raise UnsupportedCompilerFlag(self, - "the C++17 standard", - "cxx17_flag", - "< 5.0") + raise spack.compiler.UnsupportedCompilerFlag( + self, "the C++17 standard", "cxx17_flag", "< 5.0") elif self.version < ver('6.0'): return "-std=c++1z" else: @@ -102,19 +96,15 @@ def cxx17_flag(self): @property def c99_flag(self): if self.version < ver('4.5'): - raise UnsupportedCompilerFlag(self, - "the C99 standard", - "c99_flag", - "< 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'): - raise UnsupportedCompilerFlag(self, - "the C11 standard", - "c11_flag", - "< 4.7") + raise spack.compiler.UnsupportedCompilerFlag( + self, "the C11 standard", "c11_flag", "< 4.7") return "-std=c11" @property @@ -152,10 +142,10 @@ def default_version(cls, cc): 7.2.0 """ - # 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': + # Apple's gcc is actually apple clang, so skip it. Returning + # "unknown" ensures this compiler is not detected by default. + # Users can add it manually to compilers.yaml at their own risk. + if apple_clang.AppleClang.default_version(cc) != 'unknown': return 'unknown' version = super(Gcc, cls).default_version(cc) diff --git a/lib/spack/spack/test/cmd/compiler.py b/lib/spack/spack/test/cmd/compiler.py index 0476275a5f..f496727081 100644 --- a/lib/spack/spack/test/cmd/compiler.py +++ b/lib/spack/spack/test/cmd/compiler.py @@ -64,7 +64,7 @@ def test_compiler_find_without_paths(no_compilers_yaml, working_env, tmpdir): with tmpdir.as_cwd(): with open('gcc', 'w') as f: f.write("""\ -#!/bin/bash +#!/bin/sh echo "0.0.0" """) os.chmod('gcc', 0o700) @@ -75,6 +75,33 @@ def test_compiler_find_without_paths(no_compilers_yaml, working_env, tmpdir): assert 'gcc' in output +@pytest.mark.regression('17589') +def test_compiler_find_no_apple_gcc(no_compilers_yaml, working_env, tmpdir): + with tmpdir.as_cwd(): + # make a script to emulate apple gcc's version args + with open('gcc', 'w') as f: + f.write("""\ +#!/bin/sh +if [ "$1" = "-dumpversion" ]; then + echo "4.2.1" +elif [ "$1" = "--version" ]; then + echo "Configured with: --prefix=/dummy" + echo "Apple clang version 11.0.0 (clang-1100.0.33.16)" + echo "Target: x86_64-apple-darwin18.7.0" + echo "Thread model: posix" + echo "InstalledDir: /dummy" +else + echo "clang: error: no input files" +fi +""") + os.chmod('gcc', 0o700) + + os.environ['PATH'] = str(tmpdir) + output = compiler('find', '--scope=site') + + assert 'gcc' not in output + + def test_compiler_remove(mutable_config, mock_packages): args = spack.util.pattern.Bunch( all=True, compiler_spec='gcc@4.5.0', add_paths=[], scope=None