diff options
41 files changed, 1374 insertions, 697 deletions
diff --git a/lib/spack/docs/getting_started.rst b/lib/spack/docs/getting_started.rst index 25dfc95ee5..9435111c8e 100644 --- a/lib/spack/docs/getting_started.rst +++ b/lib/spack/docs/getting_started.rst @@ -478,6 +478,13 @@ prefix, you can add them to the ``extra_attributes`` field. Similarly, all other fields from the compilers config can be added to the ``extra_attributes`` field for an external representing a compiler. +Note that the format for the ``paths`` field in the +``extra_attributes`` section is different than in the ``compilers`` +config. For compilers configured as external packages, the section is +named ``compilers`` and the dictionary maps language names (``c``, +``cxx``, ``fortran``) to paths, rather than using the names ``cc``, +``fc``, and ``f77``. + .. code-block:: yaml packages: @@ -493,11 +500,10 @@ all other fields from the compilers config can be added to the - spec: llvm+clang@15.0.0 arch=linux-rhel8-skylake prefix: /usr extra_attributes: - paths: - cc: /usr/bin/clang-with-suffix + compilers: + c: /usr/bin/clang-with-suffix cxx: /usr/bin/clang++-with-extra-info - fc: /usr/bin/gfortran - f77: /usr/bin/gfortran + fortran: /usr/bin/gfortran extra_rpaths: - /usr/lib/llvm/ diff --git a/lib/spack/spack/build_systems/compiler.py b/lib/spack/spack/build_systems/compiler.py new file mode 100644 index 0000000000..d441b57b2e --- /dev/null +++ b/lib/spack/spack/build_systems/compiler.py @@ -0,0 +1,144 @@ +# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) +import itertools +import os +import pathlib +import re +import sys +from typing import Dict, List, Sequence, Tuple, Union + +import llnl.util.tty as tty +from llnl.util.lang import classproperty + +import spack.compiler +import spack.package_base + +# Local "type" for type hints +Path = Union[str, pathlib.Path] + + +class CompilerPackage(spack.package_base.PackageBase): + """A Package mixin for all common logic for packages that implement compilers""" + + # TODO: how do these play nicely with other tags + tags: Sequence[str] = ["compiler"] + + #: Optional suffix regexes for searching for this type of compiler. + #: Suffixes are used by some frameworks, e.g. macports uses an '-mp-X.Y' + #: version suffix for gcc. + compiler_suffixes: List[str] = [r"-.*"] + + #: Optional prefix regexes for searching for this compiler + compiler_prefixes: List[str] = [] + + #: Compiler argument(s) that produces version information + #: If multiple arguments, the earlier arguments must produce errors when invalid + compiler_version_argument: Union[str, Tuple[str]] = "-dumpversion" + + #: Regex used to extract version from compiler's output + compiler_version_regex: str = "(.*)" + + #: Static definition of languages supported by this class + compiler_languages: Sequence[str] = ["c", "cxx", "fortran"] + + def __init__(self, spec: "spack.spec.Spec"): + super().__init__(spec) + msg = f"Supported languages for {spec} are not a subset of possible supported languages" + msg += f" supports: {self.supported_languages}, valid values: {self.compiler_languages}" + assert set(self.supported_languages) <= set(self.compiler_languages), msg + + @property + def supported_languages(self) -> Sequence[str]: + """Dynamic definition of languages supported by this package""" + return self.compiler_languages + + @classproperty + def compiler_names(cls) -> Sequence[str]: + """Construct list of compiler names from per-language names""" + names = [] + for language in cls.compiler_languages: + names.extend(getattr(cls, f"{language}_names")) + return names + + @classproperty + def executables(cls) -> Sequence[str]: + """Construct executables for external detection from names, prefixes, and suffixes.""" + regexp_fmt = r"^({0}){1}({2})$" + prefixes = [""] + cls.compiler_prefixes + suffixes = [""] + cls.compiler_suffixes + if sys.platform == "win32": + ext = r"\.(?:exe|bat)" + suffixes += [suf + ext for suf in suffixes] + return [ + regexp_fmt.format(prefix, re.escape(name), suffix) + for prefix, name, suffix in itertools.product(prefixes, cls.compiler_names, suffixes) + ] + + @classmethod + def determine_version(cls, exe: Path): + version_argument = cls.compiler_version_argument + if isinstance(version_argument, str): + version_argument = (version_argument,) + + for va in version_argument: + try: + output = spack.compiler.get_compiler_version_output(exe, va) + match = re.search(cls.compiler_version_regex, output) + if match: + return ".".join(match.groups()) + except spack.util.executable.ProcessError: + pass + except Exception as e: + tty.debug( + f"[{__file__}] Cannot detect a valid version for the executable " + f"{str(exe)}, for package '{cls.name}': {e}" + ) + + @classmethod + def compiler_bindir(cls, prefix: Path) -> Path: + """Overridable method for the location of the compiler bindir within the preifx""" + return os.path.join(prefix, "bin") + + @classmethod + def determine_compiler_paths(cls, exes: Sequence[Path]) -> Dict[str, Path]: + """Compute the paths to compiler executables associated with this package + + This is a helper method for ``determine_variants`` to compute the ``extra_attributes`` + to include with each spec object.""" + # There are often at least two copies (not symlinks) of each compiler executable in the + # same directory: one with a canonical name, e.g. "gfortran", and another one with the + # target prefix, e.g. "x86_64-pc-linux-gnu-gfortran". There also might be a copy of "gcc" + # with the version suffix, e.g. "x86_64-pc-linux-gnu-gcc-6.3.0". To ensure the consistency + # of values in the "paths" dictionary (i.e. we prefer all of them to reference copies + # with canonical names if possible), we iterate over the executables in the reversed sorted + # order: + # First pass over languages identifies exes that are perfect matches for canonical names + # Second pass checks for names with prefix/suffix + # Second pass is sorted by language name length because longer named languages + # e.g. cxx can often contain the names of shorter named languages + # e.g. c (e.g. clang/clang++) + paths = {} + exes = sorted(exes, reverse=True) + languages = { + lang: getattr(cls, f"{lang}_names") + for lang in sorted(cls.compiler_languages, key=len, reverse=True) + } + for exe in exes: + for lang, names in languages.items(): + if os.path.basename(exe) in names: + paths[lang] = exe + break + else: + for lang, names in languages.items(): + if any(name in os.path.basename(exe) for name in names): + paths[lang] = exe + break + + return paths + + @classmethod + def determine_variants(cls, exes: Sequence[Path], version_str: str) -> Tuple: + # path determination is separated so it can be reused in subclasses + return "", {"compilers": cls.determine_compiler_paths(exes=exes)} diff --git a/lib/spack/spack/compilers/__init__.py b/lib/spack/spack/compilers/__init__.py index a52d787f02..8ce9d81120 100644 --- a/lib/spack/spack/compilers/__init__.py +++ b/lib/spack/spack/compilers/__init__.py @@ -164,33 +164,56 @@ def _compiler_config_from_package_config(config): def _compiler_config_from_external(config): + extra_attributes_key = "extra_attributes" + compilers_key = "compilers" + c_key, cxx_key, fortran_key = "c", "cxx", "fortran" + + # Allow `@x.y.z` instead of `@=x.y.z` spec = spack.spec.parse_with_version_concrete(config["spec"]) - # use str(spec.versions) to allow `@x.y.z` instead of `@=x.y.z` + compiler_spec = spack.spec.CompilerSpec( package_name_to_compiler_name.get(spec.name, spec.name), spec.version ) - extra_attributes = config.get("extra_attributes", {}) - prefix = config.get("prefix", None) - - compiler_class = class_for_compiler_name(compiler_spec.name) - paths = extra_attributes.get("paths", {}) - compiler_langs = ["cc", "cxx", "fc", "f77"] - for lang in compiler_langs: - if paths.setdefault(lang, None): - continue + err_header = f"The external spec '{spec}' cannot be used as a compiler" - if not prefix: - continue + # If extra_attributes is not there I might not want to use this entry as a compiler, + # therefore just leave a debug message, but don't be loud with a warning. + if extra_attributes_key not in config: + tty.debug(f"[{__file__}] {err_header}: missing the '{extra_attributes_key}' key") + return None + extra_attributes = config[extra_attributes_key] - # Check for files that satisfy the naming scheme for this compiler - bindir = os.path.join(prefix, "bin") - for f, regex in itertools.product(os.listdir(bindir), compiler_class.search_regexps(lang)): - if regex.match(f): - paths[lang] = os.path.join(bindir, f) + # If I have 'extra_attributes' warn if 'compilers' is missing, or we don't have a C compiler + if compilers_key not in extra_attributes: + warnings.warn( + f"{err_header}: missing the '{compilers_key}' key under '{extra_attributes_key}'" + ) + return None + attribute_compilers = extra_attributes[compilers_key] - if all(v is None for v in paths.values()): + if c_key not in attribute_compilers: + warnings.warn( + f"{err_header}: missing the C compiler path under " + f"'{extra_attributes_key}:{compilers_key}'" + ) return None + c_compiler = attribute_compilers[c_key] + + # C++ and Fortran compilers are not mandatory, so let's just leave a debug trace + if cxx_key not in attribute_compilers: + tty.debug(f"[{__file__}] The external spec {spec} does not have a C++ compiler") + + if fortran_key not in attribute_compilers: + tty.debug(f"[{__file__}] The external spec {spec} does not have a Fortran compiler") + + # compilers format has cc/fc/f77, externals format has "c/fortran" + paths = { + "cc": c_compiler, + "cxx": attribute_compilers.get(cxx_key, None), + "fc": attribute_compilers.get(fortran_key, None), + "f77": attribute_compilers.get(fortran_key, None), + } if not spec.architecture: host_platform = spack.platforms.host() diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index ac56cf1e1a..d0b7beda1d 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -39,6 +39,7 @@ from spack.build_systems.cached_cmake import ( ) from spack.build_systems.cargo import CargoPackage from spack.build_systems.cmake import CMakePackage, generator +from spack.build_systems.compiler import CompilerPackage from spack.build_systems.cuda import CudaPackage from spack.build_systems.generic import Package from spack.build_systems.gnu import GNUMirrorPackage diff --git a/lib/spack/spack/test/cmd/compiler.py b/lib/spack/spack/test/cmd/compiler.py index 150fd1af54..2fde7fbc92 100644 --- a/lib/spack/spack/test/cmd/compiler.py +++ b/lib/spack/spack/test/cmd/compiler.py @@ -261,15 +261,14 @@ def test_compiler_list_empty(no_compilers_yaml, working_env, compilers_dir): [ ( { - "spec": "gcc@=7.7.7 os=foobar target=x86_64", + "spec": "gcc@=7.7.7 languages=c,cxx,fortran os=foobar target=x86_64", "prefix": "/path/to/fake", "modules": ["gcc/7.7.7", "foobar"], "extra_attributes": { - "paths": { - "cc": "/path/to/fake/gcc", + "compilers": { + "c": "/path/to/fake/gcc", "cxx": "/path/to/fake/g++", - "fc": "/path/to/fake/gfortran", - "f77": "/path/to/fake/gfortran", + "fortran": "/path/to/fake/gfortran", }, "flags": {"fflags": "-ffree-form"}, }, @@ -285,26 +284,7 @@ def test_compiler_list_empty(no_compilers_yaml, working_env, compilers_dir): \tmodules = ['gcc/7.7.7', 'foobar'] \toperating system = foobar """, - ), - ( - { - "spec": "gcc@7.7.7", - "prefix": "{prefix}", - "modules": ["gcc/7.7.7", "foobar"], - "extra_attributes": {"flags": {"fflags": "-ffree-form"}}, - }, - """gcc@7.7.7: -\tpaths: -\t\tcc = {compilers_dir}{sep}gcc-8{suffix} -\t\tcxx = {compilers_dir}{sep}g++-8{suffix} -\t\tf77 = {compilers_dir}{sep}gfortran-8{suffix} -\t\tfc = {compilers_dir}{sep}gfortran-8{suffix} -\tflags: -\t\tfflags = ['-ffree-form'] -\tmodules = ['gcc/7.7.7', 'foobar'] -\toperating system = debian6 -""", - ), + ) ], ) def test_compilers_shows_packages_yaml( diff --git a/lib/spack/spack/test/conftest.py b/lib/spack/spack/test/conftest.py index 59d6171e3d..29c10fb2e3 100644 --- a/lib/spack/spack/test/conftest.py +++ b/lib/spack/spack/test/conftest.py @@ -1694,7 +1694,7 @@ def mock_executable(tmp_path): """Factory to create a mock executable in a temporary directory that output a custom string when run. """ - shebang = "#!/bin/sh\n" if sys.platform != "win32" else "@ECHO OFF" + shebang = "#!/bin/sh\n" if sys.platform != "win32" else "@ECHO OFF\n" def _factory(name, output, subdir=("bin",)): executable_dir = tmp_path.joinpath(*subdir) diff --git a/var/spack/repos/builtin/packages/acfl/detection_test.yaml b/var/spack/repos/builtin/packages/acfl/detection_test.yaml new file mode 100644 index 0000000000..23fc1930f2 --- /dev/null +++ b/var/spack/repos/builtin/packages/acfl/detection_test.yaml @@ -0,0 +1,83 @@ +paths: +- layout: + - executables: + - "bin/armclang" + - "bin/armclang++" + - "bin/armflang" + script: | + echo "Arm C/C++/Fortran Compiler version 19.0 (build number 73) (based on LLVM 7.0.2)" + echo "Target: aarch64--linux-gnu" + echo "Thread model: posix" + echo "InstalledDir:" + echo "/opt/arm/arm-hpc-compiler-19.0_Generic-AArch64_RHEL-7_aarch64-linux/bin" + platforms: [linux] + results: + - spec: acfl@19.0 + extra_attributes: + compilers: + c: ".*/bin/armclang" + cxx: ".*/bin/armclang[+][+]" + fortran: ".*/bin/armflang" +- layout: + - executables: + - "bin/armclang" + - "bin/armclang++" + script: | + echo "Arm C/C++/Fortran Compiler version 19.0 (build number 73) (based on LLVM 7.0.2)" + echo "Target: aarch64--linux-gnu" + echo "Thread model: posix" + echo "InstalledDir:" + echo "/opt/arm/arm-hpc-compiler-19.0_Generic-AArch64_RHEL-7_aarch64-linux/bin" + platforms: [linux] + results: + - spec: acfl@19.0 + extra_attributes: + compilers: + c: ".*/bin/armclang" + cxx: ".*/bin/armclang[+][+]" +- layout: + - executables: + - "bin/armclang" + - "bin/armclang++" + - "bin/armflang" + script: | + echo "Arm C/C++/Fortran Compiler version 19.3.1 (build number 75) (based on LLVM 7.0.2)" + echo "Target: aarch64--linux-gnu" + echo "Thread model: posix" + echo "InstalledDir:" + echo "/opt/arm/arm-hpc-compiler-19.3.5_Generic-AArch64_RHEL-7_aarch64-linux/bin" + - executables: + - "bin/armclang-18" + - "bin/armclang++-18" + - "bin/armflang-18" + script: | + echo "Arm C/C++/Fortran Compiler version 18.0 (build number 27) (based on LLVM 7.0.0)" + echo "Target: aarch64--linux-gnu" + echo "Thread model: posix" + echo "InstalledDir:" + echo "/opt/arm/arm-hpc-compiler-19_Generic-AArch64_RHEL-7_aarch64-linux/bin" + platforms: [linux] + results: + - spec: acfl@19.3.1 + extra_attributes: + compilers: + c: ".*/bin/armclang$" + cxx: ".*/bin/armclang[+][+]$" + fortran: ".*/bin/armflang$" + - spec: acfl@18.0 + extra_attributes: + compilers: + c: ".*/bin/armclang-18" + cxx: ".*/bin/armclang[+][+]-18" + fortran: ".*/bin/armflang-18" +- layout: # does not detect upstream clang + - executables: + - "bin/clang" + - "bin/clang++" + script: | + echo "clang version 8.0.0 (tags/RELEASE_800/final" + echo "Target: x86_64-unknown-linux-gnu\n" + echo "Thread model: posix\n" + echo "InstalledDir: /usr/bin" + platforms: [linux] + results: [] diff --git a/var/spack/repos/builtin/packages/acfl/package.py b/var/spack/repos/builtin/packages/acfl/package.py index fefab9b574..66d2ddc0b5 100644 --- a/var/spack/repos/builtin/packages/acfl/package.py +++ b/var/spack/repos/builtin/packages/acfl/package.py @@ -3,7 +3,6 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) import os -import re from spack.package import * @@ -228,7 +227,7 @@ def get_gcc_prefix(spec): return join_path(spec.prefix, next(dir for dir in dirlist if dir.startswith("gcc"))) -class Acfl(Package): +class Acfl(Package, CompilerPackage): """Arm Compiler combines the optimized tools and libraries from Arm with a modern LLVM-based compiler framework. """ @@ -275,33 +274,15 @@ class Acfl(Package): ) exe("--accept", "--force", "--install-to", prefix) - @classmethod - def determine_version(cls, exe): - regex_str = r"Arm C\/C\+\+\/Fortran Compiler version ([\d\.]+) " r"\(build number (\d+)\) " - version_regex = re.compile(regex_str) - try: - output = spack.compiler.get_compiler_version_output(exe, "--version") - match = version_regex.search(output) - if match: - if match.group(1).count(".") == 1: - return match.group(1) + ".0." + match.group(2) - return match.group(1) + "." + match.group(2) - except spack.util.executable.ProcessError: - pass - except Exception as e: - tty.debug(e) - - @classmethod - def determine_variants(cls, exes, version_str): - compilers = {} - for exe in exes: - if "armclang" in exe: - compilers["c"] = exe - if "armclang++" in exe: - compilers["cxx"] = exe - if "armflang" in exe: - compilers["fortran"] = exe - return "", {"compilers": compilers} + compiler_languages = ["c", "cxx", "fortran"] + c_names = ["armclang"] + cxx_names = ["armclang++"] + fortran_names = ["armflang"] + + compiler_version_argument = "--version" + compiler_version_regex = ( + r"Arm C\/C\+\+\/Fortran Compiler version ([\d\.]+) \(build number \d+\) " + ) @property def cc(self): diff --git a/var/spack/repos/builtin/packages/aocc/detection_test.yaml b/var/spack/repos/builtin/packages/aocc/detection_test.yaml new file mode 100644 index 0000000000..331ba0ba4a --- /dev/null +++ b/var/spack/repos/builtin/packages/aocc/detection_test.yaml @@ -0,0 +1,75 @@ +paths: +- layout: + - executables: + - "bin/clang" + - "bin/clang++" + - "bin/flang" + script: | + echo "AMD clang version 12.0.0 (CLANG: AOCC_3_1_0-Build#126 2021_06_07)(based on LLVM Mirror.Version.12.0.0)\n" + echo "Target: x86_64-unknown-linux-gnu\n" + echo "Thread model: posix\n" + platforms: [linux] + results: + - spec: aocc@3.1.0 + extra_attributes: + compilers: + c: ".*/bin/clang" + cxx: ".*/bin/clang[+][+]" + fortran: ".*/bin/flang" +- layout: + - executables: + - "bin/clang" + - "bin/clang++" + script: | + echo "AMD clang version 12.0.0 (CLANG: AOCC_3_1_0-Build#126 2021_06_07)(based on LLVM Mirror.Version.12.0.0)\n" + echo "Target: x86_64-unknown-linux-gnu\n" + echo "Thread model: posix\n" + platforms: [linux] + results: + - spec: aocc@3.1.0 + extra_attributes: + compilers: + c: ".*/bin/clang" + cxx: ".*/bin/clang[+][+]" +- layout: + - executables: + - "bin/clang" + - "bin/clang++" + - "bin/flang" + script: | + echo "AMD clang version 12.0.0 (CLANG: AOCC_3_0_0-Build#78 2020_12_10)(based on LLVM Mirror.Version.12.0.0)\n" + echo "Target: x86_64-unknown-linux-gnu\n" + echo "Thread model: posix\n" + - executables: + - "bin/clang-11" + - "bin/clang++-11" + - "bin/flang-11" + script: | + echo "AMD clang version 11.0.0 (CLANG: AOCC_2_3_0-Build#85 2020_11_10)(based on LLVM Mirror.Version.11.0.0)\n" + echo "Target: x86_64-unknown-linux-gnu\n" + echo "Thread model: posix\n" + platforms: [linux] + results: + - spec: aocc@3.0.0 + extra_attributes: + compilers: + c: ".*/bin/clang$" + cxx: ".*/bin/clang[+][+]$" + fortran: ".*/bin/flang$" + - spec: aocc@2.3.0 + extra_attributes: + compilers: + c: ".*/bin/clang-11" + cxx: ".*/bin/clang[+][+]-11" + fortran: ".*/bin/flang-11" +- layout: + - executables: + - "bin/clang" + - "bin/clang++" + script: | + echo "clang version 8.0.0 (tags/RELEASE_800/final" + echo "Target: x86_64-unknown-linux-gnu\n" + echo "Thread model: posix\n" + echo "InstalledDir: /usr/bin" + platforms: [linux] + results: [] diff --git a/var/spack/repos/builtin/packages/aocc/package.py b/var/spack/repos/builtin/packages/aocc/package.py index f51b5d6795..f2451d1f63 100644 --- a/var/spack/repos/builtin/packages/aocc/package.py +++ b/var/spack/repos/builtin/packages/aocc/package.py @@ -8,7 +8,7 @@ from llnl.util import tty from spack.package import * -class Aocc(Package): +class Aocc(Package, CompilerPackage): """ The AOCC compiler system is a high performance, production quality code generation tool. The AOCC environment provides various options to developers @@ -104,3 +104,9 @@ class Aocc(Package): for compiler in ["clang", "clang++"]: with open(join_path(self.prefix.bin, "{}.cfg".format(compiler)), "w") as f: f.write(compiler_options) + + compiler_version_argument = "--version" + compiler_version_regex = r"AOCC_(\d+[._]\d+[._]\d+)" + c_names = ["clang"] + cxx_names = ["clang++"] + fortran_names = ["flang"] diff --git a/var/spack/repos/builtin/packages/apple-clang/detection_test.yaml b/var/spack/repos/builtin/packages/apple-clang/detection_test.yaml index dffdf88286..1e52329116 100644 --- a/var/spack/repos/builtin/packages/apple-clang/detection_test.yaml +++ b/var/spack/repos/builtin/packages/apple-clang/detection_test.yaml @@ -1,38 +1,48 @@ paths: - # Apple Clang on MacBook Pro (Catalina) - - layout: - - executables: - - "bin/clang" - - "bin/clang++" - script: | - echo "Apple clang version 11.0.0 (clang-1100.0.33.8)" - echo "Target: x86_64-apple-darwin19.5.0" - echo "Thread model: posix" - echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin" - platforms: ["darwin"] - results: - - spec: 'apple-clang@11.0.0' - # Apple Clang on Apple M1 (Ventura) - - layout: - - executables: - - "bin/clang" - - "bin/clang++" - script: | - echo "Apple clang version 15.0.0 (clang-1500.0.40.1)" - echo "Target: arm64-apple-darwin22.6.0" - echo "Thread model: posix" - echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin" - platforms: ["darwin"] - results: - - spec: 'apple-clang@15.0.0' - # Test that missing a compiler prevents the package from being detected - - layout: - - executables: - - "bin/clang" - script: | - echo "Apple clang version 11.0.0 (clang-1100.0.33.8)" - echo "Target: x86_64-apple-darwin19.5.0" - echo "Thread model: posix" - echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin" - platforms: ["darwin"] - results: [ ] +# Apple Clang on MacBook Pro (Catalina) +- layout: + - executables: + - "bin/clang" + - "bin/clang++" + script: | + echo "Apple clang version 11.0.0 (clang-1100.0.33.8)" + echo "Target: x86_64-apple-darwin19.5.0" + echo "Thread model: posix" + echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin" + platforms: ["darwin"] + results: + - spec: 'apple-clang@11.0.0' + extra_attributes: + compilers: + c: ".*/bin/clang" + cxx: ".*/bin/clang[+][+]" + +# Apple Clang on Apple M1 (Ventura) +- layout: + - executables: + - "bin/clang" + - "bin/clang++" + script: | + echo "Apple clang version 15.0.0 (clang-1500.0.40.1)" + echo "Target: arm64-apple-darwin22.6.0" + echo "Thread model: posix" + echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin" + platforms: ["darwin"] + results: + - spec: 'apple-clang@15.0.0' + extra_attributes: + compilers: + c: ".*/bin/clang" + cxx: ".*/bin/clang[+][+]" + +# Test that missing a compiler prevents the package from being detected +- layout: + - executables: + - "bin/clang" + script: | + echo "Apple clang version 11.0.0 (clang-1100.0.33.8)" + echo "Target: x86_64-apple-darwin19.5.0" + echo "Thread model: posix" + echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin" + platforms: ["darwin"] + results: [] diff --git a/var/spack/repos/builtin/packages/apple-clang/package.py b/var/spack/repos/builtin/packages/apple-clang/package.py index 634aedf4eb..95c3eb54c0 100644 --- a/var/spack/repos/builtin/packages/apple-clang/package.py +++ b/var/spack/repos/builtin/packages/apple-clang/package.py @@ -2,12 +2,10 @@ # Spack Project Developers. See the top-level COPYRIGHT file for details. # # SPDX-License-Identifier: (Apache-2.0 OR MIT) -import re - from spack.package import * -class AppleClang(BundlePackage): +class AppleClang(BundlePackage, CompilerPackage): """Apple's Clang compiler""" homepage = "https://developer.apple.com/videos/developer-tools/compiler-and-llvm" @@ -15,44 +13,12 @@ class AppleClang(BundlePackage): maintainers("alalazo") - executables = ["^clang$", r"^clang\+\+$", "^ld.lld$", "^lldb$"] - - @classmethod - def determine_version(cls, exe): - version_regex = re.compile( - # Apple's LLVM compiler has its own versions, which are - # different from vanilla LLVM - r"^Apple (?:LLVM|clang) version ([^ )]+)", - # 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, - ) - try: - compiler = Executable(exe) - output = compiler("--version", output=str, error=str) - match = version_regex.search(output) - if match: - return match.group(match.lastindex) - except Exception: - pass - - return None - - @classmethod - def determine_variants(cls, exes, version_str): - compilers = {} - for exe in exes: - if "clang++" in exe: - compilers["cxx"] = exe - elif "clang" in exe: - compilers["c"] = exe - elif "ld.lld" in exe: - compilers["ld"] = exe - elif "lldb" in exe: - compilers["lldb"] = exe + compiler_languages = ["c", "cxx"] + c_names = ["clang"] + cxx_names = ["clang++"] - return "", {"compilers": compilers} + compiler_version_regex = r"^Apple (?:LLVM|clang) version ([^ )]+)" + compiler_version_argument = "--version" @classmethod def validate_detected_spec(cls, spec, extra_attributes): diff --git a/var/spack/repos/builtin/packages/cce/detection_test.yaml b/var/spack/repos/builtin/packages/cce/detection_test.yaml new file mode 100644 index 0000000000..b425ab439a --- /dev/null +++ b/var/spack/repos/builtin/packages/cce/detection_test.yaml @@ -0,0 +1,44 @@ +paths: +- layout: + - executables: + - "bin/craycc" + script: | + echo "Cray C : Version 8.4.6 Mon Apr 15, 2019 12:13:39" + - executables: + - "bin/crayCC" + script: | + echo "Cray C++ : Version 8.4.6 Mon Apr 15, 2019 12:13:39" + - executables: + - "bin/crayftn" + script: | + echo "Cray Fortran : Version 8.4.6 Mon Apr 15, 2019 12:13:39" + platforms: [linux] + results: + - spec: cce@8.4.6 + extra_attributes: + compilers: + c: ".*/bin/craycc" + cxx: ".*/bin/crayCC" + fortran: ".*/bin/crayftn" +- layout: + - executables: + - "bin/craycc" + - "bin/crayCC" + script: | + echo "Cray clang version 17.0.1 (5ec9405551a8c8845cf14e81dc28bff7aa3935cb)" + echo "Target: x86_64-unknown-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /opt/cray/pe/cce/17.0.1/cce-clang/x86_64/share/../bin" + echo "Configuration file: /opt/cray/pe/cce/17.0.1/cce-clang/x86_64/bin/clang.cfg" + - executables: + - "bin/crayftn" + script: | + echo "Cray Fortran : Version 17.0.1" + platforms: [linux] + results: + - spec: cce@17.0.1 + extra_attributes: + compilers: + c: ".*/bin/craycc" + cxx: ".*/bin/crayCC" + fortran: ".*/bin/crayftn" diff --git a/var/spack/repos/builtin/packages/cce/package.py b/var/spack/repos/builtin/packages/cce/package.py new file mode 100644 index 0000000000..0772be6ab1 --- /dev/null +++ b/var/spack/repos/builtin/packages/cce/package.py @@ -0,0 +1,30 @@ +# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) +from spack.package import * + + +class Cce(Package, CompilerPackage): + """Stub package for external detection of the Cray compiler package.""" + + homepage = "https://cpe.ext.hpe.com/docs/cce/index.html" + url = "https://cpe.ext.hpe.com/docs/cce/index.html" + + compiler_languages = ["c", "cxx", "fortran"] + c_names = ["craycc"] + cxx_names = ["crayCC"] + fortran_names = ["crayftn"] + + compiler_version_argument = "--version" + compiler_version_regex = ( + r"[Cc]ray (?:clang|C :|C\+\+ :|Fortran :) [Vv]ersion.*?(\d+(?:\.\d+)+)" + ) + + # notify when the package is updated. + maintainers("becker33") + + version("16.0.0") + + def install(self, spec, prefix): + raise NotImplementedError("cray compiler must be configured as external") diff --git a/var/spack/repos/builtin/packages/fj/detection_test.yaml b/var/spack/repos/builtin/packages/fj/detection_test.yaml new file mode 100644 index 0000000000..9159d20d91 --- /dev/null +++ b/var/spack/repos/builtin/packages/fj/detection_test.yaml @@ -0,0 +1,27 @@ +paths: +- layout: + - executables: + - "bin/fcc" + script: | + echo "fcc (FCC) 4.0.0a 20190314" + echo "simulating gcc version 6.1" + echo "Copyright FUJITSU LIMITED 2019" + - executables: + - "bin/FCC" + script: | + echo "FCC (FCC) 4.0.0a 20190314" + echo "simulating gcc version 6.1" + echo "Copyright FUJITSU LIMITED 2019" + - executables: + - "bin/frt" + script: | + echo "frt (FRT) 4.0.0a 20190314" + echo "Copyright FUJITSU LIMITED 2019" + platforms: [linux] + results: + - spec: fj@4.0.0a + extra_attributes: + compilers: + c: ".*/bin/fcc" + cxx: ".*/bin/FCC" + fortran: ".*/bin/frt" diff --git a/var/spack/repos/builtin/packages/fj/package.py b/var/spack/repos/builtin/packages/fj/package.py index 899f85aa78..9ebcecab2e 100644 --- a/var/spack/repos/builtin/packages/fj/package.py +++ b/var/spack/repos/builtin/packages/fj/package.py @@ -2,16 +2,10 @@ # Spack Project Developers. See the top-level COPYRIGHT file for details. # # SPDX-License-Identifier: (Apache-2.0 OR MIT) -import re - -import llnl.util.tty as tty - -import spack.compiler -import spack.util.executable from spack.package import * -class Fj(Package): +class Fj(Package, CompilerPackage): """The Fujitsu compiler system is a high performance, production quality code generation tool designed for high performance parallel computing workloads. @@ -27,29 +21,9 @@ class Fj(Package): "detected on a system where they are supplied by vendor" ) - executables = ["^fcc", "^FCC", "^frt"] - - @classmethod - def determine_version(cls, exe): - version_regex = re.compile(r"\((?:FCC|FRT)\) ([a-z\d.]+)") - try: - output = spack.compiler.get_compiler_version_output(exe, "--version") - match = version_regex.search(output) - if match: - return match.group(1) - except spack.util.executable.ProcessError: - pass - except Exception as e: - tty.debug(e) - - @classmethod - def determine_variants(cls, exes, version_str): - compilers = {} - for exe in exes: - if "fcc" in exe: - compilers["c"] = exe - if "FCC" in exe: - compilers["cxx"] = exe - if "frt" in exe: - compilers["fortran"] = exe - return "", {"compilers": compilers} + compiler_languages = ["c", "cxx", "fortran"] + c_names = ["fcc"] + cxx_names = ["FCC"] + fortran_names = ["frt"] + compiler_version_regex = r"\((?:FCC|FRT)\) ([a-z\d.]+)" + compiler_version_argument = "--version" diff --git a/var/spack/repos/builtin/packages/gcc/detection_test.yaml b/var/spack/repos/builtin/packages/gcc/detection_test.yaml index 4677a8cdab..7269c0301c 100644 --- a/var/spack/repos/builtin/packages/gcc/detection_test.yaml +++ b/var/spack/repos/builtin/packages/gcc/detection_test.yaml @@ -1,93 +1,96 @@ paths: - # Ubuntu 20.04, system compilers without Fortran. This - # test also covers which flags are expected to be used - # during the detection of gcc. - - layout: - - executables: - - "bin/gcc" - - "bin/g++" - script: | - if [ "$1" = "-dumpversion" ] ; then - echo "9" - elif [ "$1" = "-dumpfullversion" ] ; then - echo "9.4.0" - elif [ "$1" = "--version" ] ; then - echo "gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0" - echo "Copyright (C) 2019 Free Software Foundation, Inc." - echo "This is free software; see the source for copying conditions. There is NO" - echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - else - echo "mock executable got an unexpected flag: $1" - exit 1 - fi - platforms: ["darwin", "linux"] - results: - - spec: "gcc@9.4.0 languages=c,c++" - extra_attributes: - compilers: - c: ".*/bin/gcc" - cxx: ".*/bin/g++" - # Mock a version < 7 of GCC that requires -dumpversion and - # errors with -dumpfullversion - - layout: - - executables: - - "bin/gcc-5" - - "bin/g++-5" - - "bin/gfortran-5" - script: | - if [ "$1" = "-dumpversion" ] ; then - echo "5.5.0" - else - echo "gcc-5: fatal error: no input files" - echo "compilation terminated." - exit 1 - fi - platforms: ["darwin", "linux"] - results: - - spec: "gcc@5.5.0 languages=c,c++,fortran" - extra_attributes: - compilers: - c: ".*/bin/gcc-5$" - cxx: ".*/bin/g[+][+]-5$" - fortran: ".*/bin/gfortran-5$" - # Multiple compilers present at the same time - - layout: - - executables: - - "bin/x86_64-linux-gnu-gcc-6" - script: 'echo 6.5.0' - - executables: - - "bin/x86_64-linux-gnu-gcc-10" - - "bin/x86_64-linux-gnu-g++-10" - script: "echo 10.1.0" - platforms: [darwin, linux] - results: - - spec: "gcc@6.5.0 languages=c" - extra_attributes: - compilers: - c: ".*/bin/x86_64-linux-gnu-gcc-6$" - - spec: "gcc@10.1.0 languages=c,c++" - extra_attributes: - compilers: - c: ".*/bin/x86_64-linux-gnu-gcc-10$" - cxx: ".*/bin/x86_64-linux-gnu-g[+][+]-10$" - # Apple clang under disguise as gcc should not be detected - - layout: - - executables: - - "bin/gcc" - script: | - if [ "$1" = "-dumpversion" ] ; then - echo "15.0.0" - elif [ "$1" = "-dumpfullversion" ] ; then - echo "clang: error: no input files" >&2 - exit 1 - elif [ "$1" = "--version" ] ; then - echo "Apple clang version 15.0.0 (clang-1500.3.9.4)" - echo "Target: x86_64-apple-darwin23.4.0" - echo "Thread model: posix" - echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin" - else - echo "mock executable got an unexpected flag: $1" - exit 1 - fi - platforms: ["darwin"] - results: [] +# Ubuntu 20.04, system compilers without Fortran. This +# test also covers which flags are expected to be used +# during the detection of gcc. +- layout: + - executables: + - "bin/gcc" + - "bin/g++" + script: | + if [ "$1" = "-dumpversion" ] ; then + echo "9" + elif [ "$1" = "-dumpfullversion" ] ; then + echo "9.4.0" + elif [ "$1" = "--version" ] ; then + echo "gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0" + echo "Copyright (C) 2019 Free Software Foundation, Inc." + echo "This is free software; see the source for copying conditions. There is NO" + echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + else + echo "mock executable got an unexpected flag: $1" + exit 1 + fi + platforms: ["darwin", "linux"] + results: + - spec: "gcc@9.4.0 languages=c,c++" + extra_attributes: + compilers: + c: ".*/bin/gcc" + cxx: ".*/bin/g++" + +# Mock a version < 7 of GCC that requires -dumpversion and +# errors with -dumpfullversion +- layout: + - executables: + - "bin/gcc-5" + - "bin/g++-5" + - "bin/gfortran-5" + script: | + if [ "$1" = "-dumpversion" ] ; then + echo "5.5.0" + else + echo "gcc-5: fatal error: no input files" + echo "compilation terminated." + exit 1 + fi + platforms: ["darwin", "linux"] + results: + - spec: "gcc@5.5.0 languages=c,c++,fortran" + extra_attributes: + compilers: + c: ".*/bin/gcc-5$" + cxx: ".*/bin/g[+][+]-5$" + fortran: ".*/bin/gfortran-5$" + +# Multiple compilers present at the same time +- layout: + - executables: + - "bin/x86_64-linux-gnu-gcc-6" + script: 'echo 6.5.0' + - executables: + - "bin/x86_64-linux-gnu-gcc-10" + - "bin/x86_64-linux-gnu-g++-10" + script: "echo 10.1.0" + platforms: [darwin, linux] + results: + - spec: "gcc@6.5.0 languages=c" + extra_attributes: + compilers: + c: ".*/bin/x86_64-linux-gnu-gcc-6$" + - spec: "gcc@10.1.0 languages=c,c++" + extra_attributes: + compilers: + c: ".*/bin/x86_64-linux-gnu-gcc-10$" + cxx: ".*/bin/x86_64-linux-gnu-g[+][+]-10$" + +# Apple clang under disguise as gcc should not be detected +- layout: + - executables: + - "bin/gcc" + script: | + if [ "$1" = "-dumpversion" ] ; then + echo "15.0.0" + elif [ "$1" = "-dumpfullversion" ] ; then + echo "clang: error: no input files" >&2 + exit 1 + elif [ "$1" = "--version" ] ; then + echo "Apple clang version 15.0.0 (clang-1500.3.9.4)" + echo "Target: x86_64-apple-darwin23.4.0" + echo "Thread model: posix" + echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin" + else + echo "mock executable got an unexpected flag: $1" + exit 1 + fi + platforms: ["darwin"] + results: [] diff --git a/var/spack/repos/builtin/packages/gcc/package.py b/var/spack/repos/builtin/packages/gcc/package.py index 0ed2f2f3b8..f10ff1623a 100644 --- a/var/spack/repos/builtin/packages/gcc/package.py +++ b/var/spack/repos/builtin/packages/gcc/package.py @@ -5,13 +5,11 @@ import glob import itertools import os -import re import sys from archspec.cpu import UnsupportedMicroarchitecture import llnl.util.tty as tty -from llnl.util.lang import classproperty from llnl.util.symlink import readlink import spack.platforms @@ -21,7 +19,7 @@ from spack.operating_systems.mac_os import macos_sdk_path, macos_version from spack.package import * -class Gcc(AutotoolsPackage, GNUMirrorPackage): +class Gcc(AutotoolsPackage, GNUMirrorPackage, CompilerPackage): """The GNU Compiler Collection includes front ends for C, C++, Objective-C, Fortran, Ada, and Go, as well as libraries for these languages.""" @@ -503,11 +501,36 @@ class Gcc(AutotoolsPackage, GNUMirrorPackage): build_directory = "spack-build" - @classproperty - def executables(cls): - names = [r"gcc", r"[^\w]?g\+\+", r"gfortran", r"gdc", r"gccgo"] - suffixes = [r"", r"-mp-\d+\.\d", r"-\d+\.\d", r"-\d+", r"\d\d"] - return [r"".join(x) for x in itertools.product(names, suffixes)] + compiler_languages = ["c", "cxx", "fortran", "d", "go"] + + @property + def supported_languages(self): + # This weirdness is because it could be called on an abstract spec + if "languages" not in self.spec.variants: + return self.compiler_languages + return [x for x in self.compiler_languages if x in self.spec.variants["languages"].value] + + c_names = ["gcc"] + cxx_names = ["g++"] + fortran_names = ["gfortran"] + d_names = ["gdc"] + go_names = ["gccgo"] + compiler_prefixes = [r"\w+-\w+-\w+-"] + compiler_suffixes = [r"-mp-\d+(?:\.\d+)?", r"-\d+(?:\.\d+)?", r"\d\d"] + compiler_version_regex = r"(?<!clang version)\s?([0-9.]+)" + compiler_version_argument = ("-dumpfullversion", "-dumpversion") + + @classmethod + def determine_version(cls, exe): + try: + output = spack.compiler.get_compiler_version_output(exe, "--version") + except Exception: + output = "" + # Apple's gcc is actually apple clang, so skip it. + if "Apple" in output: + return None + + return super().determine_version(exe) @classmethod def filter_detected_exes(cls, prefix, exes_in_prefix): @@ -538,57 +561,13 @@ class Gcc(AutotoolsPackage, GNUMirrorPackage): return result @classmethod - def determine_version(cls, exe): - try: - output = spack.compiler.get_compiler_version_output(exe, "--version") - except Exception: - output = "" - # Apple's gcc is actually apple clang, so skip it. - # Users can add it manually to compilers.yaml at their own risk. - if "Apple" in output: - return None - - version_regex = re.compile(r"([\d\.]+)") - for vargs in ("-dumpfullversion", "-dumpversion"): - try: - output = spack.compiler.get_compiler_version_output(exe, vargs) - match = version_regex.search(output) - if match: - return match.group(1) - except spack.util.executable.ProcessError: - pass - except Exception as e: - tty.debug(e) - - return None - - @classmethod def determine_variants(cls, exes, version_str): - languages, compilers = set(), {} - # There are often at least two copies (not symlinks) of each compiler executable in the - # same directory: one with a canonical name, e.g. "gfortran", and another one with the - # target prefix, e.g. "x86_64-pc-linux-gnu-gfortran". There also might be a copy of "gcc" - # with the version suffix, e.g. "x86_64-pc-linux-gnu-gcc-6.3.0". To ensure the consistency - # of values in the "compilers" dictionary (i.e. we prefer all of them to reference copies - # with canonical names if possible), we iterate over the executables in the reversed sorted - # order: - for exe in sorted(exes, reverse=True): - basename = os.path.basename(exe) - if "g++" in basename: - languages.add("c++") - compilers["cxx"] = exe - elif "gfortran" in basename: - languages.add("fortran") - compilers["fortran"] = exe - elif "gcc" in basename: - languages.add("c") - compilers["c"] = exe - elif "gccgo" in basename: - languages.add("go") - compilers["go"] = exe - elif "gdc" in basename: - languages.add("d") - compilers["d"] = exe + compilers = cls.determine_compiler_paths(exes=exes) + + languages = set() + translation = {"cxx": "c++"} + for lang, compiler in compilers.items(): + languages.add(translation.get(lang, lang)) variant_str = "languages={0}".format(",".join(languages)) return variant_str, {"compilers": compilers} diff --git a/var/spack/repos/builtin/packages/intel-oneapi-compilers-classic/detection_test.yaml b/var/spack/repos/builtin/packages/intel-oneapi-compilers-classic/detection_test.yaml new file mode 100644 index 0000000000..0684507424 --- /dev/null +++ b/var/spack/repos/builtin/packages/intel-oneapi-compilers-classic/detection_test.yaml @@ -0,0 +1,89 @@ +paths: +- layout: + - executables: + - "bin/intel64/icc" + script: | + echo "icc (ICC) 18.0.5 20180823" + echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." + - executables: + - "bin/intel64/icpc" + script: | + echo "icpc (ICC) 18.0.5 20180823" + echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." + - executables: + - "bin/intel64/ifort" + script: | + echo "ifort (IFORT) 18.0.5 20180823" + echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." + platforms: [linux] + results: + - spec: 'intel-oneapi-compilers-classic@18.0.5' + extra_attributes: + compilers: + c: ".*/bin/intel64/icc" + cxx: ".*/bin/intel64/icpc" + fortran: ".*/bin/intel64/ifort" +- layout: + - executables: + - "bin/icc" + script: | + echo "icc (ICC) 18.0.5 20180823" + echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." + - executables: + - "bin/icpc" + script: | + echo "icpc (ICC) 18.0.5 20180823" + echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." + - executables: + - "bin/ifort" + script: | + echo "ifort (IFORT) 18.0.5 20180823" + echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." + platforms: [linux] + results: + - spec: 'intel-oneapi-compilers-classic@18.0.5' + extra_attributes: + compilers: + c: ".*/bin/icc" + cxx: ".*/bin/icpc" + fortran: ".*/bin/ifort" +- layout: + - executables: + - "compiler/18.0.5/linux/bin/intel64/icc" + script: | + echo "icc (ICC) 18.0.5 20180823" + echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." + - executables: + - "compiler/18.0.5/linux/bin/intel64/icpc" + script: | + echo "icpc (ICC) 18.0.5 20180823" + echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." + - executables: + - "compiler/18.0.5/linux/bin/intel64/ifort" + script: | + echo "ifort (IFORT) 18.0.5 20180823" + echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." + platforms: [linux] + results: + - spec: 'intel-oneapi-compilers-classic@18.0.5' + extra_attributes: + compilers: + c: ".*compiler/18.0.5/linux/bin/intel64/icc" + cxx: ".*compiler/18.0.5/linux/bin/intel64/icpc" + fortran: ".*compiler/18.0.5/linux/bin/intel64/ifort" +- layout: # oneapi compiler is not detected as classic + - executables: + - "compiler/18.0.5/linux/bin/icx" + - "compiler/18.0.5/linux/bin/icpx" + script: | + echo "Intel(R) oneAPI DPC++ Compiler 2021.2.0 (2021.2.0.20210317)" + echo "Target: x86_64-unknown-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /made/up/path", + - executables: + - "compiler/18.0.5/linux/bin/ifx" + script: | + echo "ifx (IFORT) 2021.1.2 Beta 20201214" + echo "Copyright (C) 1985-2020 Intel Corporation. All rights reserved." + platforms: [linux] + results: [] diff --git a/var/spack/repos/builtin/packages/intel-oneapi-compilers-classic/package.py b/var/spack/repos/builtin/packages/intel-oneapi-compilers-classic/package.py index aefec97197..71de26ed34 100644 --- a/var/spack/repos/builtin/packages/intel-oneapi-compilers-classic/package.py +++ b/var/spack/repos/builtin/packages/intel-oneapi-compilers-classic/package.py @@ -3,14 +3,16 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) import os +import sys +from llnl.util.lang import classproperty from llnl.util.link_tree import LinkTree from spack.package import * @IntelOneApiPackage.update_description -class IntelOneapiCompilersClassic(Package): +class IntelOneapiCompilersClassic(Package, CompilerPackage): """Relies on intel-oneapi-compilers to install the compilers, and configures modules for icc/icpc/ifort. @@ -22,6 +24,23 @@ class IntelOneapiCompilersClassic(Package): has_code = False + compiler_languages = ["c", "cxx", "fortran"] + c_names = ["icc"] + cxx_names = ["icpc"] + fortran_names = ["ifort"] + + @classproperty + def compiler_version_argument(self): + if sys.platform == "win32": + return "/QV" + return "--version" + + @classproperty + def compiler_version_regex(self): + if sys.platform == "win32": + return r"([1-9][0-9]*\.[0-9]*\.[0-9]*)" + return r"\((?:IFORT|ICC)\) ([^ ]+)" + # Versions before 2021 are in the `intel` package # intel-oneapi versions before 2022 use intel@19.0.4 for ver, oneapi_ver in { diff --git a/var/spack/repos/builtin/packages/intel-oneapi-compilers/detection_test.yaml b/var/spack/repos/builtin/packages/intel-oneapi-compilers/detection_test.yaml new file mode 100644 index 0000000000..d1e0c2252e --- /dev/null +++ b/var/spack/repos/builtin/packages/intel-oneapi-compilers/detection_test.yaml @@ -0,0 +1,23 @@ +paths: +- layout: + - executables: + - "compiler/2021.2.0/linux/bin/icx" + - "compiler/2021.2.0/linux/bin/icpx" + script: | + echo "Intel(R) oneAPI DPC++ Compiler 2021.2.0 (2021.2.0.20210317)" + echo "Target: x86_64-unknown-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /made/up/path", + - executables: + - "compiler/2021.2.0/linux/bin/ifx" + script: | + echo "ifx (IFORT) 2021.2.0 Beta 20201214" + echo "Copyright (C) 1985-2020 Intel Corporation. All rights reserved." + platforms: [linux] + results: + - spec: intel-oneapi-compilers@2021.2.0 + extra_attributes: + compilers: + c: ".*/compiler/2021.2.0/linux/bin/icx" + cxx: ".*/compiler/2021.2.0/linux/bin/icpx" + fortran: ".*/compiler/2021.2.0/linux/bin/ifx" diff --git a/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py b/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py index f52a68a9c6..f23b716b21 100644 --- a/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py +++ b/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py @@ -222,13 +222,22 @@ versions = [ @IntelOneApiPackage.update_description -class IntelOneapiCompilers(IntelOneApiPackage): +class IntelOneapiCompilers(IntelOneApiPackage, CompilerPackage): """Intel oneAPI Compilers. Includes: icc, icpc, ifort, icx, icpx, and ifx.""" maintainers("rscohn2") homepage = "https://software.intel.com/content/www/us/en/develop/tools/oneapi.html" + compiler_languages = ["c", "cxx", "fortran"] + c_names = ["icx"] + cxx_names = ["icpx"] + fortran_names = ["ifx"] + compiler_version_argument = "--version" + compiler_version_regex = ( + r"(?:(?:oneAPI DPC\+\+(?:\/C\+\+)? Compiler)|(?:\(IFORT\))|(?:\(IFX\))) (\S+)" + ) + # See https://github.com/spack/spack/issues/39252 depends_on("patchelf@:0.17", type="build") diff --git a/var/spack/repos/builtin/packages/intel/detection_test.yaml b/var/spack/repos/builtin/packages/intel/detection_test.yaml index 1a0e23b82c..dfff8fa4a1 100644 --- a/var/spack/repos/builtin/packages/intel/detection_test.yaml +++ b/var/spack/repos/builtin/packages/intel/detection_test.yaml @@ -1,20 +1,25 @@ paths: - - layout: - - executables: - - "bin/intel64/icc" - script: | - echo "icc (ICC) 18.0.5 20180823" - echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." - - executables: - - "bin/intel64/icpc" - script: | - echo "icpc (ICC) 18.0.5 20180823" - echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." - - executables: - - "bin/intel64/ifort" - script: | - echo "ifort (IFORT) 18.0.5 20180823" - echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." - platforms: ["darwin", "linux"] - results: - - spec: 'intel@18.0.5' +- layout: + - executables: + - "bin/intel64/icc" + script: | + echo "icc (ICC) 18.0.5 20180823" + echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." + - executables: + - "bin/intel64/icpc" + script: | + echo "icpc (ICC) 18.0.5 20180823" + echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." + - executables: + - "bin/intel64/ifort" + script: | + echo "ifort (IFORT) 18.0.5 20180823" + echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved." + platforms: ["darwin", "linux"] + results: + - spec: 'intel@18.0.5' + extra_attributes: + compilers: + c: ".*/bin/intel64/icc" + cxx: ".*/bin/intel64/icpc" + fortran: ".*/bin/intel64/ifort" diff --git a/var/spack/repos/builtin/packages/llvm-amdgpu/detection_test.yaml b/var/spack/repos/builtin/packages/llvm-amdgpu/detection_test.yaml new file mode 100644 index 0000000000..5fa0fb526b --- /dev/null +++ b/var/spack/repos/builtin/packages/llvm-amdgpu/detection_test.yaml @@ -0,0 +1,103 @@ +paths: +- layout: + - executables: + - "bin/amdclang" + - "bin/amdclang++" + script: | + echo "AMD clang version 17.0.0 (https://github.com/RadeonOpenCompute/llvm-project roc-5.7.1 23382 f3e174a1d286158c06e4cc8276366b1d4bc0c914)" + echo "Target: x86_64-unknown-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /opt/rocm-5.7.1/llvm/bin" + echo "Configuration file: /opt/rocm-5.7.1/llvm/bin/clang.cfg" + - executables: + - "bin/amdflang" + script: | + echo "AMD flang-classic version 17.0.0 (https://github.com/RadeonOpenCompute/llvm-project roc-5.7.1 23382 f3e174a1d286158c06e4cc8276366b1d4bc0c914)" + echo "Target: x86_64-unknown-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /opt/rocm-5.7.1/llvm/bin" + platforms: [linux] + results: + - spec: llvm-amdgpu@5.7.1 + extra_attributes: + compilers: + c: ".*/bin/amdclang" + cxx: ".*/bin/amdclang[+][+]" + fortran: ".*/bin/amdflang" + +- layout: + - executables: + - "bin/amdclang" + - "bin/amdclang++" + script: | + echo "AMD clang version 17.0.0 (https://github.com/RadeonOpenCompute/llvm-project roc-5.7.1 23382 f3e174a1d286158c06e4cc8276366b1d4bc0c914)" + echo "Target: x86_64-unknown-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /opt/rocm-5.7.1/llvm/bin" + echo "Configuration file: /opt/rocm-5.7.1/llvm/bin/clang.cfg" + platforms: [linux] + results: + - spec: llvm-amdgpu@5.7.1 + extra_attributes: + compilers: + c: ".*/bin/amdclang" + cxx: ".*/bin/amdclang[+][+]" + +- layout: + - executables: + - "bin/amdclang" + - "bin/amdclang++" + script: | + echo "AMD clang version 17.0.0 (https://github.com/RadeonOpenCompute/llvm-project roc-5.7.1 23382 f3e174a1d286158c06e4cc8276366b1d4bc0c914)" + echo "Target: x86_64-unknown-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /opt/rocm-5.7.1/llvm/bin" + echo "Configuration file: /opt/rocm-5.7.1/llvm/bin/clang.cfg" + - executables: + - "bin/amdflang" + script: | + echo "AMD flang-classic version 17.0.0 (https://github.com/RadeonOpenCompute/llvm-project roc-5.7.1 23382 f3e174a1d286158c06e4cc8276366b1d4bc0c914)" + echo "Target: x86_64-unknown-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /opt/rocm-5.7.1/llvm/bin" + - executables: + - "bin/amdclang-6" + - "bin/amdclang++-6" + script: | + echo "AMD clang version 17.0.0 (https://github.com/RadeonOpenCompute/llvm-project roc-6.0.2 24012 af27734ed982b52a9f1be0f035ac91726fc697e4)" + echo "Target: x86_64-unknown-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /opt/rocm-6.0.2/llvm/bin" + echo "Configuration file: /opt/rocm-6.0.2/llvm/bin/clang.cfg" + - executables: + - "bin/amdflang-6" + script: | + echo "AMD flang-classic version 17.0.0 (https://github.com/RadeonOpenCompute/llvm-project roc-6.0.2 24012 af27734ed982b52a9f1be0f035ac91726fc697e4)" + echo "Target: x86_64-unknown-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /opt/rocm-6.0.2/llvm/bin" + platforms: [linux] + results: + - spec: llvm-amdgpu@6.0.2 + extra_attributes: + compilers: + c: ".*/bin/amdclang-6$" + cxx: ".*/bin/amdclang[+][+]-6$" + fortran: ".*/bin/amdflang-6$" + - spec: llvm-amdgpu@5.7.1 + extra_attributes: + compilers: + c: ".*/bin/amdclang" + cxx: ".*/bin/amdclang[+][+]" + fortran: ".*/bin/amdflang" +- layout: # does not detect upstream clang + - executables: + - "bin/clang" + - "bin/clang++" + script: | + echo "clang version 8.0.0 (tags/RELEASE_800/final" + echo "Target: x86_64-unknown-linux-gnu\n" + echo "Thread model: posix\n" + echo "InstalledDir: /usr/bin" + platforms: [linux] + results: [] diff --git a/var/spack/repos/builtin/packages/llvm-amdgpu/package.py b/var/spack/repos/builtin/packages/llvm-amdgpu/package.py index f475dca999..e6c399e84b 100644 --- a/var/spack/repos/builtin/packages/llvm-amdgpu/package.py +++ b/var/spack/repos/builtin/packages/llvm-amdgpu/package.py @@ -2,15 +2,12 @@ # Spack Project Developers. See the top-level COPYRIGHT file for details. # # SPDX-License-Identifier: (Apache-2.0 OR MIT) - - import os -import re from spack.package import * -class LlvmAmdgpu(CMakePackage): +class LlvmAmdgpu(CMakePackage, CompilerPackage): """Toolkit for the construction of highly optimized compilers, optimizers, and run-time environments.""" @@ -247,18 +244,12 @@ class LlvmAmdgpu(CMakePackage): args.append("-DSANITIZER_AMDGPU:Bool=ON") return args - @classmethod - def determine_version(cls, path): - match = re.search(r"amdclang", path) - detected_version = None - if match: - version_query = Executable(path)("--version", output=str) - match = re.search(r"roc-(\d)\.(\d).(\d)", version_query) - if match: - detected_version = "{0}.{1}.{2}".format( - int(match.group(1)), int(match.group(2)), int(match.group(3)) - ) - return detected_version + compiler_languages = ["c", "cxx", "fortran"] + c_names = ["amdclang"] + cxx_names = ["amdclang++"] + fortran_names = ["amdflang"] + compiler_version_argument = "--version" + compiler_version_regex = r"roc-(\d+[._]\d+[._]\d+)" # Make sure that the compiler paths are in the LD_LIBRARY_PATH def setup_run_environment(self, env): diff --git a/var/spack/repos/builtin/packages/llvm/detection_test.yaml b/var/spack/repos/builtin/packages/llvm/detection_test.yaml index a5719fb395..e979a83626 100644 --- a/var/spack/repos/builtin/packages/llvm/detection_test.yaml +++ b/var/spack/repos/builtin/packages/llvm/detection_test.yaml @@ -1,59 +1,75 @@ paths: - - layout: - - executables: - - "bin/clang-3.9" - script: | - echo "clang version 3.9.1-19ubuntu1 (tags/RELEASE_391/rc2)" - echo "Target: x86_64-pc-linux-gnu" - echo "Thread model: posix" - echo "InstalledDir: /usr/bin" - - executables: - - "bin/clang++-3.9" - script: | - echo "clang version 3.9.1-19ubuntu1 (tags/RELEASE_391/rc2)" - echo "Target: x86_64-pc-linux-gnu" - echo "Thread model: posix" - echo "InstalledDir: /usr/bin" - platforms: ["darwin", "linux"] - results: - - spec: 'llvm@3.9.1 +clang~lld~lldb' - # Multiple LLVM packages in the same prefix - - layout: - - executables: - - "bin/clang-8" - - "bin/clang++-8" - script: | - echo "clang version 8.0.0-3~ubuntu18.04.2 (tags/RELEASE_800/final)" - echo "Target: x86_64-pc-linux-gnu" - echo "Thread model: posix" - echo "InstalledDir: /usr/bin" - - executables: - - "bin/ld.lld-8" - script: 'echo "LLD 8.0.0 (compatible with GNU linkers)"' - - executables: - - "bin/lldb" - script: 'echo "lldb version 8.0.0"' - - executables: - - "bin/clang-3.9" - - "bin/clang++-3.9" - script: | - echo "clang version 3.9.1-19ubuntu1 (tags/RELEASE_391/rc2)" - echo "Target: x86_64-pc-linux-gnu" - echo "Thread model: posix" - echo "InstalledDir: /usr/bin" - platforms: ["darwin", "linux"] - results: - - spec: 'llvm@8.0.0+clang+lld+lldb' - - spec: 'llvm@3.9.1+clang~lld~lldb' - # Apple Clang should not be detected - - layout: - - executables: - - "bin/clang" - - "bin/clang++" - script: | - echo "Apple clang version 11.0.0 (clang-1100.0.33.8)" - echo "Target: x86_64-apple-darwin19.5.0" - echo "Thread model: posix" - echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin" - platforms: ["darwin"] - results: [] +- layout: + - executables: + - "bin/clang-3.9" + script: | + echo "clang version 3.9.1-19ubuntu1 (tags/RELEASE_391/rc2)" + echo "Target: x86_64-pc-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /usr/bin" + - executables: + - "bin/clang++-3.9" + script: | + echo "clang version 3.9.1-19ubuntu1 (tags/RELEASE_391/rc2)" + echo "Target: x86_64-pc-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /usr/bin" + platforms: ["darwin", "linux"] + results: + - spec: 'llvm@3.9.1 +clang~lld~lldb' + extra_attributes: + compilers: + c: ".*/bin/clang-3.9$" + cxx: ".*/bin/clang[+][+]-3.9$" + +# Multiple LLVM packages in the same prefix +- layout: + - executables: + - "bin/clang-8" + - "bin/clang++-8" + script: | + echo "clang version 8.0.0-3~ubuntu18.04.2 (tags/RELEASE_800/final)" + echo "Target: x86_64-pc-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /usr/bin" + - executables: + - "bin/ld.lld-8" + script: 'echo "LLD 8.0.0 (compatible with GNU linkers)"' + - executables: + - "bin/lldb" + script: 'echo "lldb version 8.0.0"' + - executables: + - "bin/clang-3.9" + - "bin/clang++-3.9" + script: | + echo "clang version 3.9.1-19ubuntu1 (tags/RELEASE_391/rc2)" + echo "Target: x86_64-pc-linux-gnu" + echo "Thread model: posix" + echo "InstalledDir: /usr/bin" + platforms: ["darwin", "linux"] + results: + - spec: 'llvm@8.0.0+clang+lld+lldb' + extra_attributes: + compilers: + c: ".*/bin/clang-8$" + cxx: ".*/bin/clang[+][+]-8$" + ld: ".*/bin/ld.lld-8$" + + - spec: 'llvm@3.9.1+clang~lld~lldb' + extra_attributes: + compilers: + c: ".*/bin/clang-3.9$" + cxx: ".*/bin/clang[+][+]-3.9$" + +# Apple Clang should not be detected +- layout: + - executables: + - "bin/clang" + - "bin/clang++" + script: | + echo "Apple clang version 11.0.0 (clang-1100.0.33.8)" + echo "Target: x86_64-apple-darwin19.5.0" + echo "Thread model: posix" + echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin" + platforms: ["darwin"] + results: [] diff --git a/var/spack/repos/builtin/packages/llvm/package.py b/var/spack/repos/builtin/packages/llvm/package.py index e770b2c11d..2825a73a3f 100644 --- a/var/spack/repos/builtin/packages/llvm/package.py +++ b/var/spack/repos/builtin/packages/llvm/package.py @@ -8,13 +8,14 @@ import re import sys import llnl.util.tty as tty +from llnl.util.lang import classproperty import spack.build_environment import spack.util.executable from spack.package import * -class Llvm(CMakePackage, CudaPackage): +class Llvm(CMakePackage, CudaPackage, CompilerPackage): """The LLVM Project is a collection of modular and reusable compiler and toolchain technologies. Despite its name, LLVM has little to do with traditional virtual machines, though it does provide helpful @@ -28,7 +29,7 @@ class Llvm(CMakePackage, CudaPackage): git = "https://github.com/llvm/llvm-project" maintainers("trws", "haampie", "skosukhin") - tags = ["e4s"] + tags = ["e4s", "compiler"] generator("ninja") @@ -594,11 +595,36 @@ class Llvm(CMakePackage, CudaPackage): string=True, ) - # The functions and attributes below implement external package - # detection for LLVM. See: - # - # https://spack.readthedocs.io/en/latest/packaging_guide.html#making-a-package-discoverable-with-spack-external-find - executables = ["clang", "flang", "ld.lld", "lldb"] + compiler_version_regex = ( + # Normal clang compiler versions are left as-is + r"clang version ([^ )\n]+)-svn[~.\w\d-]*|" + # Don't include hyphenated patch numbers in the version + # (see https://github.com/spack/spack/pull/14365 for details) + r"clang version ([^ )\n]+?)-[~.\w\d-]*|" + r"clang version ([^ )\n]+)|" + # LLDB + r"lldb version ([^ )\n]+)|" + # LLD + r"LLD ([^ )\n]+) \(compatible with GNU linkers\)" + ) + compiler_version_argument = "--version" + compiler_languages = ["c", "cxx", "fortran"] + c_names = ["clang"] + cxx_names = ["clang++"] + fortran_names = ["flang"] + + @property + def supported_languages(self): + languages = [] + if self.spec.satisfies("+clang"): + languages.extend(["c", "cxx"]) + if self.spec.satisfies("+flang"): + languages.append("fortran") + return languages + + @classproperty + def executables(cls): + return super().executables + ["ld.lld", "lldb"] @classmethod def filter_detected_exes(cls, prefix, exes_in_prefix): @@ -615,26 +641,14 @@ class Llvm(CMakePackage, CudaPackage): @classmethod def determine_version(cls, exe): - version_regex = re.compile( - # Normal clang compiler versions are left as-is - r"clang version ([^ )\n]+)-svn[~.\w\d-]*|" - # Don't include hyphenated patch numbers in the version - # (see https://github.com/spack/spack/pull/14365 for details) - r"clang version ([^ )\n]+?)-[~.\w\d-]*|" - r"clang version ([^ )\n]+)|" - # LLDB - r"lldb version ([^ )\n]+)|" - # LLD - r"LLD ([^ )\n]+) \(compatible with GNU linkers\)" - ) try: compiler = Executable(exe) - output = compiler("--version", output=str, error=str) + output = compiler(cls.compiler_version_argument, output=str, error=str) if "Apple" in output: return None if "AMD" in output: return None - match = version_regex.search(output) + match = re.search(cls.compiler_version_regex, output) if match: return match.group(match.lastindex) except spack.util.executable.ProcessError: @@ -646,21 +660,23 @@ class Llvm(CMakePackage, CudaPackage): @classmethod def determine_variants(cls, exes, version_str): + # Do not need to reuse more general logic from CompilerPackage + # because LLVM has kindly named compilers variants, compilers = ["+clang"], {} lld_found, lldb_found = False, False for exe in exes: - if "clang++" in exe: + name = os.path.basename(exe) + if "clang++" in name: compilers["cxx"] = exe - elif "clang" in exe: + elif "clang" in name: compilers["c"] = exe - elif "flang" in exe: + elif "flang" in name: variants.append("+flang") - compilers["fc"] = exe - compilers["f77"] = exe - elif "ld.lld" in exe: + compilers["fortran"] = exe + elif "ld.lld" in name: lld_found = True compilers["ld"] = exe - elif "lldb" in exe: + elif "lldb" in name: lldb_found = True compilers["lldb"] = exe diff --git a/var/spack/repos/builtin/packages/msvc/detection_test.yaml b/var/spack/repos/builtin/packages/msvc/detection_test.yaml new file mode 100644 index 0000000000..9ece6297ac --- /dev/null +++ b/var/spack/repos/builtin/packages/msvc/detection_test.yaml @@ -0,0 +1,14 @@ +paths: +- layout: + - executables: + - cl.bat + script: | + echo "Microsoft (R) C/C++ Optimizing Compiler Version 19.04.54321 for x86" + platforms: [windows] + results: + - spec: msvc@19.04.54321 + extra_attributes: + compilers: + c: ".*cl.bat$" + cxx: ".*cl.bat" + diff --git a/var/spack/repos/builtin/packages/msvc/package.py b/var/spack/repos/builtin/packages/msvc/package.py new file mode 100644 index 0000000000..d58dea2f6b --- /dev/null +++ b/var/spack/repos/builtin/packages/msvc/package.py @@ -0,0 +1,66 @@ +# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) +import re + +from spack.package import * + + +class Msvc(Package, CompilerPackage): + """ + Microsoft Visual C++ is a compiler for the C, C++, C++/CLI and C++/CX programming languages. + """ + + homepage = "https://visualstudio.microsoft.com/vs/features/cplusplus/" + + def install(self, spec, prefix): + raise InstallError( + "MSVC compilers are not installable with Spack, but can be " + "detected on a system where they are externally installed" + ) + + compiler_languages = ["c", "cxx"] + c_names = ["cl"] + cxx_names = ["cl"] + compiler_version_argument = "" + compiler_version_regex = r"([1-9][0-9]*\.[0-9]*\.[0-9]*)" + + @classmethod + def determine_version(cls, exe): + # MSVC compiler does not have a proper version argument + # Errors out and prints version info with no args + match = re.search( + cls.compiler_version_regex, + spack.compiler.get_compiler_version_output(exe, version_arg=None, ignore_errors=True), + ) + if match: + return match.group(1) + + @classmethod + def determine_variants(cls, exes, version_str): + # MSVC uses same executable for both languages + spec, extras = super().determine_variants(exes, version_str) + extras["compilers"]["c"] = extras["compilers"]["cxx"] + return spec, extras + + @property + def cc(self): + if self.spec.external: + return self.spec.extra_attributes["compilers"]["c"] + msg = "cannot retrieve C compiler [spec is not concrete]" + assert self.spec.concrete, msg + + @property + def cxx(self): + if self.spec.external: + return self.spec.extra_attributes["compilers"]["cxx"] + msg = "cannot retrieve C++ compiler [spec is not concrete]" + assert self.spec.concrete, msg + + @property + def fortran(self): + if self.spec.external: + return self.spec.extra_attributes["compilers"]["fortran"] + msg = "cannot retrieve Fortran compiler [spec is not concrete]" + assert self.spec.concrete, msg diff --git a/var/spack/repos/builtin/packages/nag/detection_test.yaml b/var/spack/repos/builtin/packages/nag/detection_test.yaml new file mode 100644 index 0000000000..df2bbe9bbd --- /dev/null +++ b/var/spack/repos/builtin/packages/nag/detection_test.yaml @@ -0,0 +1,13 @@ +paths: +- layout: + - executables: + - bin/nagfor + script: | + echo "NAG Fortran Compiler Release 6.0(Hibiya) Build 1037" + echo "Product NPL6A60NA for x86-64 Linux" + platforms: [linux] + results: + - spec: nag@6.0.1037 + extra_attributes: + compilers: + fortran: ".*/bin/nagfor" diff --git a/var/spack/repos/builtin/packages/nag/package.py b/var/spack/repos/builtin/packages/nag/package.py index d00d11ea30..ab3adc9126 100644 --- a/var/spack/repos/builtin/packages/nag/package.py +++ b/var/spack/repos/builtin/packages/nag/package.py @@ -3,15 +3,11 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) import os -import re -import llnl.util.tty as tty - -import spack.compiler from spack.package import * -class Nag(Package): +class Nag(Package, CompilerPackage): """The NAG Fortran Compiler.""" homepage = "https://www.nag.com/nagware/np.asp" @@ -64,54 +60,10 @@ class Nag(Package): env.set("F77", self.prefix.bin.nagfor) env.set("FC", self.prefix.bin.nagfor) - executables = ["^nagfor$"] - - @classmethod - def determine_version(cls, exe): - version_regex = re.compile(r"NAG Fortran Compiler Release ([0-9.]+)") - # NAG does not support a flag that would enable verbose output and - # compilation/linking at the same time (with either '-#' or '-dryrun' - # the compiler only prints the commands but does not run them). - # Therefore, the only thing we can do is to pass the '-v' argument to - # the underlying GCC. In order to get verbose output from the latter - # at both compile and linking stages, we need to call NAG with two - # additional flags: '-Wc,-v' and '-Wl,-v'. However, we return only - # '-Wl,-v' for the following reasons: - # 1) the interface of this method does not support multiple flags in - # the return value and, at least currently, verbose output at the - # linking stage has a higher priority for us; - # 2) NAG is usually mixed with GCC compiler, which also accepts - # '-Wl,-v' and produces meaningful result with it: '-v' is passed - # to the linker and the latter produces verbose output for the - # linking stage ('-Wc,-v', however, would break the compilation - # with a message from GCC that the flag is not recognized). - # - # This way, we at least enable the implicit rpath detection, which is - # based on compilation of a C file (see method - # spack.compiler._get_compiler_link_paths): in the case of a mixed - # NAG/GCC toolchain, the flag will be passed to g++ (e.g. - # 'g++ -Wl,-v ./main.c'), otherwise, the flag will be passed to nagfor - # (e.g. 'nagfor -Wl,-v ./main.c' - note that nagfor recognizes '.c' - # extension and treats the file accordingly). The list of detected - # rpaths will contain only GCC-related directories and rpaths to - # NAG-related directories are injected by nagfor anyway. - try: - output = spack.compiler.get_compiler_version_output(exe, "-Wl,-v") - match = version_regex.search(output) - if match: - return match.group(1) - except spack.util.executable.ProcessError: - pass - except Exception as e: - tty.debug(e) - - @classmethod - def determine_variants(cls, exes, version_str): - compilers = {} - for exe in exes: - if "nagfor" in exe: - compilers["fortran"] = exe - return "", {"compilers": compilers} + compiler_languages = ["fortran"] + fortran_names = ["nagfor"] + compiler_version_regex = r"NAG Fortran Compiler Release (\d+).(\d+)\(.*\) Build (\d+)" + compiler_version_argument = "-V" @property def fortran(self): diff --git a/var/spack/repos/builtin/packages/nvhpc/detection_test.yaml b/var/spack/repos/builtin/packages/nvhpc/detection_test.yaml new file mode 100644 index 0000000000..bdf1c6b596 --- /dev/null +++ b/var/spack/repos/builtin/packages/nvhpc/detection_test.yaml @@ -0,0 +1,82 @@ +paths: +- layout: + - executables: + - bin/nvc + script: | + echo "nvc 20.9-0 LLVM 64-bit target on x86-64 Linux -tp haswell" + echo "NVIDIA Compilers and Tools" + echo "Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved." + - executables: + - bin/nvc++ + script: | + echo "nvc++ 20.9-0 LLVM 64-bit target on x86-64 Linux -tp haswell" + echo "NVIDIA Compilers and Tools" + echo "Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved." + - executables: + - bin/nvfortran + script: | + echo "nvfortran 20.9-0 LLVM 64-bit target on x86-64 Linux -tp haswell" + echo "NVIDIA Compilers and Tools" + echo "Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved." + platforms: [linux] + results: + - spec: nvhpc@20.9~blas~lapack~mpi + extra_attributes: + compilers: + c: ".*/bin/nvc" + cxx: ".*/bin/nvc++" + fortran: ".*/bin/nvfortran" +- layout: + - executables: + - bin/nvc + script: | + echo "nvc 20.9-0 linuxpower target on Linuxpower" + echo "NVIDIA Compilers and Tools" + echo "Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved." + - executables: + - bin/nvc++ + script: | + echo "nvc++ 20.9-0 linuxpower target on Linuxpower" + echo "NVIDIA Compilers and Tools" + echo "Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved." + - executables: + - bin/nvfortran + script: | + echo "nvfortran 20.9-0 linuxpower target on Linuxpower" + echo "NVIDIA Compilers and Tools" + echo "Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved." + platforms: [linux] + results: + - spec: nvhpc@20.9~blas~lapack~mpi + extra_attributes: + compilers: + c: ".*/bin/nvc" + cxx: ".*/bin/nvc++" + fortran: ".*/bin/nvfortran" +- layout: + - executables: + - bin/nvc + script: | + echo "nvc 20.9-0 linuxarm64 target on aarch64 Linux" + echo "NVIDIA Compilers and Tools" + echo "Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved." + - executables: + - bin/nvc++ + script: | + echo "nvc++ 20.9-0 linuxarm64 target on aarch64 Linux" + echo "NVIDIA Compilers and Tools" + echo "Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved." + - executables: + - bin/nvfortran + script: | + echo "nvfortran 20.9-0 linuxarm64 target on aarch64 Linux" + echo "NVIDIA Compilers and Tools" + echo "Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved." + platforms: [linux] + results: + - spec: nvhpc@20.9~blas~lapack~mpi + extra_attributes: + compilers: + c: ".*/bin/nvc" + cxx: ".*/bin/nvc++" + fortran: ".*/bin/nvfortran" diff --git a/var/spack/repos/builtin/packages/nvhpc/package.py b/var/spack/repos/builtin/packages/nvhpc/package.py index bc11e64a39..17a9eecb7d 100644 --- a/var/spack/repos/builtin/packages/nvhpc/package.py +++ b/var/spack/repos/builtin/packages/nvhpc/package.py @@ -370,7 +370,7 @@ _versions = { } -class Nvhpc(Package): +class Nvhpc(Package, CompilerPackage): """The NVIDIA HPC SDK is a comprehensive suite of compilers, libraries and tools essential to maximizing developer productivity and the performance and portability of HPC applications. The NVIDIA HPC @@ -419,6 +419,20 @@ class Nvhpc(Package): requires("%gcc", msg="nvhpc must be installed with %gcc") + # For now we only detect compiler components + # It will require additional work to detect mpi/lapack/blas components + compiler_languages = ["c", "cxx", "fortran"] + c_names = ["nvc"] + cxx_names = ["nvc++"] + fortran_names = ["nvfortran"] + compiler_version_argument = "--version" + compiler_version_regex = r"nv[^ ]* (?:[^ ]+ Dev-r)?([0-9.]+)(?:-[0-9]+)?" + + @classmethod + def determine_variants(cls, exes, version_str): + # TODO: use other exes to determine default_cuda/install_type/blas/lapack/mpi variants + return "~blas~lapack~mpi", {"compilers": cls.determine_compiler_paths(exes=exes)} + def _version_prefix(self): return join_path(self.prefix, "Linux_%s" % self.spec.target.family, self.version) diff --git a/var/spack/repos/builtin/packages/pgi/detection_test.yaml b/var/spack/repos/builtin/packages/pgi/detection_test.yaml new file mode 100644 index 0000000000..1a4745fc4c --- /dev/null +++ b/var/spack/repos/builtin/packages/pgi/detection_test.yaml @@ -0,0 +1,11 @@ +paths: +- layout: + - executables: + - bin/pgcc + script: | + echo "pgcc 15.10-0 64-bit target on x86-64 Linux -tp sandybridge" + echo "The Portland Group - PGI Compilers and Tools" + echo "Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved." + platforms: [linux] + results: + - spec: pgi@15.10 diff --git a/var/spack/repos/builtin/packages/pgi/package.py b/var/spack/repos/builtin/packages/pgi/package.py index 995e27ee39..37196669cf 100644 --- a/var/spack/repos/builtin/packages/pgi/package.py +++ b/var/spack/repos/builtin/packages/pgi/package.py @@ -9,7 +9,7 @@ from spack.package import * from spack.util.prefix import Prefix -class Pgi(Package): +class Pgi(Package, CompilerPackage): """PGI optimizing multi-core x64 compilers for Linux, MacOS & Windows with support for debugging and profiling of local MPI processes. @@ -58,6 +58,13 @@ class Pgi(Package): os.getcwd(), version.up_to(1), version.joined ) + compiler_languages = ["c", "cxx", "fortran"] + c_names = ["pgcc"] + cxx_names = ["pgc++", "pgCC"] + fortran_names = ["pgfortran"] # older names long deprecated + compiler_version_argument = "-V" + compiler_version_regex = r"pg[^ ]* ([0-9.]+)-[0-9]+ (?:LLVM )?[^ ]+ target on " + def install(self, spec, prefix): # Enable the silent installation feature os.environ["PGI_SILENT"] = "true" diff --git a/var/spack/repos/builtin/packages/xl/detection_test.yaml b/var/spack/repos/builtin/packages/xl/detection_test.yaml new file mode 100644 index 0000000000..da7b2fa92f --- /dev/null +++ b/var/spack/repos/builtin/packages/xl/detection_test.yaml @@ -0,0 +1,31 @@ +paths: +- layout: + - executables: + - "bin/xlc" + - "bin/xlc++" + - "bin/xlc_r" + - "bin/xlc++_r" + script: | + echo "IBM XL C/C++ for Linux, V16.1.1 (5725-C73, 5765-J13)" + echo "Version: 16.01.0001.0006" + - executables: + - "bin/xlf" + - "bin/xlf_r" + - "bin/xlcuf" + script: | + echo "IBM XL Fortran for Linux, V16.1.1 (5725-C73, 5765-J13)" + echo "Version: 16.01.0001.0006" + platforms: ["linux"] + results: + - spec: "xl~r@16.1" + extra_attributes: + compilers: + c: ".*/bin/xlc" + cxx: ".*/bin/xlc[+][+]" + fortran: ".*/bin/xlf" + - spec: "xl+r@16.1" + extra_attributes: + compilers: + c: ".*/bin/xlc_r" + cxx: ".*/bin/xlc[+][+]_r" + fortran: ".*/bin/xlf_r" diff --git a/var/spack/repos/builtin/packages/xl/package.py b/var/spack/repos/builtin/packages/xl/package.py new file mode 100644 index 0000000000..479d31b548 --- /dev/null +++ b/var/spack/repos/builtin/packages/xl/package.py @@ -0,0 +1,65 @@ +# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) +from spack.package import * + + +class Xl(Package, CompilerPackage): + """IBM XL C/C++/Fortran is an advanced, high-performance compiler that can be + used for developing complex, computationally intensive programs, including + interlanguage calls with C and Fortran programs. + """ + + homepage = "https://www.ibm.com/support/knowledgecenter/SSXVZZ_16.1.1/com.ibm.compilers.linux.doc/welcome.html" + + variant("r", default=True, description="The _r version of compilers") + + def install(self, spec, prefix): + raise InstallError( + "XL compilers are not installable yet, but can be " + "detected on a system where they are supplied by vendor" + ) + + compiler_languages = ["c", "cxx", "fortran"] + c_names = ["xlc", "xlc_r"] + cxx_names = ["xlc++", "xlC", "xlc++_r", "xlC_r"] + fortran_names = ["xlf", "xlf_r"] # TODO complete this + compiler_version_argument = "-qversion" + compiler_version_regex = r"([0-9]?[0-9]\.[0-9])" + + @classmethod + def determine_variants(cls, exes, version_str): + _r_exes = [e for e in exes if "_r" in e] + _exes = [e for e in exes if "_r" not in e] + + _r_compilers = cls.determine_compiler_paths(exes=_r_exes) if _r_exes else None + _compilers = cls.determine_compiler_paths(exes=_exes) if _exes else None + + results = [] + if _r_compilers: + results.append(("+r", {"compilers": _r_compilers})) + if _compilers: + results.append(("~r", {"compilers": _compilers})) + return results + + @property + def cc(self): + if self.spec.external: + return self.spec.extra_attributes["compilers"]["c"] + msg = "cannot retrieve C compiler [spec is not concrete]" + assert self.spec.concrete, msg + + @property + def cxx(self): + if self.spec.external: + return self.spec.extra_attributes["compilers"]["cxx"] + msg = "cannot retrieve C++ compiler [spec is not concrete]" + assert self.spec.concrete, msg + + @property + def fortran(self): + if self.spec.external: + return self.spec.extra_attributes["compilers"]["fortran"] + msg = "cannot retrieve Fortran compiler [spec is not concrete]" + assert self.spec.concrete, msg diff --git a/var/spack/repos/builtin/packages/xlc/detection_test.yaml b/var/spack/repos/builtin/packages/xlc/detection_test.yaml deleted file mode 100644 index 5bc2c1f13b..0000000000 --- a/var/spack/repos/builtin/packages/xlc/detection_test.yaml +++ /dev/null @@ -1,19 +0,0 @@ -paths: - - layout: - - executables: - - "bin/xlc" - - "bin/xlc++" - - "bin/xlc_r" - - "bin/xlc++_r" - script: | - echo "IBM XL C/C++ for Linux, V16.1.1 (5725-C73, 5765-J13)" - echo "Version: 16.01.0001.0006" - - executables: - - "bin/xlcuf" - script: | - echo "IBM XL Fortran for Linux, V16.1.1 (5725-C73, 5765-J13)" - echo "Version: 16.01.0001.0006" - platforms: ["linux"] - results: - - spec: "xlc+r@16.1" - - spec: "xlc~r@16.1" diff --git a/var/spack/repos/builtin/packages/xlc/package.py b/var/spack/repos/builtin/packages/xlc/package.py deleted file mode 100644 index 983db7739b..0000000000 --- a/var/spack/repos/builtin/packages/xlc/package.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other -# Spack Project Developers. See the top-level COPYRIGHT file for details. -# -# SPDX-License-Identifier: (Apache-2.0 OR MIT) -import collections -import re - -import llnl.util.tty as tty - -import spack.compiler -from spack.package import * - - -class Xlc(Package): - """IBM XL C/C++ is an advanced, high-performance compiler that can be - used for developing complex, computationally intensive programs, including - interlanguage calls with C and Fortran programs. - """ - - homepage = "https://www.ibm.com/support/knowledgecenter/SSXVZZ_16.1.1/com.ibm.compilers.linux.doc/welcome.html" - - variant("r", default=True, description="The _r version of compilers") - - def install(self, spec, prefix): - raise InstallError( - "XL compilers are not installable yet, but can be " - "detected on a system where they are supplied by vendor" - ) - - executables = [r"xlc", r"xlC", r"xlc\+\+"] - - @classmethod - def determine_version(cls, exe): - version_regex = re.compile(r"([0-9]?[0-9]\.[0-9])") - try: - output = spack.compiler.get_compiler_version_output(exe, "-qversion") - # Exclude spurious Fortran compilers - if "Fortran" in output: - return None - - match = version_regex.search(output) - if match: - return match.group(1) - except spack.util.executable.ProcessError: - pass - except Exception as e: - tty.debug(str(e)) - - @classmethod - def determine_variants(cls, exes, version_str): - variants = collections.defaultdict(dict) - for exe in exes: - # Determine the variant of the spec - variant_str = "+r" if "_r" in exe else "~r" - if "xlc++" in exe: - variants[variant_str]["cxx"] = exe - continue - - if "xlc" in exe: - variants[variant_str]["c"] = exe - continue - - results = [] - for variant_str, compilers in variants.items(): - results.append((variant_str, {"compilers": compilers})) - - return results - - @property - def cc(self): - if self.spec.external: - return self.spec.extra_attributes["compilers"]["c"] - msg = "cannot retrieve C compiler [spec is not concrete]" - assert self.spec.concrete, msg - - @property - def cxx(self): - if self.spec.external: - return self.spec.extra_attributes["compilers"]["cxx"] - msg = "cannot retrieve C compiler [spec is not concrete]" - assert self.spec.concrete, msg diff --git a/var/spack/repos/builtin/packages/xlf/detection_test.yaml b/var/spack/repos/builtin/packages/xlf/detection_test.yaml deleted file mode 100644 index 1ba6955a94..0000000000 --- a/var/spack/repos/builtin/packages/xlf/detection_test.yaml +++ /dev/null @@ -1,12 +0,0 @@ -paths: - - layout: - - executables: - - "bin/xlf" - - "bin/xlf_r" - script: | - echo "IBM XL Fortran for Linux, V16.1.1 (5725-C73, 5765-J13)" - echo "Version: 16.01.0001.0006" - platforms: ["linux"] - results: - - spec: "xlf+r@16.1" - - spec: "xlf~r@16.1" diff --git a/var/spack/repos/builtin/packages/xlf/package.py b/var/spack/repos/builtin/packages/xlf/package.py deleted file mode 100644 index dc26e7fd91..0000000000 --- a/var/spack/repos/builtin/packages/xlf/package.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other -# Spack Project Developers. See the top-level COPYRIGHT file for details. -# -# SPDX-License-Identifier: (Apache-2.0 OR MIT) -import collections -import os.path -import re - -import llnl.util.tty as tty - -import spack.compiler -from spack.package import * - - -class Xlf(Package): - """IBM XL Fortran is an advanced, high-performance compiler that can be - used for developing complex, computationally intensive programs, including - interlanguage calls with C and Fortran programs. - """ - - homepage = "https://www.ibm.com/support/knowledgecenter/SSXVZZ_16.1.1/com.ibm.compilers.linux.doc/welcome.html" - - variant("r", default=True, description="The _r version of compilers") - - def install(self, spec, prefix): - raise InstallError( - "XL compilers are not installable yet, but can be " - "detected on a system where they are supplied by vendor" - ) - - executables = [r"xlf"] - - @classmethod - def determine_version(cls, exe): - version_regex = re.compile(r"([0-9]?[0-9]\.[0-9])") - try: - output = spack.compiler.get_compiler_version_output(exe, "-qversion") - match = version_regex.search(output) - if match: - return match.group(1) - except spack.util.executable.ProcessError: - pass - except Exception as e: - tty.debug(e) - - @classmethod - def determine_variants(cls, exes, version_str): - variants = collections.defaultdict(dict) - for exe in exes: - if os.path.basename(exe) == "xlf": - variants["~r"]["fortran"] = exe - continue - - if os.path.basename(exe) == "xlf_r": - variants["+r"]["fortran"] = exe - continue - - results = [] - for variant_str, compilers in variants.items(): - results.append((variant_str, {"compilers": compilers})) - - return results - - @property - def fortran(self): - if self.spec.external: - return self.spec.extra_attributes["compilers"]["fortran"] - msg = "cannot retrieve C compiler [spec is not concrete]" - assert self.spec.concrete, msg |