Compare commits
32 Commits
hs/crypto/
...
develop-20
Author | SHA1 | Date | |
---|---|---|---|
![]() |
29427d3e9e | ||
![]() |
2a2d1989c1 | ||
![]() |
c6e292f55f | ||
![]() |
bf5e6b4aaf | ||
![]() |
9760089089 | ||
![]() |
da7c5c551d | ||
![]() |
a575fa8529 | ||
![]() |
39a65d88f6 | ||
![]() |
06ff8c88ac | ||
![]() |
a96b67ce3d | ||
![]() |
67d494fa0b | ||
![]() |
e37e53cfe8 | ||
![]() |
cf31d20d4c | ||
![]() |
b74db341c8 | ||
![]() |
e88a3f6f85 | ||
![]() |
9bd7483e73 | ||
![]() |
04c76fab63 | ||
![]() |
ecbf9fcacf | ||
![]() |
69fb594699 | ||
![]() |
d28614151f | ||
![]() |
f1d6af6c94 | ||
![]() |
192821f361 | ||
![]() |
18790ca397 | ||
![]() |
c22d77a38e | ||
![]() |
d82bdb3bf7 | ||
![]() |
a042bdfe0b | ||
![]() |
60e3e645e8 | ||
![]() |
51785437bc | ||
![]() |
2e8db0815d | ||
![]() |
8a6428746f | ||
![]() |
6b9c099af8 | ||
![]() |
30814fb4e0 |
2
.github/workflows/build-containers.yml
vendored
2
.github/workflows/build-containers.yml
vendored
@@ -120,7 +120,7 @@ jobs:
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build & Deploy ${{ matrix.dockerfile[0] }}
|
||||
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75
|
||||
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355
|
||||
with:
|
||||
context: dockerfiles/${{ matrix.dockerfile[0] }}
|
||||
platforms: ${{ matrix.dockerfile[1] }}
|
||||
|
@@ -24,6 +24,7 @@
|
||||
Callable,
|
||||
Deque,
|
||||
Dict,
|
||||
Generator,
|
||||
Iterable,
|
||||
List,
|
||||
Match,
|
||||
@@ -2772,22 +2773,6 @@ 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."""
|
||||
@@ -2838,6 +2823,25 @@ 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.
|
||||
|
@@ -2334,7 +2334,9 @@ def is_backup_file(file):
|
||||
if not codesign:
|
||||
return
|
||||
for binary in changed_files:
|
||||
codesign("-fs-", binary)
|
||||
# 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)
|
||||
|
||||
# If we are installing back to the same location
|
||||
# relocate the sbang location if the spack directory changed
|
||||
|
@@ -9,7 +9,7 @@
|
||||
import re
|
||||
import sys
|
||||
from itertools import chain
|
||||
from typing import Any, List, Optional, Set, Tuple
|
||||
from typing import Any, List, Optional, Tuple
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
from llnl.util.lang import stable_partition
|
||||
@@ -21,6 +21,7 @@
|
||||
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
|
||||
@@ -166,15 +167,18 @@ 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."""
|
||||
# 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 pkg.spec.traverse(root=False, order="topo") if s.dag_hash() in selected),
|
||||
lambda x: x.external,
|
||||
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]
|
||||
# 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)
|
||||
|
||||
return filter_system_paths(
|
||||
path for spec in chain(spack_built, externals) for path in spec.package.cmake_prefix_paths
|
||||
|
@@ -13,6 +13,7 @@
|
||||
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
|
||||
@@ -275,10 +276,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:
|
||||
args.append(str(cur_path))
|
||||
install_name_tool = executable.Executable("install_name_tool")
|
||||
install_name_tool(*args)
|
||||
with fs.edit_in_place_through_temporary_file(cur_path) as temp_path:
|
||||
install_name_tool(*args, temp_path)
|
||||
|
||||
|
||||
def macholib_get_paths(cur_path):
|
||||
@@ -717,8 +718,8 @@ def fixup_macos_rpath(root, filename):
|
||||
# No fixes needed
|
||||
return False
|
||||
|
||||
args.append(abspath)
|
||||
executable.Executable("install_name_tool")(*args)
|
||||
with fs.edit_in_place_through_temporary_file(abspath) as temp_path:
|
||||
executable.Executable("install_name_tool")(*args, temp_path)
|
||||
return True
|
||||
|
||||
|
||||
|
@@ -1249,3 +1249,14 @@ 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
|
||||
|
@@ -20,9 +20,8 @@ def create_dag(nodes, edges):
|
||||
"""
|
||||
specs = {name: Spec(name) for name in nodes}
|
||||
for parent, child, deptypes in edges:
|
||||
specs[parent].add_dependency_edge(
|
||||
specs[child], depflag=dt.canonicalize(deptypes), virtuals=()
|
||||
)
|
||||
depflag = deptypes if isinstance(deptypes, dt.DepFlag) else dt.canonicalize(deptypes)
|
||||
specs[parent].add_dependency_edge(specs[child], depflag=depflag, virtuals=())
|
||||
return specs
|
||||
|
||||
|
||||
@@ -454,3 +453,61 @@ 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"),
|
||||
}
|
||||
|
@@ -607,6 +607,9 @@ 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")
|
||||
|
@@ -4,7 +4,7 @@
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
from collections import defaultdict
|
||||
from typing import NamedTuple, Union
|
||||
from typing import Any, Callable, List, NamedTuple, Set, Union
|
||||
|
||||
import spack.deptypes as dt
|
||||
import spack.spec
|
||||
@@ -115,6 +115,64 @@ 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
|
||||
):
|
||||
@@ -342,9 +400,7 @@ 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, CoverEdgesVisitor(visitor, key=key), root=True, depth=False
|
||||
):
|
||||
for edge in traverse_breadth_first_edges_generator(edges, visitor, 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)
|
||||
@@ -422,9 +478,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 edges even if we are yielding
|
||||
# a subset of them, hence "paths".
|
||||
_cover = "paths" if order == "topo" else cover
|
||||
# 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
|
||||
visitor = get_visitor_from_args(_cover, direction, deptype, key, visited)
|
||||
root_edges = with_artificial_edges(specs)
|
||||
|
||||
|
@@ -4,8 +4,7 @@
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
from typing import Callable, Dict, Optional
|
||||
from typing import BinaryIO, Callable, Dict, Optional
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
||||
@@ -81,24 +80,20 @@ def hash_fun_for_digest(hexdigest: str) -> HashFactory:
|
||||
return hash_fun_for_algo(hash_algo_for_digest(hexdigest))
|
||||
|
||||
|
||||
def checksum_stream(hashlib_algo: HashFactory, fp, *, block_size: int = 2**20) -> str:
|
||||
def checksum_stream(hashlib_algo: HashFactory, fp: BinaryIO, *, block_size: int = 2**20) -> str:
|
||||
"""Returns a hex digest of the stream generated using given algorithm from hashlib."""
|
||||
hasher = hashlib_algo()
|
||||
with memoryview(bytearray(block_size)) as view:
|
||||
while True:
|
||||
n = fp.readinto(view)
|
||||
if n == block_size:
|
||||
hasher.update(view)
|
||||
else:
|
||||
hasher.update(view[:n])
|
||||
break
|
||||
while True:
|
||||
data = fp.read(block_size)
|
||||
if not data:
|
||||
break
|
||||
hasher.update(data)
|
||||
return hasher.hexdigest()
|
||||
|
||||
|
||||
def checksum(hashlib_algo: HashFactory, filename: str, *, block_size: int = 2**20) -> str:
|
||||
"""Returns a hex digest of the filename generated using an algorithm from hashlib."""
|
||||
with open(filename, "rb") as f:
|
||||
block_size = min(block_size, os.fstat(f.fileno()).st_size)
|
||||
return checksum_stream(hashlib_algo, f, block_size=block_size)
|
||||
|
||||
|
||||
|
@@ -13,7 +13,7 @@
|
||||
import sys
|
||||
|
||||
from llnl.util import tty
|
||||
from llnl.util.filesystem import join_path
|
||||
from llnl.util.filesystem import edit_in_place_through_temporary_file
|
||||
from llnl.util.lang import memoized
|
||||
|
||||
from spack.util.executable import Executable, which
|
||||
@@ -81,12 +81,11 @@ def fix_darwin_install_name(path):
|
||||
Parameters:
|
||||
path (str): directory in which .dylib files are located
|
||||
"""
|
||||
libs = glob.glob(join_path(path, "*.dylib"))
|
||||
libs = glob.glob(os.path.join(path, "*.dylib"))
|
||||
install_name_tool = Executable("install_name_tool")
|
||||
otool = Executable("otool")
|
||||
for lib in libs:
|
||||
# fix install name first:
|
||||
install_name_tool = Executable("install_name_tool")
|
||||
install_name_tool("-id", lib, lib)
|
||||
otool = Executable("otool")
|
||||
args = ["-id", lib]
|
||||
long_deps = otool("-L", lib, output=str).split("\n")
|
||||
deps = [dep.partition(" ")[0][1::] for dep in long_deps[2:-1]]
|
||||
# fix all dependencies:
|
||||
@@ -98,5 +97,8 @@ 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):
|
||||
install_name_tool("-change", dep, loc, lib)
|
||||
args.extend(("-change", dep, loc))
|
||||
break
|
||||
|
||||
with edit_in_place_through_temporary_file(lib) as tmp:
|
||||
install_name_tool(*args, tmp)
|
||||
|
@@ -25,11 +25,13 @@
|
||||
)
|
||||
from .version_types import (
|
||||
ClosedOpenRange,
|
||||
ConcreteVersion,
|
||||
GitVersion,
|
||||
StandardVersion,
|
||||
Version,
|
||||
VersionList,
|
||||
VersionRange,
|
||||
VersionType,
|
||||
_next_version,
|
||||
_prev_version,
|
||||
from_string,
|
||||
@@ -40,21 +42,23 @@
|
||||
any_version: VersionList = VersionList([":"])
|
||||
|
||||
__all__ = [
|
||||
"Version",
|
||||
"VersionRange",
|
||||
"ver",
|
||||
"from_string",
|
||||
"is_git_version",
|
||||
"infinity_versions",
|
||||
"_prev_version",
|
||||
"_next_version",
|
||||
"VersionList",
|
||||
"ClosedOpenRange",
|
||||
"StandardVersion",
|
||||
"GitVersion",
|
||||
"VersionError",
|
||||
"VersionChecksumError",
|
||||
"VersionLookupError",
|
||||
"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",
|
||||
]
|
||||
|
@@ -3,10 +3,9 @@
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import numbers
|
||||
import re
|
||||
from bisect import bisect_left
|
||||
from typing import List, Optional, Tuple, Union
|
||||
from typing import Dict, Iterable, Iterator, List, Optional, Tuple, Union
|
||||
|
||||
from spack.util.spack_yaml import syaml_dict
|
||||
|
||||
@@ -32,26 +31,44 @@
|
||||
|
||||
|
||||
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"]
|
||||
|
||||
def __init__(self, data):
|
||||
data: Union[int, str]
|
||||
|
||||
def __init__(self, data: Union[int, str]):
|
||||
# int for infinity index, str for literal.
|
||||
self.data: Union[int, str] = data
|
||||
self.data = data
|
||||
|
||||
@staticmethod
|
||||
def from_string(string):
|
||||
def from_string(string: str) -> "VersionStrComponent":
|
||||
value: Union[int, str] = string
|
||||
if len(string) >= iv_min_len:
|
||||
try:
|
||||
string = infinity_versions.index(string)
|
||||
value = infinity_versions.index(string)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return VersionStrComponent(string)
|
||||
return VersionStrComponent(value)
|
||||
|
||||
def __hash__(self):
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.data)
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return (
|
||||
("infinity" if self.data >= len(infinity_versions) else infinity_versions[self.data])
|
||||
if isinstance(self.data, int)
|
||||
@@ -61,38 +78,61 @@ def __str__(self):
|
||||
def __repr__(self) -> str:
|
||||
return f'VersionStrComponent("{self}")'
|
||||
|
||||
def __eq__(self, other):
|
||||
def __eq__(self, other: object) -> bool:
|
||||
return isinstance(other, VersionStrComponent) and self.data == other.data
|
||||
|
||||
def __lt__(self, other):
|
||||
lhs_inf = isinstance(self.data, int)
|
||||
# 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)
|
||||
if isinstance(other, int):
|
||||
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
|
||||
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
|
||||
|
||||
def __le__(self, other):
|
||||
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:
|
||||
return self < other or self == other
|
||||
|
||||
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):
|
||||
def __ge__(self, other: object) -> bool:
|
||||
return self > other or self == other
|
||||
|
||||
|
||||
def parse_string_components(string: str) -> Tuple[tuple, tuple]:
|
||||
# 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``."""
|
||||
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(m[2] for m in segments)
|
||||
separators: Tuple[str] = tuple(m[2] for m in segments)
|
||||
prerelease: Tuple[int, ...]
|
||||
|
||||
# <version>(alpha|beta|rc)<number>
|
||||
@@ -109,63 +149,150 @@ def parse_string_components(string: str) -> Tuple[tuple, tuple]:
|
||||
else:
|
||||
prerelease = (FINAL,)
|
||||
|
||||
release = tuple(int(m[0]) if m[0] else VersionStrComponent.from_string(m[1]) for m in segments)
|
||||
release: VersionComponentTuple = tuple(
|
||||
int(m[0]) if m[0] else VersionStrComponent.from_string(m[1]) for m in segments
|
||||
)
|
||||
|
||||
return (release, prerelease), separators
|
||||
|
||||
|
||||
class ConcreteVersion:
|
||||
pass
|
||||
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
|
||||
|
||||
|
||||
def _stringify_version(versions: Tuple[tuple, tuple], separators: tuple) -> str:
|
||||
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."""
|
||||
release, prerelease = versions
|
||||
string = ""
|
||||
for i in range(len(release)):
|
||||
string += f"{release[i]}{separators[i]}"
|
||||
|
||||
components = [f"{rel}{sep}" for rel, sep in zip(release, separators)]
|
||||
if prerelease[0] != FINAL:
|
||||
string += f"{PRERELEASE_TO_STRING[prerelease[0]]}{separators[len(release)]}"
|
||||
if len(prerelease) > 1:
|
||||
string += str(prerelease[1])
|
||||
return string
|
||||
components.append(PRERELEASE_TO_STRING[prerelease[0]])
|
||||
if len(prerelease) > 1:
|
||||
components.append(separators[len(release)])
|
||||
components.append(str(prerelease[1]))
|
||||
|
||||
return "".join(components)
|
||||
|
||||
|
||||
class StandardVersion(ConcreteVersion):
|
||||
"""Class to represent versions"""
|
||||
|
||||
__slots__ = ["version", "string", "separators"]
|
||||
__slots__ = ["version", "_string", "separators"]
|
||||
|
||||
def __init__(self, string: Optional[str], version: Tuple[tuple, tuple], separators: tuple):
|
||||
self.string = string
|
||||
_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
|
||||
self.version = version
|
||||
self.separators = separators
|
||||
|
||||
@staticmethod
|
||||
def from_string(string: str):
|
||||
def from_string(string: str) -> "StandardVersion":
|
||||
return StandardVersion(string, *parse_string_components(string))
|
||||
|
||||
@staticmethod
|
||||
def typemin():
|
||||
def typemin() -> "StandardVersion":
|
||||
return _STANDARD_VERSION_TYPEMIN
|
||||
|
||||
@staticmethod
|
||||
def typemax():
|
||||
def typemax() -> "StandardVersion":
|
||||
return _STANDARD_VERSION_TYPEMAX
|
||||
|
||||
def __bool__(self):
|
||||
@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:
|
||||
return True
|
||||
|
||||
def __eq__(self, other):
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if isinstance(other, StandardVersion):
|
||||
return self.version == other.version
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
def __ne__(self, other: object) -> bool:
|
||||
if isinstance(other, StandardVersion):
|
||||
return self.version != other.version
|
||||
return True
|
||||
|
||||
def __lt__(self, other):
|
||||
def __lt__(self, other: object) -> bool:
|
||||
if isinstance(other, StandardVersion):
|
||||
return self.version < other.version
|
||||
if isinstance(other, ClosedOpenRange):
|
||||
@@ -173,7 +300,7 @@ def __lt__(self, other):
|
||||
return self <= other.lo
|
||||
return NotImplemented
|
||||
|
||||
def __le__(self, other):
|
||||
def __le__(self, other: object) -> bool:
|
||||
if isinstance(other, StandardVersion):
|
||||
return self.version <= other.version
|
||||
if isinstance(other, ClosedOpenRange):
|
||||
@@ -181,7 +308,7 @@ def __le__(self, other):
|
||||
return self <= other.lo
|
||||
return NotImplemented
|
||||
|
||||
def __ge__(self, other):
|
||||
def __ge__(self, other: object) -> bool:
|
||||
if isinstance(other, StandardVersion):
|
||||
return self.version >= other.version
|
||||
if isinstance(other, ClosedOpenRange):
|
||||
@@ -189,25 +316,25 @@ def __ge__(self, other):
|
||||
return self > other.lo
|
||||
return NotImplemented
|
||||
|
||||
def __gt__(self, other):
|
||||
def __gt__(self, other: object) -> bool:
|
||||
if isinstance(other, StandardVersion):
|
||||
return self.version > other.version
|
||||
if isinstance(other, ClosedOpenRange):
|
||||
return self > other.lo
|
||||
return NotImplemented
|
||||
|
||||
def __iter__(self):
|
||||
def __iter__(self) -> Iterator:
|
||||
return iter(self.version[0])
|
||||
|
||||
def __len__(self):
|
||||
def __len__(self) -> int:
|
||||
return len(self.version[0])
|
||||
|
||||
def __getitem__(self, idx):
|
||||
def __getitem__(self, idx: Union[int, slice]):
|
||||
cls = type(self)
|
||||
|
||||
release = self.version[0]
|
||||
|
||||
if isinstance(idx, numbers.Integral):
|
||||
if isinstance(idx, int):
|
||||
return release[idx]
|
||||
|
||||
elif isinstance(idx, slice):
|
||||
@@ -220,45 +347,38 @@ def __getitem__(self, idx):
|
||||
|
||||
if string_arg:
|
||||
string_arg.pop() # We don't need the last separator
|
||||
string_arg = "".join(string_arg)
|
||||
return cls.from_string(string_arg)
|
||||
return cls.from_string("".join(string_arg))
|
||||
else:
|
||||
return StandardVersion.from_string("")
|
||||
|
||||
message = "{cls.__name__} indices must be integers"
|
||||
raise TypeError(message.format(cls=cls))
|
||||
raise TypeError(f"{cls.__name__} indices must be integers or slices")
|
||||
|
||||
def __str__(self):
|
||||
return self.string or _stringify_version(self.version, self.separators)
|
||||
def __str__(self) -> str:
|
||||
return self.string
|
||||
|
||||
def __repr__(self) -> str:
|
||||
# Print indirect repr through Version(...)
|
||||
return f'Version("{str(self)}")'
|
||||
|
||||
def __hash__(self):
|
||||
def __hash__(self) -> int:
|
||||
# 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):
|
||||
def __contains__(rhs, lhs) -> bool:
|
||||
# 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, (StandardVersion, ClosedOpenRange, VersionList)):
|
||||
if isinstance(lhs, VersionType):
|
||||
return lhs.satisfies(rhs)
|
||||
raise ValueError(lhs)
|
||||
raise TypeError(f"'in' not supported for instances of {type(lhs)}")
|
||||
|
||||
def intersects(self, other: Union["StandardVersion", "GitVersion", "ClosedOpenRange"]) -> bool:
|
||||
def intersects(self, other: VersionType) -> bool:
|
||||
if isinstance(other, StandardVersion):
|
||||
return self == other
|
||||
return other.intersects(self)
|
||||
|
||||
def overlaps(self, other) -> bool:
|
||||
return self.intersects(other)
|
||||
|
||||
def satisfies(
|
||||
self, other: Union["ClosedOpenRange", "StandardVersion", "GitVersion", "VersionList"]
|
||||
) -> bool:
|
||||
def satisfies(self, other: VersionType) -> bool:
|
||||
if isinstance(other, GitVersion):
|
||||
return False
|
||||
|
||||
@@ -271,19 +391,19 @@ def satisfies(
|
||||
if isinstance(other, VersionList):
|
||||
return other.intersects(self)
|
||||
|
||||
return NotImplemented
|
||||
raise NotImplementedError
|
||||
|
||||
def union(self, other: Union["ClosedOpenRange", "StandardVersion"]):
|
||||
def union(self, other: VersionType) -> VersionType:
|
||||
if isinstance(other, StandardVersion):
|
||||
return self if self == other else VersionList([self, other])
|
||||
return other.union(self)
|
||||
|
||||
def intersection(self, other: Union["ClosedOpenRange", "StandardVersion"]):
|
||||
def intersection(self, other: VersionType) -> VersionType:
|
||||
if isinstance(other, StandardVersion):
|
||||
return self if self == other else VersionList()
|
||||
return other.intersection(self)
|
||||
|
||||
def isdevelop(self):
|
||||
def isdevelop(self) -> bool:
|
||||
"""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]
|
||||
@@ -304,7 +424,7 @@ def dotted_numeric_string(self) -> str:
|
||||
return ".".join(str(v) for v in numeric)
|
||||
|
||||
@property
|
||||
def dotted(self):
|
||||
def dotted(self) -> "StandardVersion":
|
||||
"""The dotted representation of the version.
|
||||
|
||||
Example:
|
||||
@@ -318,7 +438,7 @@ def dotted(self):
|
||||
return type(self).from_string(self.string.replace("-", ".").replace("_", "."))
|
||||
|
||||
@property
|
||||
def underscored(self):
|
||||
def underscored(self) -> "StandardVersion":
|
||||
"""The underscored representation of the version.
|
||||
|
||||
Example:
|
||||
@@ -333,7 +453,7 @@ def underscored(self):
|
||||
return type(self).from_string(self.string.replace(".", "_").replace("-", "_"))
|
||||
|
||||
@property
|
||||
def dashed(self):
|
||||
def dashed(self) -> "StandardVersion":
|
||||
"""The dashed representation of the version.
|
||||
|
||||
Example:
|
||||
@@ -347,7 +467,7 @@ def dashed(self):
|
||||
return type(self).from_string(self.string.replace(".", "-").replace("_", "-"))
|
||||
|
||||
@property
|
||||
def joined(self):
|
||||
def joined(self) -> "StandardVersion":
|
||||
"""The joined representation of the version.
|
||||
|
||||
Example:
|
||||
@@ -362,7 +482,7 @@ def joined(self):
|
||||
self.string.replace(".", "").replace("-", "").replace("_", "")
|
||||
)
|
||||
|
||||
def up_to(self, index):
|
||||
def up_to(self, index: int) -> "StandardVersion":
|
||||
"""The version up to the specified component.
|
||||
|
||||
Examples:
|
||||
@@ -482,7 +602,7 @@ def ref_version(self) -> StandardVersion:
|
||||
)
|
||||
return self._ref_version
|
||||
|
||||
def intersects(self, other):
|
||||
def intersects(self, other: VersionType) -> bool:
|
||||
# For concrete things intersects = satisfies = equality
|
||||
if isinstance(other, GitVersion):
|
||||
return self == other
|
||||
@@ -492,19 +612,14 @@ def intersects(self, other):
|
||||
return self.ref_version.intersects(other)
|
||||
if isinstance(other, VersionList):
|
||||
return any(self.intersects(rhs) for rhs in other)
|
||||
raise ValueError(f"Unexpected type {type(other)}")
|
||||
raise TypeError(f"'intersects()' not supported for instances of {type(other)}")
|
||||
|
||||
def intersection(self, other):
|
||||
def intersection(self, other: VersionType) -> VersionType:
|
||||
if isinstance(other, ConcreteVersion):
|
||||
return self if self == other else VersionList()
|
||||
return other.intersection(self)
|
||||
|
||||
def overlaps(self, other) -> bool:
|
||||
return self.intersects(other)
|
||||
|
||||
def satisfies(
|
||||
self, other: Union["GitVersion", StandardVersion, "ClosedOpenRange", "VersionList"]
|
||||
):
|
||||
def satisfies(self, other: VersionType) -> bool:
|
||||
# Concrete versions mean we have to do an equality check
|
||||
if isinstance(other, GitVersion):
|
||||
return self == other
|
||||
@@ -514,9 +629,9 @@ def satisfies(
|
||||
return self.ref_version.satisfies(other)
|
||||
if isinstance(other, VersionList):
|
||||
return any(self.satisfies(rhs) for rhs in other)
|
||||
raise ValueError(f"Unexpected type {type(other)}")
|
||||
raise TypeError(f"'satisfies()' not supported for instances of {type(other)}")
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
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.
|
||||
@@ -534,7 +649,7 @@ def __repr__(self):
|
||||
def __bool__(self):
|
||||
return True
|
||||
|
||||
def __eq__(self, other):
|
||||
def __eq__(self, other: object) -> bool:
|
||||
# GitVersion cannot be equal to StandardVersion, otherwise == is not transitive
|
||||
return (
|
||||
isinstance(other, GitVersion)
|
||||
@@ -542,10 +657,10 @@ def __eq__(self, other):
|
||||
and self.ref_version == other.ref_version
|
||||
)
|
||||
|
||||
def __ne__(self, other):
|
||||
def __ne__(self, other: object) -> bool:
|
||||
return not self == other
|
||||
|
||||
def __lt__(self, other):
|
||||
def __lt__(self, other: object) -> bool:
|
||||
if isinstance(other, GitVersion):
|
||||
return (self.ref_version, self.ref) < (other.ref_version, other.ref)
|
||||
if isinstance(other, StandardVersion):
|
||||
@@ -553,9 +668,9 @@ def __lt__(self, other):
|
||||
return self.ref_version < other
|
||||
if isinstance(other, ClosedOpenRange):
|
||||
return self.ref_version < other
|
||||
raise ValueError(f"Unexpected type {type(other)}")
|
||||
raise TypeError(f"'<' not supported between instances of {type(self)} and {type(other)}")
|
||||
|
||||
def __le__(self, other):
|
||||
def __le__(self, other: object) -> bool:
|
||||
if isinstance(other, GitVersion):
|
||||
return (self.ref_version, self.ref) <= (other.ref_version, other.ref)
|
||||
if isinstance(other, StandardVersion):
|
||||
@@ -564,9 +679,9 @@ def __le__(self, other):
|
||||
if isinstance(other, ClosedOpenRange):
|
||||
# Equality is not a thing
|
||||
return self.ref_version < other
|
||||
raise ValueError(f"Unexpected type {type(other)}")
|
||||
raise TypeError(f"'<=' not supported between instances of {type(self)} and {type(other)}")
|
||||
|
||||
def __ge__(self, other):
|
||||
def __ge__(self, other: object) -> bool:
|
||||
if isinstance(other, GitVersion):
|
||||
return (self.ref_version, self.ref) >= (other.ref_version, other.ref)
|
||||
if isinstance(other, StandardVersion):
|
||||
@@ -574,9 +689,9 @@ def __ge__(self, other):
|
||||
return self.ref_version >= other
|
||||
if isinstance(other, ClosedOpenRange):
|
||||
return self.ref_version > other
|
||||
raise ValueError(f"Unexpected type {type(other)}")
|
||||
raise TypeError(f"'>=' not supported between instances of {type(self)} and {type(other)}")
|
||||
|
||||
def __gt__(self, other):
|
||||
def __gt__(self, other: object) -> bool:
|
||||
if isinstance(other, GitVersion):
|
||||
return (self.ref_version, self.ref) > (other.ref_version, other.ref)
|
||||
if isinstance(other, StandardVersion):
|
||||
@@ -584,14 +699,14 @@ def __gt__(self, other):
|
||||
return self.ref_version >= other
|
||||
if isinstance(other, ClosedOpenRange):
|
||||
return self.ref_version > other
|
||||
raise ValueError(f"Unexpected type {type(other)}")
|
||||
raise TypeError(f"'>' not supported between instances of {type(self)} and {type(other)}")
|
||||
|
||||
def __hash__(self):
|
||||
# hashing should not cause version lookup
|
||||
return hash(self.ref)
|
||||
|
||||
def __contains__(self, other):
|
||||
raise Exception("Not implemented yet")
|
||||
def __contains__(self, other: object) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def ref_lookup(self):
|
||||
@@ -649,7 +764,7 @@ def up_to(self, index) -> StandardVersion:
|
||||
return self.ref_version.up_to(index)
|
||||
|
||||
|
||||
class ClosedOpenRange:
|
||||
class ClosedOpenRange(VersionType):
|
||||
def __init__(self, lo: StandardVersion, hi: StandardVersion):
|
||||
if hi < lo:
|
||||
raise EmptyRangeError(f"{lo}..{hi} is an empty range")
|
||||
@@ -657,14 +772,14 @@ def __init__(self, lo: StandardVersion, hi: StandardVersion):
|
||||
self.hi: StandardVersion = hi
|
||||
|
||||
@classmethod
|
||||
def from_version_range(cls, lo: StandardVersion, hi: StandardVersion):
|
||||
def from_version_range(cls, lo: StandardVersion, hi: StandardVersion) -> "ClosedOpenRange":
|
||||
"""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):
|
||||
def __str__(self) -> str:
|
||||
# This simplifies 3.1:<3.2 to 3.1:3.1 to 3.1
|
||||
# 3:3 -> 3
|
||||
hi_prev = _prev_version(self.hi)
|
||||
@@ -726,9 +841,9 @@ def __gt__(self, other):
|
||||
def __contains__(rhs, lhs):
|
||||
if isinstance(lhs, (ConcreteVersion, ClosedOpenRange, VersionList)):
|
||||
return lhs.satisfies(rhs)
|
||||
raise ValueError(f"Unexpected type {type(lhs)}")
|
||||
raise TypeError(f"'in' not supported between instances of {type(rhs)} and {type(lhs)}")
|
||||
|
||||
def intersects(self, other: Union[ConcreteVersion, "ClosedOpenRange", "VersionList"]):
|
||||
def intersects(self, other: VersionType) -> bool:
|
||||
if isinstance(other, StandardVersion):
|
||||
return self.lo <= other < self.hi
|
||||
if isinstance(other, GitVersion):
|
||||
@@ -737,23 +852,18 @@ def intersects(self, other: Union[ConcreteVersion, "ClosedOpenRange", "VersionLi
|
||||
return (self.lo < other.hi) and (other.lo < self.hi)
|
||||
if isinstance(other, VersionList):
|
||||
return any(self.intersects(rhs) for rhs in other)
|
||||
raise ValueError(f"Unexpected type {type(other)}")
|
||||
raise TypeError(f"'intersects' not supported for instances of {type(other)}")
|
||||
|
||||
def satisfies(self, other: Union["ClosedOpenRange", ConcreteVersion, "VersionList"]):
|
||||
def satisfies(self, other: VersionType) -> bool:
|
||||
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 ValueError(other)
|
||||
raise TypeError(f"'satisfies()' not supported for instances of {type(other)}")
|
||||
|
||||
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"]:
|
||||
def _union_if_not_disjoint(self, other: VersionType) -> 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):
|
||||
@@ -770,9 +880,9 @@ def _union_if_not_disjoint(
|
||||
else None
|
||||
)
|
||||
|
||||
raise TypeError(f"Unexpected type {type(other)}")
|
||||
raise TypeError(f"'union()' not supported for instances of {type(other)}")
|
||||
|
||||
def union(self, other: Union["ClosedOpenRange", ConcreteVersion, "VersionList"]):
|
||||
def union(self, other: VersionType) -> VersionType:
|
||||
if isinstance(other, VersionList):
|
||||
v = other.copy()
|
||||
v.add(self)
|
||||
@@ -781,35 +891,51 @@ def union(self, other: Union["ClosedOpenRange", ConcreteVersion, "VersionList"])
|
||||
result = self._union_if_not_disjoint(other)
|
||||
return result if result is not None else VersionList([self, other])
|
||||
|
||||
def intersection(self, other: Union["ClosedOpenRange", ConcreteVersion]):
|
||||
def intersection(self, other: VersionType) -> VersionType:
|
||||
# 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()
|
||||
|
||||
# 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()
|
||||
raise TypeError(f"'intersection()' not supported for instances of {type(other)}")
|
||||
|
||||
|
||||
class VersionList:
|
||||
class VersionList(VersionType):
|
||||
"""Sorted, non-redundant list of Version and ClosedOpenRange elements."""
|
||||
|
||||
def __init__(self, vlist=None):
|
||||
self.versions: List[Union[StandardVersion, GitVersion, ClosedOpenRange]] = []
|
||||
versions: List[VersionType]
|
||||
|
||||
def __init__(self, vlist: Optional[Union[str, VersionType, Iterable]] = None):
|
||||
if vlist is None:
|
||||
pass
|
||||
self.versions = []
|
||||
|
||||
elif isinstance(vlist, str):
|
||||
vlist = from_string(vlist)
|
||||
if isinstance(vlist, VersionList):
|
||||
self.versions = vlist.versions
|
||||
else:
|
||||
self.versions = [vlist]
|
||||
else:
|
||||
|
||||
elif isinstance(vlist, (ConcreteVersion, ClosedOpenRange)):
|
||||
self.versions = [vlist]
|
||||
|
||||
elif isinstance(vlist, VersionList):
|
||||
self.versions = vlist[:]
|
||||
|
||||
elif isinstance(vlist, Iterable):
|
||||
self.versions = []
|
||||
for v in vlist:
|
||||
self.add(ver(v))
|
||||
|
||||
def add(self, item: Union[StandardVersion, GitVersion, ClosedOpenRange, "VersionList"]):
|
||||
else:
|
||||
raise TypeError(f"Cannot construct VersionList from {type(vlist)}")
|
||||
|
||||
def add(self, item: VersionType) -> None:
|
||||
if isinstance(item, (StandardVersion, GitVersion)):
|
||||
i = bisect_left(self, item)
|
||||
# Only insert when prev and next are not intersected.
|
||||
@@ -865,7 +991,7 @@ def concrete_range_as_version(self) -> Optional[ConcreteVersion]:
|
||||
return v.lo
|
||||
return None
|
||||
|
||||
def copy(self):
|
||||
def copy(self) -> "VersionList":
|
||||
return VersionList(self)
|
||||
|
||||
def lowest(self) -> Optional[StandardVersion]:
|
||||
@@ -889,7 +1015,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) -> bool:
|
||||
def satisfies(self, other: VersionType) -> 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):
|
||||
@@ -898,9 +1024,9 @@ def satisfies(self, other) -> bool:
|
||||
if isinstance(other, (ConcreteVersion, ClosedOpenRange)):
|
||||
return all(lhs.satisfies(other) for lhs in self)
|
||||
|
||||
raise ValueError(f"Unsupported type {type(other)}")
|
||||
raise TypeError(f"'satisfies()' not supported for instances of {type(other)}")
|
||||
|
||||
def intersects(self, other):
|
||||
def intersects(self, other: VersionType) -> bool:
|
||||
if isinstance(other, VersionList):
|
||||
s = o = 0
|
||||
while s < len(self) and o < len(other):
|
||||
@@ -915,19 +1041,16 @@ def intersects(self, other):
|
||||
if isinstance(other, (ClosedOpenRange, StandardVersion)):
|
||||
return any(v.intersects(other) for v in self)
|
||||
|
||||
raise ValueError(f"Unsupported type {type(other)}")
|
||||
raise TypeError(f"'intersects()' not supported for instances of {type(other)}")
|
||||
|
||||
def overlaps(self, other) -> bool:
|
||||
return self.intersects(other)
|
||||
|
||||
def to_dict(self):
|
||||
def to_dict(self) -> Dict:
|
||||
"""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):
|
||||
def from_dict(dictionary) -> "VersionList":
|
||||
"""Parse dict from to_dict."""
|
||||
if "versions" in dictionary:
|
||||
return VersionList(dictionary["versions"])
|
||||
@@ -935,27 +1058,29 @@ def from_dict(dictionary):
|
||||
return VersionList([Version(dictionary["version"])])
|
||||
raise ValueError("Dict must have 'version' or 'versions' in it.")
|
||||
|
||||
def update(self, other: "VersionList"):
|
||||
for v in other.versions:
|
||||
self.add(v)
|
||||
def update(self, other: "VersionList") -> None:
|
||||
self.add(other)
|
||||
|
||||
def union(self, other: "VersionList"):
|
||||
def union(self, other: VersionType) -> VersionType:
|
||||
result = self.copy()
|
||||
result.update(other)
|
||||
result.add(other)
|
||||
return result
|
||||
|
||||
def intersection(self, other: "VersionList") -> "VersionList":
|
||||
def intersection(self, other: VersionType) -> "VersionList":
|
||||
result = 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
|
||||
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))
|
||||
|
||||
def intersect(self, other) -> bool:
|
||||
def intersect(self, other: VersionType) -> bool:
|
||||
"""Intersect this spec's list with other.
|
||||
|
||||
Return True if the spec changed as a result; False otherwise
|
||||
@@ -965,6 +1090,7 @@ def intersect(self, other) -> 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)
|
||||
@@ -978,52 +1104,52 @@ def __contains__(self, other):
|
||||
def __getitem__(self, index):
|
||||
return self.versions[index]
|
||||
|
||||
def __iter__(self):
|
||||
def __iter__(self) -> Iterator:
|
||||
return iter(self.versions)
|
||||
|
||||
def __reversed__(self):
|
||||
def __reversed__(self) -> Iterator:
|
||||
return reversed(self.versions)
|
||||
|
||||
def __len__(self):
|
||||
def __len__(self) -> int:
|
||||
return len(self.versions)
|
||||
|
||||
def __bool__(self):
|
||||
def __bool__(self) -> bool:
|
||||
return bool(self.versions)
|
||||
|
||||
def __eq__(self, other):
|
||||
def __eq__(self, other) -> bool:
|
||||
if isinstance(other, VersionList):
|
||||
return self.versions == other.versions
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
def __ne__(self, other) -> bool:
|
||||
if isinstance(other, VersionList):
|
||||
return self.versions != other.versions
|
||||
return False
|
||||
|
||||
def __lt__(self, other):
|
||||
def __lt__(self, other) -> bool:
|
||||
if isinstance(other, VersionList):
|
||||
return self.versions < other.versions
|
||||
return NotImplemented
|
||||
|
||||
def __le__(self, other):
|
||||
def __le__(self, other) -> bool:
|
||||
if isinstance(other, VersionList):
|
||||
return self.versions <= other.versions
|
||||
return NotImplemented
|
||||
|
||||
def __ge__(self, other):
|
||||
def __ge__(self, other) -> bool:
|
||||
if isinstance(other, VersionList):
|
||||
return self.versions >= other.versions
|
||||
return NotImplemented
|
||||
|
||||
def __gt__(self, other):
|
||||
def __gt__(self, other) -> bool:
|
||||
if isinstance(other, VersionList):
|
||||
return self.versions > other.versions
|
||||
return NotImplemented
|
||||
|
||||
def __hash__(self):
|
||||
def __hash__(self) -> int:
|
||||
return hash(tuple(self.versions))
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
if not self.versions:
|
||||
return ""
|
||||
|
||||
@@ -1031,7 +1157,7 @@ def __str__(self):
|
||||
f"={v}" if isinstance(v, StandardVersion) else str(v) for v in self.versions
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
def __repr__(self) -> str:
|
||||
return str(self.versions)
|
||||
|
||||
|
||||
@@ -1106,12 +1232,10 @@ def _next_version(v: StandardVersion) -> StandardVersion:
|
||||
release = release[:-1] + (_next_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]))
|
||||
return StandardVersion("".join(str(c) for c in components), (release, prerelease), separators)
|
||||
|
||||
# Avoid constructing a string here for performance. Instead, pass "" to
|
||||
# StandardVersion to lazily stringify.
|
||||
return StandardVersion("", (release, prerelease), separators)
|
||||
|
||||
|
||||
def _prev_version(v: StandardVersion) -> StandardVersion:
|
||||
@@ -1130,19 +1254,15 @@ 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:]))
|
||||
|
||||
# this is only used for comparison functions, so don't bother making a string
|
||||
return StandardVersion(None, (release, prerelease), separators)
|
||||
# Avoid constructing a string here for performance. Instead, pass "" to
|
||||
# StandardVersion to lazily stringify.
|
||||
return StandardVersion("", (release, prerelease), separators)
|
||||
|
||||
|
||||
def Version(string: Union[str, int]) -> Union[GitVersion, StandardVersion]:
|
||||
def Version(string: Union[str, int]) -> ConcreteVersion:
|
||||
if not isinstance(string, (str, int)):
|
||||
raise ValueError(f"Cannot construct a version from {type(string)}")
|
||||
raise TypeError(f"Cannot construct a version from {type(string)}")
|
||||
string = str(string)
|
||||
if is_git_version(string):
|
||||
return GitVersion(string)
|
||||
@@ -1155,7 +1275,7 @@ def VersionRange(lo: Union[str, StandardVersion], hi: Union[str, StandardVersion
|
||||
return ClosedOpenRange.from_version_range(lo, hi)
|
||||
|
||||
|
||||
def from_string(string) -> Union[VersionList, ClosedOpenRange, StandardVersion, GitVersion]:
|
||||
def from_string(string: str) -> VersionType:
|
||||
"""Converts a string to a version object. This is private. Client code should use ver()."""
|
||||
string = string.replace(" ", "")
|
||||
|
||||
@@ -1184,17 +1304,17 @@ def from_string(string) -> Union[VersionList, ClosedOpenRange, StandardVersion,
|
||||
return VersionRange(v, v)
|
||||
|
||||
|
||||
def ver(obj) -> Union[VersionList, ClosedOpenRange, StandardVersion, GitVersion]:
|
||||
def ver(obj: Union[VersionType, str, list, tuple, int, float]) -> VersionType:
|
||||
"""Parses a Version, VersionRange, or VersionList from a string
|
||||
or list of strings.
|
||||
"""
|
||||
if isinstance(obj, (list, tuple)):
|
||||
return VersionList(obj)
|
||||
if isinstance(obj, VersionType):
|
||||
return 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))
|
||||
|
@@ -3,6 +3,8 @@
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import os
|
||||
|
||||
from spack.package import *
|
||||
|
||||
|
||||
@@ -126,6 +128,18 @@ 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
|
||||
|
||||
|
@@ -22,6 +22,11 @@ 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",
|
||||
|
@@ -41,6 +41,9 @@ 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)
|
||||
|
@@ -406,39 +406,71 @@ class Gcc(AutotoolsPackage, GNUMirrorPackage, CompilerPackage):
|
||||
when="@11.2.0",
|
||||
)
|
||||
|
||||
# Apple M1 support, created from branch of Darwin maintainer for GCC:
|
||||
# https://github.com/iains/gcc-11-branch
|
||||
# aarch64-darwin support from Iain Sandoe's branch
|
||||
patch(
|
||||
"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:",
|
||||
"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:",
|
||||
)
|
||||
patch(
|
||||
"https://raw.githubusercontent.com/Homebrew/formula-patches/1d184289/gcc/gcc-12.2.0-arm.diff",
|
||||
sha256="a7843b5c6bf1401e40c20c72af69c8f6fc9754ae980bb4a5f0540220b3dcb62d",
|
||||
when="@12.2.0 target=aarch64:",
|
||||
"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://raw.githubusercontent.com/Homebrew/formula-patches/5c206c47/gcc/gcc-13.1.0.diff",
|
||||
sha256="cb4e8a89387f748a744da0273025d0dc2e3c76780cc390b18ada704676afea11",
|
||||
when="@13.1.0 target=aarch64:",
|
||||
)
|
||||
patch(
|
||||
"https://raw.githubusercontent.com/Homebrew/formula-patches/3c5cbc8e9cf444a1967786af48e430588e1eb481/gcc/gcc-13.2.0.diff",
|
||||
sha256="2df7ef067871a30b2531a2013b3db661ec9e61037341977bfc451e30bf2c1035",
|
||||
"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://raw.githubusercontent.com/Homebrew/formula-patches/82b5c1cd38826ab67ac7fc498a8fe74376a40f4a/gcc/gcc-14.1.0.diff",
|
||||
sha256="1529cff128792fe197ede301a81b02036c8168cb0338df21e4bc7aafe755305a",
|
||||
when="@14.1.0 target=aarch64:",
|
||||
"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",
|
||||
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:",
|
||||
)
|
||||
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:",
|
||||
)
|
||||
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:",
|
||||
)
|
||||
|
||||
conflicts("+bootstrap", when="@11.3.0,13.1: target=aarch64:")
|
||||
|
||||
# Use -headerpad_max_install_names in the build,
|
||||
|
@@ -58,6 +58,9 @@ 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")
|
||||
@@ -531,12 +534,6 @@ 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"):
|
||||
@@ -561,7 +558,12 @@ def patch(self):
|
||||
filter_file(" -lnuma", f" -L{numactl} -lnuma", "hipBin_amd.h")
|
||||
|
||||
def cmake_args(self):
|
||||
args = []
|
||||
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),
|
||||
]
|
||||
if self.spec.satisfies("+rocm"):
|
||||
args.append(self.define("HSA_PATH", self.spec["hsa-rocr-dev"].prefix))
|
||||
args.append(self.define("HIP_COMPILER", "clang"))
|
||||
|
@@ -19,7 +19,7 @@ class Hypre(AutotoolsPackage, CudaPackage, ROCmPackage):
|
||||
git = "https://github.com/hypre-space/hypre.git"
|
||||
tags = ["e4s", "radiuss"]
|
||||
|
||||
maintainers("ulrikeyang", "osborn9", "balay")
|
||||
maintainers("ulrikeyang", "osborn9", "victorapm", "balay")
|
||||
|
||||
test_requires_compiler = True
|
||||
|
||||
@@ -74,6 +74,7 @@ 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")
|
||||
@@ -123,8 +124,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")
|
||||
depends_on("lapack")
|
||||
depends_on("blas", when="+lapack")
|
||||
depends_on("lapack", when="+lapack")
|
||||
depends_on("magma", when="+magma")
|
||||
depends_on("superlu-dist", when="+superlu-dist+mpi")
|
||||
depends_on("rocsparse", when="+rocm")
|
||||
@@ -198,17 +199,20 @@ def url_for_version(self, version):
|
||||
|
||||
def configure_args(self):
|
||||
spec = self.spec
|
||||
# Note: --with-(lapack|blas)_libs= needs space separated list of names
|
||||
lapack = spec["lapack"].libs
|
||||
blas = spec["blas"].libs
|
||||
configure_args = [f"--prefix={prefix}"]
|
||||
|
||||
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),
|
||||
]
|
||||
# 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)
|
||||
)
|
||||
|
||||
if spec.satisfies("+mpi"):
|
||||
os.environ["CC"] = spec["mpi"].mpicc
|
||||
@@ -245,7 +249,9 @@ def configure_args(self):
|
||||
configure_args.append("--without-superlu")
|
||||
# MLI and FEI do not build without superlu on Linux
|
||||
configure_args.append("--without-mli")
|
||||
configure_args.append("--without-fei")
|
||||
# FEI option was removed in hypre 2.17
|
||||
if self.version < Version("2.17.0"):
|
||||
configure_args.append("--without-fei")
|
||||
|
||||
if spec.satisfies("+superlu-dist"):
|
||||
configure_args.append(
|
||||
|
@@ -22,6 +22,12 @@ 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",
|
||||
|
@@ -21,6 +21,12 @@ 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",
|
||||
|
@@ -383,6 +383,7 @@ 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"))
|
||||
@@ -398,6 +399,8 @@ 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")
|
||||
|
||||
|
@@ -702,8 +702,10 @@ def find_optional_library(name, prefix):
|
||||
if "+mpi" in spec:
|
||||
options += ["MPICXX=%s" % spec["mpi"].mpicxx]
|
||||
hypre = spec["hypre"]
|
||||
# The hypre package always links with 'blas' and 'lapack'.
|
||||
all_hypre_libs = hypre.libs + hypre["lapack"].libs + hypre["blas"].libs
|
||||
all_hypre_libs = hypre.libs
|
||||
if "+lapack" in hypre:
|
||||
all_hypre_libs += hypre["lapack"].libs + hypre["blas"].libs
|
||||
|
||||
hypre_gpu_libs = ""
|
||||
if "+cuda" in hypre:
|
||||
hypre_gpu_libs = " -lcusparse -lcurand -lcublas"
|
||||
|
@@ -46,7 +46,8 @@ class MiopenHip(CMakePackage):
|
||||
conflicts("+asan", when="os=centos7")
|
||||
conflicts("+asan", when="os=centos8")
|
||||
|
||||
depends_on("cxx", type="build") # generated
|
||||
depends_on("c", type="build")
|
||||
depends_on("cxx", type="build")
|
||||
|
||||
depends_on("cmake@3.5:", type="build")
|
||||
depends_on("pkgconfig", type="build")
|
||||
|
@@ -92,6 +92,8 @@ 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")
|
||||
|
||||
@@ -116,6 +118,8 @@ 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")
|
||||
|
@@ -15,6 +15,7 @@ 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")
|
||||
|
@@ -19,6 +19,7 @@ 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")
|
||||
@@ -35,7 +36,10 @@ class PyJoblib(PythonPackage):
|
||||
version("0.10.2", sha256="3123553bdad83b143428033537c9e1939caf4a4d8813dade6a2246948c94494b")
|
||||
version("0.10.0", sha256="49b3a0ba956eaa2f077e1ebd230b3c8d7b98afc67520207ada20a4d8b8efd071")
|
||||
|
||||
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"))
|
||||
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")
|
||||
|
@@ -23,6 +23,7 @@ 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")
|
||||
@@ -74,10 +75,12 @@ 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")):
|
||||
# setup.py
|
||||
# pyproject.toml
|
||||
depends_on("python@3.9:", when="@3:")
|
||||
depends_on("python@3.8:", when="@2.12:")
|
||||
depends_on("py-absl-py", when="@2.6:")
|
||||
@@ -98,7 +101,8 @@ class PyKeras(PythonPackage):
|
||||
|
||||
# requirements-tensorflow-cuda.txt
|
||||
with when("backend=tensorflow"):
|
||||
depends_on("py-tensorflow@2.17", when="@3.5:")
|
||||
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.16.1:2.16", when="@3.0:3.4")
|
||||
|
||||
# requirements-jax-cuda.txt
|
||||
@@ -109,13 +113,15 @@ class PyKeras(PythonPackage):
|
||||
|
||||
# requirements-torch-cuda.txt
|
||||
with when("backend=torch"):
|
||||
depends_on("py-torch@2.4.1", when="@3.6:")
|
||||
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.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.19.1", when="@3.6:")
|
||||
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.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")
|
||||
|
@@ -2,6 +2,7 @@
|
||||
# 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 *
|
||||
|
||||
@@ -50,3 +51,35 @@ 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)
|
||||
|
@@ -12,7 +12,10 @@ class PyNbdime(PythonPackage):
|
||||
homepage = "https://nbdime.readthedocs.io/"
|
||||
pypi = "nbdime/nbdime-3.1.1.tar.gz"
|
||||
|
||||
version("3.1.1", sha256="67767320e971374f701a175aa59abd3a554723039d39fae908e72d16330d648b")
|
||||
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")
|
||||
|
||||
depends_on("python@3.6:", type=("build", "run"))
|
||||
depends_on("py-setuptools@40.8.0:", type="build")
|
||||
|
@@ -73,6 +73,7 @@ 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:")
|
||||
|
@@ -25,6 +25,12 @@ 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")
|
||||
@@ -40,6 +46,7 @@ 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
|
||||
|
@@ -33,7 +33,8 @@ 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"))
|
||||
depends_on("vtk+python", type=("build", "run"))
|
||||
# https://github.com/pyvista/pyvista/issues/6857
|
||||
depends_on("vtk@:9.3+python", type=("build", "run"))
|
||||
depends_on("py-typing-extensions", when="^python@:3.7", type=("build", "run"))
|
||||
|
||||
# Historical dependencies
|
||||
|
@@ -30,3 +30,6 @@ 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"))
|
||||
|
@@ -16,6 +16,7 @@ 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")
|
||||
|
@@ -14,6 +14,10 @@ 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")
|
||||
|
@@ -18,7 +18,8 @@ class PyTorchCluster(PythonPackage):
|
||||
|
||||
version("1.6.3", sha256="78d5a930a5bbd0d8788df8c6d66addd68d6dd292fe3edb401e3dacba26308152")
|
||||
|
||||
depends_on("cxx", type="build") # generated
|
||||
depends_on("c", type="build")
|
||||
depends_on("cxx", type="build")
|
||||
|
||||
depends_on("python", type=("build", "link", "run"))
|
||||
depends_on("py-setuptools", type="build")
|
||||
|
@@ -18,7 +18,8 @@ class PyTorchScatter(PythonPackage):
|
||||
|
||||
version("2.1.2", sha256="69b3aa435f2424ac6a1bfb6ff702da6eb73b33ca0db38fb26989c74159258e47")
|
||||
|
||||
depends_on("cxx", type="build") # generated
|
||||
depends_on("c", type="build")
|
||||
depends_on("cxx", type="build")
|
||||
|
||||
depends_on("python", type=("build", "link", "run"))
|
||||
depends_on("py-setuptools", type="build")
|
||||
|
@@ -21,7 +21,8 @@ class PyTorchSparse(PythonPackage):
|
||||
version("0.6.8", sha256="312fb5ae6e4e575fca4bbc0bd092af85e7679d5b8e53459f24492fc2a073c7b6")
|
||||
version("0.6.7", sha256="f69b2ed35baf2a9853234756a2b19e6f7ce88d2c1f029d1c7ca166d91e1adbd0")
|
||||
|
||||
depends_on("cxx", type="build") # generated
|
||||
depends_on("c", type="build")
|
||||
depends_on("cxx", type="build")
|
||||
|
||||
depends_on("py-setuptools", type="build")
|
||||
depends_on("py-scipy", type=("build", "run"))
|
||||
|
@@ -18,7 +18,8 @@ class PyTorchSplineConv(PythonPackage):
|
||||
|
||||
version("1.2.2", sha256="ed45a81da29f774665dbdd4709d7e534cdf16d2e7006dbd06957f35bd09661b2")
|
||||
|
||||
depends_on("cxx", type="build") # generated
|
||||
depends_on("c", type="build")
|
||||
depends_on("cxx", type="build")
|
||||
|
||||
depends_on("python", type=("build", "link", "run"))
|
||||
depends_on("py-setuptools", type="build")
|
||||
|
@@ -17,6 +17,7 @@ class Raylib(CMakePackage):
|
||||
|
||||
license("Zlib", checked_by="georgemalerbo")
|
||||
|
||||
version("5.5", sha256="aea98ecf5bc5c5e0b789a76de0083a21a70457050ea4cc2aec7566935f5e258e")
|
||||
version("5.0", sha256="98f049b9ea2a9c40a14e4e543eeea1a7ec3090ebdcd329c4ca2cf98bc9793482")
|
||||
|
||||
depends_on("c", type="build") # generated
|
||||
|
@@ -40,7 +40,8 @@ class Rocfft(CMakePackage):
|
||||
version("5.3.3", sha256="678c18710578c1fb36a0009311bb79de7607c3468f9102cfba56a866ebb7ff78")
|
||||
version("5.3.0", sha256="d655c5541c4aff4267e80e36d002fc3a55c2f84a0ae8631197c12af3bf03fa7d")
|
||||
|
||||
depends_on("cxx", type="build") # generated
|
||||
depends_on("c", type="build")
|
||||
depends_on("cxx", type="build")
|
||||
|
||||
amdgpu_targets = ROCmPackage.amdgpu_targets
|
||||
|
||||
|
@@ -41,7 +41,8 @@ class RoctracerDev(CMakePackage, ROCmPackage):
|
||||
version("5.3.3", sha256="f2cb1e6bb69ea1a628c04f984741f781ae1d8498dc58e15795bb03015f924d13")
|
||||
version("5.3.0", sha256="36f1da60863a113bb9fe2957949c661f00a702e249bb0523cda1fb755c053808")
|
||||
|
||||
depends_on("cxx", type="build") # generated
|
||||
depends_on("c", type="build")
|
||||
depends_on("cxx", type="build")
|
||||
|
||||
variant("asan", default=False, description="Build with address-sanitizer enabled or disabled")
|
||||
|
||||
|
@@ -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.2.4.tar.gz"
|
||||
url = "https://download.samba.org/pub/rsync/src/rsync-3.3.0.tar.gz"
|
||||
|
||||
license("GPL-3.0-or-later")
|
||||
|
||||
@@ -20,16 +20,42 @@ 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")
|
||||
|
||||
depends_on("c", type="build") # generated
|
||||
depends_on("cxx", type="build") # generated
|
||||
# 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")
|
||||
depends_on("cxx", type="build")
|
||||
depends_on("zlib-api")
|
||||
depends_on("popt")
|
||||
depends_on("openssl", when="@3.2:")
|
||||
|
@@ -304,6 +304,9 @@ 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)
|
||||
|
||||
@@ -486,6 +489,15 @@ 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))
|
||||
|
@@ -87,14 +87,15 @@ class Vtk(CMakePackage):
|
||||
|
||||
conflicts("%gcc@13", when="@9.2")
|
||||
|
||||
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"))
|
||||
# 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")
|
||||
|
||||
# We need mpi4py if buidling python wrappers and using MPI
|
||||
depends_on("py-mpi4py", when="+python+mpi", type="run")
|
||||
|
Reference in New Issue
Block a user