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.
This commit is contained in:
parent
a1fe88c95b
commit
ada2fa36a9
@ -1351,6 +1351,12 @@ def define_version_constraints(self):
|
|||||||
if v.satisfies(versions)
|
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
|
# don't bother restricting anything if all versions are allowed
|
||||||
if len(allowed_versions) == len(self.possible_versions[pkg_name]):
|
if len(allowed_versions) == len(self.possible_versions[pkg_name]):
|
||||||
continue
|
continue
|
||||||
@ -1658,16 +1664,19 @@ def build_specs(self, function_tuples):
|
|||||||
repo = spack.repo.path.repo_for_pkg(spec)
|
repo = spack.repo.path.repo_for_pkg(spec)
|
||||||
spec.namespace = repo.namespace
|
spec.namespace = repo.namespace
|
||||||
|
|
||||||
# once this is done, everything is concrete
|
|
||||||
spec._mark_concrete()
|
|
||||||
|
|
||||||
# fix flags after all specs are constructed
|
# fix flags after all specs are constructed
|
||||||
self.reorder_flags()
|
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
|
# Add external paths to specs with just external modules
|
||||||
for s in self._specs.values():
|
for s in self._specs.values():
|
||||||
spack.spec.Spec.ensure_external_path_if_external(s)
|
spack.spec.Spec.ensure_external_path_if_external(s)
|
||||||
|
|
||||||
|
for s in self._specs.values():
|
||||||
|
s._mark_concrete()
|
||||||
|
|
||||||
for s in self._specs.values():
|
for s in self._specs.values():
|
||||||
spack.spec.Spec.ensure_no_deprecated(s)
|
spack.spec.Spec.ensure_no_deprecated(s)
|
||||||
|
|
||||||
|
@ -2293,73 +2293,7 @@ def _old_concretize(self, tests=False):
|
|||||||
if extra:
|
if extra:
|
||||||
raise InvalidDependencyError(self.name, extra)
|
raise InvalidDependencyError(self.name, extra)
|
||||||
|
|
||||||
# This dictionary will store object IDs rather than Specs as keys
|
Spec.inject_patches_variant(self)
|
||||||
# since the Spec __hash__ will change as patches are added to them
|
|
||||||
spec_to_patches = {}
|
|
||||||
for s in self.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
|
|
||||||
# normalize and concretize evaluate Packages using Repo.get(),
|
|
||||||
# which respects precedence. So, a namespace assignment isn't
|
|
||||||
# changing how a package name would have been interpreted and
|
|
||||||
# we can do it as late as possible to allow as much
|
|
||||||
# compatibility across repositories as possible.
|
|
||||||
if s.namespace is None:
|
|
||||||
s.namespace = spack.repo.path.repo_for_pkg(s.name).namespace
|
|
||||||
|
|
||||||
if s.concrete:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Add any patches from the package to the spec.
|
|
||||||
patches = []
|
|
||||||
for cond, patch_list in s.package_class.patches.items():
|
|
||||||
if s.satisfies(cond, strict=True):
|
|
||||||
for patch in patch_list:
|
|
||||||
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,
|
|
||||||
cover='edges', root=False):
|
|
||||||
pkg_deps = dspec.parent.package_class.dependencies
|
|
||||||
if dspec.spec.name not in pkg_deps:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if dspec.spec.concrete:
|
|
||||||
continue
|
|
||||||
|
|
||||||
patches = []
|
|
||||||
for cond, dependency in pkg_deps[dspec.spec.name].items():
|
|
||||||
if dspec.parent.satisfies(cond, strict=True):
|
|
||||||
for pcond, patch_list in dependency.patches.items():
|
|
||||||
if dspec.spec.satisfies(pcond):
|
|
||||||
for patch in patch_list:
|
|
||||||
patches.append(patch)
|
|
||||||
if patches:
|
|
||||||
all_patches = spec_to_patches.setdefault(id(dspec.spec), [])
|
|
||||||
all_patches.extend(patches)
|
|
||||||
|
|
||||||
for spec in self.traverse():
|
|
||||||
if id(spec) not in spec_to_patches:
|
|
||||||
continue
|
|
||||||
|
|
||||||
patches = list(lang.dedupe(spec_to_patches[id(spec)]))
|
|
||||||
mvar = spec.variants.setdefault(
|
|
||||||
'patches', vt.MultiValuedVariant('patches', ())
|
|
||||||
)
|
|
||||||
mvar.value = tuple(p.sha256 for p in patches)
|
|
||||||
# FIXME: Monkey patches mvar to store patches order
|
|
||||||
full_order_keys = list(tuple(p.ordering_key) + (p.sha256,) for p
|
|
||||||
in patches)
|
|
||||||
ordered_hashes = sorted(full_order_keys)
|
|
||||||
tty.debug("Ordered hashes [{0}]: ".format(spec.name) +
|
|
||||||
', '.join('/'.join(str(e) for e in t)
|
|
||||||
for t in ordered_hashes))
|
|
||||||
mvar._patches_in_order_of_appearance = list(
|
|
||||||
t[-1] for t in ordered_hashes)
|
|
||||||
|
|
||||||
for s in self.traverse():
|
for s in self.traverse():
|
||||||
# TODO: Refactor this into a common method to build external specs
|
# TODO: Refactor this into a common method to build external specs
|
||||||
@ -2397,6 +2331,74 @@ def _old_concretize(self, tests=False):
|
|||||||
# there are declared inconsistencies)
|
# there are declared inconsistencies)
|
||||||
self.architecture.target.optimization_flags(self.compiler)
|
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 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
|
||||||
|
# normalize and concretize evaluate Packages using Repo.get(),
|
||||||
|
# which respects precedence. So, a namespace assignment isn't
|
||||||
|
# changing how a package name would have been interpreted and
|
||||||
|
# we can do it as late as possible to allow as much
|
||||||
|
# compatibility across repositories as possible.
|
||||||
|
if s.namespace is None:
|
||||||
|
s.namespace = spack.repo.path.repo_for_pkg(s.name).namespace
|
||||||
|
|
||||||
|
if s.concrete:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Add any patches from the package to the spec.
|
||||||
|
patches = []
|
||||||
|
for cond, patch_list in s.package_class.patches.items():
|
||||||
|
if s.satisfies(cond, strict=True):
|
||||||
|
for patch in patch_list:
|
||||||
|
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 root.traverse_edges(deptype=all,
|
||||||
|
cover='edges', root=False):
|
||||||
|
pkg_deps = dspec.parent.package_class.dependencies
|
||||||
|
if dspec.spec.name not in pkg_deps:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if dspec.spec.concrete:
|
||||||
|
continue
|
||||||
|
|
||||||
|
patches = []
|
||||||
|
for cond, dependency in pkg_deps[dspec.spec.name].items():
|
||||||
|
if dspec.parent.satisfies(cond, strict=True):
|
||||||
|
for pcond, patch_list in dependency.patches.items():
|
||||||
|
if dspec.spec.satisfies(pcond):
|
||||||
|
for patch in patch_list:
|
||||||
|
patches.append(patch)
|
||||||
|
if patches:
|
||||||
|
all_patches = spec_to_patches.setdefault(id(dspec.spec), [])
|
||||||
|
all_patches.extend(patches)
|
||||||
|
for spec in root.traverse():
|
||||||
|
if id(spec) not in spec_to_patches:
|
||||||
|
continue
|
||||||
|
|
||||||
|
patches = list(lang.dedupe(spec_to_patches[id(spec)]))
|
||||||
|
mvar = spec.variants.setdefault(
|
||||||
|
'patches', vt.MultiValuedVariant('patches', ())
|
||||||
|
)
|
||||||
|
mvar.value = tuple(p.sha256 for p in patches)
|
||||||
|
# FIXME: Monkey patches mvar to store patches order
|
||||||
|
full_order_keys = list(tuple(p.ordering_key) + (p.sha256,) for p
|
||||||
|
in patches)
|
||||||
|
ordered_hashes = sorted(full_order_keys)
|
||||||
|
tty.debug("Ordered hashes [{0}]: ".format(spec.name) +
|
||||||
|
', '.join('/'.join(str(e) for e in t)
|
||||||
|
for t in ordered_hashes))
|
||||||
|
mvar._patches_in_order_of_appearance = list(
|
||||||
|
t[-1] for t in ordered_hashes)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def ensure_external_path_if_external(external_spec):
|
def ensure_external_path_if_external(external_spec):
|
||||||
if external_spec.external_modules and not external_spec.external_path:
|
if external_spec.external_modules and not external_spec.external_path:
|
||||||
|
Loading…
Reference in New Issue
Block a user