Compare commits

..

3 Commits

Author SHA1 Message Date
Gregory Becker
55cc228307 tests: refactor for robustness, avoid dependence on path parsing 2024-11-25 17:34:17 -08:00
Gregory Becker
0df5b8616c set code default for config:build_stage
Signed-off-by: Gregory Becker <becker33@llnl.gov>
2024-11-25 15:23:35 -08:00
Gregory Becker
ced6f984ea config.set: allow override section 2024-11-25 15:05:03 -08:00
70 changed files with 448 additions and 1169 deletions

View File

@@ -120,7 +120,7 @@ jobs:
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build & Deploy ${{ matrix.dockerfile[0] }}
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75
with:
context: dockerfiles/${{ matrix.dockerfile[0] }}
platforms: ${{ matrix.dockerfile[1] }}

View File

@@ -1326,7 +1326,6 @@ Required:
* Microsoft Visual Studio
* Python
* Git
* 7z
Optional:
* Intel Fortran (needed for some packages)
@@ -1392,13 +1391,6 @@ as the project providing Git support on Windows. This is additionally the recomm
for installing Git on Windows, a link to which can be found above. Spack requires the
utilities vendored by this project.
"""
7zip
"""
A tool for extracting ``.xz`` files is required for extracting source tarballs. The latest 7zip
can be located at https://sourceforge.net/projects/sevenzip/.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Step 2: Install and setup Spack
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -24,7 +24,6 @@
Callable,
Deque,
Dict,
Generator,
Iterable,
List,
Match,
@@ -2773,6 +2772,22 @@ def prefixes(path):
return paths
@system_path_filter
def md5sum(file):
"""Compute the MD5 sum of a file.
Args:
file (str): file to be checksummed
Returns:
MD5 sum of the file's content
"""
md5 = hashlib.md5()
with open(file, "rb") as f:
md5.update(f.read())
return md5.digest()
@system_path_filter
def remove_directory_contents(dir):
"""Remove all contents of a directory."""
@@ -2823,25 +2838,6 @@ def temporary_dir(
remove_directory_contents(tmp_dir)
@contextmanager
def edit_in_place_through_temporary_file(file_path: str) -> Generator[str, None, None]:
"""Context manager for modifying ``file_path`` in place, preserving its inode and hardlinks,
for functions or external tools that do not support in-place editing. Notice that this function
is unsafe in that it works with paths instead of a file descriptors, but this is by design,
since we assume the call site will create a new inode at the same path."""
tmp_fd, tmp_path = tempfile.mkstemp(
dir=os.path.dirname(file_path), prefix=f"{os.path.basename(file_path)}."
)
# windows cannot replace a file with open fds, so close since the call site needs to replace.
os.close(tmp_fd)
try:
shutil.copyfile(file_path, tmp_path, follow_symlinks=True)
yield tmp_path
shutil.copyfile(tmp_path, file_path, follow_symlinks=True)
finally:
os.unlink(tmp_path)
def filesummary(path, print_bytes=16) -> Tuple[int, bytes]:
"""Create a small summary of the given file. Does not error
when file does not exist.

View File

@@ -2334,9 +2334,7 @@ def is_backup_file(file):
if not codesign:
return
for binary in changed_files:
# preserve the original inode by running codesign on a copy
with fsys.edit_in_place_through_temporary_file(binary) as tmp_binary:
codesign("-fs-", tmp_binary)
codesign("-fs-", binary)
# If we are installing back to the same location
# relocate the sbang location if the spack directory changed

View File

@@ -9,7 +9,7 @@
import re
import sys
from itertools import chain
from typing import Any, List, Optional, Tuple
from typing import Any, List, Optional, Set, Tuple
import llnl.util.filesystem as fs
from llnl.util.lang import stable_partition
@@ -21,7 +21,6 @@
import spack.phase_callbacks
import spack.spec
import spack.util.prefix
from spack import traverse
from spack.directives import build_system, conflicts, depends_on, variant
from spack.multimethod import when
from spack.util.environment import filter_system_paths
@@ -167,18 +166,15 @@ def _values(x):
def get_cmake_prefix_path(pkg: spack.package_base.PackageBase) -> List[str]:
"""Obtain the CMAKE_PREFIX_PATH entries for a package, based on the cmake_prefix_path package
attribute of direct build/test and transitive link dependencies."""
edges = traverse.traverse_topo_edges_generator(
traverse.with_artificial_edges([pkg.spec]),
visitor=traverse.MixedDepthVisitor(
direct=dt.BUILD | dt.TEST, transitive=dt.LINK, key=traverse.by_dag_hash
),
key=traverse.by_dag_hash,
root=False,
all_edges=False, # cover all nodes, not all edges
)
ordered_specs = [edge.spec for edge in edges]
# Add direct build/test deps
selected: Set[str] = {s.dag_hash() for s in pkg.spec.dependencies(deptype=dt.BUILD | dt.TEST)}
# Add transitive link deps
selected.update(s.dag_hash() for s in pkg.spec.traverse(root=False, deptype=dt.LINK))
# Separate out externals so they do not shadow Spack prefixes
externals, spack_built = stable_partition((s for s in ordered_specs), lambda x: x.external)
externals, spack_built = stable_partition(
(s for s in pkg.spec.traverse(root=False, order="topo") if s.dag_hash() in selected),
lambda x: x.external,
)
return filter_system_paths(
path for spec in chain(spack_built, externals) for path in spec.package.cmake_prefix_paths

View File

@@ -124,8 +124,8 @@ def setup_custom_environment(self, pkg, env):
# Edge cases for Intel's oneAPI compilers when using the legacy classic compilers:
# Always pass flags to disable deprecation warnings, since these warnings can
# confuse tools that parse the output of compiler commands (e.g. version checks).
if self.real_version >= Version("2021") and self.real_version < Version("2024"):
if self.real_version >= Version("2021") and self.real_version <= Version("2023"):
env.append_flags("SPACK_ALWAYS_CFLAGS", "-diag-disable=10441")
env.append_flags("SPACK_ALWAYS_CXXFLAGS", "-diag-disable=10441")
if self.real_version >= Version("2021") and self.real_version < Version("2025"):
if self.real_version >= Version("2021") and self.real_version <= Version("2024"):
env.append_flags("SPACK_ALWAYS_FFLAGS", "-diag-disable=10448")

View File

@@ -155,10 +155,10 @@ def setup_custom_environment(self, pkg, env):
# icx+icpx+ifx or icx+icpx+ifort. But to be on the safe side (some users may
# want to try to swap icpx against icpc, for example), and since the Intel LLVM
# compilers accept these diag-disable flags, we apply them for all compilers.
if self.real_version >= Version("2021") and self.real_version < Version("2024"):
if self.real_version >= Version("2021") and self.real_version <= Version("2023"):
env.append_flags("SPACK_ALWAYS_CFLAGS", "-diag-disable=10441")
env.append_flags("SPACK_ALWAYS_CXXFLAGS", "-diag-disable=10441")
if self.real_version >= Version("2021") and self.real_version < Version("2025"):
if self.real_version >= Version("2021") and self.real_version <= Version("2024"):
env.append_flags("SPACK_ALWAYS_FFLAGS", "-diag-disable=10448")
# 2024 release bumped the libsycl version because of an ABI

View File

@@ -672,11 +672,12 @@ def set(self, path: str, value: Any, scope: Optional[str] = None) -> None:
return
parts = process_config_path(path)
section = parts.pop(0)
section = parts[0]
section_data = self.get_config(section, scope=scope)
data = section_data
full_data = {section: section_data}
data = full_data
while len(parts) > 1:
key = parts.pop(0)
@@ -699,7 +700,7 @@ def set(self, path: str, value: Any, scope: Optional[str] = None) -> None:
# update new value
data[parts[0]] = value
self.update_config(section, section_data, scope=scope)
self.update_config(section, full_data[section], scope=scope)
def __iter__(self):
"""Iterate over scopes in this configuration."""

View File

@@ -13,7 +13,6 @@
import macholib.mach_o
import macholib.MachO
import llnl.util.filesystem as fs
import llnl.util.lang
import llnl.util.tty as tty
from llnl.util.lang import memoized
@@ -276,10 +275,10 @@ def modify_macho_object(cur_path, rpaths, deps, idpath, paths_to_paths):
# Deduplicate and flatten
args = list(itertools.chain.from_iterable(llnl.util.lang.dedupe(args)))
install_name_tool = executable.Executable("install_name_tool")
if args:
with fs.edit_in_place_through_temporary_file(cur_path) as temp_path:
install_name_tool(*args, temp_path)
args.append(str(cur_path))
install_name_tool = executable.Executable("install_name_tool")
install_name_tool(*args)
def macholib_get_paths(cur_path):
@@ -718,8 +717,8 @@ def fixup_macos_rpath(root, filename):
# No fixes needed
return False
with fs.edit_in_place_through_temporary_file(abspath) as temp_path:
executable.Executable("install_name_tool")(*args, temp_path)
args.append(abspath)
executable.Executable("install_name_tool")(*args)
return True

View File

@@ -176,13 +176,14 @@ def _resolve_paths(candidates):
# Cached stage path root
_stage_root = None
_default_stage_config = ["$tmpdir/$user/spack-stage", "$user_cache_path/stage"]
def get_stage_root():
global _stage_root
if _stage_root is None:
candidates = spack.config.get("config:build_stage")
candidates = spack.config.get("config:build_stage", _default_stage_config)
if isinstance(candidates, str):
candidates = [candidates]

View File

@@ -1208,8 +1208,16 @@ def test_internal_config_list_override(mock_low_high_config, write_config_file):
def test_set_section_override(mock_low_high_config, write_config_file):
write_config_file("config", config_merge_list, "low")
wanted_list = config_override_list["config"]["build_stage:"]
# Ensure test validity:
assert wanted_list != mock_low_high_config.get("config:build_stage")
# Test both bare section with full value and section override in path
with spack.config.override("config::build_stage", wanted_list):
assert mock_low_high_config.get("config:build_stage") == wanted_list
with spack.config.override("config::", {"build_stage": wanted_list}):
assert mock_low_high_config.get("config:build_stage") == wanted_list
assert config_merge_list["config"]["build_stage"] == mock_low_high_config.get(
"config:build_stage"
)

View File

@@ -1249,14 +1249,3 @@ def test_find_input_types(tmp_path: pathlib.Path):
with pytest.raises(TypeError):
fs.find(1, "file.txt") # type: ignore
def test_edit_in_place_through_temporary_file(tmp_path):
(tmp_path / "example.txt").write_text("Hello")
current_ino = os.stat(tmp_path / "example.txt").st_ino
with fs.edit_in_place_through_temporary_file(tmp_path / "example.txt") as temporary:
os.unlink(temporary)
with open(temporary, "w") as f:
f.write("World")
assert (tmp_path / "example.txt").read_text() == "World"
assert os.stat(tmp_path / "example.txt").st_ino == current_ino

View File

@@ -754,6 +754,18 @@ def test_get_stage_root_bad_path(self, clear_stage_root):
# Make sure the cached stage path values are unchanged.
assert spack.stage._stage_root is None
def test_get_stage_root_empty(self, clear_stage_root, monkeypatch, tmpdir):
expected = str(tmpdir)
monkeypatch.setattr(spack.stage, "_default_stage_config", [expected])
# build stage set to empty by user is respected and errors
with spack.config.override("config:build_stage::", []):
with pytest.raises(spack.stage.StageError):
spack.stage.get_stage_root()
# No build stage set (config section set to empty) uses default
with spack.config.override("config::", {}):
assert spack.stage.get_stage_root() == expected
@pytest.mark.parametrize(
"path,purged",
[

View File

@@ -20,8 +20,9 @@ def create_dag(nodes, edges):
"""
specs = {name: Spec(name) for name in nodes}
for parent, child, deptypes in edges:
depflag = deptypes if isinstance(deptypes, dt.DepFlag) else dt.canonicalize(deptypes)
specs[parent].add_dependency_edge(specs[child], depflag=depflag, virtuals=())
specs[parent].add_dependency_edge(
specs[child], depflag=dt.canonicalize(deptypes), virtuals=()
)
return specs
@@ -453,61 +454,3 @@ def test_topo_is_bfs_for_trees(cover):
assert list(traverse.traverse_nodes([binary_tree["A"]], order="topo", cover=cover)) == list(
traverse.traverse_nodes([binary_tree["A"]], order="breadth", cover=cover)
)
@pytest.mark.parametrize("roots", [["A"], ["A", "B"], ["B", "A"], ["A", "B", "A"]])
@pytest.mark.parametrize("order", ["breadth", "post", "pre"])
@pytest.mark.parametrize("include_root", [True, False])
def test_mixed_depth_visitor(roots, order, include_root):
"""Test that the MixedDepthVisitor lists unique edges that are reachable either directly from
roots through build type edges, or transitively through link type edges. The tests ensures that
unique edges are listed exactly once."""
my_graph = create_dag(
nodes=["A", "B", "C", "D", "E", "F", "G", "H", "I"],
edges=(
("A", "B", dt.LINK | dt.RUN),
("A", "C", dt.BUILD),
("A", "D", dt.BUILD | dt.RUN),
("A", "H", dt.LINK),
("A", "I", dt.RUN),
("B", "D", dt.BUILD | dt.LINK),
("C", "E", dt.BUILD | dt.LINK | dt.RUN),
("D", "F", dt.LINK),
("D", "G", dt.BUILD | dt.RUN),
("H", "B", dt.LINK),
),
)
starting_points = traverse.with_artificial_edges([my_graph[root] for root in roots])
visitor = traverse.MixedDepthVisitor(direct=dt.BUILD, transitive=dt.LINK)
if order == "pre":
edges = traverse.traverse_depth_first_edges_generator(
starting_points, visitor, post_order=False, root=include_root
)
elif order == "post":
edges = traverse.traverse_depth_first_edges_generator(
starting_points, visitor, post_order=True, root=include_root
)
elif order == "breadth":
edges = traverse.traverse_breadth_first_edges_generator(
starting_points, visitor, root=include_root
)
artificial_edges = [(None, root) for root in roots] if include_root else []
simple_edges = [
(None if edge.parent is None else edge.parent.name, edge.spec.name) for edge in edges
]
# make sure that every edge is listed exactly once and that the right edges are listed
assert len(simple_edges) == len(set(simple_edges))
assert set(simple_edges) == {
# the roots
*artificial_edges,
("A", "B"),
("A", "C"),
("A", "D"),
("A", "H"),
("B", "D"),
("D", "F"),
("H", "B"),
}

View File

@@ -607,9 +607,6 @@ def test_stringify_version(version_str):
v.string = None
assert str(v) == version_str
v.string = None
assert v.string == version_str
def test_len():
a = Version("1.2.3.4")

View File

@@ -4,7 +4,7 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from collections import defaultdict
from typing import Any, Callable, List, NamedTuple, Set, Union
from typing import NamedTuple, Union
import spack.deptypes as dt
import spack.spec
@@ -115,64 +115,6 @@ def neighbors(self, item):
return self.visitor.neighbors(item)
class MixedDepthVisitor:
"""Visits all unique edges of the sub-DAG induced by direct dependencies of type ``direct``
and transitive dependencies of type ``transitive``. An example use for this is traversing build
type dependencies non-recursively, and link dependencies recursively."""
def __init__(
self,
*,
direct: dt.DepFlag,
transitive: dt.DepFlag,
key: Callable[["spack.spec.Spec"], Any] = id,
) -> None:
self.direct_type = direct
self.transitive_type = transitive
self.key = key
self.seen: Set[Any] = set()
self.seen_roots: Set[Any] = set()
def accept(self, item: EdgeAndDepth) -> bool:
# Do not accept duplicate root nodes. This only happens if the user starts iterating from
# multiple roots and lists one of the roots multiple times.
if item.edge.parent is None:
node_id = self.key(item.edge.spec)
if node_id in self.seen_roots:
return False
self.seen_roots.add(node_id)
return True
def neighbors(self, item: EdgeAndDepth) -> List[EdgeAndDepth]:
# If we're here through an artificial source node, it's a root, and we return all
# direct_type and transitive_type edges. If we're here through a transitive_type edge, we
# return all transitive_type edges. To avoid returning the same edge twice:
# 1. If we had already encountered the current node through a transitive_type edge, we
# don't need to return transitive_type edges again.
# 2. If we encounter the current node through a direct_type edge, and we had already seen
# it through a transitive_type edge, only return the non-transitive_type, direct_type
# edges.
node_id = self.key(item.edge.spec)
seen = node_id in self.seen
is_root = item.edge.parent is None
follow_transitive = is_root or bool(item.edge.depflag & self.transitive_type)
follow = self.direct_type if is_root else dt.NONE
if follow_transitive and not seen:
follow |= self.transitive_type
self.seen.add(node_id)
elif follow == dt.NONE:
return []
edges = item.edge.spec.edges_to_dependencies(depflag=follow)
# filter direct_type edges already followed before becuase they were also transitive_type.
if seen:
edges = [edge for edge in edges if not edge.depflag & self.transitive_type]
return sort_edges(edges)
def get_visitor_from_args(
cover, direction, depflag: Union[dt.DepFlag, dt.DepTypes], key=id, visited=None, visitor=None
):
@@ -400,7 +342,9 @@ def traverse_topo_edges_generator(edges, visitor, key=id, root=True, all_edges=F
# maps parent identifier to a list of edges, where None is a special identifier
# for the artificial root/source.
node_to_edges = defaultdict(list)
for edge in traverse_breadth_first_edges_generator(edges, visitor, root=True, depth=False):
for edge in traverse_breadth_first_edges_generator(
edges, CoverEdgesVisitor(visitor, key=key), root=True, depth=False
):
in_edge_count[key(edge.spec)] += 1
parent_id = key(edge.parent) if edge.parent is not None else None
node_to_edges[parent_id].append(edge)
@@ -478,9 +422,9 @@ def traverse_edges(
elif order not in ("post", "pre", "breadth"):
raise ValueError(f"Unknown order {order}")
# In topo traversal we need to construct a sub-DAG including all unique edges even if we are
# yielding a subset of them, hence "edges".
_cover = "edges" if order == "topo" else cover
# In topo traversal we need to construct a sub-DAG including all edges even if we are yielding
# a subset of them, hence "paths".
_cover = "paths" if order == "topo" else cover
visitor = get_visitor_from_args(_cover, direction, deptype, key, visited)
root_edges = with_artificial_edges(specs)

View File

@@ -7,7 +7,7 @@
import re
import struct
from struct import calcsize, unpack, unpack_from
from typing import BinaryIO, Callable, Dict, List, NamedTuple, Optional, Pattern, Tuple
from typing import BinaryIO, Dict, List, NamedTuple, Optional, Pattern, Tuple
class ElfHeader(NamedTuple):
@@ -476,31 +476,6 @@ def get_interpreter(path: str) -> Optional[str]:
return None
def _delete_dynamic_array_entry(
f: BinaryIO, elf: ElfFile, should_delete: Callable[[int, int], bool]
) -> None:
f.seek(elf.pt_dynamic_p_offset)
dynamic_array_fmt = elf.byte_order + ("qQ" if elf.is_64_bit else "lL")
dynamic_array_size = calcsize(dynamic_array_fmt)
new_offset = elf.pt_dynamic_p_offset # points to the new dynamic array
old_offset = elf.pt_dynamic_p_offset # points to the current dynamic array
for _ in range(elf.pt_dynamic_p_filesz // dynamic_array_size):
data = read_exactly(f, dynamic_array_size, "Malformed dynamic array entry")
tag, val = unpack(dynamic_array_fmt, data)
if tag == ELF_CONSTANTS.DT_NULL or not should_delete(tag, val):
if new_offset != old_offset:
f.seek(new_offset)
f.write(data)
f.seek(old_offset + dynamic_array_size)
new_offset += dynamic_array_size
if tag == ELF_CONSTANTS.DT_NULL:
break
old_offset += dynamic_array_size
def delete_rpath(path: str) -> None:
"""Modifies a binary to remove the rpath. It zeros out the rpath string and also drops the
DT_R(UN)PATH entry from the dynamic section, so it doesn't show up in 'readelf -d file', nor
@@ -517,22 +492,29 @@ def delete_rpath(path: str) -> None:
f.seek(rpath_offset)
f.write(new_rpath_string)
# Delete DT_RPATH / DT_RUNPATH entries from the dynamic section
_delete_dynamic_array_entry(
f, elf, lambda tag, _: tag == ELF_CONSTANTS.DT_RPATH or tag == ELF_CONSTANTS.DT_RUNPATH
)
# Next update the dynamic array
f.seek(elf.pt_dynamic_p_offset)
dynamic_array_fmt = elf.byte_order + ("qQ" if elf.is_64_bit else "lL")
dynamic_array_size = calcsize(dynamic_array_fmt)
new_offset = elf.pt_dynamic_p_offset # points to the new dynamic array
old_offset = elf.pt_dynamic_p_offset # points to the current dynamic array
for _ in range(elf.pt_dynamic_p_filesz // dynamic_array_size):
data = read_exactly(f, dynamic_array_size, "Malformed dynamic array entry")
tag, _ = unpack(dynamic_array_fmt, data)
# Overwrite any entry that is not DT_RPATH or DT_RUNPATH, including DT_NULL
if tag != ELF_CONSTANTS.DT_RPATH and tag != ELF_CONSTANTS.DT_RUNPATH:
if new_offset != old_offset:
f.seek(new_offset)
f.write(data)
f.seek(old_offset + dynamic_array_size)
new_offset += dynamic_array_size
def delete_needed_from_elf(f: BinaryIO, elf: ElfFile, needed: bytes) -> None:
"""Delete a needed library from the dynamic section of an ELF file"""
if not elf.has_needed or needed not in elf.dt_needed_strs:
return
# End of the dynamic array
if tag == ELF_CONSTANTS.DT_NULL:
break
offset = elf.dt_needed_strtab_offsets[elf.dt_needed_strs.index(needed)]
_delete_dynamic_array_entry(
f, elf, lambda tag, val: tag == ELF_CONSTANTS.DT_NEEDED and val == offset
)
old_offset += dynamic_array_size
class CStringType:

View File

@@ -13,7 +13,7 @@
import sys
from llnl.util import tty
from llnl.util.filesystem import edit_in_place_through_temporary_file
from llnl.util.filesystem import join_path
from llnl.util.lang import memoized
from spack.util.executable import Executable, which
@@ -81,11 +81,12 @@ def fix_darwin_install_name(path):
Parameters:
path (str): directory in which .dylib files are located
"""
libs = glob.glob(os.path.join(path, "*.dylib"))
install_name_tool = Executable("install_name_tool")
otool = Executable("otool")
libs = glob.glob(join_path(path, "*.dylib"))
for lib in libs:
args = ["-id", lib]
# fix install name first:
install_name_tool = Executable("install_name_tool")
install_name_tool("-id", lib, lib)
otool = Executable("otool")
long_deps = otool("-L", lib, output=str).split("\n")
deps = [dep.partition(" ")[0][1::] for dep in long_deps[2:-1]]
# fix all dependencies:
@@ -97,8 +98,5 @@ def fix_darwin_install_name(path):
# but we don't know builddir (nor how symbolic links look
# in builddir). We thus only compare the basenames.
if os.path.basename(dep) == os.path.basename(loc):
args.extend(("-change", dep, loc))
install_name_tool("-change", dep, loc, lib)
break
with edit_in_place_through_temporary_file(lib) as tmp:
install_name_tool(*args, tmp)

View File

@@ -25,13 +25,11 @@
)
from .version_types import (
ClosedOpenRange,
ConcreteVersion,
GitVersion,
StandardVersion,
Version,
VersionList,
VersionRange,
VersionType,
_next_version,
_prev_version,
from_string,
@@ -42,23 +40,21 @@
any_version: VersionList = VersionList([":"])
__all__ = [
"ClosedOpenRange",
"ConcreteVersion",
"EmptyRangeError",
"GitVersion",
"StandardVersion",
"Version",
"VersionChecksumError",
"VersionError",
"VersionList",
"VersionLookupError",
"VersionRange",
"VersionType",
"_next_version",
"_prev_version",
"any_version",
"from_string",
"infinity_versions",
"is_git_version",
"ver",
"from_string",
"is_git_version",
"infinity_versions",
"_prev_version",
"_next_version",
"VersionList",
"ClosedOpenRange",
"StandardVersion",
"GitVersion",
"VersionError",
"VersionChecksumError",
"VersionLookupError",
"EmptyRangeError",
"any_version",
]

View File

@@ -3,9 +3,10 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import numbers
import re
from bisect import bisect_left
from typing import Dict, Iterable, Iterator, List, Optional, Tuple, Union
from typing import List, Optional, Tuple, Union
from spack.util.spack_yaml import syaml_dict
@@ -31,44 +32,26 @@
class VersionStrComponent:
"""Internal representation of the string (non-integer) components of Spack versions.
Versions comprise string and integer components (see ``SEGMENT_REGEX`` above).
This represents a string component, which is either some component consisting only
of alphabetical characters, *or* a special "infinity version" like ``main``,
``develop``, ``master``, etc.
For speed, Spack versions are designed to map to Python tuples, so that we can use
Python's fast lexicographic tuple comparison on them. ``VersionStrComponent`` is
designed to work as a component in these version tuples, and as such must compare
directly with ``int`` or other ``VersionStrComponent`` objects.
"""
__slots__ = ["data"]
data: Union[int, str]
def __init__(self, data: Union[int, str]):
def __init__(self, data):
# int for infinity index, str for literal.
self.data = data
self.data: Union[int, str] = data
@staticmethod
def from_string(string: str) -> "VersionStrComponent":
value: Union[int, str] = string
def from_string(string):
if len(string) >= iv_min_len:
try:
value = infinity_versions.index(string)
string = infinity_versions.index(string)
except ValueError:
pass
return VersionStrComponent(value)
return VersionStrComponent(string)
def __hash__(self) -> int:
def __hash__(self):
return hash(self.data)
def __str__(self) -> str:
def __str__(self):
return (
("infinity" if self.data >= len(infinity_versions) else infinity_versions[self.data])
if isinstance(self.data, int)
@@ -78,61 +61,38 @@ def __str__(self) -> str:
def __repr__(self) -> str:
return f'VersionStrComponent("{self}")'
def __eq__(self, other: object) -> bool:
def __eq__(self, other):
return isinstance(other, VersionStrComponent) and self.data == other.data
# ignore typing for certain parts of these methods b/c a) they are performance-critical, and
# b) mypy isn't smart enough to figure out that if l_inf and r_inf are the same, comparing
# self.data and other.data is type safe.
def __lt__(self, other: object) -> bool:
l_inf = isinstance(self.data, int)
def __lt__(self, other):
lhs_inf = isinstance(self.data, int)
if isinstance(other, int):
return not l_inf
r_inf = isinstance(other.data, int) # type: ignore
return (not l_inf and r_inf) if l_inf ^ r_inf else self.data < other.data # type: ignore
return not lhs_inf
rhs_inf = isinstance(other.data, int)
return (not lhs_inf and rhs_inf) if lhs_inf ^ rhs_inf else self.data < other.data
def __gt__(self, other: object) -> bool:
l_inf = isinstance(self.data, int)
if isinstance(other, int):
return l_inf
r_inf = isinstance(other.data, int) # type: ignore
return (l_inf and not r_inf) if l_inf ^ r_inf else self.data > other.data # type: ignore
def __le__(self, other: object) -> bool:
def __le__(self, other):
return self < other or self == other
def __ge__(self, other: object) -> bool:
def __gt__(self, other):
lhs_inf = isinstance(self.data, int)
if isinstance(other, int):
return lhs_inf
rhs_inf = isinstance(other.data, int)
return (lhs_inf and not rhs_inf) if lhs_inf ^ rhs_inf else self.data > other.data
def __ge__(self, other):
return self > other or self == other
# Tuple types that make up the internal representation of StandardVersion.
# We use Tuples so that Python can quickly compare versions.
#: Version components are integers for numeric parts, VersionStrComponents for string parts.
VersionComponentTuple = Tuple[Union[int, VersionStrComponent], ...]
#: A Prerelease identifier is a constant for alpha/beta/rc/final and one optional number.
#: Most versions will have this set to ``(FINAL,)``. Prereleases will have some other
#: initial constant followed by a number, e.g. ``(RC, 1)``.
PrereleaseTuple = Tuple[int, ...]
#: Actual version tuple, including the split version number itself and the prerelease,
#: all represented as tuples.
VersionTuple = Tuple[VersionComponentTuple, PrereleaseTuple]
#: Separators from a parsed version.
SeparatorTuple = Tuple[str, ...]
def parse_string_components(string: str) -> Tuple[VersionTuple, SeparatorTuple]:
"""Parse a string into a ``VersionTuple`` and ``SeparatorTuple``."""
def parse_string_components(string: str) -> Tuple[tuple, tuple]:
string = string.strip()
if string and not VALID_VERSION.match(string):
raise ValueError("Bad characters in version string: %s" % string)
segments = SEGMENT_REGEX.findall(string)
separators: Tuple[str] = tuple(m[2] for m in segments)
separators = tuple(m[2] for m in segments)
prerelease: Tuple[int, ...]
# <version>(alpha|beta|rc)<number>
@@ -149,150 +109,63 @@ def parse_string_components(string: str) -> Tuple[VersionTuple, SeparatorTuple]:
else:
prerelease = (FINAL,)
release: VersionComponentTuple = tuple(
int(m[0]) if m[0] else VersionStrComponent.from_string(m[1]) for m in segments
)
release = tuple(int(m[0]) if m[0] else VersionStrComponent.from_string(m[1]) for m in segments)
return (release, prerelease), separators
class VersionType:
"""Base type for all versions in Spack (ranges, lists, regular versions, and git versions).
Versions in Spack behave like sets, and support some basic set operations. There are
four subclasses of ``VersionType``:
* ``StandardVersion``: a single, concrete version, e.g. 3.4.5 or 5.4b0.
* ``GitVersion``: subclass of ``StandardVersion`` for handling git repositories.
* ``ClosedOpenRange``: an inclusive version range, closed or open, e.g. ``3.0:5.0``,
``3.0:``, or ``:5.0``
* ``VersionList``: An ordered list of any of the above types.
Notably, when Spack parses a version, it's always a range *unless* specified with
``@=`` to make it concrete.
"""
def intersection(self, other: "VersionType") -> "VersionType":
"""Any versions contained in both self and other, or empty VersionList if no overlap."""
raise NotImplementedError
def intersects(self, other: "VersionType") -> bool:
"""Whether self and other overlap."""
raise NotImplementedError
def overlaps(self, other: "VersionType") -> bool:
"""Whether self and other overlap (same as ``intersects()``)."""
return self.intersects(other)
def satisfies(self, other: "VersionType") -> bool:
"""Whether self is entirely contained in other."""
raise NotImplementedError
def union(self, other: "VersionType") -> "VersionType":
"""Return a VersionType containing self and other."""
raise NotImplementedError
# We can use SupportsRichComparisonT in Python 3.8 or later, but alas in 3.6 we need
# to write all the operators out
def __eq__(self, other: object) -> bool:
raise NotImplementedError
def __lt__(self, other: object) -> bool:
raise NotImplementedError
def __gt__(self, other: object) -> bool:
raise NotImplementedError
def __ge__(self, other: object) -> bool:
raise NotImplementedError
def __le__(self, other: object) -> bool:
raise NotImplementedError
def __hash__(self) -> int:
raise NotImplementedError
class ConcreteVersion:
pass
class ConcreteVersion(VersionType):
"""Base type for versions that represents a single (non-range or list) version."""
def _stringify_version(versions: VersionTuple, separators: Tuple[str, ...]) -> str:
"""Create a string representation from version components."""
def _stringify_version(versions: Tuple[tuple, tuple], separators: tuple) -> str:
release, prerelease = versions
components = [f"{rel}{sep}" for rel, sep in zip(release, separators)]
string = ""
for i in range(len(release)):
string += f"{release[i]}{separators[i]}"
if prerelease[0] != FINAL:
components.append(PRERELEASE_TO_STRING[prerelease[0]])
if len(prerelease) > 1:
components.append(separators[len(release)])
components.append(str(prerelease[1]))
return "".join(components)
string += f"{PRERELEASE_TO_STRING[prerelease[0]]}{separators[len(release)]}"
if len(prerelease) > 1:
string += str(prerelease[1])
return string
class StandardVersion(ConcreteVersion):
"""Class to represent versions"""
__slots__ = ["version", "_string", "separators"]
__slots__ = ["version", "string", "separators"]
_string: str
version: VersionTuple
separators: Tuple[str, ...]
def __init__(self, string: str, version: VersionTuple, separators: Tuple[str, ...]):
"""Create a StandardVersion from a string and parsed version components.
Arguments:
string: The original version string, or ``""`` if the it is not available.
version: A tuple as returned by ``parse_string_components()``. Contains two tuples:
one with alpha or numeric components and another with prerelease components.
separators: separators parsed from the original version string.
If constructed with ``string=""``, the string will be lazily constructed from components
when ``str()`` is called.
"""
self._string = string
def __init__(self, string: Optional[str], version: Tuple[tuple, tuple], separators: tuple):
self.string = string
self.version = version
self.separators = separators
@staticmethod
def from_string(string: str) -> "StandardVersion":
def from_string(string: str):
return StandardVersion(string, *parse_string_components(string))
@staticmethod
def typemin() -> "StandardVersion":
def typemin():
return _STANDARD_VERSION_TYPEMIN
@staticmethod
def typemax() -> "StandardVersion":
def typemax():
return _STANDARD_VERSION_TYPEMAX
@property
def string(self) -> str:
if not self._string:
self._string = _stringify_version(self.version, self.separators)
return self._string
@string.setter
def string(self, string) -> None:
self._string = string
def __bool__(self) -> bool:
def __bool__(self):
return True
def __eq__(self, other: object) -> bool:
def __eq__(self, other):
if isinstance(other, StandardVersion):
return self.version == other.version
return False
def __ne__(self, other: object) -> bool:
def __ne__(self, other):
if isinstance(other, StandardVersion):
return self.version != other.version
return True
def __lt__(self, other: object) -> bool:
def __lt__(self, other):
if isinstance(other, StandardVersion):
return self.version < other.version
if isinstance(other, ClosedOpenRange):
@@ -300,7 +173,7 @@ def __lt__(self, other: object) -> bool:
return self <= other.lo
return NotImplemented
def __le__(self, other: object) -> bool:
def __le__(self, other):
if isinstance(other, StandardVersion):
return self.version <= other.version
if isinstance(other, ClosedOpenRange):
@@ -308,7 +181,7 @@ def __le__(self, other: object) -> bool:
return self <= other.lo
return NotImplemented
def __ge__(self, other: object) -> bool:
def __ge__(self, other):
if isinstance(other, StandardVersion):
return self.version >= other.version
if isinstance(other, ClosedOpenRange):
@@ -316,25 +189,25 @@ def __ge__(self, other: object) -> bool:
return self > other.lo
return NotImplemented
def __gt__(self, other: object) -> bool:
def __gt__(self, other):
if isinstance(other, StandardVersion):
return self.version > other.version
if isinstance(other, ClosedOpenRange):
return self > other.lo
return NotImplemented
def __iter__(self) -> Iterator:
def __iter__(self):
return iter(self.version[0])
def __len__(self) -> int:
def __len__(self):
return len(self.version[0])
def __getitem__(self, idx: Union[int, slice]):
def __getitem__(self, idx):
cls = type(self)
release = self.version[0]
if isinstance(idx, int):
if isinstance(idx, numbers.Integral):
return release[idx]
elif isinstance(idx, slice):
@@ -347,38 +220,45 @@ def __getitem__(self, idx: Union[int, slice]):
if string_arg:
string_arg.pop() # We don't need the last separator
return cls.from_string("".join(string_arg))
string_arg = "".join(string_arg)
return cls.from_string(string_arg)
else:
return StandardVersion.from_string("")
raise TypeError(f"{cls.__name__} indices must be integers or slices")
message = "{cls.__name__} indices must be integers"
raise TypeError(message.format(cls=cls))
def __str__(self) -> str:
return self.string
def __str__(self):
return self.string or _stringify_version(self.version, self.separators)
def __repr__(self) -> str:
# Print indirect repr through Version(...)
return f'Version("{str(self)}")'
def __hash__(self) -> int:
def __hash__(self):
# If this is a final release, do not hash the prerelease part for backward compat.
return hash(self.version if self.is_prerelease() else self.version[0])
def __contains__(rhs, lhs) -> bool:
def __contains__(rhs, lhs):
# We should probably get rid of `x in y` for versions, since
# versions still have a dual interpretation as singleton sets
# or elements. x in y should be: is the lhs-element in the
# rhs-set. Instead this function also does subset checks.
if isinstance(lhs, VersionType):
if isinstance(lhs, (StandardVersion, ClosedOpenRange, VersionList)):
return lhs.satisfies(rhs)
raise TypeError(f"'in' not supported for instances of {type(lhs)}")
raise ValueError(lhs)
def intersects(self, other: VersionType) -> bool:
def intersects(self, other: Union["StandardVersion", "GitVersion", "ClosedOpenRange"]) -> bool:
if isinstance(other, StandardVersion):
return self == other
return other.intersects(self)
def satisfies(self, other: VersionType) -> bool:
def overlaps(self, other) -> bool:
return self.intersects(other)
def satisfies(
self, other: Union["ClosedOpenRange", "StandardVersion", "GitVersion", "VersionList"]
) -> bool:
if isinstance(other, GitVersion):
return False
@@ -391,19 +271,19 @@ def satisfies(self, other: VersionType) -> bool:
if isinstance(other, VersionList):
return other.intersects(self)
raise NotImplementedError
return NotImplemented
def union(self, other: VersionType) -> VersionType:
def union(self, other: Union["ClosedOpenRange", "StandardVersion"]):
if isinstance(other, StandardVersion):
return self if self == other else VersionList([self, other])
return other.union(self)
def intersection(self, other: VersionType) -> VersionType:
def intersection(self, other: Union["ClosedOpenRange", "StandardVersion"]):
if isinstance(other, StandardVersion):
return self if self == other else VersionList()
return other.intersection(self)
def isdevelop(self) -> bool:
def isdevelop(self):
"""Triggers on the special case of the `@develop-like` version."""
return any(
isinstance(p, VersionStrComponent) and isinstance(p.data, int) for p in self.version[0]
@@ -424,7 +304,7 @@ def dotted_numeric_string(self) -> str:
return ".".join(str(v) for v in numeric)
@property
def dotted(self) -> "StandardVersion":
def dotted(self):
"""The dotted representation of the version.
Example:
@@ -438,7 +318,7 @@ def dotted(self) -> "StandardVersion":
return type(self).from_string(self.string.replace("-", ".").replace("_", "."))
@property
def underscored(self) -> "StandardVersion":
def underscored(self):
"""The underscored representation of the version.
Example:
@@ -453,7 +333,7 @@ def underscored(self) -> "StandardVersion":
return type(self).from_string(self.string.replace(".", "_").replace("-", "_"))
@property
def dashed(self) -> "StandardVersion":
def dashed(self):
"""The dashed representation of the version.
Example:
@@ -467,7 +347,7 @@ def dashed(self) -> "StandardVersion":
return type(self).from_string(self.string.replace(".", "-").replace("_", "-"))
@property
def joined(self) -> "StandardVersion":
def joined(self):
"""The joined representation of the version.
Example:
@@ -482,7 +362,7 @@ def joined(self) -> "StandardVersion":
self.string.replace(".", "").replace("-", "").replace("_", "")
)
def up_to(self, index: int) -> "StandardVersion":
def up_to(self, index):
"""The version up to the specified component.
Examples:
@@ -602,7 +482,7 @@ def ref_version(self) -> StandardVersion:
)
return self._ref_version
def intersects(self, other: VersionType) -> bool:
def intersects(self, other):
# For concrete things intersects = satisfies = equality
if isinstance(other, GitVersion):
return self == other
@@ -612,14 +492,19 @@ def intersects(self, other: VersionType) -> bool:
return self.ref_version.intersects(other)
if isinstance(other, VersionList):
return any(self.intersects(rhs) for rhs in other)
raise TypeError(f"'intersects()' not supported for instances of {type(other)}")
raise ValueError(f"Unexpected type {type(other)}")
def intersection(self, other: VersionType) -> VersionType:
def intersection(self, other):
if isinstance(other, ConcreteVersion):
return self if self == other else VersionList()
return other.intersection(self)
def satisfies(self, other: VersionType) -> bool:
def overlaps(self, other) -> bool:
return self.intersects(other)
def satisfies(
self, other: Union["GitVersion", StandardVersion, "ClosedOpenRange", "VersionList"]
):
# Concrete versions mean we have to do an equality check
if isinstance(other, GitVersion):
return self == other
@@ -629,9 +514,9 @@ def satisfies(self, other: VersionType) -> bool:
return self.ref_version.satisfies(other)
if isinstance(other, VersionList):
return any(self.satisfies(rhs) for rhs in other)
raise TypeError(f"'satisfies()' not supported for instances of {type(other)}")
raise ValueError(f"Unexpected type {type(other)}")
def __str__(self) -> str:
def __str__(self):
s = f"git.{self.ref}" if self.has_git_prefix else self.ref
# Note: the solver actually depends on str(...) to produce the effective version.
# So when a lookup is attached, we require the resolved version to be printed.
@@ -649,7 +534,7 @@ def __repr__(self):
def __bool__(self):
return True
def __eq__(self, other: object) -> bool:
def __eq__(self, other):
# GitVersion cannot be equal to StandardVersion, otherwise == is not transitive
return (
isinstance(other, GitVersion)
@@ -657,10 +542,10 @@ def __eq__(self, other: object) -> bool:
and self.ref_version == other.ref_version
)
def __ne__(self, other: object) -> bool:
def __ne__(self, other):
return not self == other
def __lt__(self, other: object) -> bool:
def __lt__(self, other):
if isinstance(other, GitVersion):
return (self.ref_version, self.ref) < (other.ref_version, other.ref)
if isinstance(other, StandardVersion):
@@ -668,9 +553,9 @@ def __lt__(self, other: object) -> bool:
return self.ref_version < other
if isinstance(other, ClosedOpenRange):
return self.ref_version < other
raise TypeError(f"'<' not supported between instances of {type(self)} and {type(other)}")
raise ValueError(f"Unexpected type {type(other)}")
def __le__(self, other: object) -> bool:
def __le__(self, other):
if isinstance(other, GitVersion):
return (self.ref_version, self.ref) <= (other.ref_version, other.ref)
if isinstance(other, StandardVersion):
@@ -679,9 +564,9 @@ def __le__(self, other: object) -> bool:
if isinstance(other, ClosedOpenRange):
# Equality is not a thing
return self.ref_version < other
raise TypeError(f"'<=' not supported between instances of {type(self)} and {type(other)}")
raise ValueError(f"Unexpected type {type(other)}")
def __ge__(self, other: object) -> bool:
def __ge__(self, other):
if isinstance(other, GitVersion):
return (self.ref_version, self.ref) >= (other.ref_version, other.ref)
if isinstance(other, StandardVersion):
@@ -689,9 +574,9 @@ def __ge__(self, other: object) -> bool:
return self.ref_version >= other
if isinstance(other, ClosedOpenRange):
return self.ref_version > other
raise TypeError(f"'>=' not supported between instances of {type(self)} and {type(other)}")
raise ValueError(f"Unexpected type {type(other)}")
def __gt__(self, other: object) -> bool:
def __gt__(self, other):
if isinstance(other, GitVersion):
return (self.ref_version, self.ref) > (other.ref_version, other.ref)
if isinstance(other, StandardVersion):
@@ -699,14 +584,14 @@ def __gt__(self, other: object) -> bool:
return self.ref_version >= other
if isinstance(other, ClosedOpenRange):
return self.ref_version > other
raise TypeError(f"'>' not supported between instances of {type(self)} and {type(other)}")
raise ValueError(f"Unexpected type {type(other)}")
def __hash__(self):
# hashing should not cause version lookup
return hash(self.ref)
def __contains__(self, other: object) -> bool:
raise NotImplementedError
def __contains__(self, other):
raise Exception("Not implemented yet")
@property
def ref_lookup(self):
@@ -764,7 +649,7 @@ def up_to(self, index) -> StandardVersion:
return self.ref_version.up_to(index)
class ClosedOpenRange(VersionType):
class ClosedOpenRange:
def __init__(self, lo: StandardVersion, hi: StandardVersion):
if hi < lo:
raise EmptyRangeError(f"{lo}..{hi} is an empty range")
@@ -772,14 +657,14 @@ def __init__(self, lo: StandardVersion, hi: StandardVersion):
self.hi: StandardVersion = hi
@classmethod
def from_version_range(cls, lo: StandardVersion, hi: StandardVersion) -> "ClosedOpenRange":
def from_version_range(cls, lo: StandardVersion, hi: StandardVersion):
"""Construct ClosedOpenRange from lo:hi range."""
try:
return ClosedOpenRange(lo, _next_version(hi))
except EmptyRangeError as e:
raise EmptyRangeError(f"{lo}:{hi} is an empty range") from e
def __str__(self) -> str:
def __str__(self):
# This simplifies 3.1:<3.2 to 3.1:3.1 to 3.1
# 3:3 -> 3
hi_prev = _prev_version(self.hi)
@@ -841,9 +726,9 @@ def __gt__(self, other):
def __contains__(rhs, lhs):
if isinstance(lhs, (ConcreteVersion, ClosedOpenRange, VersionList)):
return lhs.satisfies(rhs)
raise TypeError(f"'in' not supported between instances of {type(rhs)} and {type(lhs)}")
raise ValueError(f"Unexpected type {type(lhs)}")
def intersects(self, other: VersionType) -> bool:
def intersects(self, other: Union[ConcreteVersion, "ClosedOpenRange", "VersionList"]):
if isinstance(other, StandardVersion):
return self.lo <= other < self.hi
if isinstance(other, GitVersion):
@@ -852,18 +737,23 @@ def intersects(self, other: VersionType) -> bool:
return (self.lo < other.hi) and (other.lo < self.hi)
if isinstance(other, VersionList):
return any(self.intersects(rhs) for rhs in other)
raise TypeError(f"'intersects' not supported for instances of {type(other)}")
raise ValueError(f"Unexpected type {type(other)}")
def satisfies(self, other: VersionType) -> bool:
def satisfies(self, other: Union["ClosedOpenRange", ConcreteVersion, "VersionList"]):
if isinstance(other, ConcreteVersion):
return False
if isinstance(other, ClosedOpenRange):
return not (self.lo < other.lo or other.hi < self.hi)
if isinstance(other, VersionList):
return any(self.satisfies(rhs) for rhs in other)
raise TypeError(f"'satisfies()' not supported for instances of {type(other)}")
raise ValueError(other)
def _union_if_not_disjoint(self, other: VersionType) -> Optional["ClosedOpenRange"]:
def overlaps(self, other: Union["ClosedOpenRange", ConcreteVersion, "VersionList"]) -> bool:
return self.intersects(other)
def _union_if_not_disjoint(
self, other: Union["ClosedOpenRange", ConcreteVersion]
) -> Optional["ClosedOpenRange"]:
"""Same as union, but returns None when the union is not connected. This function is not
implemented for version lists as right-hand side, as that makes little sense."""
if isinstance(other, StandardVersion):
@@ -880,9 +770,9 @@ def _union_if_not_disjoint(self, other: VersionType) -> Optional["ClosedOpenRang
else None
)
raise TypeError(f"'union()' not supported for instances of {type(other)}")
raise TypeError(f"Unexpected type {type(other)}")
def union(self, other: VersionType) -> VersionType:
def union(self, other: Union["ClosedOpenRange", ConcreteVersion, "VersionList"]):
if isinstance(other, VersionList):
v = other.copy()
v.add(self)
@@ -891,51 +781,35 @@ def union(self, other: VersionType) -> VersionType:
result = self._union_if_not_disjoint(other)
return result if result is not None else VersionList([self, other])
def intersection(self, other: VersionType) -> VersionType:
def intersection(self, other: Union["ClosedOpenRange", ConcreteVersion]):
# range - version -> singleton or nothing.
if isinstance(other, ClosedOpenRange):
# range - range -> range or nothing.
max_lo = max(self.lo, other.lo)
min_hi = min(self.hi, other.hi)
return ClosedOpenRange(max_lo, min_hi) if max_lo < min_hi else VersionList()
if isinstance(other, ConcreteVersion):
return other if self.intersects(other) else VersionList()
raise TypeError(f"'intersection()' not supported for instances of {type(other)}")
# range - range -> range or nothing.
max_lo = max(self.lo, other.lo)
min_hi = min(self.hi, other.hi)
return ClosedOpenRange(max_lo, min_hi) if max_lo < min_hi else VersionList()
class VersionList(VersionType):
class VersionList:
"""Sorted, non-redundant list of Version and ClosedOpenRange elements."""
versions: List[VersionType]
def __init__(self, vlist: Optional[Union[str, VersionType, Iterable]] = None):
def __init__(self, vlist=None):
self.versions: List[Union[StandardVersion, GitVersion, ClosedOpenRange]] = []
if vlist is None:
self.versions = []
pass
elif isinstance(vlist, str):
vlist = from_string(vlist)
if isinstance(vlist, VersionList):
self.versions = vlist.versions
else:
self.versions = [vlist]
elif isinstance(vlist, (ConcreteVersion, ClosedOpenRange)):
self.versions = [vlist]
elif isinstance(vlist, VersionList):
self.versions = vlist[:]
elif isinstance(vlist, Iterable):
self.versions = []
else:
for v in vlist:
self.add(ver(v))
else:
raise TypeError(f"Cannot construct VersionList from {type(vlist)}")
def add(self, item: VersionType) -> None:
def add(self, item: Union[StandardVersion, GitVersion, ClosedOpenRange, "VersionList"]):
if isinstance(item, (StandardVersion, GitVersion)):
i = bisect_left(self, item)
# Only insert when prev and next are not intersected.
@@ -991,7 +865,7 @@ def concrete_range_as_version(self) -> Optional[ConcreteVersion]:
return v.lo
return None
def copy(self) -> "VersionList":
def copy(self):
return VersionList(self)
def lowest(self) -> Optional[StandardVersion]:
@@ -1015,7 +889,7 @@ def preferred(self) -> Optional[StandardVersion]:
"""Get the preferred (latest) version in the list."""
return self.highest_numeric() or self.highest()
def satisfies(self, other: VersionType) -> bool:
def satisfies(self, other) -> bool:
# This exploits the fact that version lists are "reduced" and normalized, so we can
# never have a list like [1:3, 2:4] since that would be normalized to [1:4]
if isinstance(other, VersionList):
@@ -1024,9 +898,9 @@ def satisfies(self, other: VersionType) -> bool:
if isinstance(other, (ConcreteVersion, ClosedOpenRange)):
return all(lhs.satisfies(other) for lhs in self)
raise TypeError(f"'satisfies()' not supported for instances of {type(other)}")
raise ValueError(f"Unsupported type {type(other)}")
def intersects(self, other: VersionType) -> bool:
def intersects(self, other):
if isinstance(other, VersionList):
s = o = 0
while s < len(self) and o < len(other):
@@ -1041,16 +915,19 @@ def intersects(self, other: VersionType) -> bool:
if isinstance(other, (ClosedOpenRange, StandardVersion)):
return any(v.intersects(other) for v in self)
raise TypeError(f"'intersects()' not supported for instances of {type(other)}")
raise ValueError(f"Unsupported type {type(other)}")
def to_dict(self) -> Dict:
def overlaps(self, other) -> bool:
return self.intersects(other)
def to_dict(self):
"""Generate human-readable dict for YAML."""
if self.concrete:
return syaml_dict([("version", str(self[0]))])
return syaml_dict([("versions", [str(v) for v in self])])
@staticmethod
def from_dict(dictionary) -> "VersionList":
def from_dict(dictionary):
"""Parse dict from to_dict."""
if "versions" in dictionary:
return VersionList(dictionary["versions"])
@@ -1058,29 +935,27 @@ def from_dict(dictionary) -> "VersionList":
return VersionList([Version(dictionary["version"])])
raise ValueError("Dict must have 'version' or 'versions' in it.")
def update(self, other: "VersionList") -> None:
self.add(other)
def update(self, other: "VersionList"):
for v in other.versions:
self.add(v)
def union(self, other: VersionType) -> VersionType:
def union(self, other: "VersionList"):
result = self.copy()
result.add(other)
result.update(other)
return result
def intersection(self, other: VersionType) -> "VersionList":
def intersection(self, other: "VersionList") -> "VersionList":
result = VersionList()
if isinstance(other, VersionList):
for lhs, rhs in ((self, other), (other, self)):
for x in lhs:
i = bisect_left(rhs.versions, x)
if i > 0:
result.add(rhs[i - 1].intersection(x))
if i < len(rhs):
result.add(rhs[i].intersection(x))
return result
else:
return self.intersection(VersionList(other))
for lhs, rhs in ((self, other), (other, self)):
for x in lhs:
i = bisect_left(rhs.versions, x)
if i > 0:
result.add(rhs[i - 1].intersection(x))
if i < len(rhs):
result.add(rhs[i].intersection(x))
return result
def intersect(self, other: VersionType) -> bool:
def intersect(self, other) -> bool:
"""Intersect this spec's list with other.
Return True if the spec changed as a result; False otherwise
@@ -1090,7 +965,6 @@ def intersect(self, other: VersionType) -> bool:
self.versions = isection.versions
return changed
# typing this and getitem are a pain in Python 3.6
def __contains__(self, other):
if isinstance(other, (ClosedOpenRange, StandardVersion)):
i = bisect_left(self, other)
@@ -1104,52 +978,52 @@ def __contains__(self, other):
def __getitem__(self, index):
return self.versions[index]
def __iter__(self) -> Iterator:
def __iter__(self):
return iter(self.versions)
def __reversed__(self) -> Iterator:
def __reversed__(self):
return reversed(self.versions)
def __len__(self) -> int:
def __len__(self):
return len(self.versions)
def __bool__(self) -> bool:
def __bool__(self):
return bool(self.versions)
def __eq__(self, other) -> bool:
def __eq__(self, other):
if isinstance(other, VersionList):
return self.versions == other.versions
return False
def __ne__(self, other) -> bool:
def __ne__(self, other):
if isinstance(other, VersionList):
return self.versions != other.versions
return False
def __lt__(self, other) -> bool:
def __lt__(self, other):
if isinstance(other, VersionList):
return self.versions < other.versions
return NotImplemented
def __le__(self, other) -> bool:
def __le__(self, other):
if isinstance(other, VersionList):
return self.versions <= other.versions
return NotImplemented
def __ge__(self, other) -> bool:
def __ge__(self, other):
if isinstance(other, VersionList):
return self.versions >= other.versions
return NotImplemented
def __gt__(self, other) -> bool:
def __gt__(self, other):
if isinstance(other, VersionList):
return self.versions > other.versions
return NotImplemented
def __hash__(self) -> int:
def __hash__(self):
return hash(tuple(self.versions))
def __str__(self) -> str:
def __str__(self):
if not self.versions:
return ""
@@ -1157,7 +1031,7 @@ def __str__(self) -> str:
f"={v}" if isinstance(v, StandardVersion) else str(v) for v in self.versions
)
def __repr__(self) -> str:
def __repr__(self):
return str(self.versions)
@@ -1232,10 +1106,12 @@ def _next_version(v: StandardVersion) -> StandardVersion:
release = release[:-1] + (_next_version_str_component(release[-1]),)
else:
release = release[:-1] + (release[-1] + 1,)
# Avoid constructing a string here for performance. Instead, pass "" to
# StandardVersion to lazily stringify.
return StandardVersion("", (release, prerelease), separators)
components = [""] * (2 * len(release))
components[::2] = release
components[1::2] = separators[: len(release)]
if prerelease_type != FINAL:
components.extend((PRERELEASE_TO_STRING[prerelease_type], prerelease[1]))
return StandardVersion("".join(str(c) for c in components), (release, prerelease), separators)
def _prev_version(v: StandardVersion) -> StandardVersion:
@@ -1254,15 +1130,19 @@ def _prev_version(v: StandardVersion) -> StandardVersion:
release = release[:-1] + (_prev_version_str_component(release[-1]),)
else:
release = release[:-1] + (release[-1] - 1,)
components = [""] * (2 * len(release))
components[::2] = release
components[1::2] = separators[: len(release)]
if prerelease_type != FINAL:
components.extend((PRERELEASE_TO_STRING[prerelease_type], *prerelease[1:]))
# Avoid constructing a string here for performance. Instead, pass "" to
# StandardVersion to lazily stringify.
return StandardVersion("", (release, prerelease), separators)
# this is only used for comparison functions, so don't bother making a string
return StandardVersion(None, (release, prerelease), separators)
def Version(string: Union[str, int]) -> ConcreteVersion:
def Version(string: Union[str, int]) -> Union[GitVersion, StandardVersion]:
if not isinstance(string, (str, int)):
raise TypeError(f"Cannot construct a version from {type(string)}")
raise ValueError(f"Cannot construct a version from {type(string)}")
string = str(string)
if is_git_version(string):
return GitVersion(string)
@@ -1275,7 +1155,7 @@ def VersionRange(lo: Union[str, StandardVersion], hi: Union[str, StandardVersion
return ClosedOpenRange.from_version_range(lo, hi)
def from_string(string: str) -> VersionType:
def from_string(string) -> Union[VersionList, ClosedOpenRange, StandardVersion, GitVersion]:
"""Converts a string to a version object. This is private. Client code should use ver()."""
string = string.replace(" ", "")
@@ -1304,17 +1184,17 @@ def from_string(string: str) -> VersionType:
return VersionRange(v, v)
def ver(obj: Union[VersionType, str, list, tuple, int, float]) -> VersionType:
def ver(obj) -> Union[VersionList, ClosedOpenRange, StandardVersion, GitVersion]:
"""Parses a Version, VersionRange, or VersionList from a string
or list of strings.
"""
if isinstance(obj, VersionType):
return obj
if isinstance(obj, (list, tuple)):
return VersionList(obj)
elif isinstance(obj, str):
return from_string(obj)
elif isinstance(obj, (list, tuple)):
return VersionList(obj)
elif isinstance(obj, (int, float)):
return from_string(str(obj))
elif isinstance(obj, (StandardVersion, GitVersion, ClosedOpenRange, VersionList)):
return obj
else:
raise TypeError("ver() can't convert %s to version!" % type(obj))

View File

@@ -8,8 +8,8 @@ packages:
gromacs:
require:
- one_of:
- "gromacs@2024.3 %arm ^fftw ^openmpi"
- "gromacs@2024.3 %gcc ^armpl-gcc ^openmpi"
- "gromacs@2021.3 %arm ^fftw ^openmpi"
- "gromacs@2021.3 %gcc ^armpl-gcc ^openmpi"
libfabric:
buildable: true
externals:

View File

@@ -153,8 +153,3 @@ def install_additional_files(self):
join_path(source_directory, "ADOL-C", "examples", "additional_examples")
):
Executable("./checkpointing/checkpointing")()
@property
def libs(self):
"""The name of the library differs from the package name => own libs handling."""
return find_libraries(["libadolc"], root=self.prefix, shared=True, recursive=True)

View File

@@ -15,30 +15,21 @@ class AllLibrary(CMakePackage):
homepage = "http://slms.pages.jsc.fz-juelich.de/websites/all-website/"
url = "https://gitlab.jsc.fz-juelich.de/SLMS/loadbalancing/-/archive/v0.9.2/loadbalancing-v0.9.2.tar.gz"
git = "https://gitlab.jsc.fz-juelich.de/SLMS/loadbalancing.git"
maintainers("junghans")
license("BSD-3-Clause", checked_by="junghans")
version("master", branch="master")
version("0.9.2", sha256="2b4ef52c604c3c0c467712d0912a33c82177610b67edc14df1e034779c6ddb71")
variant("fortran", default=False, description="Build with fortran support")
variant("shared", default=True, description="Build shared libraries")
variant("vtk", default=False, description="Build with vtk support")
variant(
"voronoi",
default=False,
description="Enable voronoi-based loadbalancing scheme",
when="@0.9.3:",
)
depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("fortran", type="build", when="+fortran")
depends_on("vtk", when="+vtk")
depends_on("voropp", when="+voronoi")
depends_on("mpi")
@@ -48,7 +39,6 @@ def cmake_args(self):
self.define_from_variant("CM_ALL_FORTRAN", "fortran"),
self.define_from_variant("CM_ALL_USE_F08", "fortran"),
self.define_from_variant("CM_ALL_VTK_OUTPUT", "vtk"),
self.define_from_variant("CM_ALL_VORONOI", "voronoi"),
]
if self.run_tests:

View File

@@ -147,19 +147,6 @@ def _get_sys_type(self, spec):
sys_type = env["SYS_TYPE"]
return sys_type
@property
def cache_name(self):
hostname = socket.gethostname()
if "SYS_TYPE" in env:
hostname = hostname.rstrip("1234567890")
return "{0}-{1}-{2}@{3}-{4}.cmake".format(
hostname,
self._get_sys_type(self.spec),
self.spec.compiler.name,
self.spec.compiler.version,
self.spec.dag_hash(8),
)
def initconfig_compiler_entries(self):
spec = self.spec
entries = super().initconfig_compiler_entries()

View File

@@ -106,8 +106,7 @@ def cmake_args(self):
options.append(self.define_from_variant("ENABLE_HIP", "rocm"))
if spec.satisfies("+rocm"):
rocm_root = dirname(spec["llvm-amdgpu"].prefix)
options.append("-DROCM_PATH={0}".format(rocm_root))
options.append("-DHIP_ROOT_DIR={0}".format(spec["hip"].prefix))
archs = self.spec.variants["amdgpu_target"].value
options.append("-DCMAKE_HIP_ARCHITECTURES={0}".format(archs))

View File

@@ -25,18 +25,6 @@ class Care(CachedCMakePackage, CudaPackage, ROCmPackage):
version("develop", branch="develop", submodules=False)
version("master", branch="master", submodules=False)
version(
"0.14.1",
tag="v0.14.1",
commit="110c6e5766ead59b231e2b05deecd7567874e907",
submodules=False,
)
version(
"0.14.0",
tag="v0.14.0",
commit="2784188a067abac35747d58b5a5daa1b3852756b",
submodules=False,
)
version(
"0.13.3",
tag="v0.13.3",
@@ -263,13 +251,6 @@ def initconfig_package_entries(self):
entries.append(cmake_cache_string("CMAKE_BUILD_TYPE", spec.variants["build_type"].value))
# C++14
if spec.satisfies("@:0.14.1"):
entries.append(cmake_cache_string("BLT_CXX_STD", "c++14"))
# C++17
else:
entries.append(cmake_cache_string("BLT_CXX_STD", "c++17"))
entries.append(cmake_cache_option("ENABLE_TESTS", spec.satisfies("+tests")))
entries.append(cmake_cache_option("CARE_ENABLE_TESTS", spec.satisfies("+tests")))
# For tests to work, we also need BLT_ENABLE_TESTS to be on.

View File

@@ -13,8 +13,6 @@ class CrayLibsci(Package):
homepage = "https://docs.nersc.gov/development/libraries/libsci/"
has_code = False # Skip attempts to fetch source that is not available
version("23.02.1.1")
version("22.11.1.2")
version("21.08.1.2")
version("20.06.1")
version("20.03.1")

View File

@@ -18,10 +18,6 @@ class CrayMpich(Package):
maintainers("haampie")
version("8.1.25")
version("8.1.24")
version("8.1.21")
version("8.1.14")
version("8.1.7")
version("8.1.0")
version("8.0.16")

View File

@@ -3,8 +3,6 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
from spack.package import *
@@ -128,18 +126,6 @@ class Dbcsr(CMakePackage, CudaPackage, ROCmPackage):
generator("ninja")
depends_on("ninja@1.10:", type="build")
@when("+rocm")
def patch(self):
for directory, subdirectory, files in os.walk(os.getcwd()):
for i in files:
file_path = os.path.join(directory, i)
filter_file("USE ISO_C_BINDING", "USE,INTRINSIC :: ISO_C_BINDING", file_path)
filter_file("USE ISO_FORTRAN_ENV", "USE,INTRINSIC :: ISO_FORTRAN_ENV", file_path)
filter_file("USE omp_lib", "USE,INTRINSIC :: omp_lib", file_path)
filter_file("USE OMP_LIB", "USE,INTRINSIC :: OMP_LIB", file_path)
filter_file("USE iso_c_binding", "USE,INTRINSIC :: iso_c_binding", file_path)
filter_file("USE iso_fortran_env", "USE,INTRINSIC :: iso_fortran_env", file_path)
def cmake_args(self):
spec = self.spec

View File

@@ -22,11 +22,6 @@ class Eospac(Package):
# previous stable release will appear first as a new beta.
# - alpha and beta versions are marked with 'deprecated=True' to help
# spack's version comparison.
version(
"6.5.12",
sha256="62d5f4a6a30c9acb426bd6bd972edc7fad392e5b941f950126ed0d3be5fd5162",
url="https://laws.lanl.gov/projects/data/eos/get_file.php?package=eospac&filename=eospac_v6.5.12_39364aabc75c3312022b12e6d16d6a31f1f8945f.tgz",
)
version(
"6.5.11",
sha256="ed821b5a1bf45df1443d5f72d86190317ed9f5bad6a7c73e23bb4365bd76e24c",

View File

@@ -41,9 +41,6 @@ class Fpm(Package):
depends_on("curl", type="build")
depends_on("git@1.8.5:", type="build")
depends_on("c", type="build")
depends_on("fortran", type="build")
def setup_build_environment(self, env):
if self.spec.satisfies("@0.4.0"):
env.set("FPM_C_COMPILER", self.compiler.cc)

View File

@@ -3,7 +3,6 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import glob
import os
import re
@@ -12,7 +11,7 @@
from llnl.util import tty
from spack.package import *
from spack.util.elf import delete_needed_from_elf, parse_elf
from spack.util.elf import parse_elf
class GccRuntime(Package):
@@ -73,9 +72,6 @@ def install(self, spec, prefix):
for path, name in libraries:
install(path, os.path.join(prefix.lib, name))
if spec.platform in ("linux", "freebsd"):
_drop_libgfortran_zlib(prefix.lib)
def _get_libraries_macho(self):
"""Same as _get_libraries_elf but for Mach-O binaries"""
cc = Executable(self.compiler.cc)
@@ -128,22 +124,6 @@ def headers(self):
return HeaderList([])
def _drop_libgfortran_zlib(lib_dir: str) -> None:
"""Due to a bug in GCC's autotools setup (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87182),
libz sometimes appears as a redundant system dependency of libgfortran. Delete it."""
libraries = glob.glob(os.path.join(lib_dir, "libgfortran*.so*"))
if len(libraries) == 0:
return
with open(libraries[0], "rb+") as f:
elf = parse_elf(f, dynamic_section=True)
if not elf.has_needed:
return
libz = next((x for x in elf.dt_needed_strs if x.startswith(b"libz.so")), None)
if libz is None:
return
delete_needed_from_elf(f, elf, libz)
def get_elf_libraries(compiler, libraries):
"""Get the GCC runtime libraries for ELF binaries"""
cc = Executable(compiler.cc)

View File

@@ -406,71 +406,39 @@ class Gcc(AutotoolsPackage, GNUMirrorPackage, CompilerPackage):
when="@11.2.0",
)
# aarch64-darwin support from Iain Sandoe's branch
# Apple M1 support, created from branch of Darwin maintainer for GCC:
# https://github.com/iains/gcc-11-branch
patch(
"https://github.com/iains/gcc-14-branch/compare/04696df09633baf97cdbbdd6e9929b9d472161d3..gcc-14.2-darwin-r2.patch?full_index=1",
sha256="01ea668489f3f0fb2439060f6c333c4c17ef4c19c4c4e6e6aa4b8ea493e97685",
when="@14.2.0 target=aarch64:",
"https://raw.githubusercontent.com/Homebrew/formula-patches/22dec3fc/gcc/gcc-11.3.0-arm.diff",
sha256="e02006b7ec917cc1390645d95735a6a866caed0dfe506d5bef742f7862cab218",
when="@11.3.0 target=aarch64:",
)
# https://github.com/iains/gcc-12-branch
patch(
"https://raw.githubusercontent.com/Homebrew/formula-patches/76677f2b/gcc/gcc-12.1.0-arm.diff",
sha256="a000f1d9cb1dd98c7c4ef00df31435cd5d712d2f9d037ddc044f8bf82a16cf35",
when="@12.1.0 target=aarch64:",
)
patch(
"https://github.com/iains/gcc-14-branch/compare/cd0059a1976303638cea95f216de129334fc04d1..gcc-14.1-darwin-r1.patch?full_index=1",
sha256="159cc2a1077ad5d9a3cca87880cd977b8202d8fb464a6ec7b53804475d21a682",
when="@14.1.0 target=aarch64:",
)
patch(
"https://github.com/iains/gcc-13-branch/compare/b71f1de6e9cf7181a288c0f39f9b1ef6580cf5c8..gcc-13.3-darwin-r1.patch?full_index=1",
sha256="d957520afc286ac46aa3c4bf9b64618d02ca0bf1466f32321b5d6beec6a396eb",
when="@13.3.0 target=aarch64:",
)
patch(
"https://github.com/iains/gcc-13-branch/compare/c891d8dc23e1a46ad9f3e757d09e57b500d40044..gcc-13.2-darwin-r0.patch?full_index=1",
sha256="6a49d1074d7dd2e3b76e61613a0f143c668ed648fb8d9d48ed76a6b127815c88",
when="@13.2.0 target=aarch64:",
)
patch(
"https://github.com/iains/gcc-13-branch/compare/cc035c5d8672f87dc8c2756d9f8367903aa72d93..gcc-13.1-darwin-r0.patch?full_index=1",
sha256="36d2c04d487edb6792b48dedae6936f8b864b6f969bd3fd03763e072d471c022",
when="@13.1.0 target=aarch64:",
)
patch(
"https://github.com/iains/gcc-12-branch/compare/2bada4bc59bed4be34fab463bdb3c3ebfd2b41bb..gcc-12.4-darwin-r0.patch?full_index=1",
sha256="e242adf240a62ed3005da75a9e304bda980b84ce497f124b4bddc819ee821e2a",
when="@12.4.0 target=aarch64:",
)
patch(
"https://github.com/iains/gcc-12-branch/compare/8fc1a49c9312b05d925b7d21f1d2145d70818151..gcc-12.3-darwin-r0.patch?full_index=1",
sha256="1ebac2010eb9ced33cf46a8d8378193671ed6830f262219aa3428de5bc9fd668",
when="@12.3.0 target=aarch64:",
)
patch(
"https://github.com/iains/gcc-12-branch/compare/2ee5e4300186a92ad73f1a1a64cb918dc76c8d67..gcc-12.2-darwin-r0.patch?full_index=1",
sha256="16d5203ddb97cd43d6c1e9c34e0f681154aed1d127f2324b2a50006b92960cfd",
"https://raw.githubusercontent.com/Homebrew/formula-patches/1d184289/gcc/gcc-12.2.0-arm.diff",
sha256="a7843b5c6bf1401e40c20c72af69c8f6fc9754ae980bb4a5f0540220b3dcb62d",
when="@12.2.0 target=aarch64:",
)
patch(
"https://github.com/iains/gcc-12-branch/compare/1ea978e3066ac565a1ec28a96a4d61eaf38e2726..gcc-12.1-darwin-r1.patch?full_index=1",
sha256="b0a811e33c3451ebd1882eac4e2b4b32ce0b60cfa0b8ccf8c5fda7b24327c820",
when="@12.1.0 target=aarch64:",
)
patch(
"https://github.com/iains/gcc-11-branch/compare/5cc4c42a0d4de08715c2eef8715ad5b2e92a23b6..gcc-11.5-darwin-r0.patch?full_index=1",
sha256="6c92190a9acabd6be13bd42ca675f59f44be050a7121214abeaea99d898db30c",
when="@11.5.0 target=aarch64:",
"https://raw.githubusercontent.com/Homebrew/formula-patches/5c206c47/gcc/gcc-13.1.0.diff",
sha256="cb4e8a89387f748a744da0273025d0dc2e3c76780cc390b18ada704676afea11",
when="@13.1.0 target=aarch64:",
)
patch(
"https://github.com/iains/gcc-11-branch/compare/ff4bf326d03e750a8d4905ea49425fe7d15a04b8..gcc-11.4-darwin-r0.patch?full_index=1",
sha256="05810e5cdb052c06490f7d987c66a13d47ae7bd2eb285a3a881ad4aa6dd0d13f",
when="@11.4.0 target=aarch64:",
"https://raw.githubusercontent.com/Homebrew/formula-patches/3c5cbc8e9cf444a1967786af48e430588e1eb481/gcc/gcc-13.2.0.diff",
sha256="2df7ef067871a30b2531a2013b3db661ec9e61037341977bfc451e30bf2c1035",
when="@13.2.0 target=aarch64:",
)
patch(
"https://github.com/iains/gcc-11-branch/compare/2d280e7eafc086e9df85f50ed1a6526d6a3a204d..gcc-11.3-darwin-r2.patch?full_index=1",
sha256="a8097c232dfb21b0e02f3d99e3c3e47443db3982dafbb584938ac1a9a4afd33d",
when="@11.3.0 target=aarch64:",
"https://raw.githubusercontent.com/Homebrew/formula-patches/82b5c1cd38826ab67ac7fc498a8fe74376a40f4a/gcc/gcc-14.1.0.diff",
sha256="1529cff128792fe197ede301a81b02036c8168cb0338df21e4bc7aafe755305a",
when="@14.1.0 target=aarch64:",
)
conflicts("+bootstrap", when="@11.3.0,13.1: target=aarch64:")
# Use -headerpad_max_install_names in the build,

View File

@@ -12,36 +12,33 @@ class GdkPixbuf(MesonPackage):
GTK+ 2 but it was split off into a separate package in preparation for the change to GTK+ 3."""
homepage = "https://gitlab.gnome.org/GNOME/gdk-pixbuf"
url = "https://ftp.acc.umu.se/pub/gnome/sources/gdk-pixbuf/2.40/gdk-pixbuf-2.40.0.tar.xz"
git = "https://gitlab.gnome.org/GNOME/gdk-pixbuf"
url = "https://gitlab.gnome.org/GNOME/gdk-pixbuf/-/archive/2.40.0/gdk-pixbuf-2.40.0.tar.gz"
# Falling back to the gitlab source since the mirror here seems to be broken
# url = "https://ftp.acc.umu.se/pub/gnome/sources/gdk-pixbuf/2.40/gdk-pixbuf-2.40.0.tar.xz"
# list_url = "https://ftp.acc.umu.se/pub/gnome/sources/gdk-pixbuf/"
list_url = "https://ftp.acc.umu.se/pub/gnome/sources/gdk-pixbuf/"
list_depth = 1
license("LGPL-2.1-or-later", checked_by="wdconinc")
version("2.42.12", sha256="d41966831b3d291fcdfe31f683bea4b3f03241d591ddbe550b5db873af3da364")
version("2.42.12", sha256="b9505b3445b9a7e48ced34760c3bcb73e966df3ac94c95a148cb669ab748e3c7")
# https://nvd.nist.gov/vuln/detail/CVE-2022-48622
version(
"2.42.10",
sha256="87a086c51d9705698b22bd598a795efaccf61e4db3a96f439dcb3cd90506dab8",
sha256="ee9b6c75d13ba096907a2e3c6b27b61bcd17f5c7ebeab5a5b439d2f2e39fe44b",
deprecated=True,
)
version(
"2.42.9",
sha256="226d950375907857b23c5946ae6d30128f08cd75f65f14b14334c7a9fb686e36",
sha256="28f7958e7bf29a32d4e963556d241d0a41a6786582ff6a5ad11665e0347fc962",
deprecated=True,
)
version(
"2.42.6",
sha256="c4f3a84a04bc7c5f4fbd97dce7976ab648c60628f72ad4c7b79edce2bbdb494d",
sha256="c4a6b75b7ed8f58ca48da830b9fa00ed96d668d3ab4b1f723dcf902f78bde77f",
deprecated=True,
)
version(
"2.42.2",
sha256="249b977279f761979104d7befbb5ee23f1661e29d19a36da5875f3a97952d13f",
sha256="83c66a1cfd591d7680c144d2922c5955d38b4db336d7cd3ee109f7bcf9afef15",
deprecated=True,
)

View File

@@ -27,29 +27,11 @@ class Gromacs(CMakePackage, CudaPackage):
url = "https://ftp.gromacs.org/gromacs/gromacs-2022.2.tar.gz"
list_url = "https://ftp.gromacs.org/gromacs"
git = "https://gitlab.com/gromacs/gromacs.git"
maintainers("mabraham", "eirrgang", "junghans")
license("GPL-2.0-or-later", when="@:4.5")
license("LGPL-2.1-or-later", when="@4.6:")
# Deprecation policy:
#
# GROMACS makes an annual major release and supports it with fixes
# in minor updates for about two years. Each such annual release
# series is supported in spack for those two years, then marked as
# deprecated in Spack. Deprecated versions can be removed after
# the next major release of GROMACS is supported in Spack. Users
# needing such an old version can either do a manual installation
# or get an older version of Spack.
#
# Exception: Version 2019.6 is the last version capable of tabulated
# interactions used in the so-called "group scheme." It will be marked
# as deprecated only after equivalent functionality is available in
# a major release of GROMACS, then removed as above.
#
# Exception: Otherwise, versions before 2022 will be removed when
# 2025 is supported.
version("main", branch="main")
version("master", branch="main", deprecated=True)
version("2024.3", sha256="bbda056ee59390be7d58d84c13a9ec0d4e3635617adf2eb747034922cba1f029")
@@ -69,197 +51,45 @@ class Gromacs(CMakePackage, CudaPackage):
version("2022.2", sha256="656404f884d2fa2244c97d2a5b92af148d0dbea94ad13004724b3fcbf45e01bf")
version("2022.1", sha256="85ddab5197d79524a702c4959c2c43be875e0fc471df3a35224939dce8512450")
version("2022", sha256="fad60d606c02e6164018692c6c9f2c159a9130c2bf32e8c5f4f1b6ba2dda2b68")
version(
"2021.7",
sha256="4db7bbbfe5424de48373686ec0e8c5bfa7175d5cd74290ef1c1e840e6df67f06",
deprecated=True,
)
version(
"2021.6",
sha256="52df2c1d7586fd028d9397985c68bd6dd26e6e905ead382b7e6c473d087902c3",
deprecated=True,
)
version(
"2021.5",
sha256="eba63fe6106812f72711ef7f76447b12dd1ee6c81b3d8d4d0e3098cd9ea009b6",
deprecated=True,
)
version(
"2021.4",
sha256="cb708a3e3e83abef5ba475fdb62ef8d42ce8868d68f52dafdb6702dc9742ba1d",
deprecated=True,
)
version(
"2021.3",
sha256="e109856ec444768dfbde41f3059e3123abdb8fe56ca33b1a83f31ed4575a1cc6",
deprecated=True,
)
version(
"2021.2",
sha256="d940d865ea91e78318043e71f229ce80d32b0dc578d64ee5aa2b1a4be801aadb",
deprecated=True,
)
version(
"2021.1",
sha256="bc1d0a75c134e1fb003202262fe10d3d32c59bbb40d714bc3e5015c71effe1e5",
deprecated=True,
)
version(
"2021",
sha256="efa78ab8409b0f5bf0fbca174fb8fbcf012815326b5c71a9d7c385cde9a8f87b",
deprecated=True,
)
version(
"2020.7",
sha256="744158d8f61b0d36ffe89ec934519b7e0981a7af438897740160da648d36c2f0",
deprecated=True,
)
version(
"2020.6",
sha256="d8bbe57ed3c9925a8cb99ecfe39e217f930bed47d5268a9e42b33da544bdb2ee",
deprecated=True,
)
version(
"2020.5",
sha256="7b6aff647f7c8ee1bf12204d02cef7c55f44402a73195bd5f42cf11850616478",
deprecated=True,
)
version(
"2020.4",
sha256="5519690321b5500c7951aaf53ff624042c3edd1a5f5d6dd1f2d802a3ecdbf4e6",
deprecated=True,
)
version(
"2020.3",
sha256="903183691132db14e55b011305db4b6f4901cc4912d2c56c131edfef18cc92a9",
deprecated=True,
)
version(
"2020.2",
sha256="7465e4cd616359d84489d919ec9e4b1aaf51f0a4296e693c249e83411b7bd2f3",
deprecated=True,
)
version(
"2020.1",
sha256="e1666558831a3951c02b81000842223698016922806a8ce152e8f616e29899cf",
deprecated=True,
)
version(
"2020",
sha256="477e56142b3dcd9cb61b8f67b24a55760b04d1655e8684f979a75a5eec40ba01",
deprecated=True,
)
version("2021.7", sha256="4db7bbbfe5424de48373686ec0e8c5bfa7175d5cd74290ef1c1e840e6df67f06")
version("2021.6", sha256="52df2c1d7586fd028d9397985c68bd6dd26e6e905ead382b7e6c473d087902c3")
version("2021.5", sha256="eba63fe6106812f72711ef7f76447b12dd1ee6c81b3d8d4d0e3098cd9ea009b6")
version("2021.4", sha256="cb708a3e3e83abef5ba475fdb62ef8d42ce8868d68f52dafdb6702dc9742ba1d")
version("2021.3", sha256="e109856ec444768dfbde41f3059e3123abdb8fe56ca33b1a83f31ed4575a1cc6")
version("2021.2", sha256="d940d865ea91e78318043e71f229ce80d32b0dc578d64ee5aa2b1a4be801aadb")
version("2021.1", sha256="bc1d0a75c134e1fb003202262fe10d3d32c59bbb40d714bc3e5015c71effe1e5")
version("2021", sha256="efa78ab8409b0f5bf0fbca174fb8fbcf012815326b5c71a9d7c385cde9a8f87b")
version("2020.7", sha256="744158d8f61b0d36ffe89ec934519b7e0981a7af438897740160da648d36c2f0")
version("2020.6", sha256="d8bbe57ed3c9925a8cb99ecfe39e217f930bed47d5268a9e42b33da544bdb2ee")
version("2020.5", sha256="7b6aff647f7c8ee1bf12204d02cef7c55f44402a73195bd5f42cf11850616478")
version("2020.4", sha256="5519690321b5500c7951aaf53ff624042c3edd1a5f5d6dd1f2d802a3ecdbf4e6")
version("2020.3", sha256="903183691132db14e55b011305db4b6f4901cc4912d2c56c131edfef18cc92a9")
version("2020.2", sha256="7465e4cd616359d84489d919ec9e4b1aaf51f0a4296e693c249e83411b7bd2f3")
version("2020.1", sha256="e1666558831a3951c02b81000842223698016922806a8ce152e8f616e29899cf")
version("2020", sha256="477e56142b3dcd9cb61b8f67b24a55760b04d1655e8684f979a75a5eec40ba01")
version("2019.6", sha256="bebe396dc0db11a9d4cc205abc13b50d88225617642508168a2195324f06a358")
version(
"2019.5",
sha256="438061a4a2d45bbb5cf5c3aadd6c6df32d2d77ce8c715f1c8ffe56156994083a",
deprecated=True,
)
version(
"2019.4",
sha256="ba4366eedfc8a1dbf6bddcef190be8cd75de53691133f305a7f9c296e5ca1867",
deprecated=True,
)
version(
"2019.3",
sha256="4211a598bf3b7aca2b14ad991448947da9032566f13239b1a05a2d4824357573",
deprecated=True,
)
version(
"2019.2",
sha256="bcbf5cc071926bc67baa5be6fb04f0986a2b107e1573e15fadcb7d7fc4fb9f7e",
deprecated=True,
)
version(
"2019.1",
sha256="b2c37ed2fcd0e64c4efcabdc8ee581143986527192e6e647a197c76d9c4583ec",
deprecated=True,
)
version(
"2019",
sha256="c5b281a5f0b5b4eeb1f4c7d4dc72f96985b566561ca28acc9c7c16f6ee110d0b",
deprecated=True,
)
version(
"2018.8",
sha256="776923415df4bc78869d7f387c834141fdcda930b2e75be979dc59ecfa6ebecf",
deprecated=True,
)
version(
"2018.5",
sha256="32261df6f7ec4149fc0508f9af416953d056e281590359838c1ed6644ba097b8",
deprecated=True,
)
version(
"2018.4",
sha256="6f2ee458c730994a8549d6b4f601ecfc9432731462f8bd4ffa35d330d9aaa891",
deprecated=True,
)
version(
"2018.3",
sha256="4423a49224972969c52af7b1f151579cea6ab52148d8d7cbae28c183520aa291",
deprecated=True,
)
version(
"2018.2",
sha256="4bdde8120c510b6543afb4b18f82551fddb11851f7edbd814aa24022c5d37857",
deprecated=True,
)
version(
"2018.1",
sha256="4d3533340499323fece83b4a2d4251fa856376f2426c541e00b8e6b4c0d705cd",
deprecated=True,
)
version(
"2018",
sha256="deb5d0b749a52a0c6083367b5f50a99e08003208d81954fb49e7009e1b1fd0e9",
deprecated=True,
)
version(
"2016.6",
sha256="bac0117d2cad21f9b94fe5b854fb9ae7435b098a6da4e732ee745f18e52473d7",
deprecated=True,
)
version(
"2016.5",
sha256="57db26c6d9af84710a1e0c47a1f5bf63a22641456448dcd2eeb556ebd14e0b7c",
deprecated=True,
)
version(
"2016.4",
sha256="4be9d3bfda0bdf3b5c53041e0b8344f7d22b75128759d9bfa9442fe65c289264",
deprecated=True,
)
version(
"2016.3",
sha256="7bf00e74a9d38b7cef9356141d20e4ba9387289cbbfd4d11be479ef932d77d27",
deprecated=True,
)
version(
"5.1.5",
sha256="c25266abf07690ecad16ed3996899b1d489cbb1ef733a1befb3b5c75c91a703e",
deprecated=True,
)
version(
"5.1.4",
sha256="0f3793d8f1f0be747cf9ebb0b588fb2b2b5dc5acc32c3046a7bee2d2c03437bc",
deprecated=True,
)
version(
"5.1.2",
sha256="39d6f1d7ae8ba38cea6089da40676bfa4049a49903d21551abc030992a58f304",
deprecated=True,
)
version(
"4.6.7",
sha256="6afb1837e363192043de34b188ca3cf83db6bd189601f2001a1fc5b0b2a214d9",
deprecated=True,
)
version(
"4.5.5",
sha256="e0605e4810b0d552a8761fef5540c545beeaf85893f4a6e21df9905a33f871ba",
deprecated=True,
)
version("2019.5", sha256="438061a4a2d45bbb5cf5c3aadd6c6df32d2d77ce8c715f1c8ffe56156994083a")
version("2019.4", sha256="ba4366eedfc8a1dbf6bddcef190be8cd75de53691133f305a7f9c296e5ca1867")
version("2019.3", sha256="4211a598bf3b7aca2b14ad991448947da9032566f13239b1a05a2d4824357573")
version("2019.2", sha256="bcbf5cc071926bc67baa5be6fb04f0986a2b107e1573e15fadcb7d7fc4fb9f7e")
version("2019.1", sha256="b2c37ed2fcd0e64c4efcabdc8ee581143986527192e6e647a197c76d9c4583ec")
version("2019", sha256="c5b281a5f0b5b4eeb1f4c7d4dc72f96985b566561ca28acc9c7c16f6ee110d0b")
version("2018.8", sha256="776923415df4bc78869d7f387c834141fdcda930b2e75be979dc59ecfa6ebecf")
version("2018.5", sha256="32261df6f7ec4149fc0508f9af416953d056e281590359838c1ed6644ba097b8")
version("2018.4", sha256="6f2ee458c730994a8549d6b4f601ecfc9432731462f8bd4ffa35d330d9aaa891")
version("2018.3", sha256="4423a49224972969c52af7b1f151579cea6ab52148d8d7cbae28c183520aa291")
version("2018.2", sha256="4bdde8120c510b6543afb4b18f82551fddb11851f7edbd814aa24022c5d37857")
version("2018.1", sha256="4d3533340499323fece83b4a2d4251fa856376f2426c541e00b8e6b4c0d705cd")
version("2018", sha256="deb5d0b749a52a0c6083367b5f50a99e08003208d81954fb49e7009e1b1fd0e9")
version("2016.6", sha256="bac0117d2cad21f9b94fe5b854fb9ae7435b098a6da4e732ee745f18e52473d7")
version("2016.5", sha256="57db26c6d9af84710a1e0c47a1f5bf63a22641456448dcd2eeb556ebd14e0b7c")
version("2016.4", sha256="4be9d3bfda0bdf3b5c53041e0b8344f7d22b75128759d9bfa9442fe65c289264")
version("2016.3", sha256="7bf00e74a9d38b7cef9356141d20e4ba9387289cbbfd4d11be479ef932d77d27")
version("5.1.5", sha256="c25266abf07690ecad16ed3996899b1d489cbb1ef733a1befb3b5c75c91a703e")
version("5.1.4", sha256="0f3793d8f1f0be747cf9ebb0b588fb2b2b5dc5acc32c3046a7bee2d2c03437bc")
version("5.1.2", sha256="39d6f1d7ae8ba38cea6089da40676bfa4049a49903d21551abc030992a58f304")
version("4.6.7", sha256="6afb1837e363192043de34b188ca3cf83db6bd189601f2001a1fc5b0b2a214d9")
version("4.5.5", sha256="e0605e4810b0d552a8761fef5540c545beeaf85893f4a6e21df9905a33f871ba")
depends_on("c", type="build") # generated
depends_on("cxx", type="build") # generated
@@ -283,22 +113,11 @@ class Gromacs(CMakePackage, CudaPackage):
variant(
"heffte",
default=False,
when="@2021: +mpi",
when="@2021: +sycl+mpi",
description="Enable multi-GPU FFT support with HeFFTe",
)
depends_on("heffte +cuda", when="+heffte +cuda")
depends_on("heffte +sycl", when="+heffte +sycl")
variant("opencl", default=False, description="Enable OpenCL support")
variant("sycl", default=False, when="@2021:", description="Enable SYCL support")
requires(
"^intel-oneapi-runtime",
"^hipsycl %clang",
policy="one_of",
when="+sycl",
msg="GROMACS SYCL support comes either from intel-oneapi-runtime or a "
+ "package that provides the virtual package `sycl`, such as AdaptiveCpp "
+ "plus a clang compiler.",
)
variant("sycl", default=False, when="@2021: %clang", description="Enable SYCL support")
variant(
"intel-data-center-gpu-max",
default=False,
@@ -808,7 +627,7 @@ def cmake_args(self):
options.append("-DGMX_USE_ITT=on")
options.append(
"-DITTNOTIFY_INCLUDE_DIR=%s"
% self.spec["intel-oneapi-vtune"].package.headers.directories[0]
% join_path(self.spec["intel-oneapi-vtune"].package.headers)
)
if self.spec.satisfies("~nblib"):

View File

@@ -58,9 +58,6 @@ class Hip(CMakePackage):
conflicts("+asan", when="os=centos7")
conflicts("+asan", when="os=centos8")
depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("cuda", when="+cuda")
depends_on("cmake@3.16.8:", type="build")
@@ -534,6 +531,12 @@ def patch(self):
"clr/hipamd/hip-config-amd.cmake",
string=True,
)
filter_file(
'"${ROCM_PATH}/llvm"',
self.spec["llvm-amdgpu"].prefix,
"clr/hipamd/src/hiprtc/CMakeLists.txt",
string=True,
)
perl = self.spec["perl"].command
if self.spec.satisfies("@:5.5"):
@@ -558,12 +561,7 @@ def patch(self):
filter_file(" -lnuma", f" -L{numactl} -lnuma", "hipBin_amd.h")
def cmake_args(self):
args = [
# find_package(Clang) and find_package(LLVM) in clr/hipamd/src/hiprtc/CMakeLists.txt
# should find llvm-amdgpu
self.define("LLVM_ROOT", self.spec["llvm-amdgpu"].prefix),
self.define("Clang_ROOT", self.spec["llvm-amdgpu"].prefix),
]
args = []
if self.spec.satisfies("+rocm"):
args.append(self.define("HSA_PATH", self.spec["hsa-rocr-dev"].prefix))
args.append(self.define("HIP_COMPILER", "clang"))

View File

@@ -19,7 +19,7 @@ class Hypre(AutotoolsPackage, CudaPackage, ROCmPackage):
git = "https://github.com/hypre-space/hypre.git"
tags = ["e4s", "radiuss"]
maintainers("ulrikeyang", "osborn9", "victorapm", "balay")
maintainers("ulrikeyang", "osborn9", "balay")
test_requires_compiler = True
@@ -74,7 +74,6 @@ class Hypre(AutotoolsPackage, CudaPackage, ROCmPackage):
variant(
"superlu-dist", default=False, description="Activates support for SuperLU_Dist library"
)
variant("lapack", default=True, description="Use external blas/lapack")
variant("int64", default=False, description="Use 64bit integers")
variant("mixedint", default=False, description="Use 64bit integers while reducing memory use")
variant("complex", default=False, description="Use complex values")
@@ -124,8 +123,8 @@ def patch(self): # fix sequential compilation in 'src/seq_mv'
filter_file("\tmake", "\t$(MAKE)", "src/seq_mv/Makefile")
depends_on("mpi", when="+mpi")
depends_on("blas", when="+lapack")
depends_on("lapack", when="+lapack")
depends_on("blas")
depends_on("lapack")
depends_on("magma", when="+magma")
depends_on("superlu-dist", when="+superlu-dist+mpi")
depends_on("rocsparse", when="+rocm")
@@ -199,20 +198,17 @@ def url_for_version(self, version):
def configure_args(self):
spec = self.spec
configure_args = [f"--prefix={prefix}"]
# Note: --with-(lapack|blas)_libs= needs space separated list of names
if spec.satisfies("+lapack"):
configure_args.append("--with-lapack")
configure_args.append("--with-blas")
configure_args.append("--with-lapack-libs=%s" % " ".join(spec["lapack"].libs.names))
configure_args.append("--with-blas-libs=%s" % " ".join(spec["blas"].libs.names))
configure_args.append(
"--with-lapack-lib-dirs=%s" % " ".join(spec["lapack"].libs.directories)
)
configure_args.append(
"--with-blas-lib-dirs=%s" % " ".join(spec["blas"].libs.directories)
)
lapack = spec["lapack"].libs
blas = spec["blas"].libs
configure_args = [
"--prefix=%s" % prefix,
"--with-lapack-libs=%s" % " ".join(lapack.names),
"--with-lapack-lib-dirs=%s" % " ".join(lapack.directories),
"--with-blas-libs=%s" % " ".join(blas.names),
"--with-blas-lib-dirs=%s" % " ".join(blas.directories),
]
if spec.satisfies("+mpi"):
os.environ["CC"] = spec["mpi"].mpicc
@@ -249,9 +245,7 @@ def configure_args(self):
configure_args.append("--without-superlu")
# MLI and FEI do not build without superlu on Linux
configure_args.append("--without-mli")
# FEI option was removed in hypre 2.17
if self.version < Version("2.17.0"):
configure_args.append("--without-fei")
configure_args.append("--without-fei")
if spec.satisfies("+superlu-dist"):
configure_args.append(

View File

@@ -22,12 +22,6 @@ class IntelOneapiDpl(IntelOneApiLibraryPackage):
homepage = "https://github.com/oneapi-src/oneDPL"
version(
"2022.7.1",
url="https://registrationcenter-download.intel.com/akdlm/IRC_NAS/de3c613f-829c-4bdc-aa2b-6129eece3bd9/intel-onedpl-2022.7.1.15_offline.sh",
sha256="737f8d29f50fcb26abf7a39373305c177d8b91a70dbc5fed9d41aabfcc8bad5a",
expand=False,
)
version(
"2022.7.0",
url="https://registrationcenter-download.intel.com/akdlm/IRC_NAS/85ad74ff-f4fa-45e2-b50d-67d637d42baa/intel-onedpl-2022.7.0.647_offline.sh",

View File

@@ -21,12 +21,6 @@ class IntelOneapiMpi(IntelOneApiLibraryPackage):
homepage = "https://software.intel.com/content/www/us/en/develop/tools/oneapi/components/mpi-library.html"
version(
"2021.14.1",
url="https://registrationcenter-download.intel.com/akdlm/IRC_NAS/1acd5e79-796c-401a-ab31-a3dc7b20c6a2/intel-mpi-2021.14.1.7_offline.sh",
sha256="6459b9fc81fad9b9955de7fd9904e67fcf2ada3564ce0a74b9c14ea8fb533ddf",
expand=False,
)
version(
"2021.14.0",
url="https://registrationcenter-download.intel.com/akdlm/IRC_NAS/4b14b28c-2ca6-4559-a0ca-8a157627e0c8/intel-mpi-2021.14.0.791_offline.sh",

View File

@@ -250,9 +250,6 @@ class Julia(MakefilePackage):
depends_on("zlib-api")
depends_on("zlib +shared +pic +optimize", when="^[virtuals=zlib-api] zlib")
# https://github.com/JuliaLang/julia/pull/45649#issuecomment-1192377430
conflicts("%gcc@12:", when="@:1.7")
# Patches for julia
patch("julia-1.6-system-libwhich-and-p7zip-symlink.patch", when="@1.6.0:1.6")
patch("use-add-rpath.patch", when="@:1.8.0")

View File

@@ -3,6 +3,8 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from os import symlink
from spack.package import *
@@ -40,7 +42,9 @@ def install(self, spec, prefix):
"^TEsorter=.*$", "TEsorter={}".format(spec["py-tesorter"].prefix.bin), "paths"
)
install_tree(".", prefix)
mkdirp(prefix.opt)
mkdirp(prefix.bin)
def setup_run_environment(self, env):
env.prepend_path("PATH", self.prefix)
install_tree(".", prefix.opt.ltr_retriever)
symlink(prefix.opt.ltr_retriever.LTR_retriever, prefix.bin.LTR_retriever)

View File

@@ -383,7 +383,6 @@ def cmake_args(self):
# - MVAPICH --> mvapich
# - HPE MPT --> mpt
# - Cray MPICH --> mpich
# - HPC-X --> openmpi
if self.spec.satisfies("^mpich"):
args.append(self.define("MPI_STACK", "mpich"))
@@ -399,8 +398,6 @@ def cmake_args(self):
args.append(self.define("MPI_STACK", "mpt"))
elif self.spec.satisfies("^cray-mpich"):
args.append(self.define("MPI_STACK", "mpich"))
elif self.spec.satisfies("^hpcx-mpi"):
args.append(self.define("MPI_STACK", "openmpi"))
else:
raise InstallError("Unsupported MPI stack")

View File

@@ -702,10 +702,8 @@ def find_optional_library(name, prefix):
if "+mpi" in spec:
options += ["MPICXX=%s" % spec["mpi"].mpicxx]
hypre = spec["hypre"]
all_hypre_libs = hypre.libs
if "+lapack" in hypre:
all_hypre_libs += hypre["lapack"].libs + hypre["blas"].libs
# The hypre package always links with 'blas' and 'lapack'.
all_hypre_libs = hypre.libs + hypre["lapack"].libs + hypre["blas"].libs
hypre_gpu_libs = ""
if "+cuda" in hypre:
hypre_gpu_libs = " -lcusparse -lcurand -lcublas"

View File

@@ -46,8 +46,7 @@ class MiopenHip(CMakePackage):
conflicts("+asan", when="os=centos7")
conflicts("+asan", when="os=centos8")
depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("cxx", type="build") # generated
depends_on("cmake@3.5:", type="build")
depends_on("pkgconfig", type="build")

View File

@@ -92,8 +92,6 @@ def cmake_args(self):
or spec.satisfies("%apple-clang")
or spec.satisfies("%oneapi")
or spec.satisfies("%arm")
or spec.satisfies("%cce")
or spec.satisfies("%rocmcc")
):
c_flags.append("-Wno-error=implicit-function-declaration")
@@ -118,8 +116,6 @@ class NetlibScalapack(ScalapackBase):
git = "https://github.com/Reference-ScaLAPACK/scalapack"
tags = ["e4s"]
maintainers("etiennemlb")
license("BSD-3-Clause-Open-MPI")
version("2.2.0", sha256="40b9406c20735a9a3009d863318cb8d3e496fb073d201c5463df810e01ab2a57")

View File

@@ -15,7 +15,6 @@ class Nghttp2(AutotoolsPackage):
license("MIT")
version("1.64.0", sha256="20e73f3cf9db3f05988996ac8b3a99ed529f4565ca91a49eb0550498e10621e8")
version("1.63.0", sha256="9318a2cc00238f5dd6546212109fb833f977661321a2087f03034e25444d3dbb")
version("1.62.1", sha256="d0b0b9d00500ee4aa3bfcac00145d3b1ef372fd301c35bff96cf019c739db1b4")
version("1.62.0", sha256="482e41a46381d10adbdfdd44c1942ed5fd1a419e0ab6f4a5ff5b61468fe6f00d")

View File

@@ -58,8 +58,8 @@ class Openscenegraph(CMakePackage):
) # Qt windowing system was moved into separate osgQt project
depends_on("qt@4:", when="@3.2:3.5.4")
depends_on("qt@:4", when="@:3.1")
depends_on("libxinerama", when="platform=linux")
depends_on("libxrandr", when="platform=linux")
depends_on("libxinerama")
depends_on("libxrandr")
depends_on("libpng")
depends_on("jasper")
depends_on("libtiff")

View File

@@ -19,7 +19,6 @@ class PyJoblib(PythonPackage):
license("BSD-3-Clause")
version("1.4.2", sha256="2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e")
version("1.2.0", sha256="e1cee4a79e4af22881164f218d4311f60074197fb707e082e803b61f6d137018")
version("1.1.0", sha256="4158fcecd13733f8be669be0683b96ebdbbd38d23559f54dca7205aea1bf1e35")
version("1.0.1", sha256="9c17567692206d2f3fb9ecf5e991084254fe631665c450b443761c4186a613f7")
@@ -36,10 +35,7 @@ class PyJoblib(PythonPackage):
version("0.10.2", sha256="3123553bdad83b143428033537c9e1939caf4a4d8813dade6a2246948c94494b")
version("0.10.0", sha256="49b3a0ba956eaa2f077e1ebd230b3c8d7b98afc67520207ada20a4d8b8efd071")
with default_args(type=("build", "run")):
# https://github.com/joblib/joblib/pull/1361
depends_on("python@:3.11", when="@:1.2")
with default_args(type="build"):
depends_on("py-setuptools@61.2:", when="@1.4:")
depends_on("py-setuptools")
depends_on("python@3.7:", when="@1.2:", type=("build", "run"))
depends_on("python@3.6:", when="@0.15:", type=("build", "run"))
depends_on("python@2.7:2.8,3.4:", type=("build", "run"))
depends_on("py-setuptools", type=("build", "run"))

View File

@@ -23,7 +23,6 @@ class PyKeras(PythonPackage):
maintainers("adamjstewart")
license("Apache-2.0")
version("3.7.0", sha256="a4451a5591e75dfb414d0b84a3fd2fb9c0240cc87ebe7e397f547ce10b0e67b7")
version("3.6.0", sha256="405727525a3522ed8f9ec0b46e0667e4c65fcf714a067322c16a00d902ded41d")
version("3.5.0", sha256="53ae4f9472ec9d9c6941c82a3fda86969724ace3b7630a94ba0a1f17ba1065c3")
version("3.4.1", sha256="34cd9aeaa008914715149234c215657ca758e1b473bd2aab2e211ac967d1f8fe")
@@ -75,12 +74,10 @@ class PyKeras(PythonPackage):
)
with default_args(type="build"):
# pyproject.toml
depends_on("py-setuptools@61:", when="@3.7:")
depends_on("py-setuptools")
with default_args(type=("build", "run")):
# pyproject.toml
# setup.py
depends_on("python@3.9:", when="@3:")
depends_on("python@3.8:", when="@2.12:")
depends_on("py-absl-py", when="@2.6:")
@@ -101,8 +98,7 @@ class PyKeras(PythonPackage):
# requirements-tensorflow-cuda.txt
with when("backend=tensorflow"):
depends_on("py-tensorflow@2.18", when="@3.7:")
depends_on("py-tensorflow@2.17", when="@3.5:3.6")
depends_on("py-tensorflow@2.17", when="@3.5:")
depends_on("py-tensorflow@2.16.1:2.16", when="@3.0:3.4")
# requirements-jax-cuda.txt
@@ -113,15 +109,13 @@ class PyKeras(PythonPackage):
# requirements-torch-cuda.txt
with when("backend=torch"):
depends_on("py-torch@2.5.1", when="@3.7:")
depends_on("py-torch@2.4.1", when="@3.6")
depends_on("py-torch@2.4.1", when="@3.6:")
depends_on("py-torch@2.4.0", when="@3.5")
depends_on("py-torch@2.2.1", when="@3.1:3.4")
depends_on("py-torch@2.1.2", when="@3.0.3:3.0.5")
depends_on("py-torch@2.1.1", when="@3.0.1:3.0.2")
depends_on("py-torch@2.1.0", when="@3.0.0")
depends_on("py-torchvision@0.20.1", when="@3.7:")
depends_on("py-torchvision@0.19.1", when="@3.6")
depends_on("py-torchvision@0.19.1", when="@3.6:")
depends_on("py-torchvision@0.19.0", when="@3.5")
depends_on("py-torchvision@0.17.1", when="@3.1:3.4")
depends_on("py-torchvision@0.16.2", when="@3.0.3:3.0.5")

View File

@@ -2,7 +2,6 @@
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
from spack.package import *
@@ -51,35 +50,3 @@ def setup_build_environment(self, env):
def cythonize(self):
with working_dir(self.build_directory):
python(join_path("conf", "cythonize.py"))
def create_mpi_config_file(self, cfg_fn):
"""
create mpi.cfg file introduced since version 4.0.0.
see https://mpi4py.readthedocs.io/en/stable/mpi4py.html#mpi4py.get_config
"""
mpi_spec = self.spec["mpi"]
include_dirs = mpi_spec.headers.directories
library_dirs = mpi_spec.libs.directories
with open(cfg_fn, "w") as cfg:
cfg.write("[mpi]\n")
cfg.write("mpi_dir = {}\n".format(mpi_spec.prefix))
cfg.write("mpicc = {}\n".format(mpi_spec.mpicc))
cfg.write("mpicxx = {}\n".format(mpi_spec.mpicxx))
cfg.write("\n")
cfg.write("## define_macros =\n")
cfg.write("## undef_macros =\n")
cfg.write("include_dirs = {}\n".format(include_dirs))
cfg.write("## libraries = mpi\n")
cfg.write("library_dirs = {}\n".format(library_dirs))
cfg.write("## runtime_library_dirs = %(mpi_dir)s/lib\n")
cfg.write("\n")
cfg.write("## extra_compile_args =\n")
cfg.write("## extra_link_args =\n")
cfg.write("## extra_objects =\n")
@run_after("install", when="@4:")
def install_cfg(self):
python_dir = join_path(self.prefix, python_platlib, "mpi4py")
cfg_fn = join_path(python_dir, "mpi.cfg")
if not os.path.isfile(cfg_fn):
self.create_mpi_config_file(cfg_fn)

View File

@@ -12,10 +12,7 @@ class PyNbdime(PythonPackage):
homepage = "https://nbdime.readthedocs.io/"
pypi = "nbdime/nbdime-3.1.1.tar.gz"
version("3.2.1", sha256="31409a30f848ffc6b32540697e82d5a0a1b84dcc32716ca74e78bcc4b457c453")
with default_args(deprecated=True):
# https://nvd.nist.gov/vuln/detail/CVE-2021-41134
version("3.1.1", sha256="67767320e971374f701a175aa59abd3a554723039d39fae908e72d16330d648b")
version("3.1.1", sha256="67767320e971374f701a175aa59abd3a554723039d39fae908e72d16330d648b")
depends_on("python@3.6:", type=("build", "run"))
depends_on("py-setuptools@40.8.0:", type="build")

View File

@@ -73,7 +73,6 @@ class PyPandas(PythonPackage):
variant("excel", when="@1.4:", default=False, description="Build with support for Excel")
depends_on("c", type="build")
depends_on("cxx", type="build")
with default_args(type="build"):
depends_on("py-meson-python@0.13.1:", when="@2.1:")

View File

@@ -25,12 +25,6 @@ class PyPip(Package, PythonExtension):
license("MIT")
version("24.3.1", sha256="3790624780082365f47549d032f3770eeb2b1e8bd1f7b2e02dace1afa361b4ed")
version("24.2", sha256="2cd581cf58ab7fcfca4ce8efa6dcacd0de5bf8d0a3eb9ec927e07405f4d9e2a2")
version("24.1.2", sha256="7cd207eed4c60b0f411b444cd1464198fe186671c323b6cd6d433ed80fc9d247")
version("24.0", sha256="ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc")
version("23.3.2", sha256="5052d7889c1f9d05224cd41741acb7c5d6fa735ab34e339624a614eaaa7e7d76")
version("23.2.1", sha256="7ccf472345f20d35bdc9d1841ff5f313260c2c33fe417f48c30ac46cccabf5be")
version("23.1.2", sha256="3ef6ac33239e4027d9a5598a381b9d30880a1477e50039db2eac6e8a8f6d1b18")
version("23.0", sha256="b5f88adff801f5ef052bcdef3daa31b55eb67b0fccd6d0106c206fa248e0463c")
version("22.2.2", sha256="b61a374b5bc40a6e982426aede40c9b5a08ff20e640f5b56977f4f91fed1e39a")
@@ -46,7 +40,6 @@ class PyPip(Package, PythonExtension):
version("9.0.1", sha256="690b762c0a8460c303c089d5d0be034fb15a5ea2b75bdf565f40421f542fefb0")
extends("python")
depends_on("python@3.8:", when="@24.1:", type=("build", "run"))
depends_on("python@3.7:", when="@22:", type=("build", "run"))
# Uses collections.MutableMapping

View File

@@ -33,8 +33,7 @@ class PyPyvista(PythonPackage):
depends_on("pil", type=("build", "run"))
depends_on("py-pooch", when="@0.37:", type=("build", "run"))
depends_on("py-scooby@0.5.1:", type=("build", "run"))
# https://github.com/pyvista/pyvista/issues/6857
depends_on("vtk@:9.3+python", type=("build", "run"))
depends_on("vtk+python", type=("build", "run"))
depends_on("py-typing-extensions", when="^python@:3.7", type=("build", "run"))
# Historical dependencies

View File

@@ -30,6 +30,3 @@ class PyRiver(PythonPackage):
depends_on("py-numpy@1.22:", type=("build", "run"))
depends_on("py-scipy@1.5:", type=("build", "run"))
depends_on("py-pandas@1.3:", type=("build", "run"))
# https://github.com/online-ml/river/pull/1632
depends_on("py-numpy@:1", when="@:0.21", type=("build", "run"))

View File

@@ -16,7 +16,6 @@ class PyRuff(PythonPackage):
license("MIT")
maintainers("adamjstewart")
version("0.8.1", sha256="3583db9a6450364ed5ca3f3b4225958b24f78178908d5c4bc0f46251ccca898f")
version("0.8.0", sha256="a7ccfe6331bf8c8dad715753e157457faf7351c2b69f62f32c165c2dbcbacd44")
version("0.6.5", sha256="4d32d87fab433c0cf285c3683dd4dae63be05fd7a1d65b3f5bf7cdd05a6b96fb")
version("0.5.7", sha256="8dfc0a458797f5d9fb622dd0efc52d796f23f0a1493a9527f4e49a550ae9a7e5")

View File

@@ -14,10 +14,6 @@ class PyScooby(PythonPackage):
license("MIT")
version("0.10.0", sha256="7ea33c262c0cc6a33c6eeeb5648df787be4f22660e53c114e5fff1b811a8854f")
version("0.5.7", sha256="ae2c2b6f5f5d10adf7aaab32409028f1e28d3ce833664bdd1e8c2072e8da169a")
# https://github.com/banesullivan/scooby/pull/83
depends_on("python@:3.11", when="@:0.5", type=("build", "run"))
depends_on("py-setuptools", type="build")
depends_on("py-setuptools-scm", when="@0.10:", type="build")

View File

@@ -18,8 +18,7 @@ class PyTorchCluster(PythonPackage):
version("1.6.3", sha256="78d5a930a5bbd0d8788df8c6d66addd68d6dd292fe3edb401e3dacba26308152")
depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("cxx", type="build") # generated
depends_on("python", type=("build", "link", "run"))
depends_on("py-setuptools", type="build")

View File

@@ -18,8 +18,7 @@ class PyTorchScatter(PythonPackage):
version("2.1.2", sha256="69b3aa435f2424ac6a1bfb6ff702da6eb73b33ca0db38fb26989c74159258e47")
depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("cxx", type="build") # generated
depends_on("python", type=("build", "link", "run"))
depends_on("py-setuptools", type="build")

View File

@@ -21,8 +21,7 @@ class PyTorchSparse(PythonPackage):
version("0.6.8", sha256="312fb5ae6e4e575fca4bbc0bd092af85e7679d5b8e53459f24492fc2a073c7b6")
version("0.6.7", sha256="f69b2ed35baf2a9853234756a2b19e6f7ce88d2c1f029d1c7ca166d91e1adbd0")
depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("cxx", type="build") # generated
depends_on("py-setuptools", type="build")
depends_on("py-scipy", type=("build", "run"))

View File

@@ -18,8 +18,7 @@ class PyTorchSplineConv(PythonPackage):
version("1.2.2", sha256="ed45a81da29f774665dbdd4709d7e534cdf16d2e7006dbd06957f35bd09661b2")
depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("cxx", type="build") # generated
depends_on("python", type=("build", "link", "run"))
depends_on("py-setuptools", type="build")

View File

@@ -58,8 +58,3 @@ class RRsamtools(RPackage):
# this is not a listed dependency but is needed
depends_on("curl")
depends_on("zlib-api")
def patch(self):
with working_dir("src"):
filter_file(r"(^PKG_LIBS=)(\$\(RHTSLIB_LIBS\))", "\\1\\2 -lz", "Makevars")

View File

@@ -250,7 +250,7 @@ def initconfig_hardware_entries(self):
else:
entries.append(cmake_cache_option("ENABLE_HIP", False))
entries.append(cmake_cache_option("RAJA_ENABLE_TARGET_OPENMP", "+omptarget" in spec))
entries.append(cmake_cache_option("ENABLE_OPENMP_TARGET", "+omptarget" in spec))
if "+omptarget" in spec:
if "%xl" in spec:
entries.append(
@@ -321,7 +321,7 @@ def initconfig_package_entries(self):
entries.append(cmake_cache_option("BUILD_SHARED_LIBS", "+shared" in spec))
entries.append(cmake_cache_option("ENABLE_OPENMP", "+openmp" in spec))
entries.append(cmake_cache_option("RAJA_ENABLE_OPENMP_TASK", "+omptask" in spec))
entries.append(cmake_cache_option("RAJA_ENABLE_SYCL", spec.satisfies("+sycl")))
entries.append(cmake_cache_option("ENABLE_SYCL", spec.satisfies("+sycl")))
# C++17
if spec.satisfies("@2024.07.0:") and spec.satisfies("+sycl"):

View File

@@ -17,7 +17,6 @@ class Raylib(CMakePackage):
license("Zlib", checked_by="georgemalerbo")
version("5.5", sha256="aea98ecf5bc5c5e0b789a76de0083a21a70457050ea4cc2aec7566935f5e258e")
version("5.0", sha256="98f049b9ea2a9c40a14e4e543eeea1a7ec3090ebdcd329c4ca2cf98bc9793482")
depends_on("c", type="build") # generated

View File

@@ -40,8 +40,7 @@ class Rocfft(CMakePackage):
version("5.3.3", sha256="678c18710578c1fb36a0009311bb79de7607c3468f9102cfba56a866ebb7ff78")
version("5.3.0", sha256="d655c5541c4aff4267e80e36d002fc3a55c2f84a0ae8631197c12af3bf03fa7d")
depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("cxx", type="build") # generated
amdgpu_targets = ROCmPackage.amdgpu_targets

View File

@@ -41,8 +41,7 @@ class RoctracerDev(CMakePackage, ROCmPackage):
version("5.3.3", sha256="f2cb1e6bb69ea1a628c04f984741f781ae1d8498dc58e15795bb03015f924d13")
version("5.3.0", sha256="36f1da60863a113bb9fe2957949c661f00a702e249bb0523cda1fb755c053808")
depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("cxx", type="build") # generated
variant("asan", default=False, description="Build with address-sanitizer enabled or disabled")

View File

@@ -12,7 +12,7 @@ class Rsync(AutotoolsPackage):
"""An open source utility that provides fast incremental file transfer."""
homepage = "https://rsync.samba.org"
url = "https://download.samba.org/pub/rsync/src/rsync-3.3.0.tar.gz"
url = "https://download.samba.org/pub/rsync/src/rsync-3.2.4.tar.gz"
license("GPL-3.0-or-later")
@@ -20,42 +20,16 @@ class Rsync(AutotoolsPackage):
version("3.2.7", sha256="4e7d9d3f6ed10878c58c5fb724a67dacf4b6aac7340b13e488fb2dc41346f2bb")
version("3.2.6", sha256="fb3365bab27837d41feaf42e967c57bd3a47bc8f10765a3671efd6a3835454d3")
version("3.2.5", sha256="2ac4d21635cdf791867bc377c35ca6dda7f50d919a58be45057fd51600c69aba")
version("3.2.4", sha256="6f761838d08052b0b6579cf7f6737d93e47f01f4da04c5d24d3447b7f2a5fad1")
version("3.2.3", sha256="becc3c504ceea499f4167a260040ccf4d9f2ef9499ad5683c179a697146ce50e")
version("3.2.2", sha256="644bd3841779507665211fd7db8359c8a10670c57e305b4aab61b4e40037afa8")
version("3.1.3", sha256="55cc554efec5fdaad70de921cd5a5eeb6c29a95524c715f3bbf849235b0800c0")
version("3.1.2", sha256="ecfa62a7fa3c4c18b9eccd8c16eaddee4bd308a76ea50b5c02a5840f09c0a1c2")
version("3.1.1", sha256="7de4364fcf5fe42f3bdb514417f1c40d10bbca896abe7e7f2c581c6ea08a2621")
# Releases before 3.2.5 are deprecated because of CVE-2022-29154
# https://nvd.nist.gov/vuln/detail/CVE-2022-29154
version(
"3.2.4",
sha256="6f761838d08052b0b6579cf7f6737d93e47f01f4da04c5d24d3447b7f2a5fad1",
deprecated=True,
)
version(
"3.2.3",
sha256="becc3c504ceea499f4167a260040ccf4d9f2ef9499ad5683c179a697146ce50e",
deprecated=True,
)
version(
"3.2.2",
sha256="644bd3841779507665211fd7db8359c8a10670c57e305b4aab61b4e40037afa8",
deprecated=True,
)
version(
"3.1.3",
sha256="55cc554efec5fdaad70de921cd5a5eeb6c29a95524c715f3bbf849235b0800c0",
deprecated=True,
)
version(
"3.1.2",
sha256="ecfa62a7fa3c4c18b9eccd8c16eaddee4bd308a76ea50b5c02a5840f09c0a1c2",
deprecated=True,
)
version(
"3.1.1",
sha256="7de4364fcf5fe42f3bdb514417f1c40d10bbca896abe7e7f2c581c6ea08a2621",
deprecated=True,
)
depends_on("c", type="build") # generated
depends_on("cxx", type="build") # generated
depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("zlib-api")
depends_on("popt")
depends_on("openssl", when="@3.2:")

View File

@@ -304,9 +304,6 @@ class Seacas(CMakePackage):
when="@:2023-10-24",
)
# Based on install-tpl.sh script, cereal seems to only be used when faodel enabled
depends_on("cereal", when="@2021-04-02: +faodel")
def setup_run_environment(self, env):
env.prepend_path("PYTHONPATH", self.prefix.lib)
@@ -489,15 +486,6 @@ def cmake_args(self):
if pkg.lower() in spec:
options.append(define(pkg + "_ROOT", spec[pkg.lower()].prefix))
if "+faodel" in spec:
# faodel headers are under $faodel_prefix/include/faodel but seacas
# leaves off the faodel part
faodel_incdir = spec["faodel"].prefix.include
faodel_incdir2 = spec["faodel"].prefix.include.faodel
faodel_incdirs = [faodel_incdir, faodel_incdir2]
options.append(define("Faodel_INCLUDE_DIRS", ";".join(faodel_incdirs)))
options.append(define("Faodel_LIBRARY_DIRS", spec["faodel"].prefix.lib))
options.append(from_variant("TPL_ENABLE_ADIOS2", "adios2"))
if "+adios2" in spec:
options.append(define("ADIOS2_ROOT", spec["adios2"].prefix))

View File

@@ -190,6 +190,9 @@ def edit(self, spec, prefix):
spec["netcdf-fortran"].prefix
)
)
libs_arg.append(
"-L{0}/lib -lhdf5_fortran -lhdf5".format(spec["hdf5"].prefix)
)
if "+metis" in spec:
libs_arg.append("-L{0} -lmetis".format(self.spec["metis"].prefix.lib))

View File

@@ -87,15 +87,14 @@ class Vtk(CMakePackage):
conflicts("%gcc@13", when="@9.2")
# Based on PyPI wheel availability
with when("+python"), default_args(type=("build", "link", "run")):
depends_on("python@:3.13")
depends_on("python@:3.12", when="@:9.3")
depends_on("python@:3.11", when="@:9.2")
depends_on("python@:3.10", when="@:9.2.2")
depends_on("python@:3.9", when="@:9.1")
depends_on("python@:3.8", when="@:9.0.1")
depends_on("python@:3.7", when="@:8.2.0")
with when("+python"):
# Depend on any Python, add bounds below.
extends("python@2.7:", type=("build", "run"))
depends_on("python@:3.7", when="@:8.2.0", type=("build", "run"))
# Python 3.8 support from vtk 9 and patched 8.2
depends_on("python@:3.8", when="@:8.2.1a", type=("build", "run"))
# Python 3.10 support from vtk 9.2
depends_on("python@:3.9", when="@:9.1", type=("build", "run"))
# We need mpi4py if buidling python wrappers and using MPI
depends_on("py-mpi4py", when="+python+mpi", type="run")