External package detection for compilers (#43464)

This creates shared infrastructure for compiler packages to implement the 
detailed search capabilities from the `spack compiler find` command for the 
`spack external find` command.

After this commit, `spack compiler find` can be replaced with 
`spack external find --tag compiler`, with the exception of mixed toolchains.
This commit is contained in:
Greg Becker 2024-05-06 01:33:33 -07:00 committed by GitHub
parent 27aeb6e293
commit 1f31c3374c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 1375 additions and 698 deletions

View file

@ -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/

View file

@ -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)}

View file

@ -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)
err_header = f"The external spec '{spec}' cannot be used as a compiler"
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
if not prefix:
continue
# 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 all(v is None for v in paths.values()):
# 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]
# 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 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()

View file

@ -39,6 +39,7 @@
)
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

View file

@ -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(

View file

@ -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)

View file

@ -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: []

View file

@ -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 @@ def install(self, spec, prefix):
)
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)
compiler_languages = ["c", "cxx", "fortran"]
c_names = ["armclang"]
cxx_names = ["armclang++"]
fortran_names = ["armflang"]
@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_version_argument = "--version"
compiler_version_regex = (
r"Arm C\/C\+\+\/Fortran Compiler version ([\d\.]+) \(build number \d+\) "
)
@property
def cc(self):

View file

@ -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: []

View file

@ -8,7 +8,7 @@
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 @@ def cfg_files(self):
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"]

View file

@ -1,6 +1,6 @@
paths:
# Apple Clang on MacBook Pro (Catalina)
- layout:
# Apple Clang on MacBook Pro (Catalina)
- layout:
- executables:
- "bin/clang"
- "bin/clang++"
@ -12,8 +12,13 @@ paths:
platforms: ["darwin"]
results:
- spec: 'apple-clang@11.0.0'
# Apple Clang on Apple M1 (Ventura)
- layout:
extra_attributes:
compilers:
c: ".*/bin/clang"
cxx: ".*/bin/clang[+][+]"
# Apple Clang on Apple M1 (Ventura)
- layout:
- executables:
- "bin/clang"
- "bin/clang++"
@ -25,8 +30,13 @@ paths:
platforms: ["darwin"]
results:
- spec: 'apple-clang@15.0.0'
# Test that missing a compiler prevents the package from being detected
- layout:
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: |
@ -35,4 +45,4 @@ paths:
echo "Thread model: posix"
echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin"
platforms: ["darwin"]
results: [ ]
results: []

View file

@ -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$"]
compiler_languages = ["c", "cxx"]
c_names = ["clang"]
cxx_names = ["clang++"]
@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
return "", {"compilers": compilers}
compiler_version_regex = r"^Apple (?:LLVM|clang) version ([^ )]+)"
compiler_version_argument = "--version"
@classmethod
def validate_detected_spec(cls, spec, extra_attributes):

View file

@ -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"

View file

@ -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")

View file

@ -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"

View file

@ -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 @@ def install(self, spec, prefix):
"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"

View file

@ -1,8 +1,8 @@
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:
# 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++"
@ -27,9 +27,10 @@ paths:
compilers:
c: ".*/bin/gcc"
cxx: ".*/bin/g++"
# Mock a version < 7 of GCC that requires -dumpversion and
# errors with -dumpfullversion
- layout:
# Mock a version < 7 of GCC that requires -dumpversion and
# errors with -dumpfullversion
- layout:
- executables:
- "bin/gcc-5"
- "bin/g++-5"
@ -50,8 +51,9 @@ paths:
c: ".*/bin/gcc-5$"
cxx: ".*/bin/g[+][+]-5$"
fortran: ".*/bin/gfortran-5$"
# Multiple compilers present at the same time
- layout:
# Multiple compilers present at the same time
- layout:
- executables:
- "bin/x86_64-linux-gnu-gcc-6"
script: 'echo 6.5.0'
@ -70,8 +72,9 @@ paths:
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:
# Apple clang under disguise as gcc should not be detected
- layout:
- executables:
- "bin/gcc"
script: |

View file

@ -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.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):
@ -537,58 +560,14 @@ def filter_detected_exes(cls, prefix, exes_in_prefix):
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}

View file

@ -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: []

View file

@ -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 {

View file

@ -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"

View file

@ -222,13 +222,22 @@
@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")

View file

@ -1,5 +1,5 @@
paths:
- layout:
- layout:
- executables:
- "bin/intel64/icc"
script: |
@ -18,3 +18,8 @@ paths:
platforms: ["darwin", "linux"]
results:
- spec: 'intel@18.0.5'
extra_attributes:
compilers:
c: ".*/bin/intel64/icc"
cxx: ".*/bin/intel64/icpc"
fortran: ".*/bin/intel64/ifort"

View file

@ -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: []

View file

@ -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 @@ def cmake_args(self):
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):

View file

@ -1,5 +1,5 @@
paths:
- layout:
- layout:
- executables:
- "bin/clang-3.9"
script: |
@ -17,8 +17,13 @@ paths:
platforms: ["darwin", "linux"]
results:
- spec: 'llvm@3.9.1 +clang~lld~lldb'
# Multiple LLVM packages in the same prefix
- layout:
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"
@ -44,9 +49,20 @@ paths:
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'
# Apple Clang should not be detected
- layout:
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++"

View file

@ -8,13 +8,14 @@
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 @@ def patch(self):
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 @@ def filter_detected_exes(cls, prefix, exes_in_prefix):
@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 @@ def determine_version(cls, exe):
@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

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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 @@ def setup_run_environment(self, env):
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):

View file

@ -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"

View file

@ -370,7 +370,7 @@
}
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)

View file

@ -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

View file

@ -9,7 +9,7 @@
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 @@ def url_for_version(self, version):
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"

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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