diff --git a/lib/spack/spack/compilers/__init__.py b/lib/spack/spack/compilers/__init__.py index d98dcb8b1e5..c65685fbade 100644 --- a/lib/spack/spack/compilers/__init__.py +++ b/lib/spack/spack/compilers/__init__.py @@ -78,8 +78,8 @@ def pkg_spec_for_compiler(cspec): def _auto_compiler_spec(function): def converter(cspec_like, *args, **kwargs): - if not isinstance(cspec_like, spack.spec.CompilerSpec): - cspec_like = spack.spec.CompilerSpec(cspec_like) + if not isinstance(cspec_like, spack.spec.Spec): + cspec_like = spack.spec.Spec(cspec_like) return function(cspec_like, *args, **kwargs) return converter diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index cc396dac2eb..19a7b369eb1 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -597,7 +597,6 @@ def __contains__(self, string): return string in str(self) or string in self.target -@lang.lazy_lexicographic_ordering class CompilerSpec: """The CompilerSpec field represents the compiler or range of compiler versions that a package should be built with. CompilerSpecs have a @@ -606,109 +605,14 @@ class CompilerSpec: __slots__ = "name", "versions" def __init__(self, *args): - raise TypeError("CompilerSpec is being removed") - nargs = len(args) - if nargs == 1: - arg = args[0] - # If there is one argument, it's either another CompilerSpec - # to copy or a string to parse - if isinstance(arg, str): - spec = spack.parser.parse_one_or_raise(f"%{arg}") - self.name = spec.compiler.name - self.versions = spec.compiler.versions - - elif isinstance(arg, CompilerSpec): - self.name = arg.name - self.versions = arg.versions.copy() - - else: - raise TypeError( - "Can only build CompilerSpec from string or " - + "CompilerSpec. Found %s" % type(arg) - ) - - elif nargs == 2: - name, version = args - self.name = name - self.versions = vn.VersionList([vn.ver(version)]) - - else: - raise TypeError("__init__ takes 1 or 2 arguments. (%d given)" % nargs) - - def _autospec(self, compiler_spec_like): - if isinstance(compiler_spec_like, CompilerSpec): - return compiler_spec_like - return CompilerSpec(compiler_spec_like) - - def intersects(self, other: "CompilerSpec") -> bool: - """Return True if all concrete specs matching self also match other, otherwise False. - - For compiler specs this means that the name of the compiler must be the same for - self and other, and that the versions ranges should intersect. - - Args: - other: spec to be satisfied - """ - other = self._autospec(other) - return self.name == other.name and self.versions.intersects(other.versions) - - def satisfies(self, other: "CompilerSpec") -> bool: - """Return True if all concrete specs matching self also match other, otherwise False. - - For compiler specs this means that the name of the compiler must be the same for - self and other, and that the version range of self is a subset of that of other. - - Args: - other: spec to be satisfied - """ - other = self._autospec(other) - return self.name == other.name and self.versions.satisfies(other.versions) - - def constrain(self, other: "CompilerSpec") -> bool: - """Intersect self's versions with other. - - Return whether the CompilerSpec changed. - """ - other = self._autospec(other) - - # ensure that other will actually constrain this spec. - if not other.intersects(self): - raise UnsatisfiableCompilerSpecError(other, self) - - return self.versions.intersect(other.versions) - - @property - def concrete(self): - """A CompilerSpec is concrete if its versions are concrete and there - is an available compiler with the right version.""" - return self.versions.concrete - - @property - def version(self): - if not self.concrete: - raise spack.error.SpecError("Spec is not concrete: " + str(self)) - return self.versions[0] - - def copy(self): - clone = CompilerSpec.__new__(CompilerSpec) - clone.name = self.name - clone.versions = self.versions.copy() - return clone - - def _cmp_iter(self): - yield self.name - yield self.versions - - def to_dict(self): - d = syaml.syaml_dict([("name", self.name)]) - d.update(self.versions.to_dict()) - - return syaml.syaml_dict([("compiler", d)]) + raise SystemExit("CompilerSpec is being removed") @staticmethod def from_dict(d): d = d["compiler"] - return CompilerSpec(d["name"], vn.VersionList.from_dict(d)) + return Spec( + f"{d['name']}@{vn.VersionList.from_dict(d)}", external_path="/dev-null/", concrete=True + ) @property def display_str(self): @@ -1436,6 +1340,8 @@ class Spec: _prefix = None abstract_hash = None + compiler = lang.Const(None) + @staticmethod def default_arch(): """Return an anonymous spec for the default architecture""" @@ -1475,7 +1381,6 @@ def __init__( self.versions = vn.VersionList(":") self.variants = VariantMap(self) self.architecture = None - self.compiler = None self.compiler_flags = FlagMap(self) self._dependents = _EdgeMap(store_by_child=False) self._dependencies = _EdgeMap(store_by_child=True) @@ -3107,7 +3012,7 @@ def constrain(self, other, deps=True): if self.compiler is not None and other.compiler is not None: changed |= self.compiler.constrain(other.compiler) - elif self.compiler is None: + elif self.compiler is None and other.compiler is not None: changed |= self.compiler != other.compiler self.compiler = other.compiler @@ -3551,7 +3456,8 @@ def _dup(self, other, deps: Union[bool, dt.DepTypes, dt.DepFlag] = True, clearde self.name = other.name self.versions = other.versions.copy() self.architecture = other.architecture.copy() if other.architecture else None - self.compiler = other.compiler.copy() if other.compiler else None + # FIXME (compiler as nodes): removing compiler attribute + # self.compiler = other.compiler.copy() if other.compiler else None if cleardeps: self._dependents = _EdgeMap(store_by_child=False) self._dependencies = _EdgeMap(store_by_child=True) @@ -4810,9 +4716,8 @@ def from_node_dict(cls, node): spec.architecture = ArchSpec.from_dict(node) if "compiler" in node: - spec.compiler = CompilerSpec.from_dict(node) - else: - spec.compiler = None + # Annotate the compiler spec, might be used later + spec.compiler_annotation = CompilerSpec.from_dict(node) propagated_names = node.get("propagate", []) for name, values in node.get("parameters", {}).items():