diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py
deleted file mode 100644
index af04f3b5e55..00000000000
--- a/lib/spack/spack/compiler.py
+++ /dev/null
@@ -1,856 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import contextlib
-import hashlib
-import itertools
-import json
-import os
-import platform
-import re
-import shutil
-import sys
-import tempfile
-from typing import Dict, List, Optional, Sequence
-
-import llnl.path
-import llnl.util.lang
-import llnl.util.tty as tty
-from llnl.util.filesystem import path_contains_subdirectory, paths_containing_libs
-
-import spack.caches
-import spack.error
-import spack.schema.environment
-import spack.spec
-import spack.util.executable
-import spack.util.libc
-import spack.util.module_cmd
-import spack.version
-from spack.util.environment import filter_system_paths
-from spack.util.file_cache import FileCache
-
-__all__ = ["Compiler"]
-
-PATH_INSTANCE_VARS = ["cc", "cxx", "f77", "fc"]
-FLAG_INSTANCE_VARS = ["cflags", "cppflags", "cxxflags", "fflags"]
-
-
-@llnl.util.lang.memoized
-def _get_compiler_version_output(compiler_path, version_arg, ignore_errors=()) -> str:
- """Invokes the compiler at a given path passing a single
- version argument and returns the output.
-
- Args:
- compiler_path (path): path of the compiler to be invoked
- version_arg (str): the argument used to extract version information
- """
- compiler = spack.util.executable.Executable(compiler_path)
- compiler_invocation_args = {
- "output": str,
- "error": str,
- "ignore_errors": ignore_errors,
- "timeout": 120,
- "fail_on_error": True,
- }
- if version_arg:
- output = compiler(version_arg, **compiler_invocation_args)
- else:
- output = compiler(**compiler_invocation_args)
- return output
-
-
-def get_compiler_version_output(compiler_path, *args, **kwargs) -> str:
- """Wrapper for _get_compiler_version_output()."""
- # This ensures that we memoize compiler output by *absolute path*,
- # not just executable name. If we don't do this, and the path changes
- # (e.g., during testing), we can get incorrect results.
- if not os.path.isabs(compiler_path):
- compiler_path = spack.util.executable.which_string(compiler_path, required=True)
-
- return _get_compiler_version_output(compiler_path, *args, **kwargs)
-
-
-def tokenize_flags(flags_values, propagate=False):
- """Given a compiler flag specification as a string, this returns a list
- where the entries are the flags. For compiler options which set values
- using the syntax "-flag value", this function groups flags and their
- values together. Any token not preceded by a "-" is considered the
- value of a prior flag."""
- tokens = flags_values.split()
- if not tokens:
- return []
- flag = tokens[0]
- flags_with_propagation = []
- for token in tokens[1:]:
- if not token.startswith("-"):
- flag += " " + token
- else:
- flags_with_propagation.append((flag, propagate))
- flag = token
- flags_with_propagation.append((flag, propagate))
- return flags_with_propagation
-
-
-#: regex for parsing linker lines
-_LINKER_LINE = re.compile(r"^( *|.*[/\\])" r"(link|ld|([^/\\]+-)?ld|collect2)" r"[^/\\]*( |$)")
-
-#: components of linker lines to ignore
-_LINKER_LINE_IGNORE = re.compile(r"(collect2 version|^[A-Za-z0-9_]+=|/ldfe )")
-
-#: regex to match linker search paths
-_LINK_DIR_ARG = re.compile(r"^-L(.:)?(?P
[/\\].*)")
-
-#: regex to match linker library path arguments
-_LIBPATH_ARG = re.compile(r"^[-/](LIBPATH|libpath):(?P.*)")
-
-
-def _parse_link_paths(string):
- """Parse implicit link paths from compiler debug output.
-
- This gives the compiler runtime library paths that we need to add to
- the RPATH of generated binaries and libraries. It allows us to
- ensure, e.g., that codes load the right libstdc++ for their compiler.
- """
- lib_search_paths = False
- raw_link_dirs = []
- for line in string.splitlines():
- if lib_search_paths:
- if line.startswith("\t"):
- raw_link_dirs.append(line[1:])
- continue
- else:
- lib_search_paths = False
- elif line.startswith("Library search paths:"):
- lib_search_paths = True
-
- if not _LINKER_LINE.match(line):
- continue
- if _LINKER_LINE_IGNORE.match(line):
- continue
- tty.debug(f"implicit link dirs: link line: {line}")
-
- next_arg = False
- for arg in line.split():
- if arg in ("-L", "-Y"):
- next_arg = True
- continue
-
- if next_arg:
- raw_link_dirs.append(arg)
- next_arg = False
- continue
-
- link_dir_arg = _LINK_DIR_ARG.match(arg)
- if link_dir_arg:
- link_dir = link_dir_arg.group("dir")
- raw_link_dirs.append(link_dir)
-
- link_dir_arg = _LIBPATH_ARG.match(arg)
- if link_dir_arg:
- link_dir = link_dir_arg.group("dir")
- raw_link_dirs.append(link_dir)
-
- implicit_link_dirs = list()
- visited = set()
- for link_dir in raw_link_dirs:
- normalized_path = os.path.abspath(link_dir)
- if normalized_path not in visited:
- implicit_link_dirs.append(normalized_path)
- visited.add(normalized_path)
-
- tty.debug(f"implicit link dirs: result: {', '.join(implicit_link_dirs)}")
- return implicit_link_dirs
-
-
-@llnl.path.system_path_filter
-def _parse_non_system_link_dirs(string: str) -> List[str]:
- """Parses link paths out of compiler debug output.
-
- Args:
- string: compiler debug output as a string
-
- Returns:
- Implicit link paths parsed from the compiler output
- """
- link_dirs = _parse_link_paths(string)
-
- # Remove directories that do not exist. Some versions of the Cray compiler
- # report nonexistent directories
- link_dirs = [d for d in link_dirs if os.path.isdir(d)]
-
- # Return set of directories containing needed compiler libs, minus
- # system paths. Note that 'filter_system_paths' only checks for an
- # exact match, while 'in_system_subdirectory' checks if a path contains
- # a system directory as a subdirectory
- link_dirs = filter_system_paths(link_dirs)
- return list(p for p in link_dirs if not in_system_subdirectory(p))
-
-
-def in_system_subdirectory(path):
- system_dirs = [
- "/lib/",
- "/lib64/",
- "/usr/lib/",
- "/usr/lib64/",
- "/usr/local/lib/",
- "/usr/local/lib64/",
- ]
- return any(path_contains_subdirectory(path, x) for x in system_dirs)
-
-
-class Compiler:
- """This class encapsulates a Spack "compiler", which includes C,
- C++, and Fortran compilers. Subclasses should implement
- support for specific compilers, their possible names, arguments,
- and how to identify the particular type of compiler."""
-
- # Optional prefix regexes for searching for this type of compiler.
- # Prefixes are sometimes used for toolchains
- prefixes: List[str] = []
-
- # 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.
- suffixes = [r"-.*"]
-
- #: Compiler argument that produces version information
- version_argument = "-dumpversion"
-
- #: Return values to ignore when invoking the compiler to get its version
- ignore_version_errors: Sequence[int] = ()
-
- #: Regex used to extract version from compiler's output
- version_regex = "(.*)"
-
- # These libraries are anticipated to be required by all executables built
- # by any compiler
- _all_compiler_rpath_libraries = ["libc", "libc++", "libstdc++"]
-
- #: Platform matcher for Platform objects supported by compiler
- is_supported_on_platform = lambda x: True
-
- # Default flags used by a compiler to set an rpath
- @property
- def cc_rpath_arg(self):
- return "-Wl,-rpath,"
-
- @property
- def cxx_rpath_arg(self):
- return "-Wl,-rpath,"
-
- @property
- def f77_rpath_arg(self):
- return "-Wl,-rpath,"
-
- @property
- def fc_rpath_arg(self):
- return "-Wl,-rpath,"
-
- @property
- def linker_arg(self):
- """Flag that need to be used to pass an argument to the linker."""
- return "-Wl,"
-
- @property
- def disable_new_dtags(self):
- if platform.system() == "Darwin":
- return ""
- return "--disable-new-dtags"
-
- @property
- def enable_new_dtags(self):
- if platform.system() == "Darwin":
- return ""
- return "--enable-new-dtags"
-
- @property
- def debug_flags(self):
- return ["-g"]
-
- @property
- def opt_flags(self):
- return ["-O", "-O0", "-O1", "-O2", "-O3"]
-
- def __init__(
- self,
- cspec,
- operating_system,
- target,
- paths,
- modules: Optional[List[str]] = None,
- alias=None,
- environment=None,
- extra_rpaths=None,
- enable_implicit_rpaths=None,
- **kwargs,
- ):
- self.spec = cspec
- self.operating_system = str(operating_system)
- self.target = target
- self.modules = modules or []
- self.alias = alias
- self.environment = environment or {}
- self.extra_rpaths = extra_rpaths or []
- self.enable_implicit_rpaths = enable_implicit_rpaths
- self.cache = COMPILER_CACHE
-
- self.cc = paths[0]
- self.cxx = paths[1]
- self.f77 = None
- self.fc = None
- if len(paths) > 2:
- self.f77 = paths[2]
- if len(paths) == 3:
- self.fc = self.f77
- else:
- self.fc = paths[3]
-
- # Unfortunately have to make sure these params are accepted
- # in the same order they are returned by sorted(flags)
- # in compilers/__init__.py
- self.flags = spack.spec.FlagMap(self.spec)
- for flag in self.flags.valid_compiler_flags():
- value = kwargs.get(flag, None)
- if value is not None:
- values_with_propagation = tokenize_flags(value, False)
- for value, propagation in values_with_propagation:
- self.flags.add_flag(flag, value, propagation)
-
- # caching value for compiler reported version
- # used for version checks for API, e.g. C++11 flag
- self._real_version = None
-
- def __eq__(self, other):
- return (
- self.cc == other.cc
- and self.cxx == other.cxx
- and self.fc == other.fc
- and self.f77 == other.f77
- and self.spec == other.spec
- and self.operating_system == other.operating_system
- and self.target == other.target
- and self.flags == other.flags
- and self.modules == other.modules
- and self.environment == other.environment
- and self.extra_rpaths == other.extra_rpaths
- and self.enable_implicit_rpaths == other.enable_implicit_rpaths
- )
-
- def __hash__(self):
- return hash(
- (
- self.cc,
- self.cxx,
- self.fc,
- self.f77,
- self.spec,
- self.operating_system,
- self.target,
- str(self.flags),
- str(self.modules),
- str(self.environment),
- str(self.extra_rpaths),
- self.enable_implicit_rpaths,
- )
- )
-
- def verify_executables(self):
- """Raise an error if any of the compiler executables is not valid.
-
- This method confirms that for all of the compilers (cc, cxx, f77, fc)
- that have paths, those paths exist and are executable by the current
- user.
- Raises a CompilerAccessError if any of the non-null paths for the
- compiler are not accessible.
- """
-
- def accessible_exe(exe):
- # compilers may contain executable names (on Cray or user edited)
- if not os.path.isabs(exe):
- exe = spack.util.executable.which_string(exe)
- if not exe:
- return False
- return os.path.isfile(exe) and os.access(exe, os.X_OK)
-
- # setup environment before verifying in case we have executable names
- # instead of absolute paths
- with self.compiler_environment():
- missing = [
- cmp
- for cmp in (self.cc, self.cxx, self.f77, self.fc)
- if cmp and not accessible_exe(cmp)
- ]
- if missing:
- raise CompilerAccessError(self, missing)
-
- @property
- def version(self):
- return self.spec.version
-
- @property
- def real_version(self):
- """Executable reported compiler version used for API-determinations
-
- E.g. C++11 flag checks.
- """
- real_version_str = self.cache.get(self).real_version
- if not real_version_str or real_version_str == "unknown":
- return self.version
-
- return spack.version.StandardVersion.from_string(real_version_str)
-
- def implicit_rpaths(self) -> List[str]:
- if self.enable_implicit_rpaths is False:
- return []
-
- output = self.compiler_verbose_output
-
- if not output:
- return []
-
- link_dirs = _parse_non_system_link_dirs(output)
-
- all_required_libs = list(self.required_libs) + Compiler._all_compiler_rpath_libraries
- return list(paths_containing_libs(link_dirs, all_required_libs))
-
- @property
- def default_dynamic_linker(self) -> Optional[str]:
- """Determine default dynamic linker from compiler link line"""
- output = self.compiler_verbose_output
-
- if not output:
- return None
-
- return spack.util.libc.parse_dynamic_linker(output)
-
- @property
- def default_libc(self) -> Optional["spack.spec.Spec"]:
- """Determine libc targeted by the compiler from link line"""
- # technically this should be testing the target platform of the compiler, but we don't have
- # that, so stick to host platform for now.
- if sys.platform in ("darwin", "win32"):
- return None
-
- dynamic_linker = self.default_dynamic_linker
-
- if not dynamic_linker:
- return None
-
- return spack.util.libc.libc_from_dynamic_linker(dynamic_linker)
-
- @property
- def required_libs(self):
- """For executables created with this compiler, the compiler libraries
- that would be generally required to run it.
- """
- # By default every compiler returns the empty list
- return []
-
- @property
- def compiler_verbose_output(self) -> Optional[str]:
- """Verbose output from compiling a dummy C source file. Output is cached."""
- return self.cache.get(self).c_compiler_output
-
- def _compile_dummy_c_source(self) -> Optional[str]:
- if self.cc:
- cc = self.cc
- ext = "c"
- else:
- cc = self.cxx
- ext = "cc"
-
- if not cc or not self.verbose_flag:
- return None
-
- try:
- tmpdir = tempfile.mkdtemp(prefix="spack-implicit-link-info")
- fout = os.path.join(tmpdir, "output")
- fin = os.path.join(tmpdir, f"main.{ext}")
-
- with open(fin, "w", encoding="utf-8") as csource:
- csource.write(
- "int main(int argc, char* argv[]) { (void)argc; (void)argv; return 0; }\n"
- )
- cc_exe = spack.util.executable.Executable(cc)
- for flag_type in ["cflags" if cc == self.cc else "cxxflags", "cppflags", "ldflags"]:
- cc_exe.add_default_arg(*self.flags.get(flag_type, []))
-
- with self.compiler_environment():
- return cc_exe(self.verbose_flag, fin, "-o", fout, output=str, error=str)
- except spack.util.executable.ProcessError as pe:
- tty.debug("ProcessError: Command exited with non-zero status: " + pe.long_message)
- return None
- finally:
- shutil.rmtree(tmpdir, ignore_errors=True)
-
- @property
- def verbose_flag(self) -> Optional[str]:
- """
- This property should be overridden in the compiler subclass if a
- verbose flag is available.
-
- If it is not overridden, it is assumed to not be supported.
- """
-
- # This property should be overridden in the compiler subclass if
- # OpenMP is supported by that compiler
- @property
- def openmp_flag(self):
- # If it is not overridden, assume it is not supported and warn the user
- raise UnsupportedCompilerFlag(self, "OpenMP", "openmp_flag")
-
- # This property should be overridden in the compiler subclass if
- # C++98 is not the default standard for that compiler
- @property
- def cxx98_flag(self):
- return ""
-
- # This property should be overridden in the compiler subclass if
- # C++11 is supported by that compiler
- @property
- def cxx11_flag(self):
- # If it is not overridden, assume it is not supported and warn the user
- raise UnsupportedCompilerFlag(self, "the C++11 standard", "cxx11_flag")
-
- # This property should be overridden in the compiler subclass if
- # C++14 is supported by that compiler
- @property
- def cxx14_flag(self):
- # If it is not overridden, assume it is not supported and warn the user
- raise UnsupportedCompilerFlag(self, "the C++14 standard", "cxx14_flag")
-
- # This property should be overridden in the compiler subclass if
- # C++17 is supported by that compiler
- @property
- def cxx17_flag(self):
- # If it is not overridden, assume it is not supported and warn the user
- raise UnsupportedCompilerFlag(self, "the C++17 standard", "cxx17_flag")
-
- # This property should be overridden in the compiler subclass if
- # C99 is supported by that compiler
- @property
- def c99_flag(self):
- # If it is not overridden, assume it is not supported and warn the user
- raise UnsupportedCompilerFlag(self, "the C99 standard", "c99_flag")
-
- # This property should be overridden in the compiler subclass if
- # C11 is supported by that compiler
- @property
- def c11_flag(self):
- # If it is not overridden, assume it is not supported and warn the user
- raise UnsupportedCompilerFlag(self, "the C11 standard", "c11_flag")
-
- @property
- def cc_pic_flag(self):
- """Returns the flag used by the C compiler to produce
- Position Independent Code (PIC)."""
- return "-fPIC"
-
- @property
- def cxx_pic_flag(self):
- """Returns the flag used by the C++ compiler to produce
- Position Independent Code (PIC)."""
- return "-fPIC"
-
- @property
- def f77_pic_flag(self):
- """Returns the flag used by the F77 compiler to produce
- Position Independent Code (PIC)."""
- return "-fPIC"
-
- @property
- def fc_pic_flag(self):
- """Returns the flag used by the FC compiler to produce
- Position Independent Code (PIC)."""
- return "-fPIC"
-
- # Note: This is not a class method. The class methods are used to detect
- # compilers on PATH based systems, and do not set up the run environment of
- # the compiler. This method can be called on `module` based systems as well
- def get_real_version(self) -> str:
- """Query the compiler for its version.
-
- This is the "real" compiler version, regardless of what is in the
- compilers.yaml file, which the user can change to name their compiler.
-
- Use the runtime environment of the compiler (modules and environment
- modifications) to enable the compiler to run properly on any platform.
- """
- cc = spack.util.executable.Executable(self.cc)
- try:
- with self.compiler_environment():
- output = cc(
- self.version_argument,
- output=str,
- error=str,
- ignore_errors=tuple(self.ignore_version_errors),
- )
- return self.extract_version_from_output(output)
- except spack.util.executable.ProcessError:
- return "unknown"
-
- @property
- def prefix(self):
- """Query the compiler for its install prefix. This is the install
- path as reported by the compiler. Note that paths for cc, cxx, etc
- are not enough to find the install prefix of the compiler, since
- the can be symlinks, wrappers, or filenames instead of absolute paths."""
- raise NotImplementedError("prefix is not implemented for this compiler")
-
- #
- # Compiler classes have methods for querying the version of
- # specific compiler executables. This is used when discovering compilers.
- #
- # Compiler *instances* are just data objects, and can only be
- # constructed from an actual set of executables.
- #
- @classmethod
- def default_version(cls, cc):
- """Override just this to override all compiler version functions."""
- output = get_compiler_version_output(
- cc, cls.version_argument, tuple(cls.ignore_version_errors)
- )
- return cls.extract_version_from_output(output)
-
- @classmethod
- @llnl.util.lang.memoized
- def extract_version_from_output(cls, output: str) -> str:
- """Extracts the version from compiler's output."""
- match = re.search(cls.version_regex, output)
- return match.group(1) if match else "unknown"
-
- @classmethod
- def cc_version(cls, cc):
- return cls.default_version(cc)
-
- @classmethod
- def search_regexps(cls, language):
- # Compile all the regular expressions used for files beforehand.
- # This searches for any combination of
- # defined for the compiler
- compiler_names = getattr(cls, "{0}_names".format(language))
- prefixes = [""] + cls.prefixes
- suffixes = [""]
- if sys.platform == "win32":
- ext = r"\.(?:exe|bat)"
- cls_suf = [suf + ext for suf in cls.suffixes]
- ext_suf = [ext]
- suffixes = suffixes + cls.suffixes + cls_suf + ext_suf
- else:
- suffixes = suffixes + cls.suffixes
- regexp_fmt = r"^({0}){1}({2})$"
- return [
- re.compile(regexp_fmt.format(prefix, re.escape(name), suffix))
- for prefix, name, suffix in itertools.product(prefixes, compiler_names, suffixes)
- ]
-
- def setup_custom_environment(self, pkg, env):
- """Set any environment variables necessary to use the compiler."""
- pass
-
- def __repr__(self):
- """Return a string representation of the compiler toolchain."""
- return self.__str__()
-
- def __str__(self):
- """Return a string representation of the compiler toolchain."""
- return "%s(%s)" % (
- self.name,
- "\n ".join(
- (
- str(s)
- for s in (
- self.cc,
- self.cxx,
- self.f77,
- self.fc,
- self.modules,
- str(self.operating_system),
- )
- )
- ),
- )
-
- @contextlib.contextmanager
- def compiler_environment(self):
- # Avoid modifying os.environ if possible.
- if not self.modules and not self.environment:
- yield
- return
-
- # store environment to replace later
- backup_env = os.environ.copy()
-
- try:
- # load modules and set env variables
- for module in self.modules:
- spack.util.module_cmd.load_module(module)
-
- # apply other compiler environment changes
- spack.schema.environment.parse(self.environment).apply_modifications()
-
- yield
- finally:
- # Restore environment regardless of whether inner code succeeded
- os.environ.clear()
- os.environ.update(backup_env)
-
- def to_dict(self):
- flags_dict = {fname: " ".join(fvals) for fname, fvals in self.flags.items()}
- flags_dict.update(
- {attr: getattr(self, attr, None) for attr in FLAG_INSTANCE_VARS if hasattr(self, attr)}
- )
- result = {
- "spec": str(self.spec),
- "paths": {attr: getattr(self, attr, None) for attr in PATH_INSTANCE_VARS},
- "flags": flags_dict,
- "operating_system": str(self.operating_system),
- "target": str(self.target),
- "modules": self.modules or [],
- "environment": self.environment or {},
- "extra_rpaths": self.extra_rpaths or [],
- }
-
- if self.enable_implicit_rpaths is not None:
- result["implicit_rpaths"] = self.enable_implicit_rpaths
-
- if self.alias:
- result["alias"] = self.alias
-
- return result
-
-
-class CompilerAccessError(spack.error.SpackError):
- def __init__(self, compiler, paths):
- msg = "Compiler '%s' has executables that are missing" % compiler.spec
- msg += " or are not executable: %s" % paths
- super().__init__(msg)
-
-
-class InvalidCompilerError(spack.error.SpackError):
- def __init__(self):
- super().__init__("Compiler has no executables.")
-
-
-class UnsupportedCompilerFlag(spack.error.SpackError):
- def __init__(self, compiler, feature, flag_name, ver_string=None):
- super().__init__(
- "{0} ({1}) does not support {2} (as compiler.{3}).".format(
- compiler.name, ver_string if ver_string else compiler.version, feature, flag_name
- ),
- "If you think it should, please edit the compiler.{0} subclass to".format(
- compiler.name
- )
- + " implement the {0} property and submit a pull request or issue.".format(flag_name),
- )
-
-
-class CompilerCacheEntry:
- """Deserialized cache entry for a compiler"""
-
- __slots__ = ("c_compiler_output", "real_version")
-
- def __init__(self, c_compiler_output: Optional[str], real_version: str):
- self.c_compiler_output = c_compiler_output
- self.real_version = real_version
-
- @property
- def empty(self) -> bool:
- """Sometimes the compiler is temporarily broken, preventing us from getting output. The
- call site determines if that is a problem."""
- return self.c_compiler_output is None
-
- @classmethod
- def from_dict(cls, data: Dict[str, Optional[str]]):
- if not isinstance(data, dict):
- raise ValueError(f"Invalid {cls.__name__} data")
- c_compiler_output = data.get("c_compiler_output")
- real_version = data.get("real_version")
- if not isinstance(real_version, str) or not isinstance(
- c_compiler_output, (str, type(None))
- ):
- raise ValueError(f"Invalid {cls.__name__} data")
- return cls(c_compiler_output, real_version)
-
-
-class CompilerCache:
- """Base class for compiler output cache. Default implementation does not cache anything."""
-
- def value(self, compiler: Compiler) -> Dict[str, Optional[str]]:
- return {
- "c_compiler_output": compiler._compile_dummy_c_source(),
- "real_version": compiler.get_real_version(),
- }
-
- def get(self, compiler: Compiler) -> CompilerCacheEntry:
- return CompilerCacheEntry.from_dict(self.value(compiler))
-
-
-class FileCompilerCache(CompilerCache):
- """Cache for compiler output, which is used to determine implicit link paths, the default libc
- version, and the compiler version."""
-
- name = os.path.join("compilers", "compilers.json")
-
- def __init__(self, cache: "FileCache") -> None:
- self.cache = cache
- self.cache.init_entry(self.name)
- self._data: Dict[str, Dict[str, Optional[str]]] = {}
-
- def _get_entry(self, key: str, *, allow_empty: bool) -> Optional[CompilerCacheEntry]:
- try:
- entry = CompilerCacheEntry.from_dict(self._data[key])
- return entry if allow_empty or not entry.empty else None
- except ValueError:
- del self._data[key]
- except KeyError:
- pass
- return None
-
- def get(self, compiler: Compiler) -> CompilerCacheEntry:
- # Cache hit
- try:
- with self.cache.read_transaction(self.name) as f:
- assert f is not None
- self._data = json.loads(f.read())
- assert isinstance(self._data, dict)
- except (json.JSONDecodeError, AssertionError):
- self._data = {}
-
- key = self._key(compiler)
- value = self._get_entry(key, allow_empty=False)
- if value is not None:
- return value
-
- # Cache miss
- with self.cache.write_transaction(self.name) as (old, new):
- try:
- assert old is not None
- self._data = json.loads(old.read())
- assert isinstance(self._data, dict)
- except (json.JSONDecodeError, AssertionError):
- self._data = {}
-
- # Use cache entry that may have been created by another process in the meantime.
- entry = self._get_entry(key, allow_empty=True)
-
- # Finally compute the cache entry
- if entry is None:
- self._data[key] = self.value(compiler)
- entry = CompilerCacheEntry.from_dict(self._data[key])
-
- new.write(json.dumps(self._data, separators=(",", ":")))
-
- return entry
-
- def _key(self, compiler: Compiler) -> str:
- as_bytes = json.dumps(compiler.to_dict(), separators=(",", ":")).encode("utf-8")
- return hashlib.sha256(as_bytes).hexdigest()
-
-
-def _make_compiler_cache():
- return FileCompilerCache(spack.caches.MISC_CACHE)
-
-
-COMPILER_CACHE: CompilerCache = llnl.util.lang.Singleton(_make_compiler_cache) # type: ignore
diff --git a/lib/spack/spack/compilers/aocc.py b/lib/spack/spack/compilers/aocc.py
deleted file mode 100644
index 0d6c908df65..00000000000
--- a/lib/spack/spack/compilers/aocc.py
+++ /dev/null
@@ -1,119 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import os
-import re
-
-import llnl.util.lang
-
-from spack.compiler import Compiler
-from spack.version import ver
-
-
-class Aocc(Compiler):
- version_argument = "--version"
-
- @property
- def debug_flags(self):
- return [
- "-gcodeview",
- "-gdwarf-2",
- "-gdwarf-3",
- "-gdwarf-4",
- "-gdwarf-5",
- "-gline-tables-only",
- "-gmodules",
- "-g",
- ]
-
- @property
- def opt_flags(self):
- return ["-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os", "-Oz", "-Og", "-O", "-O4"]
-
- @property
- def link_paths(self):
- link_paths = {
- "cc": os.path.join("aocc", "clang"),
- "cxx": os.path.join("aocc", "clang++"),
- "f77": os.path.join("aocc", "flang"),
- "fc": os.path.join("aocc", "flang"),
- }
-
- return link_paths
-
- @property
- def verbose_flag(self):
- return "-v"
-
- @property
- def openmp_flag(self):
- return "-fopenmp"
-
- @property
- def cxx11_flag(self):
- return "-std=c++11"
-
- @property
- def cxx14_flag(self):
- return "-std=c++14"
-
- @property
- def cxx17_flag(self):
- return "-std=c++17"
-
- @property
- def c99_flag(self):
- return "-std=c99"
-
- @property
- def c11_flag(self):
- return "-std=c11"
-
- @property
- def cc_pic_flag(self):
- return "-fPIC"
-
- @property
- def cxx_pic_flag(self):
- return "-fPIC"
-
- @property
- def f77_pic_flag(self):
- return "-fPIC"
-
- @property
- def fc_pic_flag(self):
- return "-fPIC"
-
- required_libs = ["libclang"]
-
- @classmethod
- @llnl.util.lang.memoized
- def extract_version_from_output(cls, output):
- match = re.search(r"AOCC_(\d+)[._](\d+)[._](\d+)", output)
- if match:
- return ".".join(match.groups())
- return "unknown"
-
- @property
- def stdcxx_libs(self):
- return ("-lstdc++",)
-
- @property
- def cflags(self):
- return self._handle_default_flag_addtions()
-
- @property
- def cxxflags(self):
- return self._handle_default_flag_addtions()
-
- @property
- def fflags(self):
- return self._handle_default_flag_addtions()
-
- def _handle_default_flag_addtions(self):
- # This is a known issue for AOCC 3.0 see:
- # https://developer.amd.com/wp-content/resources/AOCC-3.0-Install-Guide.pdf
- if self.version.satisfies(ver("3.0.0")):
- return "-Wno-unused-command-line-argument " "-mllvm -eliminate-similar-expr=false"
diff --git a/lib/spack/spack/compilers/apple_clang.py b/lib/spack/spack/compilers/apple_clang.py
deleted file mode 100644
index 7962639b6fd..00000000000
--- a/lib/spack/spack/compilers/apple_clang.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-import re
-
-import llnl.util.lang
-
-import spack.compiler
-import spack.compilers.clang
-from spack.version import Version
-
-
-class AppleClang(spack.compilers.clang.Clang):
- openmp_flag = "-Xpreprocessor -fopenmp"
-
- @classmethod
- @llnl.util.lang.memoized
- def extract_version_from_output(cls, output):
- ver = "unknown"
- match = re.search(
- # Apple's LLVM compiler has its own versions, so suffix them.
- r"^Apple (?:LLVM|clang) version ([^ )]+)",
- output,
- # Multi-line, since 'Apple clang' may not be on the first line
- # in particular, when run as gcc, it seems to output
- # "Configured with: --prefix=..." as the first line
- re.M,
- )
- if match:
- ver = match.group(match.lastindex)
- return ver
-
- # C++ flags based on CMake Modules/Compiler/AppleClang-CXX.cmake
-
- @property
- def cxx11_flag(self):
- # Spack's AppleClang detection only valid from Xcode >= 4.6
- if self.real_version < Version("4.0"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C++11 standard", "cxx11_flag", "Xcode < 4.0"
- )
- return "-std=c++11"
-
- @property
- def cxx14_flag(self):
- if self.real_version < Version("5.1"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C++14 standard", "cxx14_flag", "Xcode < 5.1"
- )
- elif self.real_version < Version("6.1"):
- return "-std=c++1y"
-
- return "-std=c++14"
-
- @property
- def cxx17_flag(self):
- if self.real_version < Version("6.1"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C++17 standard", "cxx17_flag", "Xcode < 6.1"
- )
- elif self.real_version < Version("10.0"):
- return "-std=c++1z"
- return "-std=c++17"
-
- @property
- def cxx20_flag(self):
- if self.real_version < Version("10.0"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C++20 standard", "cxx20_flag", "Xcode < 10.0"
- )
- elif self.real_version < Version("13.0"):
- return "-std=c++2a"
- return "-std=c++20"
-
- @property
- def cxx23_flag(self):
- if self.real_version < Version("13.0"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C++23 standard", "cxx23_flag", "Xcode < 13.0"
- )
- return "-std=c++2b"
-
- # C flags based on CMake Modules/Compiler/AppleClang-C.cmake
-
- @property
- def c99_flag(self):
- if self.real_version < Version("4.0"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C99 standard", "c99_flag", "< 4.0"
- )
- return "-std=c99"
-
- @property
- def c11_flag(self):
- if self.real_version < Version("4.0"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C11 standard", "c11_flag", "< 4.0"
- )
- return "-std=c11"
-
- @property
- def c17_flag(self):
- if self.real_version < Version("11.0"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C17 standard", "c17_flag", "< 11.0"
- )
- return "-std=c17"
-
- @property
- def c23_flag(self):
- if self.real_version < Version("11.0.3"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C23 standard", "c23_flag", "< 11.0.3"
- )
- return "-std=c2x"
diff --git a/lib/spack/spack/compilers/arm.py b/lib/spack/spack/compilers/arm.py
deleted file mode 100644
index 880c82b321d..00000000000
--- a/lib/spack/spack/compilers/arm.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import os
-
-import spack.compiler
-
-
-class Arm(spack.compiler.Compiler):
- # Named wrapper links within lib/spack/env
- link_paths = {
- "cc": os.path.join("arm", "armclang"),
- "cxx": os.path.join("arm", "armclang++"),
- "f77": os.path.join("arm", "armflang"),
- "fc": os.path.join("arm", "armflang"),
- }
-
- # The ``--version`` option seems to be the most consistent one for
- # arm compilers. Output looks like this:
- #
- # $ armlang --version
- # Arm C/C++/Fortran Compiler version 19.0 (build number 73) (based on LLVM 7.0.2)
- # Target: aarch64--linux-gnu
- # Thread model: posix
- # InstalledDir:
- # /opt/arm/arm-hpc-compiler-19.0_Generic-AArch64_RHEL-7_aarch64-linux/bin
- version_argument = "--version"
- version_regex = r"Arm C\/C\+\+\/Fortran Compiler version ([\d\.]+) "
-
- @property
- def verbose_flag(self):
- return "-v"
-
- @property
- def opt_flags(self):
- return ["-O", "-O0", "-O1", "-O2", "-O3", "-Ofast"]
-
- @property
- def openmp_flag(self):
- return "-fopenmp"
-
- @property
- def cxx11_flag(self):
- return "-std=c++11"
-
- @property
- def cxx14_flag(self):
- return "-std=c++14"
-
- @property
- def cxx17_flag(self):
- return "-std=c++1z"
-
- @property
- def c99_flag(self):
- return "-std=c99"
-
- @property
- def c11_flag(self):
- return "-std=c11"
-
- @property
- def cc_pic_flag(self):
- return "-fPIC"
-
- @property
- def cxx_pic_flag(self):
- return "-fPIC"
-
- @property
- def f77_pic_flag(self):
- return "-fPIC"
-
- @property
- def fc_pic_flag(self):
- return "-fPIC"
-
- required_libs = ["libclang", "libflang"]
diff --git a/lib/spack/spack/compilers/cce.py b/lib/spack/spack/compilers/cce.py
deleted file mode 100644
index a127ec9d4fe..00000000000
--- a/lib/spack/spack/compilers/cce.py
+++ /dev/null
@@ -1,127 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-import os
-
-from spack.compiler import Compiler, UnsupportedCompilerFlag
-from spack.version import Version
-
-
-class Cce(Compiler):
- """Cray compiler environment compiler."""
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- # For old cray compilers on module based systems we replace
- # ``version_argument`` with the old value. Cannot be a property
- # as the new value is used in classmethods for path-based detection
- if not self.is_clang_based:
- self.version_argument = "-V"
-
- # MacPorts builds gcc versions with prefixes and -mp-X.Y suffixes.
- suffixes = [r"-mp-\d\.\d"]
-
- @property
- def link_paths(self):
- if any("PrgEnv-cray" in m for m in self.modules):
- # Old module-based interface to cray compilers
- return {
- "cc": os.path.join("cce", "cc"),
- "cxx": os.path.join("case-insensitive", "CC"),
- "f77": os.path.join("cce", "ftn"),
- "fc": os.path.join("cce", "ftn"),
- }
-
- return {
- "cc": os.path.join("cce", "craycc"),
- "cxx": os.path.join("cce", "case-insensitive", "crayCC"),
- "f77": os.path.join("cce", "crayftn"),
- "fc": os.path.join("cce", "crayftn"),
- }
-
- @property
- def is_clang_based(self):
- version = self._real_version or self.version
- return version >= Version("9.0") and "classic" not in str(version)
-
- version_argument = "--version"
- version_regex = r"[Cc]ray (?:clang|C :|C\+\+ :|Fortran :) [Vv]ersion.*?(\d+(\.\d+)+)"
-
- @property
- def verbose_flag(self):
- return "-v"
-
- @property
- def debug_flags(self):
- return ["-g", "-G0", "-G1", "-G2", "-Gfast"]
-
- @property
- def openmp_flag(self):
- if self.is_clang_based:
- return "-fopenmp"
- return "-h omp"
-
- @property
- def cxx11_flag(self):
- if self.is_clang_based:
- return "-std=c++11"
- return "-h std=c++11"
-
- @property
- def cxx14_flag(self):
- if self.is_clang_based:
- return "-std=c++14"
- return "-h std=c++14"
-
- @property
- def cxx17_flag(self):
- if self.is_clang_based:
- return "-std=c++17"
-
- @property
- def c99_flag(self):
- if self.is_clang_based:
- return "-std=c99"
- elif self.real_version >= Version("8.4"):
- return "-h std=c99,noconform,gnu"
- elif self.real_version >= Version("8.1"):
- return "-h c99,noconform,gnu"
- raise UnsupportedCompilerFlag(self, "the C99 standard", "c99_flag", "< 8.1")
-
- @property
- def c11_flag(self):
- if self.is_clang_based:
- return "-std=c11"
- elif self.real_version >= Version("8.5"):
- return "-h std=c11,noconform,gnu"
- raise UnsupportedCompilerFlag(self, "the C11 standard", "c11_flag", "< 8.5")
-
- @property
- def cc_pic_flag(self):
- if self.is_clang_based:
- return "-fPIC"
- return "-h PIC"
-
- @property
- def cxx_pic_flag(self):
- if self.is_clang_based:
- return "-fPIC"
- return "-h PIC"
-
- @property
- def f77_pic_flag(self):
- if self.is_clang_based:
- return "-fPIC"
- return "-h PIC"
-
- @property
- def fc_pic_flag(self):
- if self.is_clang_based:
- return "-fPIC"
- return "-h PIC"
-
- @property
- def stdcxx_libs(self):
- # Cray compiler wrappers link to the standard C++ library
- # without additional flags.
- return ()
diff --git a/lib/spack/spack/compilers/clang.py b/lib/spack/spack/compilers/clang.py
deleted file mode 100644
index 0e0e827de5e..00000000000
--- a/lib/spack/spack/compilers/clang.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import os
-import re
-
-import llnl.util.lang
-
-from spack.compiler import Compiler, UnsupportedCompilerFlag
-from spack.version import Version
-
-#: compiler symlink mappings for mixed f77 compilers
-f77_mapping = [
- ("gfortran", os.path.join("clang", "gfortran")),
- ("xlf_r", os.path.join("xl_r", "xlf_r")),
- ("xlf", os.path.join("xl", "xlf")),
- ("ifort", os.path.join("intel", "ifort")),
-]
-
-#: compiler symlink mappings for mixed f90/fc compilers
-fc_mapping = [
- ("gfortran", os.path.join("clang", "gfortran")),
- ("xlf90_r", os.path.join("xl_r", "xlf90_r")),
- ("xlf90", os.path.join("xl", "xlf90")),
- ("ifort", os.path.join("intel", "ifort")),
-]
-
-
-class Clang(Compiler):
- version_argument = "--version"
-
- @property
- def debug_flags(self):
- return [
- "-gcodeview",
- "-gdwarf-2",
- "-gdwarf-3",
- "-gdwarf-4",
- "-gdwarf-5",
- "-gline-tables-only",
- "-gmodules",
- "-g",
- ]
-
- @property
- def opt_flags(self):
- return ["-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os", "-Oz", "-Og", "-O", "-O4"]
-
- # Clang has support for using different fortran compilers with the
- # clang executable.
- @property
- def link_paths(self):
- # clang links are always the same
- link_paths = {
- "cc": os.path.join("clang", "clang"),
- "cxx": os.path.join("clang", "clang++"),
- }
-
- # fortran links need to look at the actual compiler names from
- # compilers.yaml to figure out which named symlink to use
- for compiler_name, link_path in f77_mapping:
- if self.f77 and compiler_name in self.f77:
- link_paths["f77"] = link_path
- break
- else:
- link_paths["f77"] = os.path.join("clang", "flang")
-
- for compiler_name, link_path in fc_mapping:
- if self.fc and compiler_name in self.fc:
- link_paths["fc"] = link_path
- break
- else:
- link_paths["fc"] = os.path.join("clang", "flang")
-
- return link_paths
-
- @property
- def verbose_flag(self):
- return "-v"
-
- openmp_flag = "-fopenmp"
-
- # C++ flags based on CMake Modules/Compiler/Clang.cmake
-
- @property
- def cxx11_flag(self):
- if self.real_version < Version("3.3"):
- raise UnsupportedCompilerFlag(self, "the C++11 standard", "cxx11_flag", "< 3.3")
- return "-std=c++11"
-
- @property
- def cxx14_flag(self):
- if self.real_version < Version("3.4"):
- raise UnsupportedCompilerFlag(self, "the C++14 standard", "cxx14_flag", "< 3.5")
- elif self.real_version < Version("3.5"):
- return "-std=c++1y"
-
- return "-std=c++14"
-
- @property
- def cxx17_flag(self):
- if self.real_version < Version("3.5"):
- raise UnsupportedCompilerFlag(self, "the C++17 standard", "cxx17_flag", "< 3.5")
- elif self.real_version < Version("5.0"):
- return "-std=c++1z"
-
- return "-std=c++17"
-
- @property
- def cxx20_flag(self):
- if self.real_version < Version("5.0"):
- raise UnsupportedCompilerFlag(self, "the C++20 standard", "cxx20_flag", "< 5.0")
- elif self.real_version < Version("11.0"):
- return "-std=c++2a"
- else:
- return "-std=c++20"
-
- @property
- def cxx23_flag(self):
- if self.real_version < Version("12.0"):
- raise UnsupportedCompilerFlag(self, "the C++23 standard", "cxx23_flag", "< 12.0")
- elif self.real_version < Version("17.0"):
- return "-std=c++2b"
- else:
- return "-std=c++23"
-
- @property
- def c99_flag(self):
- return "-std=c99"
-
- @property
- def c11_flag(self):
- if self.real_version < Version("3.0"):
- raise UnsupportedCompilerFlag(self, "the C11 standard", "c11_flag", "< 3.0")
- if self.real_version < Version("3.1"):
- return "-std=c1x"
- return "-std=c11"
-
- @property
- def c17_flag(self):
- if self.real_version < Version("6.0"):
- raise UnsupportedCompilerFlag(self, "the C17 standard", "c17_flag", "< 6.0")
- return "-std=c17"
-
- @property
- def c23_flag(self):
- if self.real_version < Version("9.0"):
- raise UnsupportedCompilerFlag(self, "the C23 standard", "c23_flag", "< 9.0")
- elif self.real_version < Version("18.0"):
- return "-std=c2x"
- else:
- return "-std=c23"
-
- @property
- def cc_pic_flag(self):
- return "-fPIC"
-
- @property
- def cxx_pic_flag(self):
- return "-fPIC"
-
- @property
- def f77_pic_flag(self):
- return "-fPIC"
-
- @property
- def fc_pic_flag(self):
- return "-fPIC"
-
- required_libs = ["libclang"]
-
- @classmethod
- @llnl.util.lang.memoized
- def extract_version_from_output(cls, output):
- ver = "unknown"
- if ("Apple" in output) or ("AMD" in output):
- return ver
-
- match = re.search(
- # Normal clang compiler versions are left as-is
- r"(?:clang|flang-new) 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|flang-new) version ([^ )\n]+?)-[~.\w\d-]*|"
- r"(?:clang|flang-new) version ([^ )\n]+)",
- output,
- )
- if match:
- ver = match.group(match.lastindex)
- return ver
diff --git a/lib/spack/spack/compilers/fj.py b/lib/spack/spack/compilers/fj.py
deleted file mode 100644
index 85c94130d49..00000000000
--- a/lib/spack/spack/compilers/fj.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import os
-
-import spack.compiler
-
-
-class Fj(spack.compiler.Compiler):
- # Named wrapper links within build_env_path
- link_paths = {
- "cc": os.path.join("fj", "fcc"),
- "cxx": os.path.join("fj", "case-insensitive", "FCC"),
- "f77": os.path.join("fj", "frt"),
- "fc": os.path.join("fj", "frt"),
- }
-
- version_argument = "--version"
- version_regex = r"\((?:FCC|FRT)\) ([a-z\d.]+)"
-
- required_libs = ["libfj90i", "libfj90f", "libfjsrcinfo"]
-
- @property
- def verbose_flag(self):
- return "-v"
-
- @property
- def debug_flags(self):
- return "-g"
-
- @property
- def opt_flags(self):
- return ["-O0", "-O1", "-O2", "-O3", "-Ofast"]
-
- @property
- def openmp_flag(self):
- return "-Kopenmp"
-
- @property
- def cxx98_flag(self):
- return "-std=c++98"
-
- @property
- def cxx11_flag(self):
- return "-std=c++11"
-
- @property
- def cxx14_flag(self):
- return "-std=c++14"
-
- @property
- def cxx17_flag(self):
- return "-std=c++17"
-
- @property
- def c99_flag(self):
- return "-std=c99"
-
- @property
- def c11_flag(self):
- return "-std=c11"
-
- @property
- def cc_pic_flag(self):
- return "-KPIC"
-
- @property
- def cxx_pic_flag(self):
- return "-KPIC"
-
- @property
- def f77_pic_flag(self):
- return "-KPIC"
-
- @property
- def fc_pic_flag(self):
- return "-KPIC"
diff --git a/lib/spack/spack/compilers/gcc.py b/lib/spack/spack/compilers/gcc.py
deleted file mode 100644
index db1f9eec26a..00000000000
--- a/lib/spack/spack/compilers/gcc.py
+++ /dev/null
@@ -1,190 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import os
-
-from llnl.util.filesystem import ancestor
-
-import spack.compiler
-import spack.compilers.apple_clang as apple_clang
-import spack.util.executable
-from spack.version import Version
-
-
-class Gcc(spack.compiler.Compiler):
- # MacPorts builds gcc versions with prefixes and -mp-X or -mp-X.Y suffixes.
- # Homebrew and Linuxbrew may build gcc with -X, -X.Y suffixes.
- # Old compatibility versions may contain XY suffixes.
- suffixes = [r"-mp-\d+(?:\.\d+)?", r"-\d+(?:\.\d+)?", r"\d\d"]
-
- # Named wrapper links within build_env_path
- link_paths = {
- "cc": os.path.join("gcc", "gcc"),
- "cxx": os.path.join("gcc", "g++"),
- "f77": os.path.join("gcc", "gfortran"),
- "fc": os.path.join("gcc", "gfortran"),
- }
-
- @property
- def verbose_flag(self):
- return "-v"
-
- @property
- def debug_flags(self):
- return ["-g", "-gstabs+", "-gstabs", "-gxcoff+", "-gxcoff", "-gvms"]
-
- @property
- def opt_flags(self):
- return ["-O", "-O0", "-O1", "-O2", "-O3", "-Os", "-Ofast", "-Og"]
-
- @property
- def openmp_flag(self):
- return "-fopenmp"
-
- @property
- def cxx98_flag(self):
- if self.real_version < Version("6.0"):
- return ""
- else:
- return "-std=c++98"
-
- @property
- def cxx11_flag(self):
- if self.real_version < Version("4.3"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C++11 standard", "cxx11_flag", " < 4.3"
- )
- elif self.real_version < Version("4.7"):
- return "-std=c++0x"
- else:
- return "-std=c++11"
-
- @property
- def cxx14_flag(self):
- if self.real_version < Version("4.8"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C++14 standard", "cxx14_flag", "< 4.8"
- )
- elif self.real_version < Version("4.9"):
- return "-std=c++1y"
- else:
- return "-std=c++14"
-
- @property
- def cxx17_flag(self):
- if self.real_version < Version("5.0"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C++17 standard", "cxx17_flag", "< 5.0"
- )
- elif self.real_version < Version("6.0"):
- return "-std=c++1z"
- else:
- return "-std=c++17"
-
- @property
- def cxx20_flag(self):
- if self.real_version < Version("8.0"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C++20 standard", "cxx20_flag", "< 8.0"
- )
- elif self.real_version < Version("11.0"):
- return "-std=c++2a"
- else:
- return "-std=c++20"
-
- @property
- def cxx23_flag(self):
- if self.real_version < Version("11.0"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C++23 standard", "cxx23_flag", "< 11.0"
- )
- elif self.real_version < Version("14.0"):
- return "-std=c++2b"
- else:
- return "-std=c++23"
-
- @property
- def c99_flag(self):
- if self.real_version < Version("4.5"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C99 standard", "c99_flag", "< 4.5"
- )
- return "-std=c99"
-
- @property
- def c11_flag(self):
- if self.real_version < Version("4.7"):
- raise spack.compiler.UnsupportedCompilerFlag(
- self, "the C11 standard", "c11_flag", "< 4.7"
- )
- return "-std=c11"
-
- @property
- def cc_pic_flag(self):
- return "-fPIC"
-
- @property
- def cxx_pic_flag(self):
- return "-fPIC"
-
- @property
- def f77_pic_flag(self):
- return "-fPIC"
-
- @property
- def fc_pic_flag(self):
- return "-fPIC"
-
- required_libs = ["libgcc", "libgfortran"]
-
- @classmethod
- def default_version(cls, cc):
- """Older versions of gcc use the ``-dumpversion`` option.
- Output looks like this::
-
- 4.4.7
-
- In GCC 7, this option was changed to only return the major
- version of the compiler::
-
- 7
-
- A new ``-dumpfullversion`` option was added that gives us
- what we want::
-
- 7.2.0
- """
- # Apple's gcc is actually apple clang, so skip it. Returning
- # "unknown" ensures this compiler is not detected by default.
- # Users can add it manually to compilers.yaml at their own risk.
- if apple_clang.AppleClang.default_version(cc) != "unknown":
- return "unknown"
-
- version = super(Gcc, cls).default_version(cc)
- if Version(version) >= Version("7"):
- output = spack.compiler.get_compiler_version_output(cc, "-dumpfullversion")
- version = cls.extract_version_from_output(output)
- return version
-
- @property
- def stdcxx_libs(self):
- return ("-lstdc++",)
-
- @property
- def prefix(self):
- # GCC reports its install prefix when running ``-print-search-dirs``
- # on the first line ``install: ``.
- cc = spack.util.executable.Executable(self.cc)
- with self.compiler_environment():
- gcc_output = cc("-print-search-dirs", output=str, error=str)
-
- for line in gcc_output.splitlines():
- if line.startswith("install:"):
- gcc_prefix = line.split(":")[1].strip()
- # Go from /lib/gcc/// to
- return ancestor(gcc_prefix, 4)
-
- raise RuntimeError(
- "could not find install prefix of GCC from output:\n\t{}".format(gcc_output)
- )
diff --git a/lib/spack/spack/compilers/intel.py b/lib/spack/spack/compilers/intel.py
deleted file mode 100644
index f20e263d051..00000000000
--- a/lib/spack/spack/compilers/intel.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import os
-import sys
-
-from spack.compiler import Compiler, UnsupportedCompilerFlag
-from spack.version import Version
-
-
-class Intel(Compiler):
- # Named wrapper links within build_env_path
- link_paths = {
- "cc": os.path.join("intel", "icc"),
- "cxx": os.path.join("intel", "icpc"),
- "f77": os.path.join("intel", "ifort"),
- "fc": os.path.join("intel", "ifort"),
- }
-
- if sys.platform == "win32":
- version_argument = "/QV"
- else:
- version_argument = "--version"
-
- if sys.platform == "win32":
- version_regex = r"([1-9][0-9]*\.[0-9]*\.[0-9]*)"
- else:
- version_regex = r"\((?:IFORT|ICC)\) ([^ ]+)"
-
- @property
- def verbose_flag(self):
- return "-v"
-
- required_libs = ["libirc", "libifcore", "libifcoremt", "libirng"]
-
- @property
- def debug_flags(self):
- return ["-debug", "-g", "-g0", "-g1", "-g2", "-g3"]
-
- @property
- def opt_flags(self):
- return ["-O", "-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os"]
-
- @property
- def openmp_flag(self):
- if self.real_version < Version("16.0"):
- return "-openmp"
- else:
- return "-qopenmp"
-
- @property
- def cxx11_flag(self):
- if self.real_version < Version("11.1"):
- raise UnsupportedCompilerFlag(self, "the C++11 standard", "cxx11_flag", "< 11.1")
-
- elif self.real_version < Version("13"):
- return "-std=c++0x"
- else:
- return "-std=c++11"
-
- @property
- def cxx14_flag(self):
- # Adapted from CMake's Intel-CXX rules.
- if self.real_version < Version("15"):
- raise UnsupportedCompilerFlag(self, "the C++14 standard", "cxx14_flag", "< 15")
- elif self.real_version < Version("15.0.2"):
- return "-std=c++1y"
- else:
- return "-std=c++14"
-
- @property
- def cxx17_flag(self):
- # https://www.intel.com/content/www/us/en/developer/articles/news/c17-features-supported-by-c-compiler.html
- if self.real_version < Version("19"):
- raise UnsupportedCompilerFlag(self, "the C++17 standard", "cxx17_flag", "< 19")
- else:
- return "-std=c++17"
-
- @property
- def c99_flag(self):
- if self.real_version < Version("12"):
- raise UnsupportedCompilerFlag(self, "the C99 standard", "c99_flag", "< 12")
- else:
- return "-std=c99"
-
- @property
- def c11_flag(self):
- if self.real_version < Version("16"):
- raise UnsupportedCompilerFlag(self, "the C11 standard", "c11_flag", "< 16")
- else:
- return "-std=c1x"
-
- @property
- def c18_flag(self):
- # c18 supported since oneapi 2022, which is classic version 2021.5.0
- if self.real_version < Version("21.5.0"):
- raise UnsupportedCompilerFlag(self, "the C18 standard", "c18_flag", "< 21.5.0")
- else:
- return "-std=c18"
-
- @property
- def cc_pic_flag(self):
- return "-fPIC"
-
- @property
- def cxx_pic_flag(self):
- return "-fPIC"
-
- @property
- def f77_pic_flag(self):
- return "-fPIC"
-
- @property
- def fc_pic_flag(self):
- return "-fPIC"
-
- @property
- def stdcxx_libs(self):
- return ("-cxxlib",)
-
- def setup_custom_environment(self, pkg, env):
- # Edge cases for Intel's oneAPI compilers when using the legacy classic compilers:
- # Always pass flags to disable deprecation warnings, since these warnings can
- # confuse tools that parse the output of compiler commands (e.g. version checks).
- if self.real_version >= Version("2021") and self.real_version < Version("2024"):
- env.append_flags("SPACK_ALWAYS_CFLAGS", "-diag-disable=10441")
- env.append_flags("SPACK_ALWAYS_CXXFLAGS", "-diag-disable=10441")
- if self.real_version >= Version("2021") and self.real_version < Version("2025"):
- env.append_flags("SPACK_ALWAYS_FFLAGS", "-diag-disable=10448")
diff --git a/lib/spack/spack/compilers/msvc.py b/lib/spack/spack/compilers/msvc.py
deleted file mode 100644
index 34d95606808..00000000000
--- a/lib/spack/spack/compilers/msvc.py
+++ /dev/null
@@ -1,393 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import os
-import re
-import subprocess
-import sys
-import tempfile
-from typing import Dict
-
-import archspec.cpu
-
-import spack.compiler
-import spack.operating_systems.windows_os
-import spack.platforms
-import spack.util.executable
-from spack.compiler import Compiler
-from spack.error import SpackError
-from spack.version import Version, VersionRange
-
-FC_PATH: Dict[str, str] = dict()
-
-
-class CmdCall:
- """Compose a call to `cmd` for an ordered series of cmd commands/scripts"""
-
- def __init__(self, *cmds):
- if not cmds:
- raise RuntimeError(
- """Attempting to run commands from CMD without specifying commands.
- Please add commands to be run."""
- )
- self._cmds = cmds
-
- def __call__(self):
- out = subprocess.check_output(self.cmd_line, stderr=subprocess.STDOUT) # novermin
- return out.decode("utf-16le", errors="replace") # novermin
-
- @property
- def cmd_line(self):
- base_call = "cmd /u /c "
- commands = " && ".join([x.command_str() for x in self._cmds])
- # If multiple commands are being invoked by a single subshell
- # they must be encapsulated by a double quote. Always double
- # quote to be sure of proper handling
- # cmd will properly resolve nested double quotes as needed
- #
- # `set`` writes out the active env to the subshell stdout,
- # and in this context we are always trying to obtain env
- # state so it should always be appended
- return base_call + f'"{commands} && set"'
-
-
-class VarsInvocation:
- def __init__(self, script):
- self._script = script
-
- def command_str(self):
- return f'"{self._script}"'
-
- @property
- def script(self):
- return self._script
-
-
-class VCVarsInvocation(VarsInvocation):
- def __init__(self, script, arch, msvc_version):
- super(VCVarsInvocation, self).__init__(script)
- self._arch = arch
- self._msvc_version = msvc_version
-
- @property
- def sdk_ver(self):
- """Accessor for Windows SDK version property
-
- Note: This property may not be set by
- the calling context and as such this property will
- return an empty string
-
- This property will ONLY be set if the SDK package
- is a dependency somewhere in the Spack DAG of the package
- for which we are constructing an MSVC compiler env.
- Otherwise this property should be unset to allow the VCVARS
- script to use its internal heuristics to determine appropriate
- SDK version
- """
- if getattr(self, "_sdk_ver", None):
- return self._sdk_ver + ".0"
- return ""
-
- @sdk_ver.setter
- def sdk_ver(self, val):
- self._sdk_ver = val
-
- @property
- def arch(self):
- return self._arch
-
- @property
- def vcvars_ver(self):
- return f"-vcvars_ver={self._msvc_version}"
-
- def command_str(self):
- script = super(VCVarsInvocation, self).command_str()
- return f"{script} {self.arch} {self.sdk_ver} {self.vcvars_ver}"
-
-
-def get_valid_fortran_pth():
- """Assign maximum available fortran compiler version"""
- # TODO (johnwparent): validate compatibility w/ try compiler
- # functionality when added
- sort_fn = lambda fc_ver: Version(fc_ver)
- sort_fc_ver = sorted(list(FC_PATH.keys()), key=sort_fn)
- return FC_PATH[sort_fc_ver[-1]] if sort_fc_ver else None
-
-
-class Msvc(Compiler):
- # Named wrapper links within build_env_path
- # Due to the challenges of supporting compiler wrappers
- # in Windows, we leave these blank, and dynamically compute
- # based on proper versions of MSVC from there
- # pending acceptance of #28117 for full support using
- # compiler wrappers
- link_paths = {"cc": "", "cxx": "", "f77": "", "fc": ""}
-
- #: Compiler argument that produces version information
- version_argument = ""
-
- # For getting ifx's version, call it with version_argument
- # and ignore the error code
- ignore_version_errors = [1]
-
- #: Regex used to extract version from compiler's output
- version_regex = r"([1-9][0-9]*\.[0-9]*\.[0-9]*)"
- # The MSVC compiler class overrides this to prevent instances
- # of erroneous matching on executable names that cannot be msvc
- # compilers
- suffixes = []
-
- is_supported_on_platform = lambda x: isinstance(x, spack.platforms.Windows)
-
- def __init__(self, *args, **kwargs):
- # This positional argument "paths" is later parsed and process by the base class
- # via the call to `super` later in this method
- paths = args[3]
- latest_fc = get_valid_fortran_pth()
- new_pth = [pth if pth else latest_fc for pth in paths[2:]]
- paths[2:] = new_pth
- # Initialize, deferring to base class but then adding the vcvarsallfile
- # file based on compiler executable path.
- super().__init__(*args, **kwargs)
- # To use the MSVC compilers, VCVARS must be invoked
- # VCVARS is located at a fixed location, referencable
- # idiomatically by the following relative path from the
- # compiler.
- # Spack first finds the compilers via VSWHERE
- # and stores their path, but their respective VCVARS
- # file must be invoked before useage.
- env_cmds = []
- compiler_root = os.path.join(os.path.dirname(self.cc), "../../../../../..")
- vcvars_script_path = os.path.join(compiler_root, "Auxiliary", "Build", "vcvars64.bat")
- # get current platform architecture and format for vcvars argument
- arch = spack.platforms.real_host().default.lower()
- arch = arch.replace("-", "_")
- if str(archspec.cpu.host().family) == "x86_64":
- arch = "amd64"
-
- self.vcvars_call = VCVarsInvocation(vcvars_script_path, arch, self.msvc_version)
- env_cmds.append(self.vcvars_call)
- # Below is a check for a valid fortran path
- # paths has c, cxx, fc, and f77 paths in that order
- # paths[2] refers to the fc path and is a generic check
- # for a fortran compiler
- if paths[2]:
-
- def get_oneapi_root(pth: str):
- """From within a prefix known to be a oneAPI path
- determine the oneAPI root path from arbitrary point
- under root
-
- Args:
- pth: path prefixed within oneAPI root
- """
- if not pth:
- return ""
- while os.path.basename(pth) and os.path.basename(pth) != "oneAPI":
- pth = os.path.dirname(pth)
- return pth
-
- # If this found, it sets all the vars
- oneapi_root = get_oneapi_root(self.fc)
- if not oneapi_root:
- raise RuntimeError(f"Non-oneAPI Fortran compiler {self.fc} assigned to MSVC")
- oneapi_root_setvars = os.path.join(oneapi_root, "setvars.bat")
- # some oneAPI exes return a version more precise than their
- # install paths specify, so we determine path from
- # the install path rather than the fc executable itself
- numver = r"\d+\.\d+(?:\.\d+)?"
- pattern = f"((?:{numver})|(?:latest))"
- version_from_path = re.search(pattern, self.fc).group(1)
- oneapi_version_setvars = os.path.join(
- oneapi_root, "compiler", version_from_path, "env", "vars.bat"
- )
- # order matters here, the specific version env must be invoked first,
- # otherwise it will be ignored if the root setvars sets up the oneapi
- # env first
- env_cmds.extend(
- [VarsInvocation(oneapi_version_setvars), VarsInvocation(oneapi_root_setvars)]
- )
- self.msvc_compiler_environment = CmdCall(*env_cmds)
-
- @property
- def cxx11_flag(self):
- return "/std:c++11"
-
- @property
- def cxx14_flag(self):
- return "/std:c++14"
-
- @property
- def cxx17_flag(self):
- return "/std:c++17"
-
- @property
- def cxx20_flag(self):
- return "/std:c++20"
-
- @property
- def c11_flag(self):
- return "/std:c11"
-
- @property
- def c17_flag(self):
- return "/std:c17"
-
- @property
- def msvc_version(self):
- """This is the VCToolset version *NOT* the actual version of the cl compiler
- For CL version, query `Msvc.cl_version`"""
- return Version(re.search(Msvc.version_regex, self.cc).group(1))
-
- @property
- def short_msvc_version(self):
- """This is the shorthand VCToolset version of form
- MSVC
- """
- return "MSVC" + self.vc_toolset_ver
-
- @property
- def vc_toolset_ver(self):
- """
- The toolset version is the version of the combined set of cl and link
- This typically relates directly to VS version i.e. VS 2022 is v143
- VS 19 is v142, etc.
- This value is defined by the first three digits of the major + minor
- version of the VS toolset (143 for 14.3x.bbbbb). Traditionally the
- minor version has remained a static two digit number for a VS release
- series, however, as of VS22, this is no longer true, both
- 14.4x.bbbbb and 14.3x.bbbbb are considered valid VS22 VC toolset
- versions due to a change in toolset minor version sentiment.
-
- This is *NOT* the full version, for that see
- Msvc.msvc_version or MSVC.platform_toolset_ver for the
- raw platform toolset version
-
- """
- ver = self.msvc_version[:2].joined.string[:3]
- return ver
-
- @property
- def platform_toolset_ver(self):
- """
- This is the platform toolset version of current MSVC compiler
- i.e. 142. The platform toolset is the targeted MSVC library/compiler
- versions by compilation (this is different from the VC Toolset)
-
-
- This is different from the VC toolset version as established
- by `short_msvc_version`, but typically are represented by the same
- three digit value
- """
- # Typically VS toolset version and platform toolset versions match
- # VS22 introduces the first divergence of VS toolset version
- # (144 for "recent" releases) and platform toolset version (143)
- # so it needs additional handling until MS releases v144
- # (assuming v144 is also for VS22)
- # or adds better support for detection
- # TODO: (johnwparent) Update this logic for the next platform toolset
- # or VC toolset version update
- toolset_ver = self.vc_toolset_ver
- vs22_toolset = Version(toolset_ver) > Version("142")
- return toolset_ver if not vs22_toolset else "143"
-
- @property
- def visual_studio_version(self):
- """The four digit Visual Studio version (i.e. 2019 or 2022)
-
- Note: This differs from the msvc version or toolset version as
- those properties track the compiler and build tools version
- respectively, whereas this tracks the VS release associated
- with a given MSVC compiler.
- """
- return re.search(r"[0-9]{4}", self.cc).group(0)
-
- def _compiler_version(self, compiler):
- """Returns version object for given compiler"""
- # ignore_errors below is true here due to ifx's
- # non zero return code if it is not provided
- # and input file
- return Version(
- re.search(
- Msvc.version_regex,
- spack.compiler.get_compiler_version_output(
- compiler, version_arg=None, ignore_errors=True
- ),
- ).group(1)
- )
-
- @property
- def cl_version(self):
- """Cl toolset version"""
- return self._compiler_version(self.cc)
-
- @property
- def ifx_version(self):
- """Ifx compiler version associated with this version of MSVC"""
- return self._compiler_version(self.fc)
-
- @property
- def vs_root(self):
- # The MSVC install root is located at a fix level above the compiler
- # and is referenceable idiomatically via the pattern below
- # this should be consistent accross versions
- return os.path.abspath(os.path.join(self.cc, "../../../../../../../.."))
-
- def setup_custom_environment(self, pkg, env):
- """Set environment variables for MSVC using the
- Microsoft-provided script."""
- # Set the build environment variables for spack. Just using
- # subprocess.call() doesn't work since that operates in its own
- # environment which is destroyed (along with the adjusted variables)
- # once the process terminates. So go the long way around: examine
- # output, sort into dictionary, use that to make the build
- # environment.
-
- # vcvars can target specific sdk versions, force it to pick up concretized sdk
- # version, if needed by spec
- if pkg.name != "win-sdk" and "win-sdk" in pkg.spec:
- self.vcvars_call.sdk_ver = pkg.spec["win-sdk"].version.string
-
- out = self.msvc_compiler_environment()
- int_env = dict(
- (key, value)
- for key, _, value in (line.partition("=") for line in out.splitlines())
- if key and value
- )
-
- for env_var in int_env:
- if os.pathsep not in int_env[env_var]:
- env.set(env_var, int_env[env_var])
- else:
- env.set_path(env_var, int_env[env_var].split(os.pathsep))
-
- # certain versions of ifx (2021.3.0:2023.1.0) do not play well with env:TMP
- # that has a "." character in the path
- # Work around by pointing tmp to the stage for the duration of the build
- if self.fc and Version(self.fc_version(self.fc)).satisfies(
- VersionRange("2021.3.0", "2023.1.0")
- ):
- new_tmp = tempfile.mkdtemp(dir=pkg.stage.path)
- env.set("TMP", new_tmp)
-
- env.set("CC", self.cc)
- env.set("CXX", self.cxx)
- env.set("FC", self.fc)
- env.set("F77", self.f77)
-
- @classmethod
- def fc_version(cls, fc):
- if not sys.platform == "win32":
- return "unknown"
- fc_ver = cls.default_version(fc)
- FC_PATH[fc_ver] = fc
- try:
- sps = spack.operating_systems.windows_os.WindowsOs().compiler_search_paths
- except AttributeError:
- raise SpackError(
- "Windows compiler search paths not established, "
- "please report this behavior to github.com/spack/spack"
- )
- clp = spack.util.executable.which_string("cl", path=sps)
- return cls.default_version(clp) if clp else fc_ver
diff --git a/lib/spack/spack/compilers/nag.py b/lib/spack/spack/compilers/nag.py
deleted file mode 100644
index 7b78b06eaa3..00000000000
--- a/lib/spack/spack/compilers/nag.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import os
-import re
-
-import llnl.util.lang
-
-import spack.compiler
-
-
-class Nag(spack.compiler.Compiler):
- # Named wrapper links within build_env_path
- # Use default wrappers for C and C++, in case provided in compilers.yaml
- link_paths = {
- "cc": "cc",
- "cxx": "c++",
- "f77": os.path.join("nag", "nagfor"),
- "fc": os.path.join("nag", "nagfor"),
- }
-
- version_argument = "-V"
-
- @classmethod
- @llnl.util.lang.memoized
- def extract_version_from_output(cls, output):
- match = re.search(r"NAG Fortran Compiler Release (\d+).(\d+)\(.*\) Build (\d+)", output)
- if match:
- return ".".join(match.groups())
-
- @property
- def verbose_flag(self):
- # 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._compile_dummy_c_source): 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.
- return "-Wl,-v"
-
- @property
- def openmp_flag(self):
- return "-openmp"
-
- @property
- def debug_flags(self):
- return ["-g", "-gline", "-g90"]
-
- @property
- def opt_flags(self):
- return ["-O", "-O0", "-O1", "-O2", "-O3", "-O4"]
-
- @property
- def cxx11_flag(self):
- # NAG does not have a C++ compiler
- # However, it can be mixed with a compiler that does support it
- return "-std=c++11"
-
- @property
- def f77_pic_flag(self):
- return "-PIC"
-
- @property
- def fc_pic_flag(self):
- return "-PIC"
-
- # Unlike other compilers, the NAG compiler passes options to GCC, which
- # then passes them to the linker. Therefore, we need to doubly wrap the
- # options with '-Wl,-Wl,,'
- @property
- def f77_rpath_arg(self):
- return "-Wl,-Wl,,-rpath,,"
-
- @property
- def fc_rpath_arg(self):
- return "-Wl,-Wl,,-rpath,,"
-
- @property
- def linker_arg(self):
- return "-Wl,-Wl,,"
-
- @property
- def disable_new_dtags(self):
- # Disable RPATH/RUNPATH forcing for NAG/GCC mixed toolchains:
- return ""
-
- @property
- def enable_new_dtags(self):
- # Disable RPATH/RUNPATH forcing for NAG/GCC mixed toolchains:
- return ""
diff --git a/lib/spack/spack/compilers/nvhpc.py b/lib/spack/spack/compilers/nvhpc.py
deleted file mode 100644
index 1c8e159f190..00000000000
--- a/lib/spack/spack/compilers/nvhpc.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import os
-
-from spack.compiler import Compiler
-
-
-class Nvhpc(Compiler):
- # Named wrapper links within build_env_path
- link_paths = {
- "cc": os.path.join("nvhpc", "nvc"),
- "cxx": os.path.join("nvhpc", "nvc++"),
- "f77": os.path.join("nvhpc", "nvfortran"),
- "fc": os.path.join("nvhpc", "nvfortran"),
- }
-
- version_argument = "--version"
- version_regex = r"nv[^ ]* (?:[^ ]+ Dev-r)?([0-9.]+)(?:-[0-9]+)?"
-
- @property
- def verbose_flag(self):
- return "-v"
-
- @property
- def debug_flags(self):
- return ["-g", "-gopt"]
-
- @property
- def opt_flags(self):
- return ["-O", "-O0", "-O1", "-O2", "-O3", "-O4"]
-
- @property
- def openmp_flag(self):
- return "-mp"
-
- @property
- def cc_pic_flag(self):
- return "-fpic"
-
- @property
- def cxx_pic_flag(self):
- return "-fpic"
-
- @property
- def f77_pic_flag(self):
- return "-fpic"
-
- @property
- def fc_pic_flag(self):
- return "-fpic"
-
- @property
- def c99_flag(self):
- return "-c99"
-
- @property
- def c11_flag(self):
- return "-c11"
-
- @property
- def cxx11_flag(self):
- return "--c++11"
-
- @property
- def cxx14_flag(self):
- return "--c++14"
-
- @property
- def cxx17_flag(self):
- return "--c++17"
-
- @property
- def stdcxx_libs(self):
- return ("-c++libs",)
-
- required_libs = ["libnvc", "libnvf"]
diff --git a/lib/spack/spack/compilers/oneapi.py b/lib/spack/spack/compilers/oneapi.py
deleted file mode 100644
index 255705c67be..00000000000
--- a/lib/spack/spack/compilers/oneapi.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import os
-from os.path import dirname, join
-
-from llnl.util import tty
-from llnl.util.filesystem import ancestor
-
-import spack.util.executable
-from spack.compiler import Compiler
-from spack.version import Version
-
-
-class Oneapi(Compiler):
- # Named wrapper links within build_env_path
- link_paths = {
- "cc": os.path.join("oneapi", "icx"),
- "cxx": os.path.join("oneapi", "icpx"),
- "f77": os.path.join("oneapi", "ifx"),
- "fc": os.path.join("oneapi", "ifx"),
- }
-
- version_argument = "--version"
- version_regex = r"(?:(?:oneAPI DPC\+\+(?:\/C\+\+)? Compiler)|(?:\(IFORT\))|(?:\(IFX\))) (\S+)"
-
- @property
- def verbose_flag(self):
- return "-v"
-
- required_libs = [
- "libirc",
- "libifcore",
- "libifcoremt",
- "libirng",
- "libsvml",
- "libintlc",
- "libimf",
- "libsycl",
- "libOpenCL",
- ]
-
- @property
- def debug_flags(self):
- return ["-debug", "-g", "-g0", "-g1", "-g2", "-g3"]
-
- @property
- def opt_flags(self):
- return ["-O", "-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os"]
-
- @property
- def openmp_flag(self):
- return "-fiopenmp"
-
- # There may be some additional options here for offload, e.g. :
- # -fopenmp-simd Emit OpenMP code only for SIMD-based constructs.
- # -fopenmp-targets=
- # -fopenmp-version=
- # -fopenmp Parse OpenMP pragmas and generate parallel code.
- # -qno-openmp Disable OpenMP support
- # -qopenmp-link= Choose whether to link with the static or
- # dynamic OpenMP libraries. Default is dynamic.
- # -qopenmp-simd Emit OpenMP code only for SIMD-based constructs.
- # -qopenmp-stubs enables the user to compile OpenMP programs in
- # sequential mode. The OpenMP directives are
- # ignored and a stub OpenMP library is linked.
- # -qopenmp-threadprivate=
- # -qopenmp Parse OpenMP pragmas and generate parallel code.
- # -static-openmp Use the static host OpenMP runtime while
- # linking.
- # -Xopenmp-target=
- # -Xopenmp-target Pass to the target offloading toolchain.
- # Source: icx --help output
-
- @property
- def cxx11_flag(self):
- return "-std=c++11"
-
- @property
- def cxx14_flag(self):
- return "-std=c++14"
-
- @property
- def cxx17_flag(self):
- return "-std=c++17"
-
- @property
- def cxx20_flag(self):
- return "-std=c++20"
-
- @property
- def c99_flag(self):
- return "-std=c99"
-
- @property
- def c11_flag(self):
- return "-std=c1x"
-
- @property
- def cc_pic_flag(self):
- return "-fPIC"
-
- @property
- def cxx_pic_flag(self):
- return "-fPIC"
-
- @property
- def f77_pic_flag(self):
- return "-fPIC"
-
- @property
- def fc_pic_flag(self):
- return "-fPIC"
-
- @property
- def stdcxx_libs(self):
- return ("-cxxlib",)
-
- @property
- def prefix(self):
- # OneAPI reports its install prefix when running ``--version``
- # on the line ``InstalledDir: /bin/compiler``.
- cc = spack.util.executable.Executable(self.cc)
- with self.compiler_environment():
- oneapi_output = cc("--version", output=str, error=str)
-
- for line in oneapi_output.splitlines():
- if line.startswith("InstalledDir:"):
- oneapi_prefix = line.split(":")[1].strip()
- # Go from /bin/compiler to
- return ancestor(oneapi_prefix, 2)
-
- raise RuntimeError(
- "could not find install prefix of OneAPI from output:\n\t{}".format(oneapi_output)
- )
-
- def setup_custom_environment(self, pkg, env):
- # workaround bug in icpx driver where it requires sycl-post-link is on the PATH
- # It is located in the same directory as the driver. Error message:
- # clang++: error: unable to execute command:
- # Executable "sycl-post-link" doesn't exist!
- # also ensures that shared objects and libraries required by the compiler,
- # e.g. libonnx, can be found succesfully
- # due to a fix, this is no longer required for OneAPI versions >= 2024.2
- if self.cxx and pkg.spec.satisfies("%oneapi@:2024.1"):
- env.prepend_path("PATH", dirname(self.cxx))
- env.prepend_path("LD_LIBRARY_PATH", join(dirname(dirname(self.cxx)), "lib"))
-
- # Edge cases for Intel's oneAPI compilers when using the legacy classic compilers:
- # Always pass flags to disable deprecation warnings, since these warnings can
- # confuse tools that parse the output of compiler commands (e.g. version checks).
- # This is really only needed for Fortran, since oneapi@ should be using either
- # icx+icpx+ifx or icx+icpx+ifort. But to be on the safe side (some users may
- # want to try to swap icpx against icpc, for example), and since the Intel LLVM
- # compilers accept these diag-disable flags, we apply them for all compilers.
- if self.real_version >= Version("2021") and self.real_version < Version("2024"):
- env.append_flags("SPACK_ALWAYS_CFLAGS", "-diag-disable=10441")
- env.append_flags("SPACK_ALWAYS_CXXFLAGS", "-diag-disable=10441")
- if self.real_version >= Version("2021") and self.real_version < Version("2025"):
- env.append_flags("SPACK_ALWAYS_FFLAGS", "-diag-disable=10448")
-
- # 2024 release bumped the libsycl version because of an ABI
- # change, 2024 compilers are required. You will see this
- # error:
- #
- # /usr/bin/ld: warning: libsycl.so.7, needed by ...., not found
- if pkg.spec.satisfies("%oneapi@:2023"):
- for c in ["dnn"]:
- if pkg.spec.satisfies(f"^intel-oneapi-{c}@2024:"):
- tty.warn(f"intel-oneapi-{c}@2024 SYCL APIs requires %oneapi@2024:")
diff --git a/lib/spack/spack/compilers/rocmcc.py b/lib/spack/spack/compilers/rocmcc.py
deleted file mode 100644
index e397dc90795..00000000000
--- a/lib/spack/spack/compilers/rocmcc.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import re
-
-import llnl.util.lang
-
-import spack.compilers.clang
-
-
-class Rocmcc(spack.compilers.clang.Clang):
- @property
- def link_paths(self):
- link_paths = {
- "cc": "rocmcc/amdclang",
- "cxx": "rocmcc/amdclang++",
- "f77": "rocmcc/amdflang",
- "fc": "rocmcc/amdflang",
- }
-
- return link_paths
-
- @property
- def cxx11_flag(self):
- return "-std=c++11"
-
- @property
- def cxx14_flag(self):
- return "-std=c++14"
-
- @property
- def cxx17_flag(self):
- return "-std=c++17"
-
- @property
- def c99_flag(self):
- return "-std=c99"
-
- @property
- def c11_flag(self):
- return "-std=c11"
-
- @classmethod
- @llnl.util.lang.memoized
- def extract_version_from_output(cls, output):
- match = re.search(r"llvm-project roc-(\d+)[._](\d+)[._](\d+)", output)
- if match:
- return ".".join(match.groups())
-
- @property
- def stdcxx_libs(self):
- return ("-lstdc++",)
diff --git a/lib/spack/spack/compilers/xl.py b/lib/spack/spack/compilers/xl.py
deleted file mode 100644
index 8bdec9586b7..00000000000
--- a/lib/spack/spack/compilers/xl.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import os
-
-from spack.compiler import Compiler, UnsupportedCompilerFlag
-from spack.version import Version
-
-
-class Xl(Compiler):
- # Named wrapper links within build_env_path
- link_paths = {
- "cc": os.path.join("xl", "xlc"),
- "cxx": os.path.join("xl", "xlc++"),
- "f77": os.path.join("xl", "xlf"),
- "fc": os.path.join("xl", "xlf90"),
- }
-
- version_argument = "-qversion"
- version_regex = r"([0-9]?[0-9]\.[0-9])"
-
- @property
- def verbose_flag(self):
- return "-V"
-
- @property
- def debug_flags(self):
- return ["-g", "-g0", "-g1", "-g2", "-g8", "-g9"]
-
- @property
- def opt_flags(self):
- return ["-O", "-O0", "-O1", "-O2", "-O3", "-O4", "-O5", "-Ofast"]
-
- @property
- def openmp_flag(self):
- return "-qsmp=omp"
-
- @property
- def cxx11_flag(self):
- if self.real_version < Version("13.1"):
- raise UnsupportedCompilerFlag(self, "the C++11 standard", "cxx11_flag", "< 13.1")
- else:
- return "-qlanglvl=extended0x"
-
- @property
- def c99_flag(self):
- if self.real_version >= Version("13.1.1"):
- return "-std=gnu99"
- if self.real_version >= Version("10.1"):
- return "-qlanglvl=extc99"
- raise UnsupportedCompilerFlag(self, "the C99 standard", "c99_flag", "< 10.1")
-
- @property
- def c11_flag(self):
- if self.real_version >= Version("13.1.2"):
- return "-std=gnu11"
- if self.real_version >= Version("12.1"):
- return "-qlanglvl=extc1x"
- raise UnsupportedCompilerFlag(self, "the C11 standard", "c11_flag", "< 12.1")
-
- @property
- def cxx14_flag(self):
- # .real_version does not have the "y.z" component of "w.x.y.z", which
- # is required to distinguish whether support is available
- if self.version >= Version("16.1.1.8"):
- return "-std=c++14"
- raise UnsupportedCompilerFlag(self, "the C++14 standard", "cxx14_flag", "< 16.1.1.8")
-
- @property
- def cc_pic_flag(self):
- return "-qpic"
-
- @property
- def cxx_pic_flag(self):
- return "-qpic"
-
- @property
- def f77_pic_flag(self):
- return "-qpic"
-
- @property
- def fc_pic_flag(self):
- return "-qpic"
-
- @property
- def fflags(self):
- # The -qzerosize flag is effective only for the Fortran 77
- # compilers and allows the use of zero size objects.
- # For Fortran 90 and beyond, it is set by default and has not impact.
- # Its use has no negative side effects.
- return "-qzerosize"
diff --git a/lib/spack/spack/compilers/xl_r.py b/lib/spack/spack/compilers/xl_r.py
deleted file mode 100644
index 2ed31fff453..00000000000
--- a/lib/spack/spack/compilers/xl_r.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-import os
-
-import spack.compilers.xl
-
-
-class XlR(spack.compilers.xl.Xl):
- # Named wrapper links within build_env_path
- link_paths = {
- "cc": os.path.join("xl_r", "xlc_r"),
- "cxx": os.path.join("xl_r", "xlc++_r"),
- "f77": os.path.join("xl_r", "xlf_r"),
- "fc": os.path.join("xl_r", "xlf90_r"),
- }
diff --git a/lib/spack/spack/test/compilers/__init__.py b/lib/spack/spack/test/compilers/__init__.py
deleted file mode 100644
index c4ecc87fb8a..00000000000
--- a/lib/spack/spack/test/compilers/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
diff --git a/lib/spack/spack/test/compilers/basics.py b/lib/spack/spack/test/compilers/basics.py
deleted file mode 100644
index 0e5a28be4ca..00000000000
--- a/lib/spack/spack/test/compilers/basics.py
+++ /dev/null
@@ -1,778 +0,0 @@
-# Copyright Spack Project Developers. See COPYRIGHT file for details.
-#
-# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-"""Test basic behavior of compilers in Spack"""
-import json
-import os
-from copy import copy
-from typing import Optional
-
-import pytest
-
-import llnl.util.filesystem as fs
-
-import spack.compiler
-import spack.compilers
-import spack.config
-import spack.spec
-import spack.util.module_cmd
-from spack.compiler import Compiler
-from spack.util.executable import Executable
-from spack.util.file_cache import FileCache
-
-
-# FIXME (compiler as nodes): revisit this test
-# def test_multiple_conflicting_compiler_definitions(mutable_config):
-# compiler_def = {
-# "compiler": {
-# "flags": {},
-# "modules": [],
-# "paths": {"cc": "cc", "cxx": "cxx", "f77": "null", "fc": "null"},
-# "extra_rpaths": [],
-# "operating_system": "test",
-# "target": "test",
-# "environment": {},
-# "spec": "clang@0.0.0",
-# }
-# }
-#
-# compiler_config = [compiler_def, compiler_def]
-# compiler_config[0]["compiler"]["paths"]["f77"] = "f77"
-# mutable_config.update_config("compilers", compiler_config)
-#
-# arch_spec = spack.spec.ArchSpec(("test", "test", "test"))
-# cmp = spack.compilers.compiler_for_spec("clang@=0.0.0", arch_spec)
-# assert cmp.f77 == "f77"
-
-
-def test_compiler_flags_from_config_are_grouped():
- compiler_entry = {
- "spec": "intel@17.0.2",
- "operating_system": "foo-os",
- "paths": {"cc": "cc-path", "cxx": "cxx-path", "fc": None, "f77": None},
- "flags": {"cflags": "-O0 -foo-flag foo-val"},
- "modules": None,
- }
-
- compiler = spack.compilers.compiler_from_dict(compiler_entry)
- assert any(x == "-foo-flag foo-val" for x in compiler.flags["cflags"])
-
-
-# Test behavior of flags and UnsupportedCompilerFlag.
-
-# Utility function to test most flags.
-default_compiler_entry = {
- "spec": "apple-clang@2.0.0",
- "operating_system": "foo-os",
- "paths": {"cc": "cc-path", "cxx": "cxx-path", "fc": "fc-path", "f77": "f77-path"},
- "flags": {},
- "modules": None,
-}
-
-
-# Fake up a mock compiler where everything is defaulted.
-class MockCompiler(Compiler):
- def __init__(self):
- super().__init__(
- cspec="badcompiler@1.0.0",
- operating_system=default_compiler_entry["operating_system"],
- target=None,
- paths=[
- default_compiler_entry["paths"]["cc"],
- default_compiler_entry["paths"]["cxx"],
- default_compiler_entry["paths"]["fc"],
- default_compiler_entry["paths"]["f77"],
- ],
- environment={},
- )
-
- @property
- def name(self):
- return "mockcompiler"
-
- @property
- def version(self):
- return "1.0.0"
-
- _verbose_flag = "--verbose"
-
- @property
- def verbose_flag(self):
- return self._verbose_flag
-
- required_libs = ["libgfortran"]
-
-
-@pytest.mark.not_on_windows("Not supported on Windows (yet)")
-def test_implicit_rpaths(dirs_with_libfiles, monkeypatch):
- lib_to_dirs, all_dirs = dirs_with_libfiles
- monkeypatch.setattr(
- MockCompiler,
- "_compile_dummy_c_source",
- lambda self: "ld " + " ".join(f"-L{d}" for d in all_dirs),
- )
- retrieved_rpaths = MockCompiler().implicit_rpaths()
- assert set(retrieved_rpaths) == set(lib_to_dirs["libstdc++"] + lib_to_dirs["libgfortran"])
-
-
-without_flag_output = "ld -L/path/to/first/lib -L/path/to/second/lib64"
-with_flag_output = "ld -L/path/to/first/with/flag/lib -L/path/to/second/lib64"
-
-
-def call_compiler(exe, *args, **kwargs):
- # This method can replace Executable.__call__ to emulate a compiler that
- # changes libraries depending on a flag.
- if "--correct-flag" in exe.exe:
- return with_flag_output
- return without_flag_output
-
-
-@pytest.mark.not_on_windows("Not supported on Windows (yet)")
-@pytest.mark.parametrize(
- "exe,flagname",
- [
- ("cxx", "cxxflags"),
- ("cxx", "cppflags"),
- ("cxx", "ldflags"),
- ("cc", "cflags"),
- ("cc", "cppflags"),
- ],
-)
-@pytest.mark.enable_compiler_execution
-def test_compile_dummy_c_source_adds_flags(monkeypatch, exe, flagname):
- # create fake compiler that emits mock verbose output
- compiler = MockCompiler()
- monkeypatch.setattr(Executable, "__call__", call_compiler)
-
- if exe == "cxx":
- compiler.cc = None
- compiler.fc = None
- compiler.f77 = None
- elif exe == "cc":
- compiler.cxx = None
- compiler.fc = None
- compiler.f77 = None
- else:
- assert False
-
- # Test without flags
- assert compiler._compile_dummy_c_source() == without_flag_output
-
- if flagname:
- # set flags and test
- compiler.flags = {flagname: ["--correct-flag"]}
- assert compiler._compile_dummy_c_source() == with_flag_output
-
-
-@pytest.mark.enable_compiler_execution
-def test_compile_dummy_c_source_no_path():
- compiler = MockCompiler()
- compiler.cc = None
- compiler.cxx = None
- assert compiler._compile_dummy_c_source() is None
-
-
-@pytest.mark.enable_compiler_execution
-def test_compile_dummy_c_source_no_verbose_flag():
- compiler = MockCompiler()
- compiler._verbose_flag = None
- assert compiler._compile_dummy_c_source() is None
-
-
-@pytest.mark.not_on_windows("Not supported on Windows (yet)")
-@pytest.mark.enable_compiler_execution
-def test_compile_dummy_c_source_load_env(working_env, monkeypatch, tmpdir):
- gcc = str(tmpdir.join("gcc"))
- with open(gcc, "w", encoding="utf-8") as f:
- f.write(
- f"""#!/bin/sh
-if [ "$ENV_SET" = "1" ] && [ "$MODULE_LOADED" = "1" ]; then
- printf '{without_flag_output}'
-fi
-"""
- )
- fs.set_executable(gcc)
-
- # Set module load to turn compiler on
- def module(*args):
- if args[0] == "show":
- return ""
- elif args[0] == "load":
- os.environ["MODULE_LOADED"] = "1"
-
- monkeypatch.setattr(spack.util.module_cmd, "module", module)
-
- compiler = MockCompiler()
- compiler.cc = gcc
- compiler.environment = {"set": {"ENV_SET": "1"}}
- compiler.modules = ["turn_on"]
-
- assert compiler._compile_dummy_c_source() == without_flag_output
-
-
-# Get the desired flag from the specified compiler spec.
-def flag_value(flag, spec):
- compiler = None
- if spec is None:
- compiler = MockCompiler()
- else:
- compiler_entry = copy(default_compiler_entry)
- compiler_entry["spec"] = spec
- compiler = spack.compilers.compiler_from_dict(compiler_entry)
-
- return getattr(compiler, flag)
-
-
-# Utility function to verify that the expected exception is thrown for
-# an unsupported flag.
-def unsupported_flag_test(flag, spec=None):
- caught_exception = None
- try:
- flag_value(flag, spec)
- except spack.compiler.UnsupportedCompilerFlag:
- caught_exception = True
-
- assert caught_exception and "Expected exception not thrown."
-
-
-# Verify the expected flag value for the give compiler spec.
-def supported_flag_test(flag, flag_value_ref, spec=None):
- assert flag_value(flag, spec) == flag_value_ref
-
-
-# Tests for UnsupportedCompilerFlag exceptions from default
-# implementations of flags.
-def test_default_flags():
- supported_flag_test("cc_rpath_arg", "-Wl,-rpath,")
- supported_flag_test("cxx_rpath_arg", "-Wl,-rpath,")
- supported_flag_test("f77_rpath_arg", "-Wl,-rpath,")
- supported_flag_test("fc_rpath_arg", "-Wl,-rpath,")
- supported_flag_test("linker_arg", "-Wl,")
- unsupported_flag_test("openmp_flag")
- unsupported_flag_test("cxx11_flag")
- unsupported_flag_test("cxx14_flag")
- unsupported_flag_test("cxx17_flag")
- supported_flag_test("cxx98_flag", "")
- unsupported_flag_test("c99_flag")
- unsupported_flag_test("c11_flag")
- supported_flag_test("cc_pic_flag", "-fPIC")
- supported_flag_test("cxx_pic_flag", "-fPIC")
- supported_flag_test("f77_pic_flag", "-fPIC")
- supported_flag_test("fc_pic_flag", "-fPIC")
- supported_flag_test("debug_flags", ["-g"])
- supported_flag_test("opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3"])
-
-
-# Verify behavior of particular compiler definitions.
-def test_arm_flags():
- supported_flag_test("openmp_flag", "-fopenmp", "arm@1.0")
- supported_flag_test("cxx11_flag", "-std=c++11", "arm@1.0")
- supported_flag_test("cxx14_flag", "-std=c++14", "arm@1.0")
- supported_flag_test("cxx17_flag", "-std=c++1z", "arm@1.0")
- supported_flag_test("c99_flag", "-std=c99", "arm@1.0")
- supported_flag_test("c11_flag", "-std=c11", "arm@1.0")
- supported_flag_test("cc_pic_flag", "-fPIC", "arm@1.0")
- supported_flag_test("cxx_pic_flag", "-fPIC", "arm@1.0")
- supported_flag_test("f77_pic_flag", "-fPIC", "arm@1.0")
- supported_flag_test("fc_pic_flag", "-fPIC", "arm@1.0")
- supported_flag_test("opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-Ofast"], "arm@1.0")
-
-
-def test_cce_flags():
- supported_flag_test("version_argument", "--version", "cce@9.0.1")
- supported_flag_test("version_argument", "-V", "cce@9.0.1-classic")
- supported_flag_test("openmp_flag", "-fopenmp", "cce@9.0.1")
- supported_flag_test("openmp_flag", "-h omp", "cce@9.0.1-classic")
- supported_flag_test("openmp_flag", "-h omp", "cce@1.0")
- supported_flag_test("cxx11_flag", "-std=c++11", "cce@9.0.1")
- supported_flag_test("cxx11_flag", "-h std=c++11", "cce@9.0.1-classic")
- supported_flag_test("cxx11_flag", "-h std=c++11", "cce@1.0")
- unsupported_flag_test("c99_flag", "cce@8.0")
- supported_flag_test("c99_flag", "-std=c99", "cce@9.0.1")
- supported_flag_test("c99_flag", "-h c99,noconform,gnu", "cce@8.1")
- supported_flag_test("c99_flag", "-h std=c99,noconform,gnu", "cce@8.4")
- unsupported_flag_test("c11_flag", "cce@8.4")
- supported_flag_test("c11_flag", "-std=c11", "cce@9.0.1")
- supported_flag_test("c11_flag", "-h std=c11,noconform,gnu", "cce@8.5")
- supported_flag_test("cc_pic_flag", "-h PIC", "cce@1.0")
- supported_flag_test("cxx_pic_flag", "-h PIC", "cce@1.0")
- supported_flag_test("f77_pic_flag", "-h PIC", "cce@1.0")
- supported_flag_test("fc_pic_flag", "-h PIC", "cce@1.0")
- supported_flag_test("cc_pic_flag", "-fPIC", "cce@9.1.0")
- supported_flag_test("cxx_pic_flag", "-fPIC", "cce@9.1.0")
- supported_flag_test("f77_pic_flag", "-fPIC", "cce@9.1.0")
- supported_flag_test("fc_pic_flag", "-fPIC", "cce@9.1.0")
- supported_flag_test("stdcxx_libs", (), "cce@1.0")
- supported_flag_test("debug_flags", ["-g", "-G0", "-G1", "-G2", "-Gfast"], "cce@1.0")
-
-
-def test_apple_clang_flags():
- supported_flag_test("openmp_flag", "-Xpreprocessor -fopenmp", "apple-clang@2.0.0")
- unsupported_flag_test("cxx11_flag", "apple-clang@2.0.0")
- supported_flag_test("cxx11_flag", "-std=c++11", "apple-clang@4.0.0")
- unsupported_flag_test("cxx14_flag", "apple-clang@5.0.0")
- supported_flag_test("cxx14_flag", "-std=c++1y", "apple-clang@5.1.0")
- supported_flag_test("cxx14_flag", "-std=c++14", "apple-clang@6.1.0")
- unsupported_flag_test("cxx17_flag", "apple-clang@6.0.0")
- supported_flag_test("cxx17_flag", "-std=c++1z", "apple-clang@6.1.0")
- supported_flag_test("c99_flag", "-std=c99", "apple-clang@6.1.0")
- unsupported_flag_test("c11_flag", "apple-clang@3.0.0")
- supported_flag_test("c11_flag", "-std=c11", "apple-clang@6.1.0")
- supported_flag_test("cc_pic_flag", "-fPIC", "apple-clang@2.0.0")
- supported_flag_test("cxx_pic_flag", "-fPIC", "apple-clang@2.0.0")
- supported_flag_test("f77_pic_flag", "-fPIC", "apple-clang@2.0.0")
- supported_flag_test("fc_pic_flag", "-fPIC", "apple-clang@2.0.0")
-
-
-def test_clang_flags():
- supported_flag_test("version_argument", "--version", "clang@foo.bar")
- supported_flag_test("openmp_flag", "-fopenmp", "clang@3.3")
- unsupported_flag_test("cxx11_flag", "clang@3.2")
- supported_flag_test("cxx11_flag", "-std=c++11", "clang@3.3")
- unsupported_flag_test("cxx14_flag", "clang@3.3")
- supported_flag_test("cxx14_flag", "-std=c++1y", "clang@3.4")
- supported_flag_test("cxx14_flag", "-std=c++14", "clang@3.5")
- unsupported_flag_test("cxx17_flag", "clang@3.4")
- supported_flag_test("cxx17_flag", "-std=c++1z", "clang@3.5")
- supported_flag_test("cxx17_flag", "-std=c++17", "clang@5.0")
- unsupported_flag_test("cxx20_flag", "clang@4.0")
- supported_flag_test("cxx20_flag", "-std=c++2a", "clang@5.0")
- supported_flag_test("cxx20_flag", "-std=c++20", "clang@11.0")
- unsupported_flag_test("cxx23_flag", "clang@11.0")
- supported_flag_test("cxx23_flag", "-std=c++2b", "clang@12.0")
- supported_flag_test("cxx23_flag", "-std=c++23", "clang@17.0")
- supported_flag_test("c99_flag", "-std=c99", "clang@3.3")
- unsupported_flag_test("c11_flag", "clang@2.0")
- supported_flag_test("c11_flag", "-std=c11", "clang@6.1.0")
- unsupported_flag_test("c23_flag", "clang@8.0")
- supported_flag_test("c23_flag", "-std=c2x", "clang@9.0")
- supported_flag_test("c23_flag", "-std=c23", "clang@18.0")
- supported_flag_test("cc_pic_flag", "-fPIC", "clang@3.3")
- supported_flag_test("cxx_pic_flag", "-fPIC", "clang@3.3")
- supported_flag_test("f77_pic_flag", "-fPIC", "clang@3.3")
- supported_flag_test("fc_pic_flag", "-fPIC", "clang@3.3")
- supported_flag_test(
- "debug_flags",
- [
- "-gcodeview",
- "-gdwarf-2",
- "-gdwarf-3",
- "-gdwarf-4",
- "-gdwarf-5",
- "-gline-tables-only",
- "-gmodules",
- "-g",
- ],
- "clang@3.3",
- )
- supported_flag_test(
- "opt_flags",
- ["-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os", "-Oz", "-Og", "-O", "-O4"],
- "clang@3.3",
- )
-
-
-def test_aocc_flags():
- supported_flag_test(
- "debug_flags",
- [
- "-gcodeview",
- "-gdwarf-2",
- "-gdwarf-3",
- "-gdwarf-4",
- "-gdwarf-5",
- "-gline-tables-only",
- "-gmodules",
- "-g",
- ],
- "aocc@2.2.0",
- )
- supported_flag_test(
- "opt_flags",
- ["-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os", "-Oz", "-Og", "-O", "-O4"],
- "aocc@2.2.0",
- )
-
- supported_flag_test("stdcxx_libs", ("-lstdc++",), "aocc@2.2.0")
- supported_flag_test("openmp_flag", "-fopenmp", "aocc@2.2.0")
- supported_flag_test("cxx11_flag", "-std=c++11", "aocc@2.2.0")
- supported_flag_test("cxx14_flag", "-std=c++14", "aocc@2.2.0")
- supported_flag_test("cxx17_flag", "-std=c++17", "aocc@2.2.0")
- supported_flag_test("c99_flag", "-std=c99", "aocc@2.2.0")
- supported_flag_test("c11_flag", "-std=c11", "aocc@2.2.0")
- supported_flag_test("cc_pic_flag", "-fPIC", "aocc@2.2.0")
- supported_flag_test("cxx_pic_flag", "-fPIC", "aocc@2.2.0")
- supported_flag_test("f77_pic_flag", "-fPIC", "aocc@2.2.0")
- supported_flag_test("fc_pic_flag", "-fPIC", "aocc@2.2.0")
- supported_flag_test("version_argument", "--version", "aocc@2.2.0")
- flg = "-Wno-unused-command-line-argument -mllvm -eliminate-similar-expr=false"
- supported_flag_test("cflags", flg, "aocc@3.0.0")
- supported_flag_test("cxxflags", flg, "aocc@3.0.0")
- supported_flag_test("fflags", flg, "aocc@3.0.0")
-
-
-def test_fj_flags():
- supported_flag_test("openmp_flag", "-Kopenmp", "fj@4.0.0")
- supported_flag_test("cxx98_flag", "-std=c++98", "fj@4.0.0")
- supported_flag_test("cxx11_flag", "-std=c++11", "fj@4.0.0")
- supported_flag_test("cxx14_flag", "-std=c++14", "fj@4.0.0")
- supported_flag_test("cxx17_flag", "-std=c++17", "fj@4.0.0")
- supported_flag_test("c99_flag", "-std=c99", "fj@4.0.0")
- supported_flag_test("c11_flag", "-std=c11", "fj@4.0.0")
- supported_flag_test("cc_pic_flag", "-KPIC", "fj@4.0.0")
- supported_flag_test("cxx_pic_flag", "-KPIC", "fj@4.0.0")
- supported_flag_test("f77_pic_flag", "-KPIC", "fj@4.0.0")
- supported_flag_test("fc_pic_flag", "-KPIC", "fj@4.0.0")
- supported_flag_test("opt_flags", ["-O0", "-O1", "-O2", "-O3", "-Ofast"], "fj@4.0.0")
- supported_flag_test("debug_flags", "-g", "fj@4.0.0")
-
-
-def test_gcc_flags():
- supported_flag_test("openmp_flag", "-fopenmp", "gcc@4.1")
- supported_flag_test("cxx98_flag", "", "gcc@5.2")
- supported_flag_test("cxx98_flag", "-std=c++98", "gcc@6.0")
- unsupported_flag_test("cxx11_flag", "gcc@4.2")
- supported_flag_test("cxx11_flag", "-std=c++0x", "gcc@4.3")
- supported_flag_test("cxx11_flag", "-std=c++11", "gcc@4.7")
- unsupported_flag_test("cxx14_flag", "gcc@4.7")
- supported_flag_test("cxx14_flag", "-std=c++1y", "gcc@4.8")
- supported_flag_test("cxx14_flag", "-std=c++14", "gcc@4.9")
- supported_flag_test("cxx14_flag", "-std=c++14", "gcc@6.0")
- unsupported_flag_test("cxx17_flag", "gcc@4.9")
- supported_flag_test("cxx17_flag", "-std=c++1z", "gcc@5.0")
- supported_flag_test("cxx17_flag", "-std=c++17", "gcc@6.0")
- unsupported_flag_test("c99_flag", "gcc@4.4")
- supported_flag_test("c99_flag", "-std=c99", "gcc@4.5")
- unsupported_flag_test("c11_flag", "gcc@4.6")
- supported_flag_test("c11_flag", "-std=c11", "gcc@4.7")
- supported_flag_test("cc_pic_flag", "-fPIC", "gcc@4.0")
- supported_flag_test("cxx_pic_flag", "-fPIC", "gcc@4.0")
- supported_flag_test("f77_pic_flag", "-fPIC", "gcc@4.0")
- supported_flag_test("fc_pic_flag", "-fPIC", "gcc@4.0")
- supported_flag_test("stdcxx_libs", ("-lstdc++",), "gcc@4.1")
- supported_flag_test(
- "debug_flags", ["-g", "-gstabs+", "-gstabs", "-gxcoff+", "-gxcoff", "-gvms"], "gcc@4.0"
- )
- supported_flag_test(
- "opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-Os", "-Ofast", "-Og"], "gcc@4.0"
- )
-
-
-def test_intel_flags():
- supported_flag_test("openmp_flag", "-openmp", "intel@=15.0")
- supported_flag_test("openmp_flag", "-qopenmp", "intel@=16.0")
- unsupported_flag_test("cxx11_flag", "intel@=11.0")
- supported_flag_test("cxx11_flag", "-std=c++0x", "intel@=12.0")
- supported_flag_test("cxx11_flag", "-std=c++11", "intel@=13")
- unsupported_flag_test("cxx14_flag", "intel@=14.0")
- supported_flag_test("cxx14_flag", "-std=c++1y", "intel@=15.0")
- supported_flag_test("cxx14_flag", "-std=c++14", "intel@=15.0.2")
- unsupported_flag_test("cxx17_flag", "intel@=18")
- supported_flag_test("cxx17_flag", "-std=c++17", "intel@=19.0")
- unsupported_flag_test("c99_flag", "intel@=11.0")
- supported_flag_test("c99_flag", "-std=c99", "intel@=12.0")
- unsupported_flag_test("c11_flag", "intel@=15.0")
- supported_flag_test("c18_flag", "-std=c18", "intel@=21.5.0")
- unsupported_flag_test("c18_flag", "intel@=21.4.0")
- supported_flag_test("c11_flag", "-std=c1x", "intel@=16.0")
- supported_flag_test("cc_pic_flag", "-fPIC", "intel@=1.0")
- supported_flag_test("cxx_pic_flag", "-fPIC", "intel@=1.0")
- supported_flag_test("f77_pic_flag", "-fPIC", "intel@=1.0")
- supported_flag_test("fc_pic_flag", "-fPIC", "intel@=1.0")
- supported_flag_test("stdcxx_libs", ("-cxxlib",), "intel@=1.0")
- supported_flag_test("debug_flags", ["-debug", "-g", "-g0", "-g1", "-g2", "-g3"], "intel@=1.0")
- supported_flag_test(
- "opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os"], "intel@=1.0"
- )
-
-
-def test_oneapi_flags():
- supported_flag_test("openmp_flag", "-fiopenmp", "oneapi@=2020.8.0.0827")
- supported_flag_test("cxx11_flag", "-std=c++11", "oneapi@=2020.8.0.0827")
- supported_flag_test("cxx14_flag", "-std=c++14", "oneapi@=2020.8.0.0827")
- supported_flag_test("c99_flag", "-std=c99", "oneapi@=2020.8.0.0827")
- supported_flag_test("c11_flag", "-std=c1x", "oneapi@=2020.8.0.0827")
- supported_flag_test("cc_pic_flag", "-fPIC", "oneapi@=2020.8.0.0827")
- supported_flag_test("cxx_pic_flag", "-fPIC", "oneapi@=2020.8.0.0827")
- supported_flag_test("f77_pic_flag", "-fPIC", "oneapi@=2020.8.0.0827")
- supported_flag_test("fc_pic_flag", "-fPIC", "oneapi@=2020.8.0.0827")
- supported_flag_test("stdcxx_libs", ("-cxxlib",), "oneapi@=2020.8.0.0827")
- supported_flag_test(
- "debug_flags", ["-debug", "-g", "-g0", "-g1", "-g2", "-g3"], "oneapi@=2020.8.0.0827"
- )
- supported_flag_test(
- "opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os"], "oneapi@=2020.8.0.0827"
- )
-
-
-def test_nag_flags():
- supported_flag_test("openmp_flag", "-openmp", "nag@=1.0")
- supported_flag_test("cxx11_flag", "-std=c++11", "nag@=1.0")
- supported_flag_test("cc_pic_flag", "-fPIC", "nag@=1.0")
- supported_flag_test("cxx_pic_flag", "-fPIC", "nag@=1.0")
- supported_flag_test("f77_pic_flag", "-PIC", "nag@=1.0")
- supported_flag_test("fc_pic_flag", "-PIC", "nag@=1.0")
- supported_flag_test("cc_rpath_arg", "-Wl,-rpath,", "nag@=1.0")
- supported_flag_test("cxx_rpath_arg", "-Wl,-rpath,", "nag@=1.0")
- supported_flag_test("f77_rpath_arg", "-Wl,-Wl,,-rpath,,", "nag@=1.0")
- supported_flag_test("fc_rpath_arg", "-Wl,-Wl,,-rpath,,", "nag@=1.0")
- supported_flag_test("linker_arg", "-Wl,-Wl,,", "nag@=1.0")
- supported_flag_test("debug_flags", ["-g", "-gline", "-g90"], "nag@=1.0")
- supported_flag_test("opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-O4"], "nag@=1.0")
-
-
-def test_nvhpc_flags():
- supported_flag_test("openmp_flag", "-mp", "nvhpc@=20.9")
- supported_flag_test("cxx11_flag", "--c++11", "nvhpc@=20.9")
- supported_flag_test("cxx14_flag", "--c++14", "nvhpc@=20.9")
- supported_flag_test("cxx17_flag", "--c++17", "nvhpc@=20.9")
- supported_flag_test("c99_flag", "-c99", "nvhpc@=20.9")
- supported_flag_test("c11_flag", "-c11", "nvhpc@=20.9")
- supported_flag_test("cc_pic_flag", "-fpic", "nvhpc@=20.9")
- supported_flag_test("cxx_pic_flag", "-fpic", "nvhpc@=20.9")
- supported_flag_test("f77_pic_flag", "-fpic", "nvhpc@=20.9")
- supported_flag_test("fc_pic_flag", "-fpic", "nvhpc@=20.9")
- supported_flag_test("debug_flags", ["-g", "-gopt"], "nvhpc@=20.9")
- supported_flag_test("opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-O4"], "nvhpc@=20.9")
- supported_flag_test("stdcxx_libs", ("-c++libs",), "nvhpc@=20.9")
-
-
-def test_xl_flags():
- supported_flag_test("openmp_flag", "-qsmp=omp", "xl@=1.0")
- unsupported_flag_test("cxx11_flag", "xl@=13.0")
- supported_flag_test("cxx11_flag", "-qlanglvl=extended0x", "xl@=13.1")
- unsupported_flag_test("c99_flag", "xl@=10.0")
- supported_flag_test("c99_flag", "-qlanglvl=extc99", "xl@=10.1")
- supported_flag_test("c99_flag", "-std=gnu99", "xl@=13.1.1")
- unsupported_flag_test("c11_flag", "xl@=12.0")
- supported_flag_test("c11_flag", "-qlanglvl=extc1x", "xl@=12.1")
- supported_flag_test("c11_flag", "-std=gnu11", "xl@=13.1.2")
- supported_flag_test("cc_pic_flag", "-qpic", "xl@=1.0")
- supported_flag_test("cxx_pic_flag", "-qpic", "xl@=1.0")
- supported_flag_test("f77_pic_flag", "-qpic", "xl@=1.0")
- supported_flag_test("fc_pic_flag", "-qpic", "xl@=1.0")
- supported_flag_test("fflags", "-qzerosize", "xl@=1.0")
- supported_flag_test("debug_flags", ["-g", "-g0", "-g1", "-g2", "-g8", "-g9"], "xl@=1.0")
- supported_flag_test(
- "opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-O4", "-O5", "-Ofast"], "xl@=1.0"
- )
-
-
-def test_xl_r_flags():
- supported_flag_test("openmp_flag", "-qsmp=omp", "xl_r@=1.0")
- unsupported_flag_test("cxx11_flag", "xl_r@=13.0")
- supported_flag_test("cxx11_flag", "-qlanglvl=extended0x", "xl_r@=13.1")
- unsupported_flag_test("c99_flag", "xl_r@=10.0")
- supported_flag_test("c99_flag", "-qlanglvl=extc99", "xl_r@=10.1")
- supported_flag_test("c99_flag", "-std=gnu99", "xl_r@=13.1.1")
- unsupported_flag_test("c11_flag", "xl_r@=12.0")
- supported_flag_test("c11_flag", "-qlanglvl=extc1x", "xl_r@=12.1")
- supported_flag_test("c11_flag", "-std=gnu11", "xl_r@=13.1.2")
- supported_flag_test("cc_pic_flag", "-qpic", "xl_r@=1.0")
- supported_flag_test("cxx_pic_flag", "-qpic", "xl_r@=1.0")
- supported_flag_test("f77_pic_flag", "-qpic", "xl_r@=1.0")
- supported_flag_test("fc_pic_flag", "-qpic", "xl_r@=1.0")
- supported_flag_test("fflags", "-qzerosize", "xl_r@=1.0")
- supported_flag_test("debug_flags", ["-g", "-g0", "-g1", "-g2", "-g8", "-g9"], "xl@=1.0")
- supported_flag_test(
- "opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-O4", "-O5", "-Ofast"], "xl@=1.0"
- )
-
-
-# FIXME (compiler as nodes): revisit this test
-# @pytest.mark.regression("14798,13733")
-# def test_raising_if_compiler_target_is_over_specific(config):
-# # Compiler entry with an overly specific target
-# compilers = [
-# {
-# "compiler": {
-# "spec": "gcc@9.0.1",
-# "paths": {
-# "cc": "/usr/bin/gcc-9",
-# "cxx": "/usr/bin/g++-9",
-# "f77": "/usr/bin/gfortran-9",
-# "fc": "/usr/bin/gfortran-9",
-# },
-# "flags": {},
-# "operating_system": "ubuntu18.04",
-# "target": "haswell",
-# "modules": [],
-# "environment": {},
-# "extra_rpaths": [],
-# }
-# }
-# ]
-# arch_spec = spack.spec.ArchSpec(("linux", "ubuntu18.04", "haswell"))
-# with spack.config.override("compilers", compilers):
-# cfg = spack.compilers.get_compiler_config(config)
-# with pytest.raises(ValueError):
-# spack.compilers.get_compilers(cfg, spack.spec.CompilerSpec("gcc@9.0.1"), arch_spec)
-
-# FIXME (compiler as nodes): revisit this test
-# @pytest.mark.regression("42679")
-# def test_get_compilers(config):
-# """Tests that we can select compilers whose versions differ only for a suffix."""
-# common = {
-# "flags": {},
-# "operating_system": "ubuntu23.10",
-# "target": "x86_64",
-# "modules": [],
-# "environment": {},
-# "extra_rpaths": [],
-# }
-# with_suffix = {
-# "spec": "gcc@13.2.0-suffix",
-# "paths": {
-# "cc": "/usr/bin/gcc-13.2.0-suffix",
-# "cxx": "/usr/bin/g++-13.2.0-suffix",
-# "f77": "/usr/bin/gfortran-13.2.0-suffix",
-# "fc": "/usr/bin/gfortran-13.2.0-suffix",
-# },
-# **common,
-# }
-# without_suffix = {
-# "spec": "gcc@13.2.0",
-# "paths": {
-# "cc": "/usr/bin/gcc-13.2.0",
-# "cxx": "/usr/bin/g++-13.2.0",
-# "f77": "/usr/bin/gfortran-13.2.0",
-# "fc": "/usr/bin/gfortran-13.2.0",
-# },
-# **common,
-# }
-#
-# compilers = [{"compiler": without_suffix}, {"compiler": with_suffix}]
-#
-# assert spack.compilers.get_compilers(
-# compilers, cspec=spack.spec.CompilerSpec("gcc@=13.2.0-suffix")
-# ) == [spack.compilers._compiler_from_config_entry(with_suffix)]
-#
-# assert spack.compilers.get_compilers(
-# compilers, cspec=spack.spec.CompilerSpec("gcc@=13.2.0")
-# ) == [spack.compilers._compiler_from_config_entry(without_suffix)]
-
-
-@pytest.mark.enable_compiler_verification
-def test_compiler_executable_verification_raises(tmpdir):
- compiler = MockCompiler()
- compiler.cc = "/this/path/does/not/exist"
-
- with pytest.raises(spack.compiler.CompilerAccessError):
- compiler.verify_executables()
-
-
-@pytest.mark.enable_compiler_verification
-def test_compiler_executable_verification_success(tmpdir):
- def prepare_executable(name):
- real = str(tmpdir.join("cc").ensure())
- fs.set_executable(real)
- setattr(compiler, name, real)
-
- # setup mock compiler with real paths
- compiler = MockCompiler()
- for name in ("cc", "cxx", "f77", "fc"):
- prepare_executable(name)
-
- # testing that this doesn't raise an error because the paths exist and
- # are executable
- compiler.verify_executables()
-
- # Test that null entries don't fail
- compiler.cc = None
- compiler.verify_executables()
-
-
-@pytest.mark.parametrize(
- "compilers_extra_attributes,expected_length",
- [
- # If we detect a C compiler we expect the result to be valid
- ({"c": "/usr/bin/clang-12", "cxx": "/usr/bin/clang-12"}, 1),
- # If we detect only a C++ compiler we expect the result to be discarded
- ({"cxx": "/usr/bin/clang-12"}, 0),
- ],
-)
-def test_detection_requires_c_compiler(compilers_extra_attributes, expected_length):
- """Tests that compilers automatically added to the configuration have
- at least a C compiler.
- """
- packages_yaml = {
- "llvm": {
- "externals": [
- {
- "spec": "clang@12.0.0",
- "prefix": "/usr",
- "extra_attributes": {"compilers": compilers_extra_attributes},
- }
- ]
- }
- }
- result = spack.compilers.CompilerFactory.from_packages_yaml(packages_yaml)
- assert len(result) == expected_length
-
-
-def test_compiler_environment(working_env):
- """Test whether environment modifications from compilers are applied in compiler_environment"""
- os.environ.pop("TEST", None)
- compiler = Compiler(
- "gcc@=13.2.0",
- operating_system="ubuntu20.04",
- target="x86_64",
- paths=["/test/bin/gcc", "/test/bin/g++"],
- environment={"set": {"TEST": "yes"}},
- )
- with compiler.compiler_environment():
- assert os.environ["TEST"] == "yes"
-
-
-class MockCompilerWithoutExecutables(MockCompiler):
- def __init__(self):
- super().__init__()
- self._compile_dummy_c_source_count = 0
- self._get_real_version_count = 0
-
- def _compile_dummy_c_source(self) -> Optional[str]:
- self._compile_dummy_c_source_count += 1
- return "gcc helloworld.c -o helloworld"
-
- def get_real_version(self) -> str:
- self._get_real_version_count += 1
- return "1.0.0"
-
-
-def test_compiler_output_caching(tmp_path):
- """Test that compiler output is cached on the filesystem."""
- # The first call should trigger the cache to updated.
- a = MockCompilerWithoutExecutables()
- cache = spack.compiler.FileCompilerCache(FileCache(str(tmp_path)))
- assert cache.get(a).c_compiler_output == "gcc helloworld.c -o helloworld"
- assert cache.get(a).real_version == "1.0.0"
- assert a._compile_dummy_c_source_count == 1
- assert a._get_real_version_count == 1
-
- # The second call on an equivalent but distinct object should not trigger compiler calls.
- b = MockCompilerWithoutExecutables()
- cache = spack.compiler.FileCompilerCache(FileCache(str(tmp_path)))
- assert cache.get(b).c_compiler_output == "gcc helloworld.c -o helloworld"
- assert cache.get(b).real_version == "1.0.0"
- assert b._compile_dummy_c_source_count == 0
- assert b._get_real_version_count == 0
-
- # Cache schema change should be handled gracefully.
- with open(cache.cache.cache_path(cache.name), "w", encoding="utf-8") as f:
- for k in cache._data:
- cache._data[k] = "corrupted entry"
- f.write(json.dumps(cache._data))
-
- c = MockCompilerWithoutExecutables()
- cache = spack.compiler.FileCompilerCache(FileCache(str(tmp_path)))
- assert cache.get(c).c_compiler_output == "gcc helloworld.c -o helloworld"
- assert cache.get(c).real_version == "1.0.0"
-
- # Cache corruption should be handled gracefully.
- with open(cache.cache.cache_path(cache.name), "w", encoding="utf-8") as f:
- f.write("corrupted cache")
-
- d = MockCompilerWithoutExecutables()
- cache = spack.compiler.FileCompilerCache(FileCache(str(tmp_path)))
- assert cache.get(d).c_compiler_output == "gcc helloworld.c -o helloworld"
- assert cache.get(d).real_version == "1.0.0"