summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMassimiliano Culpo <massimiliano.culpo@gmail.com>2020-10-21 23:57:09 +0200
committerTodd Gamblin <tgamblin@llnl.gov>2020-11-17 10:04:13 -0800
commitada2fa36a9aae3b2f328ac5c553c30cf25bd79df (patch)
tree1fa70749adcc05563876969876e41623d1d045f0
parenta1fe88c95b3ba95cb5490db96c950b139c11b659 (diff)
downloadspack-ada2fa36a9aae3b2f328ac5c553c30cf25bd79df.tar.gz
spack-ada2fa36a9aae3b2f328ac5c553c30cf25bd79df.tar.bz2
spack-ada2fa36a9aae3b2f328ac5c553c30cf25bd79df.tar.xz
spack-ada2fa36a9aae3b2f328ac5c553c30cf25bd79df.zip
concretizer: account for patches variant
This is done after the builder has actually built the specs, to respect the semantics use with the old concretizer. Later we could move this to the solver as a multivalued variant.
-rw-r--r--lib/spack/spack/solver/asp.py15
-rw-r--r--lib/spack/spack/spec.py84
2 files changed, 55 insertions, 44 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index 1d4602ce62..292d3a5a3f 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -1351,6 +1351,12 @@ class SpackSolverSetup(object):
if v.satisfies(versions)
]
+ # This is needed to account for a variable number of
+ # numbers e.g. if both 1.0 and 1.0.2 are possible versions
+ exact_match = [v for v in allowed_versions if v == versions]
+ if exact_match:
+ allowed_versions = exact_match
+
# don't bother restricting anything if all versions are allowed
if len(allowed_versions) == len(self.possible_versions[pkg_name]):
continue
@@ -1658,17 +1664,20 @@ class SpecBuilder(object):
repo = spack.repo.path.repo_for_pkg(spec)
spec.namespace = repo.namespace
- # once this is done, everything is concrete
- spec._mark_concrete()
-
# fix flags after all specs are constructed
self.reorder_flags()
+ for s in self._specs.values():
+ spack.spec.Spec.inject_patches_variant(s)
+
# Add external paths to specs with just external modules
for s in self._specs.values():
spack.spec.Spec.ensure_external_path_if_external(s)
for s in self._specs.values():
+ s._mark_concrete()
+
+ for s in self._specs.values():
spack.spec.Spec.ensure_no_deprecated(s)
return self._specs
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
index 1e42e90214..fb7c0a93ce 100644
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -2293,10 +2293,50 @@ class Spec(object):
if extra:
raise InvalidDependencyError(self.name, extra)
+ Spec.inject_patches_variant(self)
+
+ for s in self.traverse():
+ # TODO: Refactor this into a common method to build external specs
+ # TODO: or turn external_path into a lazy property
+ Spec.ensure_external_path_if_external(s)
+
+ # Mark everything in the spec as concrete, as well.
+ self._mark_concrete()
+
+ # If any spec in the DAG is deprecated, throw an error
+ Spec.ensure_no_deprecated(self)
+
+ # Now that the spec is concrete we should check if
+ # there are declared conflicts
+ #
+ # TODO: this needs rethinking, as currently we can only express
+ # TODO: internal configuration conflicts within one package.
+ matches = []
+ for x in self.traverse():
+ if x.external:
+ # external specs are already built, don't worry about whether
+ # it's possible to build that configuration with Spack
+ continue
+ for conflict_spec, when_list in x.package_class.conflicts.items():
+ if x.satisfies(conflict_spec, strict=True):
+ for when_spec, msg in when_list:
+ if x.satisfies(when_spec, strict=True):
+ when = when_spec.copy()
+ when.name = x.name
+ matches.append((x, conflict_spec, when, msg))
+ if matches:
+ raise ConflictsInSpecError(self, matches)
+
+ # Check if we can produce an optimized binary (will throw if
+ # there are declared inconsistencies)
+ self.architecture.target.optimization_flags(self.compiler)
+
+ @staticmethod
+ def inject_patches_variant(root):
# This dictionary will store object IDs rather than Specs as keys
# since the Spec __hash__ will change as patches are added to them
spec_to_patches = {}
- for s in self.traverse():
+ for s in root.traverse():
# After concretizing, assign namespaces to anything left.
# Note that this doesn't count as a "change". The repository
# configuration is constant throughout a spack run, and
@@ -2319,10 +2359,9 @@ class Spec(object):
patches.append(patch)
if patches:
spec_to_patches[id(s)] = patches
-
# Also record all patches required on dependencies by
# depends_on(..., patch=...)
- for dspec in self.traverse_edges(deptype=all,
+ for dspec in root.traverse_edges(deptype=all,
cover='edges', root=False):
pkg_deps = dspec.parent.package_class.dependencies
if dspec.spec.name not in pkg_deps:
@@ -2341,8 +2380,7 @@ class Spec(object):
if patches:
all_patches = spec_to_patches.setdefault(id(dspec.spec), [])
all_patches.extend(patches)
-
- for spec in self.traverse():
+ for spec in root.traverse():
if id(spec) not in spec_to_patches:
continue
@@ -2361,42 +2399,6 @@ class Spec(object):
mvar._patches_in_order_of_appearance = list(
t[-1] for t in ordered_hashes)
- for s in self.traverse():
- # TODO: Refactor this into a common method to build external specs
- # TODO: or turn external_path into a lazy property
- Spec.ensure_external_path_if_external(s)
-
- # Mark everything in the spec as concrete, as well.
- self._mark_concrete()
-
- # If any spec in the DAG is deprecated, throw an error
- Spec.ensure_no_deprecated(self)
-
- # Now that the spec is concrete we should check if
- # there are declared conflicts
- #
- # TODO: this needs rethinking, as currently we can only express
- # TODO: internal configuration conflicts within one package.
- matches = []
- for x in self.traverse():
- if x.external:
- # external specs are already built, don't worry about whether
- # it's possible to build that configuration with Spack
- continue
- for conflict_spec, when_list in x.package_class.conflicts.items():
- if x.satisfies(conflict_spec, strict=True):
- for when_spec, msg in when_list:
- if x.satisfies(when_spec, strict=True):
- when = when_spec.copy()
- when.name = x.name
- matches.append((x, conflict_spec, when, msg))
- if matches:
- raise ConflictsInSpecError(self, matches)
-
- # Check if we can produce an optimized binary (will throw if
- # there are declared inconsistencies)
- self.architecture.target.optimization_flags(self.compiler)
-
@staticmethod
def ensure_external_path_if_external(external_spec):
if external_spec.external_modules and not external_spec.external_path: