diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index 039ceec1de9..387788623d9 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -2742,7 +2742,7 @@ def visit(node): arg = ast_sym(ast_sym(term.atom).arguments[0]) symbol = AspFunction(name)(arg.string) self.assumptions.append((parse_term(str(symbol)), True)) - self.gen.asp_problem.append(f"{symbol}.\n") + self.gen.asp_problem.append(f"{{ {symbol} }}.\n") path = os.path.join(parent_dir, "concretize.lp") parse_files([path], visit) @@ -3160,20 +3160,30 @@ def reject_requirement_constraint( self, pkg_name: str, *, constraint: spack.spec.Spec, kind: RequirementKind ) -> bool: """Returns True if a requirement constraint should be rejected""" - if kind == RequirementKind.DEFAULT: - # Requirements under all: are applied only if they are satisfiable considering only - # package rules, so e.g. variants must exist etc. Otherwise, they are rejected. - try: - s = spack.spec.Spec(pkg_name) - s.constrain(constraint) - s.validate_or_raise() - except spack.error.SpackError as e: - tty.debug( - f"[SETUP] Rejecting the default '{constraint}' requirement " - f"on '{pkg_name}': {str(e)}", - level=2, - ) - return True + # If it's a specific package requirement, it's never rejected + if kind != RequirementKind.DEFAULT: + return False + + # Reject default requirements for runtimes and compilers + if pkg_name in spack.repo.PATH.packages_with_tags("runtime"): + return True + + if pkg_name in spack.repo.PATH.packages_with_tags("compiler"): + return True + + # Requirements under all: are applied only if they are satisfiable considering only + # package rules, so e.g. variants must exist etc. Otherwise, they are rejected. + try: + s = spack.spec.Spec(pkg_name) + s.constrain(constraint) + s.validate_or_raise() + except spack.error.SpackError as e: + tty.debug( + f"[SETUP] Rejecting the default '{constraint}' requirement " + f"on '{pkg_name}': {str(e)}", + level=2, + ) + return True return False diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp index 5df99f545b1..a0b394e9853 100644 --- a/lib/spack/spack/solver/concretize.lp +++ b/lib/spack/spack/solver/concretize.lp @@ -316,18 +316,21 @@ possible_version_weight(node(ID, Package), Weight) % If there is at least a version that satisfy the constraint, impose a lower % bound on the choice rule to avoid false positives with the error below -1 { attr("version", node(ID, Package), Version) : pkg_fact(Package, version_satisfies(Constraint, Version)) } +{ attr("version", node(ID, Package), Version) : pkg_fact(Package, version_satisfies(Constraint, Version)) } :- attr("node_version_satisfies", node(ID, Package), Constraint), - pkg_fact(Package, version_satisfies(Constraint, _)), - internal_error("must choose a single version to satisfy version constraints"). + pkg_fact(Package, version_satisfies(Constraint, _)). % More specific error message if the version cannot satisfy some constraint % Otherwise covered by `no_version_error` and `versions_conflict_error`. -error(10, "Cannot satisfy '{0}@{1}'", Package, Constraint) +error(1, "Cannot satisfy '{0}@{1}'", Package, Constraint) :- attr("node_version_satisfies", node(ID, Package), Constraint), attr("version", node(ID, Package), Version), not pkg_fact(Package, version_satisfies(Constraint, Version)). +error(10, "Cannot satisfy '{0}@{1}'", Package, Constraint) + :- attr("node_version_satisfies", node(ID, Package), Constraint), + not attr("version", node(ID, Package), _). + attr("node_version_satisfies", node(ID, Package), Constraint) :- attr("version", node(ID, Package), Version), pkg_fact(Package, version_satisfies(Constraint, Version)). @@ -1233,7 +1236,7 @@ propagated_flag(node(PackageID, Package), node_flag(FlagType, Flag, FlagGroup, S attr("node_flag", PackageNode, NodeFlag) :- propagated_flag(PackageNode, NodeFlag, _). % Cannot propagate the same flag from two distinct sources -error(100, "{0} and {1} cannot both propagate compiler flags '{2}' to {3}", Source1, Source2, Package, FlagType) :- +error(100, "{0} and {1} cannot both propagate compiler flags '{2}' to {3}", Source1, Source2, FlagType, Package) :- propagated_flag(node(ID, Package), node_flag(FlagType, _, _, _), node(_, Source1)), propagated_flag(node(ID, Package), node_flag(FlagType, _, _, _), node(_, Source2)), Source1 < Source2. @@ -1266,7 +1269,7 @@ has_built_packages() :- build(X), not external(X). % FIXME (compiler as nodes): is this version constraint always required and better than the callback? % "gcc-runtime" and the "gcc" it depends on must be at the same version -% attr("version", node(X, "gcc"), Version) :- +% attr("version", node(Y, "gcc"), Version) :- % attr("version", node(X, "gcc-runtime"), Version), % attr("depends_on", node(X, "gcc-runtime"), node(Y, "gcc"), "build"). diff --git a/var/spack/repos/builtin.mock/packages/gcc/package.py b/var/spack/repos/builtin.mock/packages/gcc/package.py index eea9b364a9c..6d3416bc086 100644 --- a/var/spack/repos/builtin.mock/packages/gcc/package.py +++ b/var/spack/repos/builtin.mock/packages/gcc/package.py @@ -13,9 +13,10 @@ class Gcc(CompilerPackage, Package): homepage = "http://www.example.com" url = "http://www.example.com/gcc-1.0.tar.gz" - version("1.0", md5="0123456789abcdef0123456789abcdef") - version("2.0", md5="abcdef0123456789abcdef0123456789") + version("14.0", md5="abcdef0123456789abcdef0123456789") version("3.0", md5="def0123456789abcdef0123456789abc") + version("2.0", md5="abcdef0123456789abcdef0123456789") + version("1.0", md5="0123456789abcdef0123456789abcdef") variant( "languages", @@ -29,6 +30,8 @@ class Gcc(CompilerPackage, Package): provides("cxx", when="languages=c++") provides("fortran", when="languages=fortran") + depends_on("c", type="build") + c_names = ["gcc"] cxx_names = ["g++"] fortran_names = ["gfortran"]