Compilers can inject first order rules into the solver
* Restore PackageBase class, and modify only ASP This prevents a noticeable slowdown in concretization due to the number of directives involved. * Fix issue with 'clang' being preferred to 'gcc', due to runtime version weights * Constraints on runtimes are declared by compilers The declaration of available runtime versions, and of their compatibility constraints are in the associated compiler class. Co-authored-by: Harmen Stoppels <harmenstoppels@gmail.com>
This commit is contained in:
parent
8371bb4e19
commit
ea7e3e4f9f
@ -36,7 +36,6 @@
|
|||||||
import spack.config
|
import spack.config
|
||||||
import spack.environment as ev
|
import spack.environment as ev
|
||||||
import spack.modules
|
import spack.modules
|
||||||
import spack.package_base
|
|
||||||
import spack.paths
|
import spack.paths
|
||||||
import spack.platforms
|
import spack.platforms
|
||||||
import spack.repo
|
import spack.repo
|
||||||
@ -608,7 +607,6 @@ def setup_main_options(args):
|
|||||||
[(key, [spack.paths.mock_packages_path])]
|
[(key, [spack.paths.mock_packages_path])]
|
||||||
)
|
)
|
||||||
spack.repo.PATH = spack.repo.create(spack.config.CONFIG)
|
spack.repo.PATH = spack.repo.create(spack.config.CONFIG)
|
||||||
spack.package_base.WITH_GCC_RUNTIME = False
|
|
||||||
|
|
||||||
# If the user asked for it, don't check ssl certs.
|
# If the user asked for it, don't check ssl certs.
|
||||||
if args.insecure:
|
if args.insecure:
|
||||||
|
@ -53,7 +53,6 @@
|
|||||||
import spack.util.environment
|
import spack.util.environment
|
||||||
import spack.util.path
|
import spack.util.path
|
||||||
import spack.util.web
|
import spack.util.web
|
||||||
from spack.directives import _depends_on
|
|
||||||
from spack.filesystem_view import YamlFilesystemView
|
from spack.filesystem_view import YamlFilesystemView
|
||||||
from spack.install_test import (
|
from spack.install_test import (
|
||||||
PackageTest,
|
PackageTest,
|
||||||
@ -77,7 +76,6 @@
|
|||||||
"""Allowed URL schemes for spack packages."""
|
"""Allowed URL schemes for spack packages."""
|
||||||
_ALLOWED_URL_SCHEMES = ["http", "https", "ftp", "file", "git"]
|
_ALLOWED_URL_SCHEMES = ["http", "https", "ftp", "file", "git"]
|
||||||
|
|
||||||
WITH_GCC_RUNTIME = True
|
|
||||||
|
|
||||||
#: Filename for the Spack build/install log.
|
#: Filename for the Spack build/install log.
|
||||||
_spack_build_logfile = "spack-build-out.txt"
|
_spack_build_logfile = "spack-build-out.txt"
|
||||||
@ -373,20 +371,6 @@ def _wrapper(instance, *args, **kwargs):
|
|||||||
return _execute_under_condition
|
return _execute_under_condition
|
||||||
|
|
||||||
|
|
||||||
class BinaryPackage:
|
|
||||||
"""This adds a universal dependency on gcc-runtime."""
|
|
||||||
|
|
||||||
def maybe_depend_on_gcc_runtime(self):
|
|
||||||
# Do not depend on itself, and allow tests to disable this universal dep
|
|
||||||
if self.name == "gcc-runtime" or not WITH_GCC_RUNTIME:
|
|
||||||
return
|
|
||||||
for v in ["13", "12", "11", "10", "9", "8", "7", "6", "5", "4"]:
|
|
||||||
_depends_on(self, f"gcc-runtime@{v}:", type="link", when=f"%gcc@{v} platform=linux")
|
|
||||||
_depends_on(self, f"gcc-runtime@{v}:", type="link", when=f"%gcc@{v} platform=cray")
|
|
||||||
|
|
||||||
_directives_to_be_executed = [maybe_depend_on_gcc_runtime]
|
|
||||||
|
|
||||||
|
|
||||||
class PackageViewMixin:
|
class PackageViewMixin:
|
||||||
"""This collects all functionality related to adding installed Spack
|
"""This collects all functionality related to adding installed Spack
|
||||||
package to views. Packages can customize how they are added to views by
|
package to views. Packages can customize how they are added to views by
|
||||||
@ -449,7 +433,7 @@ def remove_files_from_view(self, view, merge_map):
|
|||||||
Pb = TypeVar("Pb", bound="PackageBase")
|
Pb = TypeVar("Pb", bound="PackageBase")
|
||||||
|
|
||||||
|
|
||||||
class PackageBase(WindowsRPath, PackageViewMixin, BinaryPackage, metaclass=PackageMeta):
|
class PackageBase(WindowsRPath, PackageViewMixin, metaclass=PackageMeta):
|
||||||
"""This is the superclass for all spack packages.
|
"""This is the superclass for all spack packages.
|
||||||
|
|
||||||
***The Package class***
|
***The Package class***
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
import pathlib
|
import pathlib
|
||||||
import pprint
|
import pprint
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
import types
|
import types
|
||||||
import warnings
|
import warnings
|
||||||
from typing import Callable, Dict, List, NamedTuple, Optional, Sequence, Set, Tuple, Union
|
from typing import Callable, Dict, List, NamedTuple, Optional, Sequence, Set, Tuple, Union
|
||||||
@ -61,6 +62,8 @@
|
|||||||
ASTType = None
|
ASTType = None
|
||||||
parse_files = None
|
parse_files = None
|
||||||
|
|
||||||
|
#: Enable the addition of a runtime node
|
||||||
|
WITH_RUNTIME = sys.platform != "win32"
|
||||||
|
|
||||||
#: Data class that contain configuration on what a
|
#: Data class that contain configuration on what a
|
||||||
#: clingo solve should output.
|
#: clingo solve should output.
|
||||||
@ -122,6 +125,8 @@ class Provenance(enum.IntEnum):
|
|||||||
PACKAGE_PY = enum.auto()
|
PACKAGE_PY = enum.auto()
|
||||||
# An installed spec
|
# An installed spec
|
||||||
INSTALLED = enum.auto()
|
INSTALLED = enum.auto()
|
||||||
|
# A runtime injected from another package (e.g. a compiler)
|
||||||
|
RUNTIME = enum.auto()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self._name_.lower()}"
|
return f"{self._name_.lower()}"
|
||||||
@ -2023,7 +2028,9 @@ class Body:
|
|||||||
f.node_compiler_version(spec.name, spec.compiler.name, spec.compiler.version)
|
f.node_compiler_version(spec.name, spec.compiler.name, spec.compiler.version)
|
||||||
)
|
)
|
||||||
|
|
||||||
elif spec.compiler.versions:
|
elif spec.compiler.versions and spec.compiler.versions != vn.any_version:
|
||||||
|
# The condition above emits a facts only if we have an actual constraint
|
||||||
|
# on the compiler version, and avoids emitting them if any version is fine
|
||||||
clauses.append(
|
clauses.append(
|
||||||
fn.attr(
|
fn.attr(
|
||||||
"node_compiler_version_satisfies",
|
"node_compiler_version_satisfies",
|
||||||
@ -2578,6 +2585,9 @@ def setup(
|
|||||||
self.possible_virtuals = node_counter.possible_virtuals()
|
self.possible_virtuals = node_counter.possible_virtuals()
|
||||||
self.pkgs = node_counter.possible_dependencies()
|
self.pkgs = node_counter.possible_dependencies()
|
||||||
|
|
||||||
|
runtimes = spack.repo.PATH.packages_with_tags("runtime")
|
||||||
|
self.pkgs.update(set(runtimes))
|
||||||
|
|
||||||
# Fail if we already know an unreachable node is requested
|
# Fail if we already know an unreachable node is requested
|
||||||
for spec in specs:
|
for spec in specs:
|
||||||
missing_deps = [
|
missing_deps = [
|
||||||
@ -2678,6 +2688,10 @@ def setup(
|
|||||||
self.gen.h1("Variant Values defined in specs")
|
self.gen.h1("Variant Values defined in specs")
|
||||||
self.define_variant_values()
|
self.define_variant_values()
|
||||||
|
|
||||||
|
if WITH_RUNTIME:
|
||||||
|
self.gen.h1("Runtimes")
|
||||||
|
self.define_runtime_constraints()
|
||||||
|
|
||||||
self.gen.h1("Version Constraints")
|
self.gen.h1("Version Constraints")
|
||||||
self.collect_virtual_constraints()
|
self.collect_virtual_constraints()
|
||||||
self.define_version_constraints()
|
self.define_version_constraints()
|
||||||
@ -2688,6 +2702,21 @@ def setup(
|
|||||||
self.gen.h1("Target Constraints")
|
self.gen.h1("Target Constraints")
|
||||||
self.define_target_constraints()
|
self.define_target_constraints()
|
||||||
|
|
||||||
|
def define_runtime_constraints(self):
|
||||||
|
"""Define the constraints to be imposed on the runtimes"""
|
||||||
|
recorder = RuntimePropertyRecorder(self)
|
||||||
|
for compiler in self.possible_compilers:
|
||||||
|
if compiler.name != "gcc":
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
compiler_cls = spack.repo.PATH.get_pkg_class(compiler.name)
|
||||||
|
except spack.repo.UnknownPackageError:
|
||||||
|
continue
|
||||||
|
if hasattr(compiler_cls, "runtime_constraints"):
|
||||||
|
compiler_cls.runtime_constraints(compiler=compiler, pkg=recorder)
|
||||||
|
|
||||||
|
recorder.consume_facts()
|
||||||
|
|
||||||
def literal_specs(self, specs):
|
def literal_specs(self, specs):
|
||||||
for spec in specs:
|
for spec in specs:
|
||||||
self.gen.h2("Spec: %s" % str(spec))
|
self.gen.h2("Spec: %s" % str(spec))
|
||||||
@ -2796,6 +2825,157 @@ def _specs_from_requires(self, pkg_name, section):
|
|||||||
yield _spec_with_default_name(s, pkg_name)
|
yield _spec_with_default_name(s, pkg_name)
|
||||||
|
|
||||||
|
|
||||||
|
class RuntimePropertyRecorder:
|
||||||
|
"""An object of this class is injected in callbacks to compilers, to let them declare
|
||||||
|
properties of the runtimes they support and of the runtimes they provide, and to add
|
||||||
|
runtime dependencies to the nodes using said compiler.
|
||||||
|
|
||||||
|
The usage of the object is the following. First, a runtime package name or the wildcard
|
||||||
|
"*" are passed as an argument to __call__, to set which kind of package we are referring to.
|
||||||
|
Then we can call one method with a directive-like API.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
>>> pkg = RuntimePropertyRecorder(setup)
|
||||||
|
>>> # Every package compiled with %gcc has a link dependency on 'gcc-runtime'
|
||||||
|
>>> pkg("*").depends_on(
|
||||||
|
... "gcc-runtime",
|
||||||
|
... when="%gcc",
|
||||||
|
... type="link",
|
||||||
|
... description="If any package uses %gcc, it depends on gcc-runtime"
|
||||||
|
... )
|
||||||
|
>>> # The version of gcc-runtime is the same as the %gcc used to "compile" it
|
||||||
|
>>> pkg("gcc-runtime").requires("@=9.4.0", when="%gcc@=9.4.0")
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, setup):
|
||||||
|
self._setup = setup
|
||||||
|
self.rules = []
|
||||||
|
self.runtime_conditions = set()
|
||||||
|
# State of this object set in the __call__ method, and reset after
|
||||||
|
# each directive-like method
|
||||||
|
self.current_package = None
|
||||||
|
|
||||||
|
def __call__(self, package_name: str) -> "RuntimePropertyRecorder":
|
||||||
|
"""Sets a package name for the next directive-like method call"""
|
||||||
|
assert self.current_package is None, f"state was already set to '{self.current_package}'"
|
||||||
|
self.current_package = package_name
|
||||||
|
return self
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""Resets the current state."""
|
||||||
|
self.current_package = None
|
||||||
|
|
||||||
|
def depends_on(self, dependency_str: str, *, when: str, type: str, description: str) -> None:
|
||||||
|
"""Injects conditional dependencies on packages.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
dependency_str: the dependency spec to inject
|
||||||
|
when: anonymous condition to be met on a package to have the dependency
|
||||||
|
type: dependency type
|
||||||
|
description: human-readable description of the rule for adding the dependency
|
||||||
|
"""
|
||||||
|
# TODO: The API for this function is not final, and is still subject to change. At
|
||||||
|
# TODO: the moment, we implemented only the features strictly needed for the
|
||||||
|
# TODO: functionality currently provided by Spack, and we assert nothing else is required.
|
||||||
|
msg = "the 'depends_on' method can be called only with pkg('*')"
|
||||||
|
assert self.current_package == "*", msg
|
||||||
|
|
||||||
|
when_spec = spack.spec.Spec(when)
|
||||||
|
assert when_spec.name is None, "only anonymous when specs are accepted"
|
||||||
|
|
||||||
|
dependency_spec = spack.spec.Spec(dependency_str)
|
||||||
|
if dependency_spec.versions != vn.any_version:
|
||||||
|
self._setup.version_constraints.add((dependency_spec.name, dependency_spec.versions))
|
||||||
|
|
||||||
|
placeholder = "XXX"
|
||||||
|
node_variable = "node(ID, Package)"
|
||||||
|
when_spec.name = placeholder
|
||||||
|
|
||||||
|
body_clauses = self._setup.spec_clauses(when_spec, body=True)
|
||||||
|
body_str = (
|
||||||
|
f" {f',{os.linesep} '.join(str(x) for x in body_clauses)},\n"
|
||||||
|
f" not runtime(Package)"
|
||||||
|
).replace(f'"{placeholder}"', f"{node_variable}")
|
||||||
|
head_clauses = self._setup.spec_clauses(dependency_spec, body=False)
|
||||||
|
|
||||||
|
runtime_pkg = dependency_spec.name
|
||||||
|
main_rule = (
|
||||||
|
f"% {description}\n"
|
||||||
|
f'1 {{ attr("depends_on", {node_variable}, node(0..X-1, "{runtime_pkg}"), "{type}") :'
|
||||||
|
f' max_dupes("gcc-runtime", X)}} 1:-\n'
|
||||||
|
f"{body_str}.\n\n"
|
||||||
|
)
|
||||||
|
self.rules.append(main_rule)
|
||||||
|
for clause in head_clauses:
|
||||||
|
if clause.args[0] == "node":
|
||||||
|
continue
|
||||||
|
runtime_node = f'node(RuntimeID, "{runtime_pkg}")'
|
||||||
|
head_str = str(clause).replace(f'"{runtime_pkg}"', runtime_node)
|
||||||
|
rule = (
|
||||||
|
f"{head_str} :-\n"
|
||||||
|
f' attr("depends_on", {node_variable}, {runtime_node}, "{type}"),\n'
|
||||||
|
f"{body_str}.\n\n"
|
||||||
|
)
|
||||||
|
self.rules.append(rule)
|
||||||
|
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def requires(self, impose: str, *, when: str):
|
||||||
|
"""Injects conditional requirements on a given package.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
impose: constraint to be imposed
|
||||||
|
when: condition triggering the constraint
|
||||||
|
"""
|
||||||
|
msg = "the 'requires' method cannot be called with pkg('*') or without setting the package"
|
||||||
|
assert self.current_package is not None and self.current_package != "*", msg
|
||||||
|
|
||||||
|
imposed_spec = spack.spec.Spec(f"{self.current_package}{impose}")
|
||||||
|
when_spec = spack.spec.Spec(f"{self.current_package}{when}")
|
||||||
|
|
||||||
|
assert imposed_spec.versions.concrete, f"{impose} must have a concrete version"
|
||||||
|
assert when_spec.compiler.concrete, f"{when} must have a concrete compiler"
|
||||||
|
|
||||||
|
# Add versions to possible versions
|
||||||
|
for s in (imposed_spec, when_spec):
|
||||||
|
if not s.versions.concrete:
|
||||||
|
continue
|
||||||
|
self._setup.possible_versions[s.name].add(s.version)
|
||||||
|
self._setup.declared_versions[s.name].append(
|
||||||
|
DeclaredVersion(version=s.version, idx=0, origin=Provenance.RUNTIME)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.runtime_conditions.add((imposed_spec, when_spec))
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def consume_facts(self):
|
||||||
|
"""Consume the facts collected by this object, and emits rules and
|
||||||
|
facts for the runtimes.
|
||||||
|
"""
|
||||||
|
self._setup.gen.h2("Runtimes: rules")
|
||||||
|
self._setup.gen.newline()
|
||||||
|
for rule in self.rules:
|
||||||
|
if not isinstance(self._setup.gen.out, llnl.util.lang.Devnull):
|
||||||
|
self._setup.gen.out.write(rule)
|
||||||
|
self._setup.gen.control.add("base", [], rule)
|
||||||
|
|
||||||
|
self._setup.gen.h2("Runtimes: conditions")
|
||||||
|
for runtime_pkg in spack.repo.PATH.packages_with_tags("runtime"):
|
||||||
|
self._setup.gen.fact(fn.runtime(runtime_pkg))
|
||||||
|
self._setup.gen.fact(fn.possible_in_link_run(runtime_pkg))
|
||||||
|
self._setup.gen.newline()
|
||||||
|
# Inject version rules for runtimes (versions are declared based
|
||||||
|
# on the available compilers)
|
||||||
|
self._setup.pkg_version_rules(runtime_pkg)
|
||||||
|
|
||||||
|
for imposed_spec, when_spec in self.runtime_conditions:
|
||||||
|
msg = f"{when_spec} requires {imposed_spec} at runtime"
|
||||||
|
_ = self._setup.condition(when_spec, imposed_spec=imposed_spec, msg=msg)
|
||||||
|
|
||||||
|
self._setup.trigger_rules()
|
||||||
|
self._setup.effect_rules()
|
||||||
|
|
||||||
|
|
||||||
class SpecBuilder:
|
class SpecBuilder:
|
||||||
"""Class with actions to rebuild a spec from ASP results."""
|
"""Class with actions to rebuild a spec from ASP results."""
|
||||||
|
|
||||||
|
42
lib/spack/spack/test/concretize_compiler_runtimes.py
Normal file
42
lib/spack/spack/test/concretize_compiler_runtimes.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
|
||||||
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import spack.paths
|
||||||
|
import spack.repo
|
||||||
|
import spack.solver.asp
|
||||||
|
import spack.spec
|
||||||
|
from spack.version import Version
|
||||||
|
|
||||||
|
pytestmark = [pytest.mark.only_clingo("Original concretizer does not support compiler runtimes")]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def runtime_repo(config):
|
||||||
|
repo = os.path.join(spack.paths.repos_path, "compiler_runtime.test")
|
||||||
|
with spack.repo.use_repositories(repo) as mock_repo:
|
||||||
|
yield mock_repo
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def enable_runtimes():
|
||||||
|
original = spack.solver.asp.WITH_RUNTIME
|
||||||
|
spack.solver.asp.WITH_RUNTIME = True
|
||||||
|
yield
|
||||||
|
spack.solver.asp.WITH_RUNTIME = original
|
||||||
|
|
||||||
|
|
||||||
|
def test_correct_gcc_runtime_is_injected_as_dependency(runtime_repo, enable_runtimes):
|
||||||
|
s = spack.spec.Spec("a%gcc@10.2.1 ^b%gcc@4.5.0").concretized()
|
||||||
|
a, b = s["a"], s["b"]
|
||||||
|
|
||||||
|
# Both a and b should depend on the same gcc-runtime directly
|
||||||
|
assert a.dependencies("gcc-runtime") == b.dependencies("gcc-runtime")
|
||||||
|
|
||||||
|
# And the gcc-runtime version should be that of the newest gcc used in the dag.
|
||||||
|
assert a["gcc-runtime"].version == Version("10.2.1")
|
@ -44,6 +44,7 @@
|
|||||||
import spack.paths
|
import spack.paths
|
||||||
import spack.platforms
|
import spack.platforms
|
||||||
import spack.repo
|
import spack.repo
|
||||||
|
import spack.solver.asp
|
||||||
import spack.stage
|
import spack.stage
|
||||||
import spack.store
|
import spack.store
|
||||||
import spack.subprocess_context
|
import spack.subprocess_context
|
||||||
@ -57,11 +58,6 @@
|
|||||||
from spack.util.pattern import Bunch
|
from spack.util.pattern import Bunch
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session", autouse=True)
|
|
||||||
def drop_gcc_runtime():
|
|
||||||
spack.package_base.WITH_GCC_RUNTIME = False
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_configuration_fixture_run_before(request):
|
def ensure_configuration_fixture_run_before(request):
|
||||||
"""Ensure that fixture mutating the configuration run before the one where
|
"""Ensure that fixture mutating the configuration run before the one where
|
||||||
the function is called.
|
the function is called.
|
||||||
|
@ -20,6 +20,8 @@ class GccRuntime(Package):
|
|||||||
homepage = "https://gcc.gnu.org"
|
homepage = "https://gcc.gnu.org"
|
||||||
has_code = False
|
has_code = False
|
||||||
|
|
||||||
|
tags = ["runtime"]
|
||||||
|
|
||||||
maintainers("haampie")
|
maintainers("haampie")
|
||||||
|
|
||||||
license("GPL-3.0-or-later WITH GCC-exception-3.1")
|
license("GPL-3.0-or-later WITH GCC-exception-3.1")
|
||||||
@ -42,76 +44,6 @@ class GccRuntime(Package):
|
|||||||
"ubsan",
|
"ubsan",
|
||||||
]
|
]
|
||||||
|
|
||||||
for v in [
|
|
||||||
"13.2",
|
|
||||||
"13.1",
|
|
||||||
"12.3",
|
|
||||||
"12.2",
|
|
||||||
"12.1",
|
|
||||||
"11.4",
|
|
||||||
"11.3",
|
|
||||||
"11.2",
|
|
||||||
"11.1",
|
|
||||||
"10.5",
|
|
||||||
"10.4",
|
|
||||||
"10.3",
|
|
||||||
"10.2",
|
|
||||||
"10.1",
|
|
||||||
"9.5",
|
|
||||||
"9.4",
|
|
||||||
"9.3",
|
|
||||||
"9.2",
|
|
||||||
"9.1",
|
|
||||||
"8.5",
|
|
||||||
"8.4",
|
|
||||||
"8.3",
|
|
||||||
"8.2",
|
|
||||||
"8.1",
|
|
||||||
"7.5",
|
|
||||||
"7.4",
|
|
||||||
"7.3",
|
|
||||||
"7.2",
|
|
||||||
"7.1",
|
|
||||||
"6.5",
|
|
||||||
"6.4",
|
|
||||||
"6.3",
|
|
||||||
"6.2",
|
|
||||||
"6.1",
|
|
||||||
"5.5",
|
|
||||||
"5.4",
|
|
||||||
"5.3",
|
|
||||||
"5.2",
|
|
||||||
"5.1",
|
|
||||||
"4.9.4",
|
|
||||||
"4.9.3",
|
|
||||||
"4.9.2",
|
|
||||||
"4.9.1",
|
|
||||||
"4.9.0",
|
|
||||||
"4.8.5",
|
|
||||||
"4.8.4",
|
|
||||||
"4.8.3",
|
|
||||||
"4.8.2",
|
|
||||||
"4.8.1",
|
|
||||||
"4.8.0",
|
|
||||||
"4.7.4",
|
|
||||||
"4.7.3",
|
|
||||||
"4.7.2",
|
|
||||||
"4.7.1",
|
|
||||||
"4.7.0",
|
|
||||||
"4.6.4",
|
|
||||||
"4.6.3",
|
|
||||||
"4.6.2",
|
|
||||||
"4.6.1",
|
|
||||||
"4.6.0",
|
|
||||||
"4.5.4",
|
|
||||||
"4.5.3",
|
|
||||||
"4.5.2",
|
|
||||||
"4.5.1",
|
|
||||||
"4.5.0",
|
|
||||||
]:
|
|
||||||
version(v)
|
|
||||||
requires(f"%gcc@{v}", when=f"@{v}")
|
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
def install(self, spec, prefix):
|
||||||
if spec.platform in ["linux", "cray", "freebsd"]:
|
if spec.platform in ["linux", "cray", "freebsd"]:
|
||||||
libraries = self._get_libraries_elf()
|
libraries = self._get_libraries_elf()
|
||||||
|
@ -1111,3 +1111,32 @@ def detect_gdc(self):
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def runtime_constraints(cls, *, compiler, pkg):
|
||||||
|
"""Callback function to inject runtime-related rules into the solver.
|
||||||
|
|
||||||
|
Rule-injection is obtained through method calls of the ``pkg`` argument.
|
||||||
|
|
||||||
|
Documentation for this function is temporary. When the API will be in its final state,
|
||||||
|
we'll document the behavior at https://spack.readthedocs.io/en/latest/
|
||||||
|
|
||||||
|
Args:
|
||||||
|
compiler: compiler object (node attribute) currently considered
|
||||||
|
pkg: object used to forward information to the solver
|
||||||
|
"""
|
||||||
|
pkg("*").depends_on(
|
||||||
|
"gcc-runtime",
|
||||||
|
when="%gcc",
|
||||||
|
type="link",
|
||||||
|
description="If any package uses %gcc, it depends on gcc-runtime",
|
||||||
|
)
|
||||||
|
pkg("*").depends_on(
|
||||||
|
f"gcc-runtime@{str(compiler.version)}:",
|
||||||
|
when=f"%{str(compiler.spec)}",
|
||||||
|
type="link",
|
||||||
|
description=f"If any package uses %{str(compiler.spec)}, "
|
||||||
|
f"it depends on gcc-runtime@{str(compiler.version)}:",
|
||||||
|
)
|
||||||
|
# The version of gcc-runtime is the same as the %gcc used to "compile" it
|
||||||
|
pkg("gcc-runtime").requires(f"@={str(compiler.version)}", when=f"%{str(compiler.spec)}")
|
||||||
|
13
var/spack/repos/compiler_runtime.test/packages/a/package.py
Normal file
13
var/spack/repos/compiler_runtime.test/packages/a/package.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
|
||||||
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
from spack.package import *
|
||||||
|
|
||||||
|
|
||||||
|
class A(Package):
|
||||||
|
homepage = "http://www.example.com"
|
||||||
|
has_code = False
|
||||||
|
|
||||||
|
version("1.0")
|
||||||
|
depends_on("b")
|
12
var/spack/repos/compiler_runtime.test/packages/b/package.py
Normal file
12
var/spack/repos/compiler_runtime.test/packages/b/package.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
|
||||||
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
from spack.package import *
|
||||||
|
|
||||||
|
|
||||||
|
class B(Package):
|
||||||
|
homepage = "http://www.example.com"
|
||||||
|
has_code = False
|
||||||
|
|
||||||
|
version("1.0")
|
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
|
||||||
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
from spack.package import *
|
||||||
|
|
||||||
|
|
||||||
|
class GccRuntime(Package):
|
||||||
|
homepage = "https://example.com"
|
||||||
|
has_code = False
|
||||||
|
tags = ["runtime"]
|
||||||
|
requires("%gcc")
|
@ -0,0 +1,32 @@
|
|||||||
|
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
|
||||||
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
from spack.package import *
|
||||||
|
|
||||||
|
|
||||||
|
class Gcc(Package):
|
||||||
|
homepage = "http://www.example.com/"
|
||||||
|
has_code = False
|
||||||
|
|
||||||
|
version("13.2.0")
|
||||||
|
version("12.3.0")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def runtime_constraints(cls, *, compiler, pkg):
|
||||||
|
pkg("*").depends_on(
|
||||||
|
"gcc-runtime",
|
||||||
|
when="%gcc",
|
||||||
|
type="link",
|
||||||
|
description="If any package uses %gcc, it depends on gcc-runtime",
|
||||||
|
)
|
||||||
|
pkg("*").depends_on(
|
||||||
|
f"gcc-runtime@{str(compiler.version)}:",
|
||||||
|
when=f"%{str(compiler.spec)}",
|
||||||
|
type="link",
|
||||||
|
description=f"If any package uses %{str(compiler.spec)}, "
|
||||||
|
f"it depends on gcc-runtime@{str(compiler.version)}:",
|
||||||
|
)
|
||||||
|
# The version of gcc-runtime is the same as the %gcc used to "compile" it
|
||||||
|
pkg("gcc-runtime").requires(f"@={str(compiler.version)}", when=f"%{str(compiler.spec)}")
|
2
var/spack/repos/compiler_runtime.test/repo.yaml
Normal file
2
var/spack/repos/compiler_runtime.test/repo.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
repo:
|
||||||
|
namespace: compiler_runtime.test
|
Loading…
Reference in New Issue
Block a user