also break circular import concretize.py and solver/asp.py

This commit is contained in:
Harmen Stoppels 2024-12-07 21:32:20 +01:00 committed by Harmen Stoppels
parent 4e9fe1fc5d
commit 0239d77842
7 changed files with 65 additions and 67 deletions

View File

@ -33,7 +33,6 @@
import spack import spack
import spack.binary_distribution as bindist import spack.binary_distribution as bindist
import spack.builder import spack.builder
import spack.concretize
import spack.config as cfg import spack.config as cfg
import spack.error import spack.error
import spack.main import spack.main
@ -41,6 +40,7 @@
import spack.mirrors.utils import spack.mirrors.utils
import spack.paths import spack.paths
import spack.repo import spack.repo
import spack.solver.asp
import spack.spec import spack.spec
import spack.util.git import spack.util.git
import spack.util.gpg as gpg_util import spack.util.gpg as gpg_util
@ -707,7 +707,7 @@ def generate_gitlab_ci_yaml(
files (spack.yaml, spack.lock), etc should be written. GitLab files (spack.yaml, spack.lock), etc should be written. GitLab
requires this to be within the project directory. requires this to be within the project directory.
""" """
with spack.concretize.disable_compiler_existence_check(): with spack.solver.asp.disable_compiler_existence_check():
with env.write_transaction(): with env.write_transaction():
env.concretize() env.concretize()
env.write() env.write()

View File

@ -17,6 +17,7 @@
import spack.mirrors.mirror import spack.mirrors.mirror
import spack.mirrors.utils import spack.mirrors.utils
import spack.repo import spack.repo
import spack.solver.asp
import spack.spec import spack.spec
import spack.util.web as web_util import spack.util.web as web_util
from spack.cmd.common import arguments from spack.cmd.common import arguments
@ -516,7 +517,7 @@ def extend_with_dependencies(specs):
def concrete_specs_from_cli_or_file(args): def concrete_specs_from_cli_or_file(args):
tty.msg("Concretizing input specs") tty.msg("Concretizing input specs")
with spack.concretize.disable_compiler_existence_check(): with spack.solver.asp.disable_compiler_existence_check():
if args.specs: if args.specs:
specs = spack.cmd.parse_specs(args.specs, concretize=True) specs = spack.cmd.parse_specs(args.specs, concretize=True)
if not specs: if not specs:

View File

@ -5,8 +5,7 @@
"""High-level functions to concretize list of specs""" """High-level functions to concretize list of specs"""
import sys import sys
import time import time
from contextlib import contextmanager from typing import Iterable, Sequence, Tuple, Union
from typing import Iterable, Optional, Sequence, Tuple, Union
import llnl.util.tty as tty import llnl.util.tty as tty
@ -15,26 +14,7 @@
import spack.error import spack.error
import spack.repo import spack.repo
import spack.util.parallel import spack.util.parallel
from spack.spec import ArchSpec, CompilerSpec, Spec from spack.spec import Spec
CHECK_COMPILER_EXISTENCE = True
@contextmanager
def disable_compiler_existence_check():
global CHECK_COMPILER_EXISTENCE
CHECK_COMPILER_EXISTENCE, saved = False, CHECK_COMPILER_EXISTENCE
yield
CHECK_COMPILER_EXISTENCE = saved
@contextmanager
def enable_compiler_existence_check():
global CHECK_COMPILER_EXISTENCE
CHECK_COMPILER_EXISTENCE, saved = True, CHECK_COMPILER_EXISTENCE
yield
CHECK_COMPILER_EXISTENCE = saved
SpecPair = Tuple[Spec, Spec] SpecPair = Tuple[Spec, Spec]
SpecLike = Union[Spec, str] SpecLike = Union[Spec, str]
@ -51,11 +31,10 @@ def concretize_specs_together(
tests: list of package names for which to consider tests dependencies. If True, all nodes tests: list of package names for which to consider tests dependencies. If True, all nodes
will have test dependencies. If False, test dependencies will be disregarded. will have test dependencies. If False, test dependencies will be disregarded.
""" """
import spack.solver.asp from spack.solver.asp import Solver
allow_deprecated = spack.config.get("config:deprecated", False) allow_deprecated = spack.config.get("config:deprecated", False)
solver = spack.solver.asp.Solver() result = Solver().solve(abstract_specs, tests=tests, allow_deprecated=allow_deprecated)
result = solver.solve(abstract_specs, tests=tests, allow_deprecated=allow_deprecated)
return [s.copy() for s in result.specs] return [s.copy() for s in result.specs]
@ -90,7 +69,7 @@ def concretize_together_when_possible(
tests: list of package names for which to consider tests dependencies. If True, all nodes tests: list of package names for which to consider tests dependencies. If True, all nodes
will have test dependencies. If False, test dependencies will be disregarded. will have test dependencies. If False, test dependencies will be disregarded.
""" """
import spack.solver.asp from spack.solver.asp import Solver
to_concretize = [concrete if concrete else abstract for abstract, concrete in spec_list] to_concretize = [concrete if concrete else abstract for abstract, concrete in spec_list]
old_concrete_to_abstract = { old_concrete_to_abstract = {
@ -98,9 +77,8 @@ def concretize_together_when_possible(
} }
result_by_user_spec = {} result_by_user_spec = {}
solver = spack.solver.asp.Solver()
allow_deprecated = spack.config.get("config:deprecated", False) allow_deprecated = spack.config.get("config:deprecated", False)
for result in solver.solve_in_rounds( for result in Solver().solve_in_rounds(
to_concretize, tests=tests, allow_deprecated=allow_deprecated to_concretize, tests=tests, allow_deprecated=allow_deprecated
): ):
result_by_user_spec.update(result.specs_by_input) result_by_user_spec.update(result.specs_by_input)
@ -124,7 +102,7 @@ def concretize_separately(
tests: list of package names for which to consider tests dependencies. If True, all nodes tests: list of package names for which to consider tests dependencies. If True, all nodes
will have test dependencies. If False, test dependencies will be disregarded. will have test dependencies. If False, test dependencies will be disregarded.
""" """
import spack.bootstrap from spack.bootstrap import ensure_bootstrap_configuration, ensure_clingo_importable_or_raise
to_concretize = [abstract for abstract, concrete in spec_list if not concrete] to_concretize = [abstract for abstract, concrete in spec_list if not concrete]
args = [ args = [
@ -134,8 +112,8 @@ def concretize_separately(
] ]
ret = [(i, abstract) for i, abstract in enumerate(to_concretize) if abstract.concrete] ret = [(i, abstract) for i, abstract in enumerate(to_concretize) if abstract.concrete]
# Ensure we don't try to bootstrap clingo in parallel # Ensure we don't try to bootstrap clingo in parallel
with spack.bootstrap.ensure_bootstrap_configuration(): with ensure_bootstrap_configuration():
spack.bootstrap.ensure_clingo_importable_or_raise() ensure_clingo_importable_or_raise()
# Ensure all the indexes have been built or updated, since # Ensure all the indexes have been built or updated, since
# otherwise the processes in the pool may timeout on waiting # otherwise the processes in the pool may timeout on waiting
@ -201,6 +179,8 @@ def concretized(spec: Spec, tests: Union[bool, Iterable[str]] = False) -> Spec:
tests: if False disregard 'test' dependencies, if a list of names activate them for tests: if False disregard 'test' dependencies, if a list of names activate them for
the packages in the list, if True activate 'test' dependencies for all packages. the packages in the list, if True activate 'test' dependencies for all packages.
""" """
from spack.solver.asp import Solver, SpecBuilder
spec.replace_hash() spec.replace_hash()
for node in spec.traverse(): for node in spec.traverse():
@ -213,8 +193,7 @@ def concretized(spec: Spec, tests: Union[bool, Iterable[str]] = False) -> Spec:
return spec.copy() return spec.copy()
allow_deprecated = spack.config.get("config:deprecated", False) allow_deprecated = spack.config.get("config:deprecated", False)
solver = spack.solver.asp.Solver() result = Solver().solve([spec], tests=tests, allow_deprecated=allow_deprecated)
result = solver.solve([spec], tests=tests, allow_deprecated=allow_deprecated)
# take the best answer # take the best answer
opt, i, answer = min(result.answers) opt, i, answer = min(result.answers)
@ -224,27 +203,10 @@ def concretized(spec: Spec, tests: Union[bool, Iterable[str]] = False) -> Spec:
providers = [s.name for s in answer.values() if s.package.provides(name)] providers = [s.name for s in answer.values() if s.package.provides(name)]
name = providers[0] name = providers[0]
node = spack.solver.asp.SpecBuilder.make_node(pkg=name) node = SpecBuilder.make_node(pkg=name)
assert ( assert (
node in answer node in answer
), f"cannot find {name} in the list of specs {','.join([n.pkg for n in answer.keys()])}" ), f"cannot find {name} in the list of specs {','.join([n.pkg for n in answer.keys()])}"
concretized = answer[node] concretized = answer[node]
return concretized return concretized
class UnavailableCompilerVersionError(spack.error.SpackError):
"""Raised when there is no available compiler that satisfies a
compiler spec."""
def __init__(self, compiler_spec: CompilerSpec, arch: Optional[ArchSpec] = None) -> None:
err_msg = f"No compilers with spec {compiler_spec} found"
if arch:
err_msg += f" for operating system {arch.os} and target {arch.target}."
super().__init__(
err_msg,
"Run 'spack compiler find' to add compilers or "
"'spack compilers' to see which compilers are already recognized"
" by spack.",
)

View File

@ -29,7 +29,6 @@
import spack.binary_distribution import spack.binary_distribution
import spack.compiler import spack.compiler
import spack.compilers import spack.compilers
import spack.concretize
import spack.config import spack.config
import spack.deptypes as dt import spack.deptypes as dt
import spack.environment as ev import spack.environment as ev
@ -48,6 +47,7 @@
import spack.version as vn import spack.version as vn
import spack.version.git_ref_lookup import spack.version.git_ref_lookup
from spack import traverse from spack import traverse
from spack.spec import ArchSpec, CompilerSpec
from .core import ( from .core import (
AspFunction, AspFunction,
@ -66,6 +66,8 @@
from .requirements import RequirementKind, RequirementParser, RequirementRule from .requirements import RequirementKind, RequirementParser, RequirementRule
from .version_order import concretization_version_order from .version_order import concretization_version_order
CHECK_COMPILER_EXISTENCE = True
GitOrStandardVersion = Union[spack.version.GitVersion, spack.version.StandardVersion] GitOrStandardVersion = Union[spack.version.GitVersion, spack.version.StandardVersion]
TransformFunction = Callable[["spack.spec.Spec", List[AspFunction]], List[AspFunction]] TransformFunction = Callable[["spack.spec.Spec", List[AspFunction]], List[AspFunction]]
@ -3103,7 +3105,6 @@ def with_input_specs(self, input_specs: List["spack.spec.Spec"]) -> "CompilerPar
Args: Args:
input_specs: specs to be concretized input_specs: specs to be concretized
""" """
strict = spack.concretize.CHECK_COMPILER_EXISTENCE
default_os = str(spack.platforms.host().default_os) default_os = str(spack.platforms.host().default_os)
default_target = str(archspec.cpu.host().family) default_target = str(archspec.cpu.host().family)
for s in traverse.traverse_nodes(input_specs): for s in traverse.traverse_nodes(input_specs):
@ -3117,8 +3118,8 @@ def with_input_specs(self, input_specs: List["spack.spec.Spec"]) -> "CompilerPar
continue continue
# Error when a compiler is not found and strict mode is enabled # Error when a compiler is not found and strict mode is enabled
if strict: if CHECK_COMPILER_EXISTENCE:
raise spack.concretize.UnavailableCompilerVersionError(s.compiler) raise UnavailableCompilerVersionError(s.compiler)
# Make up a compiler matching the input spec. This is for bootstrapping. # Make up a compiler matching the input spec. This is for bootstrapping.
compiler_cls = spack.compilers.class_for_compiler_name(s.compiler.name) compiler_cls = spack.compilers.class_for_compiler_name(s.compiler.name)
@ -4012,6 +4013,22 @@ def _specs_from_environment_included_concrete(env, included_concrete):
return [] return []
@contextmanager
def disable_compiler_existence_check():
global CHECK_COMPILER_EXISTENCE
CHECK_COMPILER_EXISTENCE, saved = False, CHECK_COMPILER_EXISTENCE
yield
CHECK_COMPILER_EXISTENCE = saved
@contextmanager
def enable_compiler_existence_check():
global CHECK_COMPILER_EXISTENCE
CHECK_COMPILER_EXISTENCE, saved = True, CHECK_COMPILER_EXISTENCE
yield
CHECK_COMPILER_EXISTENCE = saved
class ReuseStrategy(enum.Enum): class ReuseStrategy(enum.Enum):
ROOTS = enum.auto() ROOTS = enum.auto()
DEPENDENCIES = enum.auto() DEPENDENCIES = enum.auto()
@ -4295,3 +4312,20 @@ def __init__(self, provided, conflicts):
class InvalidSpliceError(spack.error.SpackError): class InvalidSpliceError(spack.error.SpackError):
"""For cases in which the splice configuration is invalid.""" """For cases in which the splice configuration is invalid."""
class UnavailableCompilerVersionError(spack.error.SpackError):
"""Raised when there is no available compiler that satisfies a
compiler spec."""
def __init__(self, compiler_spec: CompilerSpec, arch: Optional[ArchSpec] = None) -> None:
err_msg = f"No compilers with spec {compiler_spec} found"
if arch:
err_msg += f" for operating system {arch.os} and target {arch.target}."
super().__init__(
err_msg,
"Run 'spack compiler find' to add compilers or "
"'spack compilers' to see which compilers are already recognized"
" by spack.",
)

View File

@ -11,6 +11,7 @@
import spack.concretize import spack.concretize
import spack.operating_systems import spack.operating_systems
import spack.platforms import spack.platforms
import spack.solver.asp
from spack.spec import ArchSpec, Spec from spack.spec import ArchSpec, Spec
@ -133,6 +134,6 @@ def test_concretize_target_ranges(root_target_range, dep_target_range, result, m
spec = Spec( spec = Spec(
f"pkg-a %gcc@10 foobar=bar target={root_target_range} ^pkg-b target={dep_target_range}" f"pkg-a %gcc@10 foobar=bar target={root_target_range} ^pkg-b target={dep_target_range}"
) )
with spack.concretize.disable_compiler_existence_check(): with spack.solver.asp.disable_compiler_existence_check():
spec = spack.concretize.concretized(spec) spec = spack.concretize.concretized(spec)
assert spec.target == spec["pkg-b"].target == result assert spec.target == spec["pkg-b"].target == result

View File

@ -348,11 +348,11 @@ def test_concretize_with_restricted_virtual(self):
assert concrete["mpich2"].satisfies("mpich2@1.3.1:1.4") assert concrete["mpich2"].satisfies("mpich2@1.3.1:1.4")
def test_concretize_enable_disable_compiler_existence_check(self): def test_concretize_enable_disable_compiler_existence_check(self):
with spack.concretize.enable_compiler_existence_check(): with spack.solver.asp.enable_compiler_existence_check():
with pytest.raises(spack.concretize.UnavailableCompilerVersionError): with pytest.raises(spack.solver.asp.UnavailableCompilerVersionError):
check_concretize("dttop %gcc@=100.100") check_concretize("dttop %gcc@=100.100")
with spack.concretize.disable_compiler_existence_check(): with spack.solver.asp.disable_compiler_existence_check():
spec = check_concretize("dttop %gcc@=100.100") spec = check_concretize("dttop %gcc@=100.100")
assert spec.satisfies("%gcc@100.100") assert spec.satisfies("%gcc@100.100")
assert spec["dtlink3"].satisfies("%gcc@100.100") assert spec["dtlink3"].satisfies("%gcc@100.100")
@ -723,9 +723,9 @@ def test_concretize_propagate_variant_second_level_dep_not_in_source(self):
def test_no_matching_compiler_specs(self, mock_low_high_config): def test_no_matching_compiler_specs(self, mock_low_high_config):
# only relevant when not building compilers as needed # only relevant when not building compilers as needed
with spack.concretize.enable_compiler_existence_check(): with spack.solver.asp.enable_compiler_existence_check():
s = Spec("pkg-a %gcc@=0.0.0") s = Spec("pkg-a %gcc@=0.0.0")
with pytest.raises(spack.concretize.UnavailableCompilerVersionError): with pytest.raises(spack.solver.asp.UnavailableCompilerVersionError):
s = spack.concretize.concretized(s) s = spack.concretize.concretized(s)
def test_no_compilers_for_arch(self): def test_no_compilers_for_arch(self):
@ -951,7 +951,7 @@ def test_adjusting_default_target_based_on_compiler(
): ):
best_achievable = archspec.cpu.TARGETS[best_achievable] best_achievable = archspec.cpu.TARGETS[best_achievable]
expected = best_achievable if best_achievable < current_host else current_host expected = best_achievable if best_achievable < current_host else current_host
with spack.concretize.disable_compiler_existence_check(): with spack.solver.asp.disable_compiler_existence_check():
s = spack.concretize.concretized(Spec(spec)) s = spack.concretize.concretized(Spec(spec))
assert str(s.architecture.target) == str(expected) assert str(s.architecture.target) == str(expected)
@ -966,7 +966,7 @@ def test_compiler_version_matches_any_entry_in_compilers_yaml(self):
) )
# This compiler does not exist # This compiler does not exist
with pytest.raises(spack.concretize.UnavailableCompilerVersionError): with pytest.raises(spack.solver.asp.UnavailableCompilerVersionError):
spack.concretize.concretized(Spec("mpileaks %gcc@=10.2")) spack.concretize.concretized(Spec("mpileaks %gcc@=10.2"))
def test_concretize_anonymous(self): def test_concretize_anonymous(self):

View File

@ -7,8 +7,8 @@
import spack.compilers import spack.compilers
import spack.spec import spack.spec
from spack.concretize import UnavailableCompilerVersionError
from spack.solver import asp from spack.solver import asp
from spack.solver.asp import UnavailableCompilerVersionError
class TestCompilerParser: class TestCompilerParser: