diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index 1de346b80a..b4da31c3c1 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -818,6 +818,9 @@ def __init__(self, tests=False): self.compiler_version_constraints = set() self.post_facts = [] + # (ID, CompilerSpec) -> dictionary of attributes + self.compiler_info = collections.defaultdict(dict) + # hashes we've already added facts for self.seen_hashes = set() self.reusable_and_possible = {} @@ -942,54 +945,38 @@ def conflict_rules(self, pkg): self.gen.fact(fn.conflict(pkg.name, trigger_id, constraint_id, conflict_msg)) self.gen.newline() - def available_compilers(self): + def compiler_facts(self): """Facts about available compilers.""" self.gen.h2("Available compilers") - compilers = self.possible_compilers + indexed_possible_compilers = list(enumerate(self.possible_compilers)) + for compiler_id, compiler in indexed_possible_compilers: + self.gen.fact(fn.compiler_id(compiler_id)) + self.gen.fact(fn.compiler_name(compiler_id, compiler.spec.name)) + self.gen.fact(fn.compiler_version(compiler_id, compiler.spec.version)) - compiler_versions = collections.defaultdict(lambda: set()) - for compiler in compilers: - compiler_versions[compiler.name].add(compiler.version) + if compiler.operating_system: + self.gen.fact(fn.compiler_os(compiler_id, compiler.operating_system)) - for compiler in sorted(compiler_versions): - for v in sorted(compiler_versions[compiler]): - self.gen.fact(fn.compiler_version(compiler, v)) + if compiler.target is not None: + self.gen.fact(fn.compiler_target(compiler_id, compiler.target)) + + for flag_type, flags in compiler.flags.items(): + for flag in flags: + self.gen.fact(fn.compiler_flag(compiler_id, flag_type, flag)) self.gen.newline() - def compiler_defaults(self): - """Set compiler defaults, given a list of possible compilers.""" - self.gen.h2("Default compiler preferences") + # Set compiler defaults, given a list of possible compilers + self.gen.h2("Default compiler preferences (CompilerID, Weight)") - compiler_list = self.possible_compilers.copy() - compiler_list = sorted(compiler_list, key=lambda x: (x.name, x.version), reverse=True) ppk = spack.package_prefs.PackagePrefs("all", "compiler", all=False) - matches = sorted(compiler_list, key=ppk) + matches = sorted(indexed_possible_compilers, key=lambda x: ppk(x[1].spec)) - for i, cspec in enumerate(matches): - f = fn.default_compiler_preference(cspec.name, cspec.version, i) + for weight, (compiler_id, cspec) in enumerate(matches): + f = fn.default_compiler_preference(compiler_id, weight) self.gen.fact(f) - # Enumerate target families. This may be redundant, but compilers with - # custom versions will be able to concretize properly. - for entry in spack.compilers.all_compilers_config(): - compiler_entry = entry["compiler"] - cspec = spack.spec.CompilerSpec(compiler_entry["spec"]) - if not compiler_entry.get("target", None): - continue - - self.gen.fact( - fn.compiler_supports_target(cspec.name, cspec.version, compiler_entry["target"]) - ) - - def compiler_supports_os(self): - compilers_yaml = spack.compilers.all_compilers_config() - for entry in compilers_yaml: - c = spack.spec.CompilerSpec(entry["compiler"]["spec"]) - operating_system = entry["compiler"]["operating_system"] - self.gen.fact(fn.compiler_supports_os(c.name, c.version, operating_system)) - def package_compiler_defaults(self, pkg): """Facts about packages' compiler prefs.""" @@ -998,14 +985,16 @@ def package_compiler_defaults(self, pkg): if not pkg_prefs or "compiler" not in pkg_prefs: return - compiler_list = self.possible_compilers.copy() + compiler_list = self.possible_compilers compiler_list = sorted(compiler_list, key=lambda x: (x.name, x.version), reverse=True) ppk = spack.package_prefs.PackagePrefs(pkg.name, "compiler", all=False) - matches = sorted(compiler_list, key=ppk) + matches = sorted(compiler_list, key=lambda x: ppk(x.spec)) - for i, cspec in enumerate(reversed(matches)): + for i, compiler in enumerate(reversed(matches)): self.gen.fact( - fn.node_compiler_preference(pkg.name, cspec.name, cspec.version, -i * 100) + fn.node_compiler_preference( + pkg.name, compiler.spec.name, compiler.spec.version, -i * 100 + ) ) def package_requirement_rules(self, pkg): @@ -1392,28 +1381,6 @@ def target_preferences(self, pkg_name): fn.target_weight(pkg_name, str(preferred.architecture.target), i + offset) ) - def flag_defaults(self): - self.gen.h2("Compiler flag defaults") - - # types of flags that can be on specs - for flag in spack.spec.FlagMap.valid_compiler_flags(): - self.gen.fact(fn.flag_type(flag)) - self.gen.newline() - - # flags from compilers.yaml - compilers = all_compilers_in_config() - seen = set() - for compiler in compilers: - # if there are multiple with the same spec, only use the first - if compiler.spec in seen: - continue - seen.add(compiler.spec) - for name, flags in compiler.flags.items(): - for flag in flags: - self.gen.fact( - fn.compiler_version_flag(compiler.name, compiler.version, name, flag) - ) - def spec_clauses(self, *args, **kwargs): """Wrap a call to `_spec_clauses()` into a try/except block that raises a comprehensible error message in case of failure. @@ -1770,8 +1737,6 @@ def target_defaults(self, specs): if granularity == "generic": candidate_targets = [t for t in candidate_targets if t.vendor == "generic"] - compilers = self.possible_compilers - # Add targets explicitly requested from specs for spec in specs: if not spec.architecture or not spec.architecture.target: @@ -1788,8 +1753,14 @@ def target_defaults(self, specs): if ancestor not in candidate_targets: candidate_targets.append(ancestor) - best_targets = set([uarch.family.name]) - for compiler in sorted(compilers): + best_targets = {uarch.family.name} + for compiler_id, compiler in enumerate(self.possible_compilers): + # Stub support for cross-compilation, to be expanded later + if compiler.target is not None and compiler.target != str(uarch.family): + self.gen.fact(fn.compiler_supports_target(compiler_id, compiler.target)) + self.gen.newline() + continue + supported = self._supported_targets(compiler.name, compiler.version, candidate_targets) # If we can't find supported targets it may be due to custom @@ -1808,20 +1779,19 @@ def target_defaults(self, specs): for target in supported: best_targets.add(target.name) - self.gen.fact( - fn.compiler_supports_target(compiler.name, compiler.version, target.name) - ) + self.gen.fact(fn.compiler_supports_target(compiler_id, target.name)) - self.gen.fact( - fn.compiler_supports_target(compiler.name, compiler.version, uarch.family.name) - ) + self.gen.fact(fn.compiler_supports_target(compiler_id, uarch.family.name)) + self.gen.newline() i = 0 # TODO compute per-target offset? for target in candidate_targets: self.gen.fact(fn.target(target.name)) self.gen.fact(fn.target_family(target.name, target.family.name)) - for parent in sorted(target.parents): - self.gen.fact(fn.target_parent(target.name, parent.name)) + self.gen.fact(fn.target_compatible(target.name, target.name)) + # Code for ancestor can run on target + for ancestor in target.ancestors: + self.gen.fact(fn.target_compatible(target.name, ancestor.name)) # prefer best possible targets; weight others poorly so # they're not used unless set explicitly @@ -1832,10 +1802,10 @@ def target_defaults(self, specs): i += 1 else: self.default_targets.append((100, target.name)) - - self.default_targets = list(sorted(set(self.default_targets))) self.gen.newline() + self.default_targets = list(sorted(set(self.default_targets))) + def virtual_providers(self): self.gen.h2("Virtual providers") msg = ( @@ -1851,6 +1821,22 @@ def virtual_providers(self): def generate_possible_compilers(self, specs): compilers = all_compilers_in_config() + + # Search for compilers which differs only by aspects that are + # not selectable by users using the spec syntax + seen, sanitized_list = set(), [] + for compiler in compilers: + key = compiler.spec, compiler.operating_system, compiler.target + if key in seen: + warnings.warn( + f"duplicate found for {compiler.spec} on " + f"{compiler.operating_system}/{compiler.target}. " + f"Edit your compilers.yaml configuration to remove it." + ) + continue + sanitized_list.append(compiler) + seen.add(key) + cspecs = set([c.spec for c in compilers]) # add compiler specs from the input line to possibilities if we @@ -1871,10 +1857,21 @@ def generate_possible_compilers(self, specs): # Allow unknown compilers to exist if the associated spec # is already built else: - cspecs.add(s.compiler) + compiler_cls = spack.compilers.class_for_compiler_name(s.compiler.name) + compilers.append( + compiler_cls( + s.compiler, operating_system=None, target=None, paths=[None] * 4 + ) + ) self.gen.fact(fn.allow_compiler(s.compiler.name, s.compiler.version)) - return cspecs + return list( + sorted( + compilers, + key=lambda compiler: (compiler.spec.name, compiler.spec.version), + reverse=True, + ) + ) def define_version_constraints(self): """Define what version_satisfies(...) means in ASP logic.""" @@ -1931,14 +1928,12 @@ def versions_for(v): self.possible_versions[pkg_name].add(version) def define_compiler_version_constraints(self): - compiler_list = spack.compilers.all_compiler_specs() - compiler_list = list(sorted(set(compiler_list))) for constraint in sorted(self.compiler_version_constraints): - for compiler in compiler_list: - if compiler.satisfies(constraint): + for compiler_id, compiler in enumerate(self.possible_compilers): + if compiler.spec.satisfies(constraint): self.gen.fact( fn.compiler_version_satisfies( - constraint.name, constraint.versions, compiler.version + constraint.name, constraint.versions, compiler_id ) ) self.gen.newline() @@ -2099,10 +2094,13 @@ def setup(self, driver, specs, reuse=None): for reusable_spec in reuse: self._facts_from_concrete_spec(reusable_spec, possible) + self.gen.h1("Possible flags on nodes") + for flag in spack.spec.FlagMap.valid_compiler_flags(): + self.gen.fact(fn.flag_type(flag)) + self.gen.newline() + self.gen.h1("General Constraints") - self.available_compilers() - self.compiler_defaults() - self.compiler_supports_os() + self.compiler_facts() # architecture defaults self.platform_defaults() @@ -2113,7 +2111,6 @@ def setup(self, driver, specs, reuse=None): self.provider_defaults() self.provider_requirements() self.external_packages() - self.flag_defaults() self.gen.h1("Package Constraints") for pkg in sorted(self.pkgs): @@ -2294,7 +2291,7 @@ def reorder_flags(self): flags will appear last on the compile line, in the order they were specified. - The solver determines wihch flags are on nodes; this routine + The solver determines which flags are on nodes; this routine imposes order afterwards. """ # reverse compilers so we get highest priority compilers that share a spec diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp index a71631aa11..ca6d4baf13 100644 --- a/lib/spack/spack/solver/concretize.lp +++ b/lib/spack/spack/solver/concretize.lp @@ -522,7 +522,7 @@ error(2, "{0} and {1} cannot both propagate variant '{2}' to package {3} with va attr("variant_propagate", Package, Variant, Value1, Source1), attr("variant_propagate", Package, Variant, Value2, Source2), variant(Package, Variant), - Value1 != Value2. + Value1 < Value2. % a variant cannot be set if it is not a variant on the package error(2, "Cannot set variant '{0}' for package '{1}' because the variant condition cannot be satisfied for the given spec", Variant, Package) @@ -816,25 +816,15 @@ node_target_compatible(Package, Target) :- attr("node_target", Package, MyTarget), target_compatible(Target, MyTarget). -% target_compatible(T1, T2) means code for T2 can run on T1 -% This order is dependent -> dependency in the node DAG, which -% is contravariant with the target DAG. -target_compatible(Target, Target) :- target(Target). -target_compatible(Child, Parent) :- target_parent(Child, Parent). -target_compatible(Descendent, Ancestor) - :- target_parent(Target, Ancestor), - target_compatible(Descendent, Target), - target(Target). - #defined target_satisfies/2. -#defined target_parent/2. % can't use targets on node if the compiler for the node doesn't support them error(2, "{0} compiler '{2}@{3}' incompatible with 'target={1}'", Package, Target, Compiler, Version) :- attr("node_target", Package, Target), - not compiler_supports_target(Compiler, Version, Target), - attr("node_compiler", Package, Compiler), - attr("node_compiler_version", Package, Compiler, Version), + node_compiler(Package, CompilerID), + not compiler_supports_target(CompilerID, Target), + compiler_name(CompilerID, Compiler), + compiler_version(CompilerID, Version), build(Package). % if a target is set explicitly, respect it @@ -868,32 +858,44 @@ error(2, "'{0} target={1}' is not compatible with this machine", Package, Target %----------------------------------------------------------------------------- % Compiler semantics %----------------------------------------------------------------------------- -compiler(Compiler) :- compiler_version(Compiler, _). - -% There must be only one compiler set per built node. The compiler -% is chosen among available versions. -{ attr("node_compiler_version", Package, Compiler, Version) : compiler_version(Compiler, Version) } :- +% There must be only one compiler set per built node. +{ node_compiler(Package, CompilerID) : compiler_id(CompilerID) } :- attr("node", Package), build(Package). +% Infer the compiler that matches a reused node +node_compiler(Package, CompilerID) + :- attr("node_compiler_version", Package, CompilerName, CompilerVersion), + attr("node", Package), + compiler_name(CompilerID, CompilerName), + compiler_version(CompilerID, CompilerVersion), + concrete(Package). + +% Expand the internal attribute into "attr("node_compiler_version") +attr("node_compiler_version", Package, CompilerName, CompilerVersion) + :- node_compiler(Package, CompilerID), + compiler_name(CompilerID, CompilerName), + compiler_version(CompilerID, CompilerVersion), + build(Package). + +attr("node_compiler", Package, CompilerName) + :- attr("node_compiler_version", Package, CompilerName, CompilerVersion). + error(2, "No valid compiler version found for '{0}'", Package) :- attr("node", Package), - C = #count{ Version : attr("node_compiler_version", Package, _, Version)}, - C < 1. -error(2, "'{0}' compiler constraints '%{1}@{2}' and '%{3}@{4}' are incompatible", Package, Compiler1, Version1, Compiler2, Version2) - :- attr("node", Package), - attr("node_compiler_version", Package, Compiler1, Version1), - attr("node_compiler_version", Package, Compiler2, Version2), - (Compiler1, Version1) < (Compiler2, Version2). % see[1] + not node_compiler(Package, _). -% Sometimes we just need to know the compiler and not the version -attr("node_compiler", Package, Compiler) :- attr("node_compiler_version", Package, Compiler, _). +error(2, "Cannot concretize {0} with two compilers {1}@{2} and {3}@{4}", Package, C1, V1, C2, V2) + :- attr("node", Package), + attr("node_compiler_version", Package, C1, V1), + attr("node_compiler_version", Package, C2, V2), + (C1, V1) < (C2, V2). % see[1] % We can't have a compiler be enforced and select the version from another compiler error(2, "Cannot concretize {0} with two compilers {1}@{2} and {3}@{4}", Package, C1, V1, C2, V2) :- attr("node_compiler_version", Package, C1, V1), attr("node_compiler_version", Package, C2, V2), - (C1, V1) != (C2, V2). + (C1, V1) < (C2, V2). error(2, "Cannot concretize {0} with two compilers {1} and {2}@{3}", Package, Compiler1, Compiler2, Version) :- attr("node_compiler", Package, Compiler1), @@ -904,37 +906,41 @@ error(2, "Cannot concretize {0} with two compilers {1} and {2}@{3}", Package, Co error(1, "No valid compiler for {0} satisfies '%{1}'", Package, Compiler) :- attr("node", Package), attr("node_compiler_version_satisfies", Package, Compiler, ":"), - C = #count{ Version : attr("node_compiler_version", Package, Compiler, Version), compiler_version_satisfies(Compiler, ":", Version) }, - C < 1. + not compiler_version_satisfies(Compiler, ":", _). % If the compiler of a node must satisfy a constraint, then its version % must be chosen among the ones that satisfy said constraint error(2, "No valid version for '{0}' compiler '{1}' satisfies '@{2}'", Package, Compiler, Constraint) :- attr("node", Package), attr("node_compiler_version_satisfies", Package, Compiler, Constraint), - C = #count{ Version : attr("node_compiler_version", Package, Compiler, Version), compiler_version_satisfies(Compiler, Constraint, Version) }, - C < 1. + not compiler_version_satisfies(Compiler, Constraint, _). % If the node is associated with a compiler and the compiler satisfy a constraint, then % the compiler associated with the node satisfy the same constraint attr("node_compiler_version_satisfies", Package, Compiler, Constraint) - :- attr("node_compiler_version", Package, Compiler, Version), - compiler_version_satisfies(Compiler, Constraint, Version). + :- node_compiler(Package, CompilerID), + compiler_name(CompilerID, Compiler), + compiler_version_satisfies(Compiler, Constraint, CompilerID). #defined compiler_version_satisfies/3. % If the compiler version was set from the command line, % respect it verbatim -attr("node_compiler_version", Package, Compiler, Version) :- - attr("node_compiler_version_set", Package, Compiler, Version). +:- attr("node_compiler_version_set", Package, Compiler, Version), + not attr("node_compiler_version", Package, Compiler, Version). + +:- attr("node_compiler_set", Package, Compiler), + not attr("node_compiler_version", Package, Compiler, _). % Cannot select a compiler if it is not supported on the OS % Compilers that are explicitly marked as allowed % are excluded from this check error(2, "{0} compiler '%{1}@{2}' incompatible with 'os={3}'", Package, Compiler, Version, OS) - :- attr("node_compiler_version", Package, Compiler, Version), - attr("node_os", Package, OS), - not compiler_supports_os(Compiler, Version, OS), + :- attr("node_os", Package, OS), + node_compiler(Package, CompilerID), + compiler_name(CompilerID, Compiler), + compiler_version(CompilerID, Version), + not compiler_os(CompilerID, OS), not allow_compiler(Compiler, Version), build(Package). @@ -942,8 +948,8 @@ error(2, "{0} compiler '%{1}@{2}' incompatible with 'os={3}'", Package, Compiler % same compiler there's a mismatch. compiler_match(Package, Dependency) :- depends_on(Package, Dependency), - attr("node_compiler_version", Package, Compiler, Version), - attr("node_compiler_version", Dependency, Compiler, Version). + node_compiler(Package, CompilerID), + node_compiler(Dependency, CompilerID). compiler_mismatch(Package, Dependency) :- depends_on(Package, Dependency), @@ -955,25 +961,32 @@ compiler_mismatch_required(Package, Dependency) attr("node_compiler_set", Dependency, _), not compiler_match(Package, Dependency). -#defined compiler_supports_os/3. +#defined compiler_os/3. #defined allow_compiler/2. % compilers weighted by preference according to packages.yaml compiler_weight(Package, Weight) - :- attr("node_compiler_version", Package, Compiler, V), + :- node_compiler(Package, CompilerID), + compiler_name(CompilerID, Compiler), + compiler_version(CompilerID, V), node_compiler_preference(Package, Compiler, V, Weight). compiler_weight(Package, Weight) - :- attr("node_compiler_version", Package, Compiler, V), + :- node_compiler(Package, CompilerID), + compiler_name(CompilerID, Compiler), + compiler_version(CompilerID, V), not node_compiler_preference(Package, Compiler, V, _), - default_compiler_preference(Compiler, V, Weight). + default_compiler_preference(CompilerID, Weight). compiler_weight(Package, 100) - :- attr("node_compiler_version", Package, Compiler, Version), - not node_compiler_preference(Package, Compiler, Version, _), - not default_compiler_preference(Compiler, Version, _). + :- node_compiler(Package, CompilerID), + compiler_name(CompilerID, Compiler), + compiler_version(CompilerID, V), + not node_compiler_preference(Package, Compiler, V, _), + not default_compiler_preference(CompilerID, _). % For the time being, be strict and reuse only if the compiler match one we have on the system error(2, "Compiler {1}@{2} requested for {0} cannot be found. Set install_missing_compilers:true if intended.", Package, Compiler, Version) - :- attr("node_compiler_version", Package, Compiler, Version), not compiler_version(Compiler, Version). + :- attr("node_compiler_version", Package, Compiler, Version), + not node_compiler(Package, _). #defined node_compiler_preference/4. #defined default_compiler_preference/3. @@ -985,10 +998,11 @@ error(2, "Compiler {1}@{2} requested for {0} cannot be found. Set install_missin % propagate flags when compiler match can_inherit_flags(Package, Dependency, FlagType) :- depends_on(Package, Dependency), - attr("node_compiler", Package, Compiler), - attr("node_compiler", Dependency, Compiler), + node_compiler(Package, CompilerID), + node_compiler(Dependency, CompilerID), not attr("node_flag_set", Dependency, FlagType, _), - compiler(Compiler), flag_type(FlagType). + compiler_id(CompilerID), + flag_type(FlagType). node_flag_inherited(Dependency, FlagType, Flag) :- attr("node_flag_set", Package, FlagType, Flag), can_inherit_flags(Package, Dependency, FlagType), @@ -1005,7 +1019,7 @@ error(2, "{0} and {1} cannot both propagate compiler flags '{2}' to {3}", Source attr("node_flag_propagate", Source2, FlagType), can_inherit_flags(Source1, Package, FlagType), can_inherit_flags(Source2, Package, FlagType), - Source1 != Source2. + Source1 < Source2. % remember where flags came from attr("node_flag_source", Package, FlagType, Package) :- attr("node_flag_set", Package, FlagType, _). @@ -1015,19 +1029,21 @@ attr("node_flag_source", Dependency, FlagType, Q) % compiler flags from compilers.yaml are put on nodes if compiler matches attr("node_flag", Package, FlagType, Flag) - :- compiler_version_flag(Compiler, Version, FlagType, Flag), - attr("node_compiler_version", Package, Compiler, Version), + :- compiler_flag(CompilerID, FlagType, Flag), + node_compiler(Package, CompilerID), flag_type(FlagType), - compiler(Compiler), - compiler_version(Compiler, Version). + compiler_id(CompilerID), + compiler_name(CompilerID, CompilerName), + compiler_version(CompilerID, Version). attr("node_flag_compiler_default", Package) :- not attr("node_flag_set", Package, FlagType, _), - compiler_version_flag(Compiler, Version, FlagType, Flag), - attr("node_compiler_version", Package, Compiler, Version), + compiler_flag(CompilerID, FlagType, Flag), + node_compiler(Package, CompilerID), flag_type(FlagType), - compiler(Compiler), - compiler_version(Compiler, Version). + compiler_id(CompilerID), + compiler_name(CompilerID, CompilerName), + compiler_version(CompilerID, Version). % if a flag is set to something or inherited, it's included attr("node_flag", Package, FlagType, Flag) :- attr("node_flag_set", Package, FlagType, Flag). @@ -1038,7 +1054,7 @@ attr("node_flag", Package, FlagType, Flag) attr("no_flags", Package, FlagType) :- not attr("node_flag", Package, FlagType, _), attr("node", Package), flag_type(FlagType). -#defined compiler_version_flag/4. +#defined compiler_flag/3. %----------------------------------------------------------------------------- @@ -1054,7 +1070,7 @@ attr("no_flags", Package, FlagType) % You can't install a hash, if it is not installed :- attr("hash", Package, Hash), not installed_hash(Package, Hash). % This should be redundant given the constraint above -:- attr("hash", Package, Hash1), attr("hash", Package, Hash2), Hash1 != Hash2. +:- attr("hash", Package, Hash1), attr("hash", Package, Hash2), Hash1 < Hash2. % if a hash is selected, we impose all the constraints that implies impose(Hash) :- attr("hash", Package, Hash). @@ -1311,13 +1327,29 @@ opt_criterion(5, "non-preferred targets"). %----------------- % Domain heuristic %----------------- -#heuristic attr("version", Package, Version) : version_declared(Package, Version, 0), attr("node", Package). [10, true] -#heuristic version_weight(Package, 0) : version_declared(Package, Version, 0), attr("node", Package). [10, true] -#heuristic attr("node_target", Package, Target) : package_target_weight(Target, Package, 0), attr("node", Package). [10, true] -#heuristic node_target_weight(Package, 0) : attr("node", Package). [10, true] +#heuristic literal_solved(ID) : literal(ID). [1, sign] +#heuristic literal_solved(ID) : literal(ID). [50, init] +#heuristic attr("hash", Package, Hash) : attr("root", Package). [45, init] + +#heuristic attr("version", Package, Version) : version_declared(Package, Version, 0), attr("root", Package). [40, true] +#heuristic version_weight(Package, 0) : version_declared(Package, Version, 0), attr("root", Package). [40, true] +#heuristic attr("variant_value", Package, Variant, Value) : variant_default_value(Package, Variant, Value), attr("root", Package). [40, true] +#heuristic attr("node_target", Package, Target) : package_target_weight(Target, Package, 0), attr("root", Package). [40, true] +#heuristic node_target_weight(Package, 0) : attr("root", Package). [40, true] +#heuristic node_compiler(Package, CompilerID) : default_compiler_preference(ID, 0), compiler_id(ID), attr("root", Package). [40, true] + +#heuristic provider(Package, Virtual) : possible_provider_weight(Package, Virtual, 0, _), attr("virtual_node", Virtual). [30, true] +#heuristic provider_weight(Package, Virtual, 0, R) : possible_provider_weight(Package, Virtual, 0, R), attr("virtual_node", Virtual). [30, true] +#heuristic attr("node", Package) : possible_provider_weight(Package, Virtual, 0, _), attr("virtual_node", Virtual). [30, true] + +#heuristic attr("version", Package, Version) : version_declared(Package, Version, 0), attr("node", Package). [20, true] +#heuristic version_weight(Package, 0) : version_declared(Package, Version, 0), attr("node", Package). [20, true] + +#heuristic attr("node_target", Package, Target) : package_target_weight(Target, Package, 0), attr("node", Package). [20, true] +#heuristic node_target_weight(Package, 0) : attr("node", Package). [20, true] +#heuristic node_compiler(Package, CompilerID) : default_compiler_preference(ID, 0), compiler_id(ID), attr("node", Package). [15, true] + #heuristic attr("variant_value", Package, Variant, Value) : variant_default_value(Package, Variant, Value), attr("node", Package). [10, true] -#heuristic provider(Package, Virtual) : possible_provider_weight(Package, Virtual, 0, _), attr("virtual_node", Virtual). [10, true] -#heuristic attr("node", Package) : possible_provider_weight(Package, Virtual, 0, _), attr("virtual_node", Virtual). [10, true] #heuristic attr("node_os", Package, OS) : buildable_os(OS). [10, true] %-----------