Compare commits

..

27 Commits

Author SHA1 Message Date
Gregory Becker
540c37cb06 allow lists and dicts since we get them for free 2022-11-04 17:51:58 -07:00
Gregory Becker
be89a18971 becker: show simplification idea 2022-11-04 17:51:58 -07:00
Peter Josef Scheibel
104023e7cb auto style fix 2022-11-04 17:51:58 -07:00
Peter Josef Scheibel
1412251d79 account for attributes that should be deleted (i.e. if they weren't set originally on the package) 2022-11-04 17:51:58 -07:00
Peter Josef Scheibel
186532bac1 style fixes 2022-11-04 17:51:58 -07:00
Peter Josef Scheibel
e09623060b update test to clarify parsing 2022-11-04 17:51:58 -07:00
Peter Josef Scheibel
8dbd7b423b add placeholders for assigning collection types 2022-11-04 17:51:58 -07:00
Peter Josef Scheibel
4f5afbe97b do type inference on strings (this works well for values that are not collections) 2022-11-04 17:51:57 -07:00
Peter Josef Scheibel
469401d4a1 style fix 2022-11-04 17:51:57 -07:00
Peter Josef Scheibel
4bc2d12a68 intermediate work on arbitrary types for pkg_attribute 2022-11-04 17:51:57 -07:00
Peter Josef Scheibel
2b5be8c52a only delete the attribute if it exists 2022-11-04 17:51:57 -07:00
Peter Josef Scheibel
2ad94bc76a make sure to remove old overidden_attrs 2022-11-04 17:51:57 -07:00
Peter Josef Scheibel
56671984b5 only set storage variable on class if there is anything to keep track of 2022-11-04 17:51:57 -07:00
Peter Josef Scheibel
bd40a98ccd Revert "remove new test and see if that's part of the problem (even though it isn't run before the failing test)"
This reverts commit 48c15d2f6be8a0bd88428e015ea41a8c814130f8.
2022-11-04 17:51:57 -07:00
Peter Josef Scheibel
25e875c1d6 remove new test and see if that's part of the problem (even though it isn't run before the failing test) 2022-11-04 17:51:56 -07:00
Peter Josef Scheibel
de59410216 Revert "temporarily undo everything in this PR to check if it could somehow be causing a failure in an unrelated test"
This reverts commit c138b808304d68748308ea21e46a08bb028ab584.
2022-11-04 17:51:56 -07:00
Peter Josef Scheibel
edc3a3d19b temporarily undo everything in this PR to check if it could somehow be causing a failure in an unrelated test 2022-11-04 17:51:56 -07:00
Peter Josef Scheibel
114ad6dd0a auto style fix 2022-11-04 17:51:56 -07:00
Peter Josef Scheibel
3ddc16b1ff add clarifying comment 2022-11-04 17:51:56 -07:00
Peter Josef Scheibel
d38ad41b65 move setattr back to get_pkg_class (since these config settings can affect class-level attrs) 2022-11-04 17:51:56 -07:00
Peter Josef Scheibel
d68e1c976d add note for consideration 2022-11-04 17:51:56 -07:00
Peter Josef Scheibel
821d20cf06 auto style fix 2022-11-04 17:51:55 -07:00
Peter Josef Scheibel
a92eacd3c8 rename 'set' to 'package_attributes' 2022-11-04 17:51:55 -07:00
Peter Josef Scheibel
bb079ee356 move set logic to PackageBase initializer (otherwise, users could instantiate package_class() in other locations and bypass the config) 2022-11-04 17:51:55 -07:00
Peter Josef Scheibel
0b24c820b4 auto style fix 2022-11-04 17:51:55 -07:00
Peter Josef Scheibel
2db85d240a add test; set attributes on instance vs. on class 2022-11-04 17:51:55 -07:00
Peter Josef Scheibel
a8fa5f6ca1 core changes to allow setting git/url attribute on packages 2022-11-04 17:51:55 -07:00
31 changed files with 125 additions and 483 deletions

View File

@@ -531,25 +531,3 @@ directories inside the install prefix. This will ensure that even
manually placed files within the install prefix are owned by the
assigned group. If no group is assigned, Spack will allow the OS
default behavior to go as expected.
----------------------------
Assigning Package Attributes
----------------------------
You can assign class-level attributes in the configuration:
.. code-block:: yaml
packages:
mpileaks:
# Override existing attributes
url: http://www.somewhereelse.com/mpileaks-1.0.tar.gz
# ... or add new ones
x: 1
Attributes set this way will be accessible to any method executed
in the package.py file (e.g. the ``install()`` method). Values for these
attributes may be any value parseable by yaml.
These can only be applied to specific packages, not "all" or
virtual packages.

View File

@@ -4406,9 +4406,16 @@ In addition to invoking the right compiler, the compiler wrappers add
flags to the compile line so that dependencies can be easily found.
These flags are added for each dependency, if they exist:
* Compile-time library search paths: ``-L$dep_prefix/lib``, ``-L$dep_prefix/lib64``
* Runtime library search paths (RPATHs): ``$rpath_flag$dep_prefix/lib``, ``$rpath_flag$dep_prefix/lib64``
* Include search paths: ``-I$dep_prefix/include``
Compile-time library search paths
* ``-L$dep_prefix/lib``
* ``-L$dep_prefix/lib64``
Runtime library search paths (RPATHs)
* ``$rpath_flag$dep_prefix/lib``
* ``$rpath_flag$dep_prefix/lib64``
Include search paths
* ``-I$dep_prefix/include``
An example of this would be the ``libdwarf`` build, which has one
dependency: ``libelf``. Every call to ``cc`` in the ``libdwarf``

View File

@@ -1600,19 +1600,13 @@ def relocate_package(spec, allow_root):
install_path = spack.hooks.sbang.sbang_install_path()
prefix_to_prefix_text[old_sbang_install_path] = install_path
# First match specific prefix paths. Possibly the *local* install prefix
# of some dependency is in an upstream, so we cannot assume the original
# spack store root can be mapped uniformly to the new spack store root.
for orig_prefix, hash in prefix_to_hash.items():
prefix_to_prefix_text[orig_prefix] = hash_to_prefix.get(hash, None)
prefix_to_prefix_bin[orig_prefix] = hash_to_prefix.get(hash, None)
# Only then add the generic fallback of install prefix -> install prefix.
prefix_to_prefix_text[old_prefix] = new_prefix
prefix_to_prefix_bin[old_prefix] = new_prefix
prefix_to_prefix_text[old_layout_root] = new_layout_root
prefix_to_prefix_bin[old_layout_root] = new_layout_root
for orig_prefix, hash in prefix_to_hash.items():
prefix_to_prefix_text[orig_prefix] = hash_to_prefix.get(hash, None)
prefix_to_prefix_bin[orig_prefix] = hash_to_prefix.get(hash, None)
# This is vestigial code for the *old* location of sbang. Previously,
# sbang was a bash script, and it lived in the spack prefix. It is
# now a POSIX script that lives in the install prefix. Old packages

View File

@@ -61,30 +61,23 @@ def __init__(self, file_path, old_len, new_len):
class BinaryTextReplaceError(spack.error.SpackError):
def __init__(self, msg):
msg += (
" To fix this, compile with more padding "
"(config:install_tree:padded_length), or install to a shorter prefix."
)
super(BinaryTextReplaceError, self).__init__(msg)
def __init__(self, old_path, new_path):
"""Raised when the new install path is longer than the
old one, so binary text replacement cannot occur.
Args:
old_path (str): original path to be substituted
new_path (str): candidate path for substitution
"""
class CannotGrowString(BinaryTextReplaceError):
def __init__(self, old, new):
msg = "Cannot replace {!r} with {!r} because the new prefix is longer.".format(old, new)
super(CannotGrowString, self).__init__(msg)
class CannotShrinkCString(BinaryTextReplaceError):
def __init__(self, old, new, full_old_string):
# Just interpolate binary string to not risk issues with invalid
# unicode, which would be really bad user experience: error in error.
# We have no clue if we actually deal with a real C-string nor what
# encoding it has.
msg = "Cannot replace {!r} with {!r} in the C-string {!r}.".format(
old, new, full_old_string
)
super(CannotShrinkCString, self).__init__(msg)
msg = "New path longer than old path: binary text"
msg += " replacement not possible."
err_msg = "The new path %s" % new_path
err_msg += " is longer than the old path %s.\n" % old_path
err_msg += "Text replacement in binaries will not work.\n"
err_msg += "Create buildcache from an install path "
err_msg += "longer than new path."
super(BinaryTextReplaceError, self).__init__(msg, err_msg)
@memoized
@@ -458,116 +451,43 @@ def _replace_prefix_text(filename, compiled_prefixes):
f.truncate()
def apply_binary_replacements(f, prefix_to_prefix, suffix_safety_size=7):
"""
Given a file opened in rb+ mode, apply the string replacements as
specified by an ordered dictionary of prefix to prefix mappings. This
method takes special care of null-terminated C-strings. C-string constants
are problematic because compilers and linkers optimize readonly strings for
space by aliasing those that share a common suffix (only suffix since all
of them are null terminated). See https://github.com/spack/spack/pull/31739
and https://github.com/spack/spack/pull/32253 for details. Our logic matches
the original prefix with a ``suffix_safety_size + 1`` lookahead for null bytes.
If no null terminator is found, we simply pad with leading /, assuming that
it's a long C-string; the full C-string after replacement has a large suffix
in common with its original value.
If there *is* a null terminator we can do the same as long as the replacement
has a sufficiently long common suffix with the original prefix.
As a last resort when the replacement does not have a long enough common suffix,
we can try to shorten the string, but this only works if the new length is
sufficiently short (typically the case when going from large padding -> normal path)
If the replacement string is longer, or all of the above fails, we error out.
def _replace_prefix_bin(filename, byte_prefixes):
"""Replace all the occurrences of the old install prefix with a
new install prefix in binary files.
Arguments:
f: file opened in rb+ mode
prefix_to_prefix (OrderedDict): OrderedDictionary where the keys are
bytes representing the old prefixes and the values are the new
suffix_safety_size (int): in case of null terminated strings, what size
of the suffix should remain to avoid aliasing issues?
"""
assert suffix_safety_size >= 0
assert f.tell() == 0
# Look for exact matches of our paths, and also look if there's a null terminator
# soon after (this covers the case where we search for /abc but match /abc/ with
# a trailing dir seperator).
regex = re.compile(
b"("
+ b"|".join(re.escape(p) for p in prefix_to_prefix.keys())
+ b")([^\0]{0,%d}\0)?" % suffix_safety_size
)
# We *could* read binary data in chunks to avoid loading all in memory,
# but it's nasty to deal with matches across boundaries, so let's stick to
# something simple.
for match in regex.finditer(f.read()):
# The matching prefix (old) and its replacement (new)
old = match.group(1)
new = prefix_to_prefix[old]
# Did we find a trailing null within a N + 1 bytes window after the prefix?
null_terminated = match.end(0) > match.end(1)
# Suffix string length, excluding the null byte
# Only makes sense if null_terminated
suffix_strlen = match.end(0) - match.end(1) - 1
# How many bytes are we shrinking our string?
bytes_shorter = len(old) - len(new)
# We can't make strings larger.
if bytes_shorter < 0:
raise CannotGrowString(old, new)
# If we don't know whether this is a null terminated C-string (we're looking
# only N + 1 bytes ahead), or if it is and we have a common suffix, we can
# simply pad with leading dir separators.
elif (
not null_terminated
or suffix_strlen >= suffix_safety_size # == is enough, but let's be defensive
or old[-suffix_safety_size + suffix_strlen :]
== new[-suffix_safety_size + suffix_strlen :]
):
replacement = b"/" * bytes_shorter + new
# If it *was* null terminated, all that matters is that we can leave N bytes
# of old suffix in place. Note that > is required since we also insert an
# additional null terminator.
elif bytes_shorter > suffix_safety_size:
replacement = new + match.group(2) # includes the trailing null
# Otherwise... we can't :(
else:
raise CannotShrinkCString(old, new, match.group()[:-1])
f.seek(match.start())
f.write(replacement)
def _replace_prefix_bin(filename, prefix_to_prefix):
"""Replace all the occurrences of the old prefix with a new prefix in binary
files. See :func:`~spack.relocate.apply_binary_replacements` for details.
The new install prefix is prefixed with ``b'/'`` until the
lengths of the prefixes are the same.
Args:
filename (str): target binary file
byte_prefixes (OrderedDict): ordered dictionary where the keys are
bytes representing the old prefixes and the values are the new
prefixes (all bytes utf-8 encoded)
byte_prefixes (OrderedDict): OrderedDictionary where the keys are
binary strings of the old prefixes and the values are the new
binary prefixes
"""
all_prefixes = re.compile(b"|".join(re.escape(prefix) for prefix in byte_prefixes.keys()))
def padded_replacement(old):
new = byte_prefixes[old]
pad = len(old) - len(new)
if pad < 0:
raise BinaryTextReplaceError(old, new)
return new + b"/" * pad
with open(filename, "rb+") as f:
apply_binary_replacements(f, prefix_to_prefix)
# Register what replacement string to put on what offsets in the file.
replacements_at_offset = [
(padded_replacement(m.group(0)), m.start())
for m in re.finditer(all_prefixes, f.read())
]
# Apply the replacements
for replacement, offset in replacements_at_offset:
f.seek(offset)
f.write(replacement)
def relocate_macho_binaries(
path_names,
old_layout_root,
new_layout_root,
prefix_to_prefix,
rel,
old_prefix,
new_prefix,
path_names, old_layout_root, new_layout_root, prefix_to_prefix, rel, old_prefix, new_prefix
):
"""
Use macholib python package to get the rpaths, depedent libraries

View File

@@ -1366,32 +1366,32 @@ def get_pkg_class(self, pkg_name):
spack.config.get("packages").get(pkg_name, {}).get("package_attributes", {})
)
overridden_attrs = getattr(cls, "overridden_attrs", {})
overidden_attrs = getattr(cls, "overidden_attrs", {})
attrs_exclusively_from_config = getattr(cls, "attrs_exclusively_from_config", [])
# Clear any prior changes to class attributes in case the config has
# since changed
for key, val in overridden_attrs.items():
for key, val in overidden_attrs.items():
setattr(cls, key, val)
for key in attrs_exclusively_from_config:
delattr(cls, key)
# Keep track of every class attribute that is overridden by the config:
# Keep track of every class attribute that is overidden by the config:
# if the config changes between calls to this method, we make sure to
# restore the original config values (in case the new config no longer
# sets attributes that it used to)
new_overridden_attrs = {}
new_overidden_attrs = {}
new_attrs_exclusively_from_config = set()
for key, val in new_cfg_settings.items():
if hasattr(cls, key):
new_overridden_attrs[key] = getattr(cls, key)
new_overidden_attrs[key] = getattr(cls, key)
else:
new_attrs_exclusively_from_config.add(key)
setattr(cls, key, val)
if new_overridden_attrs:
setattr(cls, "overridden_attrs", dict(new_overridden_attrs))
elif hasattr(cls, "overridden_attrs"):
delattr(cls, "overridden_attrs")
if new_overidden_attrs:
setattr(cls, "overidden_attrs", dict(new_overidden_attrs))
elif hasattr(cls, "overidden_attrs"):
delattr(cls, "overidden_attrs")
if new_attrs_exclusively_from_config:
setattr(cls, "attrs_exclusively_from_config", new_attrs_exclusively_from_config)
elif hasattr(cls, "attrs_exclusively_from_config"):

View File

@@ -1741,12 +1741,7 @@ def spec_hash(self, hash):
return hash.override(self)
node_dict = self.to_node_dict(hash=hash)
json_text = sjson.dump(node_dict)
# This implements "frankenhashes", preserving the last 7 characters of the
# original hash when splicing so that we can avoid relocation issues
out = spack.util.hash.b32_hash(json_text)
if self.build_spec is not self:
return out[:-7] + self.build_spec.spec_hash(hash)[-7:]
return out
return spack.util.hash.b32_hash(json_text)
def _cached_hash(self, hash, length=None, force=False):
"""Helper function for storing a cached hash on the spec.

View File

@@ -180,7 +180,7 @@ def test_preferred_providers(self):
assert "zmpi" in spec
def test_config_set_pkg_property_url(self, mutable_mock_repo):
"""Test setting an existing attribute in the package class"""
"""Test setting an attribute that is explicitly-handled in the schema"""
update_packages(
"mpileaks",
"package_attributes",
@@ -195,36 +195,26 @@ def test_config_set_pkg_property_url(self, mutable_mock_repo):
def test_config_set_pkg_property_new(self, mutable_mock_repo):
"""Test that you can set arbitrary attributes on the Package class"""
conf = syaml.load_config(
"""\
mpileaks:
package_attributes:
v1: 1
v2: true
v3: yesterday
v4: "true"
v5:
x: 1
y: 2
v6:
- 1
- 2
"""
update_packages(
"mpileaks",
"package_attributes",
{"x": 1, "y": True, "z": "yesterday"},
)
spack.config.set("packages", conf, scope="concretize")
spec = concretize("mpileaks")
assert spec.package.v1 == 1
assert spec.package.v2 is True
assert spec.package.v3 == "yesterday"
assert spec.package.v4 == "true"
assert dict(spec.package.v5) == {"x": 1, "y": 2}
assert list(spec.package.v6) == [1, 2]
assert spec.package.x == 1
assert spec.package.y is True
assert spec.package.z == "yesterday"
update_packages("mpileaks", "package_attributes", {})
spec = concretize("mpileaks")
with pytest.raises(AttributeError):
spec.package.v1
spec.package.x
def test_config_set_pkg_property_collection_unsupported(self, mutable_mock_repo):
"""Test that an error is raised if you attempt to assign a list value"""
update_packages("mpileaks", "package_attributes", {"x": ["a", "b"]})
with pytest.raises(ConfigError):
concretize("mpileaks")
def test_preferred(self):
""" "Test packages with some version marked as preferred=True"""

View File

@@ -1643,7 +1643,7 @@ def mock_executable(tmpdir):
"""
import jinja2
shebang = "#!/bin/sh\n" if not is_windows else "@ECHO OFF"
shebang = "#!/bin/bash\n" if not is_windows else "@ECHO OFF"
def _factory(name, output, subdir=("bin",)):
f = tmpdir.ensure(*subdir, dir=True).join(name)
@@ -1808,24 +1808,14 @@ def mock_tty_stdout(monkeypatch):
monkeypatch.setattr(sys.stdout, "isatty", lambda: True)
@pytest.fixture
def prefix_like():
return "package-0.0.0.a1-hashhashhashhashhashhashhashhash"
@pytest.fixture()
def prefix_tmpdir(tmpdir, prefix_like):
return tmpdir.mkdir(prefix_like)
@pytest.fixture()
def binary_with_rpaths(prefix_tmpdir):
def binary_with_rpaths(tmpdir):
"""Factory fixture that compiles an ELF binary setting its RPATH. Relative
paths are encoded with `$ORIGIN` prepended.
"""
def _factory(rpaths, message="Hello world!"):
source = prefix_tmpdir.join("main.c")
source = tmpdir.join("main.c")
source.write(
"""
#include <stdio.h>

View File

@@ -2,7 +2,6 @@
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import io
import os
import os.path
import re
@@ -142,13 +141,13 @@ def _factory():
@pytest.fixture()
def copy_binary(prefix_like):
def copy_binary():
"""Returns a function that copies a binary somewhere and
returns the new location.
"""
def _copy_somewhere(orig_binary):
new_root = orig_binary.mkdtemp().mkdir(prefix_like)
new_root = orig_binary.mkdtemp()
new_binary = new_root.join("main.x")
shutil.copy(str(orig_binary), str(new_binary))
return new_binary
@@ -262,33 +261,29 @@ def test_set_elf_rpaths_warning(mock_patchelf):
@pytest.mark.requires_executables("patchelf", "strings", "file", "gcc")
@skip_unless_linux
def test_replace_prefix_bin(binary_with_rpaths, prefix_like):
prefix = "/usr/" + prefix_like
prefix_bytes = prefix.encode("utf-8")
new_prefix = "/foo/" + prefix_like
new_prefix_bytes = new_prefix.encode("utf-8")
def test_replace_prefix_bin(binary_with_rpaths):
# Compile an "Hello world!" executable and set RPATHs
executable = binary_with_rpaths(rpaths=[prefix + "/lib", prefix + "/lib64"])
executable = binary_with_rpaths(rpaths=["/usr/lib", "/usr/lib64"])
# Relocate the RPATHs
spack.relocate._replace_prefix_bin(str(executable), {prefix_bytes: new_prefix_bytes})
spack.relocate._replace_prefix_bin(str(executable), {b"/usr": b"/foo"})
# Some compilers add rpaths so ensure changes included in final result
assert "%s/lib:%s/lib64" % (new_prefix, new_prefix) in rpaths_for(executable)
assert "/foo/lib:/foo/lib64" in rpaths_for(executable)
@pytest.mark.requires_executables("patchelf", "strings", "file", "gcc")
@skip_unless_linux
def test_relocate_elf_binaries_absolute_paths(binary_with_rpaths, copy_binary, prefix_tmpdir):
def test_relocate_elf_binaries_absolute_paths(binary_with_rpaths, copy_binary, tmpdir):
# Create an executable, set some RPATHs, copy it to another location
orig_binary = binary_with_rpaths(rpaths=[str(prefix_tmpdir.mkdir("lib")), "/usr/lib64"])
orig_binary = binary_with_rpaths(rpaths=[str(tmpdir.mkdir("lib")), "/usr/lib64"])
new_binary = copy_binary(orig_binary)
spack.relocate.relocate_elf_binaries(
binaries=[str(new_binary)],
orig_root=str(orig_binary.dirpath()),
new_root=None, # Not needed when relocating absolute paths
new_prefixes={str(orig_binary.dirpath()): "/foo"},
new_prefixes={str(tmpdir): "/foo"},
rel=False,
# Not needed when relocating absolute paths
orig_prefix=None,
@@ -322,13 +317,9 @@ def test_relocate_elf_binaries_relative_paths(binary_with_rpaths, copy_binary):
@pytest.mark.requires_executables("patchelf", "strings", "file", "gcc")
@skip_unless_linux
def test_make_elf_binaries_relative(binary_with_rpaths, copy_binary, prefix_tmpdir):
def test_make_elf_binaries_relative(binary_with_rpaths, copy_binary, tmpdir):
orig_binary = binary_with_rpaths(
rpaths=[
str(prefix_tmpdir.mkdir("lib")),
str(prefix_tmpdir.mkdir("lib64")),
"/opt/local/lib",
]
rpaths=[str(tmpdir.mkdir("lib")), str(tmpdir.mkdir("lib64")), "/opt/local/lib"]
)
new_binary = copy_binary(orig_binary)
@@ -348,19 +339,15 @@ def test_raise_if_not_relocatable(monkeypatch):
@pytest.mark.requires_executables("patchelf", "strings", "file", "gcc")
@skip_unless_linux
def test_relocate_text_bin(binary_with_rpaths, copy_binary, prefix_tmpdir):
def test_relocate_text_bin(binary_with_rpaths, copy_binary, tmpdir):
orig_binary = binary_with_rpaths(
rpaths=[
str(prefix_tmpdir.mkdir("lib")),
str(prefix_tmpdir.mkdir("lib64")),
"/opt/local/lib",
],
message=str(prefix_tmpdir),
rpaths=[str(tmpdir.mkdir("lib")), str(tmpdir.mkdir("lib64")), "/opt/local/lib"],
message=str(tmpdir),
)
new_binary = copy_binary(orig_binary)
# Check original directory is in the executable and the new one is not
assert text_in_bin(str(prefix_tmpdir), new_binary)
# Check original directory is in the executabel and the new one is not
assert text_in_bin(str(tmpdir), new_binary)
assert not text_in_bin(str(new_binary.dirpath()), new_binary)
# Check this call succeed
@@ -371,7 +358,7 @@ def test_relocate_text_bin(binary_with_rpaths, copy_binary, prefix_tmpdir):
# Check original directory is not there anymore and it was
# substituted with the new one
assert not text_in_bin(str(prefix_tmpdir), new_binary)
assert not text_in_bin(str(tmpdir), new_binary)
assert text_in_bin(str(new_binary.dirpath()), new_binary)
@@ -463,144 +450,30 @@ def test_utf8_paths_to_single_binary_regex():
assert regex.search(string).group(0) == b"/safe/[a-z]/file"
def test_ordered_replacement():
def test_ordered_replacement(tmpdir):
# This tests whether binary text replacement respects order, so that
# a long package prefix is replaced before a shorter sub-prefix like
# the root of the spack store (as a fallback).
def replace_and_expect(prefix_map, before, after=None, suffix_safety_size=7):
f = io.BytesIO(before)
spack.relocate.apply_binary_replacements(f, OrderedDict(prefix_map), suffix_safety_size)
f.seek(0)
assert f.read() == after
def replace_and_expect(prefix_map, before, after):
file = str(tmpdir.join("file"))
with open(file, "wb") as f:
f.write(before)
spack.relocate._replace_prefix_bin(file, prefix_map)
with open(file, "rb") as f:
assert f.read() == after
# The case of having a non-null terminated common suffix.
replace_and_expect(
[
(b"/old-spack/opt/specific-package", b"/first/specific-package"),
(b"/old-spack/opt", b"/sec/spack/opt"),
],
OrderedDict(
[(b"/old-spack/opt/specific-package", b"/first"), (b"/old-spack/opt", b"/second")]
),
b"Binary with /old-spack/opt/specific-package and /old-spack/opt",
b"Binary with /////////first/specific-package and /sec/spack/opt",
suffix_safety_size=7,
b"Binary with /first///////////////////////// and /second///////",
)
# The case of having a direct null terminated common suffix.
replace_and_expect(
[
(b"/old-spack/opt/specific-package", b"/first/specific-package"),
(b"/old-spack/opt", b"/sec/spack/opt"),
],
b"Binary with /old-spack/opt/specific-package\0 and /old-spack/opt\0",
b"Binary with /////////first/specific-package\0 and /sec/spack/opt\0",
suffix_safety_size=7,
)
# Testing the order of operations (not null terminated, long enough common suffix)
replace_and_expect(
[
(b"/old-spack/opt", b"/s/spack/opt"),
(b"/old-spack/opt/specific-package", b"/first/specific-package"),
],
OrderedDict(
[(b"/old-spack/opt", b"/second"), (b"/old-spack/opt/specific-package", b"/first")]
),
b"Binary with /old-spack/opt/specific-package and /old-spack/opt",
b"Binary with ///s/spack/opt/specific-package and ///s/spack/opt",
suffix_safety_size=7,
b"Binary with /second////////specific-package and /second///////",
)
# Testing the order of operations (null terminated, long enough common suffix)
replace_and_expect(
[
(b"/old-spack/opt", b"/s/spack/opt"),
(b"/old-spack/opt/specific-package", b"/first/specific-package"),
],
b"Binary with /old-spack/opt/specific-package\0 and /old-spack/opt\0",
b"Binary with ///s/spack/opt/specific-package\0 and ///s/spack/opt\0",
suffix_safety_size=7,
)
# Null terminated within the lookahead window, common suffix long enough
replace_and_expect(
[(b"/old-spack/opt/specific-package", b"/opt/specific-XXXXage")],
b"Binary with /old-spack/opt/specific-package/sub\0 data",
b"Binary with ///////////opt/specific-XXXXage/sub\0 data",
suffix_safety_size=7,
)
# Null terminated within the lookahead window, common suffix too short, but
# shortening is enough to spare more than 7 bytes of old suffix.
replace_and_expect(
[(b"/old-spack/opt/specific-package", b"/opt/specific-XXXXXge")],
b"Binary with /old-spack/opt/specific-package/sub\0 data",
b"Binary with /opt/specific-XXXXXge/sub\0ckage/sub\0 data", # ckage/sub = 9 bytes
suffix_safety_size=7,
)
# Null terminated within the lookahead window, common suffix too short,
# shortening leaves exactly 7 suffix bytes untouched, amazing!
replace_and_expect(
[(b"/old-spack/opt/specific-package", b"/spack/specific-XXXXXge")],
b"Binary with /old-spack/opt/specific-package/sub\0 data",
b"Binary with /spack/specific-XXXXXge/sub\0age/sub\0 data", # age/sub = 7 bytes
suffix_safety_size=7,
)
# Null terminated within the lookahead window, common suffix too short,
# shortening doesn't leave space for 7 bytes, sad!
error_msg = "Cannot replace {!r} with {!r} in the C-string {!r}.".format(
b"/old-spack/opt/specific-package",
b"/snacks/specific-XXXXXge",
b"/old-spack/opt/specific-package/sub",
)
with pytest.raises(spack.relocate.CannotShrinkCString, match=error_msg):
replace_and_expect(
[(b"/old-spack/opt/specific-package", b"/snacks/specific-XXXXXge")],
b"Binary with /old-spack/opt/specific-package/sub\0 data",
# expect failure!
suffix_safety_size=7,
)
# Check that it works when changing suffix_safety_size.
replace_and_expect(
[(b"/old-spack/opt/specific-package", b"/snacks/specific-XXXXXXe")],
b"Binary with /old-spack/opt/specific-package/sub\0 data",
b"Binary with /snacks/specific-XXXXXXe/sub\0ge/sub\0 data",
suffix_safety_size=6,
)
# Finally check the case of no shortening but a long enough common suffix.
replace_and_expect(
[(b"pkg-gwixwaalgczp6", b"pkg-zkesfralgczp6")],
b"Binary with pkg-gwixwaalgczp6/config\0 data",
b"Binary with pkg-zkesfralgczp6/config\0 data",
suffix_safety_size=7,
)
# Too short matching suffix, identical string length
error_msg = "Cannot replace {!r} with {!r} in the C-string {!r}.".format(
b"pkg-gwixwaxlgczp6",
b"pkg-zkesfrzlgczp6",
b"pkg-gwixwaxlgczp6",
)
with pytest.raises(spack.relocate.CannotShrinkCString, match=error_msg):
replace_and_expect(
[(b"pkg-gwixwaxlgczp6", b"pkg-zkesfrzlgczp6")],
b"Binary with pkg-gwixwaxlgczp6\0 data",
# expect failure
suffix_safety_size=7,
)
# Finally, make sure that the regex is not greedily finding the LAST null byte
# it should find the first null byte in the window. In this test we put one null
# at a distance where we cant keep a long enough suffix, and one where we can,
# so we should expect failure when the first null is used.
error_msg = "Cannot replace {!r} with {!r} in the C-string {!r}.".format(
b"pkg-abcdef",
b"pkg-xyzabc",
b"pkg-abcdef",
)
with pytest.raises(spack.relocate.CannotShrinkCString, match=error_msg):
replace_and_expect(
[(b"pkg-abcdef", b"pkg-xyzabc")],
b"Binary with pkg-abcdef\0/xx\0", # def\0/xx is 7 bytes.
# expect failure
suffix_safety_size=7,
)

View File

@@ -18,7 +18,7 @@
if sys.platform == "darwin":
args.extend(["/usr/bin/clang++", "install_name_tool"])
else:
args.extend(["g++", "patchelf"])
args.extend(["/usr/bin/g++", "patchelf"])
@pytest.mark.requires_executables(*args)

View File

@@ -178,14 +178,16 @@ async def f():
"""
def assertASTEqual(ast1, ast2):
ast.dump(ast1) == ast.dump(ast2)
def check_ast_roundtrip(code1, filename="internal", mode="exec"):
ast1 = compile(str(code1), filename, mode, ast.PyCF_ONLY_AST)
code2 = spack.util.unparse.unparse(ast1)
ast2 = compile(code2, filename, mode, ast.PyCF_ONLY_AST)
error_msg = "Failed to roundtrip {} [mode={}]".format(filename, mode)
assert ast.dump(ast1) == ast.dump(ast2), error_msg
assertASTEqual(ast1, ast2)
def test_core_lib_files():

View File

@@ -83,12 +83,7 @@ class Garply
f.write(garply_cc % prefix.config)
with open("%s/garply/garplinator.cc" % self.stage.source_path, "w") as f:
f.write(garplinator_cc)
gpp = which(
"g++",
path=":".join(
[s for s in os.environ["PATH"].split(os.pathsep) if "lib/spack/env" not in s]
),
)
gpp = which("/usr/bin/g++")
if sys.platform == "darwin":
gpp = which("/usr/bin/clang++")
gpp(

View File

@@ -97,12 +97,7 @@ class Quux
f.write(quux_h)
with open("%s/quux/quuxifier.cc" % self.stage.source_path, "w") as f:
f.write(quuxifier_cc)
gpp = which(
"g++",
path=":".join(
[s for s in os.environ["PATH"].split(os.pathsep) if "lib/spack/env" not in s]
),
)
gpp = which("/usr/bin/g++")
if sys.platform == "darwin":
gpp = which("/usr/bin/clang++")
gpp(

View File

@@ -97,7 +97,6 @@ class Hypre(AutotoolsPackage, CudaPackage, ROCmPackage):
depends_on("rocsparse", when="+rocm")
depends_on("rocthrust", when="+rocm")
depends_on("rocrand", when="+rocm")
depends_on("rocprim", when="+rocm")
depends_on("umpire", when="+umpire")
for sm_ in CudaPackage.cuda_arch_values:
depends_on(

View File

@@ -27,12 +27,6 @@ class IntelOneapiAdvisor(IntelOneApiPackage):
)
if platform.system() == "Linux":
version(
"2022.3.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18985/l_oneapi_advisor_p_2022.3.1.15323_offline.sh",
sha256="f05b58c2f13972b3ac979e4796bcc12a234b1e077400b5d00fc5df46cd228899",
expand=False,
)
version(
"2022.3.0",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18872/l_oneapi_advisor_p_2022.3.0.8704_offline.sh",

View File

@@ -30,12 +30,6 @@ class IntelOneapiCcl(IntelOneApiLibraryPackage):
depends_on("intel-oneapi-mpi")
if platform.system() == "Linux":
version(
"2021.7.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/19029/l_oneapi_ccl_p_2021.7.1.16948_offline.sh",
sha256="daab05a0779db343b600253df8fea93ab0ed20bd630d89883dd651b6b540b1b2",
expand=False,
)
version(
"2021.7.0",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18891/l_oneapi_ccl_p_2021.7.0.8733_offline.sh",

View File

@@ -10,17 +10,6 @@
from spack.package import *
linux_versions = [
{
"version": "2022.2.1",
"cpp": {
"url": "https://registrationcenter-download.intel.com/akdlm/irc_nas/19049/l_dpcpp-cpp-compiler_p_2022.2.1.16991_offline.sh",
"sha256": "3f0f02f9812a0cdf01922d2df9348910c6a4cb4f9dfe50fc7477a59bbb1f7173",
},
"ftn": {
"url": "https://registrationcenter-download.intel.com/akdlm/irc_nas/18998/l_fortran-compiler_p_2022.2.1.16992_offline.sh",
"sha256": "64f1d1efbcdc3ac2182bec18313ca23f800d94f69758db83a1394490d9d4b042",
},
},
{
"version": "2022.2.0",
"cpp": {

View File

@@ -29,12 +29,6 @@ class IntelOneapiDal(IntelOneApiLibraryPackage):
)
if platform.system() == "Linux":
version(
"2021.7.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/19032/l_daal_oneapi_p_2021.7.1.16996_offline.sh",
sha256="2328927480b0ba5d380028f981717b63ee323f8a1616a491a160a0a0b239e285",
expand=False,
)
version(
"2021.7.0",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18895/l_daal_oneapi_p_2021.7.0.8746_offline.sh",

View File

@@ -29,12 +29,6 @@ class IntelOneapiDnn(IntelOneApiLibraryPackage):
)
if platform.system() == "Linux":
version(
"2022.2.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/19035/l_onednn_p_2022.2.1.16994_offline.sh",
sha256="2102964a36a5b58b529385706e6829456ee5225111c33dfce6326fff5175aace",
expand=False,
)
version(
"2022.2.0",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18933/l_onednn_p_2022.2.0.8750_offline.sh",

View File

@@ -22,12 +22,6 @@ class IntelOneapiDpct(IntelOneApiPackage):
homepage = "https://www.intel.com/content/www/us/en/developer/tools/oneapi/dpc-compatibility-tool.html#gs.2p8km6"
if platform.system() == "Linux":
version(
"2022.2.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18991/l_dpcpp-ct_p_2022.2.1.14994_offline.sh",
sha256="ea2fbe36de70eb3c78c97133f81e0b2a2fbcfc9525e77125a183d7af446ef3e6",
expand=False,
)
version(
"2022.2.0",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18908/l_dpcpp-ct_p_2022.2.0.8701_offline.sh",

View File

@@ -25,12 +25,6 @@ class IntelOneapiDpl(IntelOneApiLibraryPackage):
homepage = "https://github.com/oneapi-src/oneDPL"
if platform.system() == "Linux":
version(
"2021.7.2",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/19046/l_oneDPL_p_2021.7.2.15007_offline.sh",
sha256="84d60a6b1978ff45d2c416f18ca7df542eaa8c0b18dc3abf4bb0824a91b4fc44",
expand=False,
)
version(
"2021.7.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18846/l_oneDPL_p_2021.7.1.8713_offline.sh",

View File

@@ -27,12 +27,6 @@ class IntelOneapiInspector(IntelOneApiPackage):
homepage = "https://software.intel.com/content/www/us/en/develop/tools/oneapi/components/inspector.html"
if platform.system() == "Linux":
version(
"2022.3.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/19005/l_inspector_oneapi_p_2022.3.1.15318_offline.sh",
sha256="62aa2abf6928c0f4fc60ccfb69375297f823c183aea2519d7344e09c9734c1f8",
expand=False,
)
version(
"2022.3.0",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18924/l_inspector_oneapi_p_2022.3.0.8706_offline.sh",

View File

@@ -30,12 +30,6 @@ class IntelOneapiIpp(IntelOneApiLibraryPackage):
)
if platform.system() == "Linux":
version(
"2021.6.2",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/19007/l_ipp_oneapi_p_2021.6.2.16995_offline.sh",
sha256="23ae49afa9f13c2bed0c8a32e447e1c6b3528685cebdd32e4aa2a9736827cc4e",
expand=False,
)
version(
"2021.6.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18925/l_ipp_oneapi_p_2021.6.1.8749_offline.sh",

View File

@@ -31,12 +31,6 @@ class IntelOneapiIppcp(IntelOneApiLibraryPackage):
)
if platform.system() == "Linux":
version(
"2021.6.2",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18999/l_ippcp_oneapi_p_2021.6.2.15006_offline.sh",
sha256="3c285c12da98a4d16e9a5ba237c8c51780475af54b1d1162185480ac891f16ee",
expand=False,
)
version(
"2021.6.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18923/l_ippcp_oneapi_p_2021.6.1.8714_offline.sh",

View File

@@ -30,12 +30,6 @@ class IntelOneapiItac(IntelOneApiPackage):
maintainers = ["rscohn2"]
if platform.system() == "Linux":
version(
"2021.7.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/19024/l_itac_oneapi_p_2021.7.1.15324_offline.sh",
sha256="fb26689efdb7369e211b5cf05f3e30d491a2787f24fef174b23241b997cc442f",
expand=False,
)
version(
"2021.7.0",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18886/l_itac_oneapi_p_2021.7.0.8707_offline.sh",

View File

@@ -27,12 +27,6 @@ class IntelOneapiMkl(IntelOneApiLibraryPackage):
)
if platform.system() == "Linux":
version(
"2022.2.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/19038/l_onemkl_p_2022.2.1.16993_offline.sh",
sha256="eedd4b795720de776b1fc5f542ae0fac37ec235cdb567f7c2ee3182e73e3e59d",
expand=False,
)
version(
"2022.2.0",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18898/l_onemkl_p_2022.2.0.8748_offline.sh",

View File

@@ -26,12 +26,6 @@ class IntelOneapiMpi(IntelOneApiLibraryPackage):
homepage = "https://software.intel.com/content/www/us/en/develop/tools/oneapi/components/mpi-library.html"
if platform.system() == "Linux":
version(
"2021.7.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/19010/l_mpi_oneapi_p_2021.7.1.16815_offline.sh",
sha256="90e7804f2367d457cd4cbf7aa29f1c5676287aa9b34f93e7c9a19e4b8583fff7",
expand=False,
)
version(
"2021.7.0",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18926/l_mpi_oneapi_p_2021.7.0.8711_offline.sh",

View File

@@ -25,12 +25,6 @@ class IntelOneapiTbb(IntelOneApiLibraryPackage):
)
if platform.system() == "Linux":
version(
"2021.7.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/19041/l_tbb_oneapi_p_2021.7.1.15005_offline.sh",
sha256="f13a8e740d69347b5985c1be496a3259a86d64ec94933b3d26100dbc2f059fd4",
expand=False,
)
version(
"2021.7.0",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18901/l_tbb_oneapi_p_2021.7.0.8712_offline.sh",

View File

@@ -28,12 +28,6 @@ class IntelOneapiVtune(IntelOneApiPackage):
homepage = "https://software.intel.com/content/www/us/en/develop/tools/oneapi/components/vtune-profiler.html"
if platform.system() == "Linux":
version(
"2022.4.1",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/19027/l_oneapi_vtune_p_2022.4.1.16919_offline.sh",
sha256="eb4b4da61eea52c08fc139dbf4630e2c52cbcfaea8f1376c545c0863839366d1",
expand=False,
)
version(
"2022.4.0",
url="https://registrationcenter-download.intel.com/akdlm/irc_nas/18888/l_oneapi_vtune_p_2022.4.0.8705_offline.sh",

View File

@@ -37,7 +37,6 @@ class PyMatplotlib(PythonPackage):
"pylab",
]
version("3.6.2", sha256="b03fd10a1709d0101c054883b550f7c4c5e974f751e2680318759af005964990")
version("3.6.1", sha256="e2d1b7225666f7e1bcc94c0bc9c587a82e3e8691da4757e357e5c2515222ee37")
version("3.6.0", sha256="c5108ebe67da60a9204497d8d403316228deb52b550388190c53a57394d41531")
version("3.5.3", sha256="339cac48b80ddbc8bfd05daae0a3a73414651a8596904c2a881cfd1edb65f26c")

View File

@@ -26,7 +26,7 @@ class Tau(Package):
tags = ["e4s"]
version("master", branch="master")
version("2.32", sha256="ee774a06e30ce0ef0f053635a52229152c39aba4f4933bed92da55e5e13466f3")
version("2.32", sha256="a404f51ae48fbfb9a2fb03643e555b4d978af4c83f365bacfead91e0095ee1ea")
version("2.31.1", sha256="bf445b9d4fe40a5672a7b175044d2133791c4dfb36a214c1a55a931aebc06b9d")
version("2.31", sha256="27e73c395dd2a42b91591ce4a76b88b1f67663ef13aa19ef4297c68f45d946c2")
version("2.30.2", sha256="43f84a15b71a226f8a64d966f0cb46022bcfbaefb341295ecc6fa80bb82bbfb4")