summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-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: