Compare commits

...

3 Commits

Author SHA1 Message Date
Gregory Becker
36d263a2cb black 2023-01-18 10:36:17 -08:00
Gregory Becker
99ecbcf3ef solver: fix build deps that are also non-build deps 2022-12-15 09:42:10 -08:00
Gregory Becker
a14403d641 solver: use process spaces for separate concretization of build deps 2022-12-14 22:17:17 -08:00
4 changed files with 591 additions and 501 deletions

View File

@@ -496,10 +496,12 @@ def _compute_specs_from_answer_set(self):
best = min(self.answers) best = min(self.answers)
opt, _, answer = best opt, _, answer = best
for input_spec in self.abstract_specs: for input_spec in self.abstract_specs:
key = input_spec.name key = (input_spec.name, "0")
if input_spec.virtual: if input_spec.virtual:
providers = [spec.name for spec in answer.values() if spec.package.provides(key)] providers = [
key = providers[0] spec.name for spec in answer.values() if spec.package.provides(input_spec.name)
]
key = (providers[0], "0")
candidate = answer.get(key) candidate = answer.get(key)
if candidate and candidate.satisfies(input_spec): if candidate and candidate.satisfies(input_spec):
@@ -1562,7 +1564,9 @@ class Body(object):
for dtype in dspec.deptypes: for dtype in dspec.deptypes:
# skip build dependencies of already-installed specs # skip build dependencies of already-installed specs
if concrete_build_deps or dtype != "build": if concrete_build_deps or dtype != "build":
clauses.append(fn.attr("depends_on", spec.name, dep.name, dtype)) clauses.append(
fn.attr("depends_on_unknown", spec.name, dep.name, dtype)
)
# Ensure Spack will not coconcretize this with another provider # Ensure Spack will not coconcretize this with another provider
# for the same virtual # for the same virtual
@@ -2171,89 +2175,102 @@ def __init__(self, specs, hash_lookup=None):
# from this dictionary during reconstruction # from this dictionary during reconstruction
self._hash_lookup = hash_lookup or {} self._hash_lookup = hash_lookup or {}
def hash(self, pkg, h): def hash(self, pkg, psid, h):
if pkg not in self._specs: key = (pkg, psid)
self._specs[pkg] = self._hash_lookup[h] if key not in self._specs:
self._specs[key] = self._hash_lookup[h]
def node(self, pkg): def node(self, pkg, psid):
if pkg not in self._specs: key = (pkg, psid)
self._specs[pkg] = spack.spec.Spec(pkg) if key not in self._specs:
self._specs[key] = spack.spec.Spec(pkg)
def _arch(self, pkg): def _arch(self, pkg, psid):
arch = self._specs[pkg].architecture key = (pkg, psid)
arch = self._specs[key].architecture
if not arch: if not arch:
arch = spack.spec.ArchSpec() arch = spack.spec.ArchSpec()
self._specs[pkg].architecture = arch self._specs[key].architecture = arch
return arch return arch
def node_platform(self, pkg, platform): def node_platform(self, pkg, psid, platform):
self._arch(pkg).platform = platform self._arch(pkg, psid).platform = platform
def node_os(self, pkg, os): def node_os(self, pkg, psid, os):
self._arch(pkg).os = os self._arch(pkg, psid).os = os
def node_target(self, pkg, target): def node_target(self, pkg, psid, target):
self._arch(pkg).target = target self._arch(pkg, psid).target = target
def variant_value(self, pkg, name, value): def variant_value(self, pkg, psid, name, value):
# FIXME: is there a way not to special case 'dev_path' everywhere? # FIXME: is there a way not to special case 'dev_path' everywhere?
key = (pkg, psid)
if name == "dev_path": if name == "dev_path":
self._specs[pkg].variants.setdefault( self._specs[key].variants.setdefault(
name, spack.variant.SingleValuedVariant(name, value) name, spack.variant.SingleValuedVariant(name, value)
) )
return return
if name == "patches": if name == "patches":
self._specs[pkg].variants.setdefault( self._specs[key].variants.setdefault(
name, spack.variant.MultiValuedVariant(name, value) name, spack.variant.MultiValuedVariant(name, value)
) )
return return
self._specs[pkg].update_variant_validate(name, value) self._specs[key].update_variant_validate(name, value)
def version(self, pkg, version): def version(self, pkg, psid, version):
self._specs[pkg].versions = spack.version.ver([version]) key = (pkg, psid)
self._specs[key].versions = spack.version.ver([version])
def node_compiler(self, pkg, compiler): def node_compiler(self, pkg, psid, compiler):
self._specs[pkg].compiler = spack.spec.CompilerSpec(compiler) key = (pkg, psid)
self._specs[key].compiler = spack.spec.CompilerSpec(compiler)
def node_compiler_version(self, pkg, compiler, version): def node_compiler_version(self, pkg, psid, compiler, version):
self._specs[pkg].compiler.versions = spack.version.VersionList([version]) key = (pkg, psid)
self._specs[key].compiler.versions = spack.version.VersionList([version])
def node_flag_compiler_default(self, pkg): def node_flag_compiler_default(self, pkg, psid):
self._flag_compiler_defaults.add(pkg) key = (pkg, psid)
self._flag_compiler_defaults.add(key)
def node_flag(self, pkg, flag_type, flag): def node_flag(self, pkg, psid, flag_type, flag):
self._specs[pkg].compiler_flags.add_flag(flag_type, flag, False) key = (pkg, psid)
self._specs[key].compiler_flags.add_flag(flag_type, flag, False)
def node_flag_source(self, pkg, flag_type, source): def node_flag_source(self, pkg, psid, flag_type, source):
self._flag_sources[(pkg, flag_type)].add(source) self._flag_sources[(pkg, psid, flag_type)].add(source)
def no_flags(self, pkg, flag_type): def no_flags(self, pkg, psid, flag_type):
self._specs[pkg].compiler_flags[flag_type] = [] key = (pkg, psid)
self._specs[key].compiler_flags[flag_type] = []
def external_spec_selected(self, pkg, idx): def external_spec_selected(self, pkg, psid, idx):
"""This means that the external spec and index idx """This means that the external spec and index idx
has been selected for this package. has been selected for this package.
""" """
packages_yaml = spack.config.get("packages") packages_yaml = spack.config.get("packages")
packages_yaml = _normalize_packages_yaml(packages_yaml) packages_yaml = _normalize_packages_yaml(packages_yaml)
spec_info = packages_yaml[pkg]["externals"][int(idx)] spec_info = packages_yaml[pkg]["externals"][int(idx)]
self._specs[pkg].external_path = spec_info.get("prefix", None) key = (pkg, psid)
self._specs[pkg].external_modules = spack.spec.Spec._format_module_list( self._specs[key].external_path = spec_info.get("prefix", None)
self._specs[key].external_modules = spack.spec.Spec._format_module_list(
spec_info.get("modules", None) spec_info.get("modules", None)
) )
self._specs[pkg].extra_attributes = spec_info.get("extra_attributes", {}) self._specs[key].extra_attributes = spec_info.get("extra_attributes", {})
def depends_on(self, pkg, dep, type): def depends_on(self, pkg, psid1, dep, psid2, type):
dependencies = self._specs[pkg].edges_to_dependencies(name=dep) pkg_key = (pkg, psid1)
dep_key = (dep, psid2)
dependencies = self._specs[pkg_key].edges_to_dependencies(name=dep)
# TODO: assertion to be removed when cross-compilation is handled correctly # TODO: assertion to be removed when cross-compilation is handled correctly
msg = "Current solver does not handle multiple dependency edges of the same name" msg = "Current solver does not handle multiple dependency edges of the same name"
assert len(dependencies) < 2, msg assert len(dependencies) < 2, msg
if not dependencies: if not dependencies:
self._specs[pkg].add_dependency_edge(self._specs[dep], (type,)) self._specs[pkg_key].add_dependency_edge(self._specs[dep_key], (type,))
else: else:
# TODO: This assumes that each solve unifies dependencies # TODO: This assumes that each solve unifies dependencies
dependencies[0].add_type(type) dependencies[0].add_type(type)
@@ -2272,7 +2289,8 @@ def reorder_flags(self):
compilers = dict((c.spec, c) for c in all_compilers_in_config()) compilers = dict((c.spec, c) for c in all_compilers_in_config())
cmd_specs = dict((s.name, s) for spec in self._command_line_specs for s in spec.traverse()) cmd_specs = dict((s.name, s) for spec in self._command_line_specs for s in spec.traverse())
for spec in self._specs.values(): for key, spec in self._specs.items():
name, psid = key
# if bootstrapping, compiler is not in config and has no flags # if bootstrapping, compiler is not in config and has no flags
flagmap_from_compiler = {} flagmap_from_compiler = {}
if spec.compiler in compilers: if spec.compiler in compilers:
@@ -2284,7 +2302,7 @@ def reorder_flags(self):
# order is determined by the DAG. A spec's flags come after any of its ancestors # order is determined by the DAG. A spec's flags come after any of its ancestors
# on the compile line # on the compile line
source_key = (spec.name, flag_type) source_key = (spec.name, psid, flag_type)
if source_key in self._flag_sources: if source_key in self._flag_sources:
order = [s.name for s in spec.traverse(order="post", direction="parents")] order = [s.name for s in spec.traverse(order="post", direction="parents")]
sorted_sources = sorted( sorted_sources = sorted(
@@ -2305,7 +2323,7 @@ def reorder_flags(self):
spec.compiler_flags.update({flag_type: ordered_compiler_flags}) spec.compiler_flags.update({flag_type: ordered_compiler_flags})
def deprecated(self, pkg, version): def deprecated(self, pkg, psid, version):
msg = 'using "{0}@{1}" which is a deprecated version' msg = 'using "{0}@{1}" which is a deprecated version'
tty.warn(msg.format(pkg, version)) tty.warn(msg.format(pkg, version))
@@ -2353,12 +2371,14 @@ def build_specs(self, function_tuples):
# predicates on virtual packages. # predicates on virtual packages.
if name != "error": if name != "error":
pkg = args[0] pkg = args[0]
psid = args[1]
if spack.repo.path.is_virtual(pkg): if spack.repo.path.is_virtual(pkg):
continue continue
# if we've already gotten a concrete spec for this pkg, # if we've already gotten a concrete spec for this pkg,
# do not bother calling actions on it. # do not bother calling actions on it.
spec = self._specs.get(pkg) key = (pkg, psid)
spec = self._specs.get(key)
if spec and spec.concrete: if spec and spec.concrete:
continue continue

File diff suppressed because it is too large Load Diff

View File

@@ -10,9 +10,10 @@
%============================================================================== %==============================================================================
% Spec attributes % Spec attributes
#show attr/2.
#show attr/3. #show attr/3.
#show attr/4. #show attr/4.
#show attr/5.
#show attr/6.
% names of optimization criteria % names of optimization criteria
#show opt_criterion/2. #show opt_criterion/2.

View File

@@ -2933,9 +2933,10 @@ def _new_concretize(self, tests=False):
providers = [spec.name for spec in answer.values() if spec.package.provides(name)] providers = [spec.name for spec in answer.values() if spec.package.provides(name)]
name = providers[0] name = providers[0]
assert name in answer key = (name, "0")
assert key in answer
concretized = answer[name] concretized = answer[key]
self._dup(concretized) self._dup(concretized)
def concretize(self, tests=False): def concretize(self, tests=False):