Compare commits
180 Commits
packages/a
...
develop-20
Author | SHA1 | Date | |
---|---|---|---|
![]() |
962498095d | ||
![]() |
d0217cf04e | ||
![]() |
65745fa0df | ||
![]() |
9f7cff1780 | ||
![]() |
bb43fa5444 | ||
![]() |
847f560a6e | ||
![]() |
623ff835fc | ||
![]() |
ca19790ff2 | ||
![]() |
f23366e4f8 | ||
![]() |
42fb689501 | ||
![]() |
c33bbdb77d | ||
![]() |
1af6aa22c1 | ||
![]() |
03d9373e5c | ||
![]() |
f469a3d6ab | ||
![]() |
25f24d947a | ||
![]() |
af25a84a56 | ||
![]() |
59a71959e7 | ||
![]() |
00e804a94b | ||
![]() |
db997229f2 | ||
![]() |
6fac041d40 | ||
![]() |
f8b2c65ddf | ||
![]() |
c504304d39 | ||
![]() |
976f1c2198 | ||
![]() |
e7c591a8b8 | ||
![]() |
f3522cba74 | ||
![]() |
0bd9c235a0 | ||
![]() |
335fca7049 | ||
![]() |
ce5ef14fdb | ||
![]() |
2447d16e55 | ||
![]() |
8196c68ff3 | ||
![]() |
308f74fe8b | ||
![]() |
864f09fef0 | ||
![]() |
29b53581e2 | ||
![]() |
e441e780b9 | ||
![]() |
4c642df5ae | ||
![]() |
217774c972 | ||
![]() |
8ec89fc54c | ||
![]() |
66ce93a2e3 | ||
![]() |
116ffe5809 | ||
![]() |
6b0ea2db1d | ||
![]() |
d72b371c8a | ||
![]() |
aa88ced154 | ||
![]() |
d89ae7bcde | ||
![]() |
53d1665a8b | ||
![]() |
9fa1654102 | ||
![]() |
2c692a5755 | ||
![]() |
c0df012b18 | ||
![]() |
66e8523e14 | ||
![]() |
3932299768 | ||
![]() |
3eba6b8379 | ||
![]() |
369928200a | ||
![]() |
81ed0f8d87 | ||
![]() |
194b6311e9 | ||
![]() |
8420898f79 | ||
![]() |
f556ba46d9 | ||
![]() |
ddaa9d5d81 | ||
![]() |
b878fe5555 | ||
![]() |
b600bfc779 | ||
![]() |
612c289c41 | ||
![]() |
e42c76cccf | ||
![]() |
25013bacf2 | ||
![]() |
3d554db198 | ||
![]() |
b6def50dcb | ||
![]() |
bf591c96bd | ||
![]() |
edf1d2ec40 | ||
![]() |
07f607ec9f | ||
![]() |
93747c5e24 | ||
![]() |
b746d4596a | ||
![]() |
8814705936 | ||
![]() |
c989541ebc | ||
![]() |
1759ce05dd | ||
![]() |
c0c1a4aea1 | ||
![]() |
53353ae64e | ||
![]() |
62f7a4c9b1 | ||
![]() |
39679d0882 | ||
![]() |
50e6bf9979 | ||
![]() |
b874c31cc8 | ||
![]() |
04baad90f5 | ||
![]() |
1022527923 | ||
![]() |
7ef19ec1d8 | ||
![]() |
6e45b51f27 | ||
![]() |
5f9cd0991b | ||
![]() |
98c44fc351 | ||
![]() |
b99f850c8e | ||
![]() |
cbbd68d16b | ||
![]() |
e4fbf99497 | ||
![]() |
6a225d5405 | ||
![]() |
af9fd82476 | ||
![]() |
29c1152484 | ||
![]() |
d6a8af6a1d | ||
![]() |
3c3dad0a7a | ||
![]() |
109efdff88 | ||
![]() |
fa318e2c92 | ||
![]() |
064e70990d | ||
![]() |
c40139b7d6 | ||
![]() |
c302e1a768 | ||
![]() |
7171015f1c | ||
![]() |
8ab6f33eb6 | ||
![]() |
a66ab9cc6c | ||
![]() |
70534ac9d4 | ||
![]() |
b369d8b250 | ||
![]() |
4d2319a785 | ||
![]() |
d6a9511f39 | ||
![]() |
dd69b646ad | ||
![]() |
b670205e54 | ||
![]() |
d6d8800466 | ||
![]() |
7a32954f7f | ||
![]() |
92564ecd42 | ||
![]() |
c1258a1431 | ||
![]() |
d46ac9b1e4 | ||
![]() |
2e472a13e5 | ||
![]() |
7edb525599 | ||
![]() |
93cd216603 | ||
![]() |
c1d385ada2 | ||
![]() |
464390962f | ||
![]() |
16734cd8c6 | ||
![]() |
1dd9eeb0c6 | ||
![]() |
f4ef0aec28 | ||
![]() |
ea2c70a21a | ||
![]() |
72ddc03da9 | ||
![]() |
32de71b0b6 | ||
![]() |
e94d5b935f | ||
![]() |
85649be232 | ||
![]() |
c23d2cdb2b | ||
![]() |
dc5dd896a2 | ||
![]() |
43f23589ef | ||
![]() |
5085f635dd | ||
![]() |
46da7952d3 | ||
![]() |
72783bcb0a | ||
![]() |
f4d2ff0068 | ||
![]() |
a2b7fee3fe | ||
![]() |
2ebf2df421 | ||
![]() |
e725aa527e | ||
![]() |
7455c8d173 | ||
![]() |
99e2bce99f | ||
![]() |
4204d16fd3 | ||
![]() |
e76677cbd5 | ||
![]() |
57357a540f | ||
![]() |
97e0b39b32 | ||
![]() |
247da9ea7a | ||
![]() |
07f89a73d1 | ||
![]() |
60cfdcb6cc | ||
![]() |
1c9b042d3a | ||
![]() |
c424611010 | ||
![]() |
35963d7d7d | ||
![]() |
7e62ca864a | ||
![]() |
fa9ef0ac89 | ||
![]() |
55d9fe20e5 | ||
![]() |
434a8d54d4 | ||
![]() |
7328c64fc7 | ||
![]() |
4be7b98fd2 | ||
![]() |
25ce6cce47 | ||
![]() |
418a9194e7 | ||
![]() |
d16a578242 | ||
![]() |
aee2f5cf41 | ||
![]() |
ca8ea63796 | ||
![]() |
3b21ff109f | ||
![]() |
d503f03473 | ||
![]() |
770d2fe4d7 | ||
![]() |
fcc35b70bb | ||
![]() |
074387b29c | ||
![]() |
4d26b93070 | ||
![]() |
9d15a006f8 | ||
![]() |
7e69650806 | ||
![]() |
142469f92e | ||
![]() |
cb6cb023d2 | ||
![]() |
920614a799 | ||
![]() |
5be40f1a5a | ||
![]() |
aa0ab3b38b | ||
![]() |
85c125a0f5 | ||
![]() |
2842c6d191 | ||
![]() |
e8309b16fc | ||
![]() |
4dd55e1b67 | ||
![]() |
227fa1a482 | ||
![]() |
ee47d877ff | ||
![]() |
4b4be2e2c2 | ||
![]() |
0e6e61b32f | ||
![]() |
79027884c7 | ||
![]() |
beadf06caa | ||
![]() |
fc24be5c2b |
2
.github/workflows/coverage.yml
vendored
2
.github/workflows/coverage.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
- run: coverage xml
|
||||
|
||||
- name: "Upload coverage report to CodeCov"
|
||||
uses: codecov/codecov-action@05f5a9cfad807516dbbef9929c4a42df3eb78766
|
||||
uses: codecov/codecov-action@1e68e06f1dbfde0e4cefc87efeba9e4643565303
|
||||
with:
|
||||
verbose: true
|
||||
fail_ci_if_error: false
|
||||
|
@@ -2,6 +2,6 @@ black==24.10.0
|
||||
clingo==5.7.1
|
||||
flake8==7.1.1
|
||||
isort==5.13.2
|
||||
mypy==1.8.0
|
||||
mypy==1.11.2
|
||||
types-six==1.17.0.20241205
|
||||
vermin==1.6.0
|
||||
|
6
.github/workflows/valid-style.yml
vendored
6
.github/workflows/valid-style.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
- uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b
|
||||
with:
|
||||
python-version: '3.11'
|
||||
python-version: '3.13'
|
||||
cache: 'pip'
|
||||
- name: Install Python Packages
|
||||
run: |
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b
|
||||
with:
|
||||
python-version: '3.11'
|
||||
python-version: '3.13'
|
||||
cache: 'pip'
|
||||
- name: Install Python packages
|
||||
run: |
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
secrets: inherit
|
||||
with:
|
||||
with_coverage: ${{ inputs.with_coverage }}
|
||||
python_version: '3.11'
|
||||
python_version: '3.13'
|
||||
# Check that spack can bootstrap the development environment on Python 3.6 - RHEL8
|
||||
bootstrap-dev-rhel8:
|
||||
runs-on: ubuntu-latest
|
||||
|
@@ -25,14 +25,23 @@ These settings can be overridden in ``etc/spack/config.yaml`` or
|
||||
The location where Spack will install packages and their dependencies.
|
||||
Default is ``$spack/opt/spack``.
|
||||
|
||||
---------------------------------------------------
|
||||
``install_hash_length`` and ``install_path_scheme``
|
||||
---------------------------------------------------
|
||||
---------------
|
||||
``projections``
|
||||
---------------
|
||||
|
||||
The default Spack installation path can be very long and can create problems
|
||||
for scripts with hardcoded shebangs. Additionally, when using the Intel
|
||||
compiler, and if there is also a long list of dependencies, the compiler may
|
||||
segfault. If you see the following:
|
||||
.. warning::
|
||||
|
||||
Modifying projections of the install tree is strongly discouraged.
|
||||
|
||||
By default Spack installs all packages into a unique directory relative to the install
|
||||
tree root with the following layout:
|
||||
|
||||
.. code-block::
|
||||
|
||||
{architecture}/{compiler.name}-{compiler.version}/{name}-{version}-{hash}
|
||||
|
||||
In very rare cases, it may be necessary to reduce the length of this path. For example,
|
||||
very old versions of the Intel compiler are known to segfault when input paths are too long:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
@@ -40,36 +49,25 @@ segfault. If you see the following:
|
||||
** Segmentation violation signal raised. **
|
||||
Access violation or stack overflow. Please contact Intel Support for assistance.
|
||||
|
||||
it may be because variables containing dependency specs may be too long. There
|
||||
are two parameters to help with long path names. Firstly, the
|
||||
``install_hash_length`` parameter can set the length of the hash in the
|
||||
installation path from 1 to 32. The default path uses the full 32 characters.
|
||||
Another case is Python and R packages with many runtime dependencies, which can result
|
||||
in very large ``PYTHONPATH`` and ``R_LIBS`` environment variables. This can cause the
|
||||
``execve`` system call to fail with ``E2BIG``, preventing processes from starting.
|
||||
|
||||
Secondly, it is also possible to modify the entire installation
|
||||
scheme. By default Spack uses
|
||||
``{architecture}/{compiler.name}-{compiler.version}/{name}-{version}-{hash}``
|
||||
where the tokens that are available for use in this directive are the
|
||||
same as those understood by the :meth:`~spack.spec.Spec.format`
|
||||
method. Using this parameter it is possible to use a different package
|
||||
layout or reduce the depth of the installation paths. For example
|
||||
For this reason, Spack allows users to modify the installation layout through custom
|
||||
projections. For example
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
config:
|
||||
install_path_scheme: '{name}/{version}/{hash:7}'
|
||||
install_tree:
|
||||
root: $spack/opt/spack
|
||||
projections:
|
||||
all: "{name}/{version}/{hash:16}"
|
||||
|
||||
would install packages into sub-directories using only the package
|
||||
name, version and a hash length of 7 characters.
|
||||
would install packages into sub-directories using only the package name, version and a
|
||||
hash length of 16 characters.
|
||||
|
||||
When using either parameter to set the hash length it only affects the
|
||||
representation of the hash in the installation directory. You
|
||||
should be aware that the smaller the hash length the more likely
|
||||
naming conflicts will occur. These parameters are independent of those
|
||||
used to configure module names.
|
||||
|
||||
.. warning:: Modifying the installation hash length or path scheme after
|
||||
packages have been installed will prevent Spack from being
|
||||
able to find the old installation directories.
|
||||
Notice that reducing the hash length increases the likelihood of hash collisions.
|
||||
|
||||
--------------------
|
||||
``build_stage``
|
||||
|
@@ -543,10 +543,10 @@ With either interpreter you can run a single command:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ spack python -c 'from spack.spec import Spec; Spec("python").concretized()'
|
||||
$ spack python -c 'from spack.concretize import concretize_one; concretize_one("python")'
|
||||
...
|
||||
|
||||
$ spack python -i ipython -c 'from spack.spec import Spec; Spec("python").concretized()'
|
||||
$ spack python -i ipython -c 'from spack.concretize import concretize_one; concretize_one("python")'
|
||||
Out[1]: ...
|
||||
|
||||
or a file:
|
||||
|
@@ -456,14 +456,13 @@ For instance, the following config options,
|
||||
tcl:
|
||||
all:
|
||||
suffixes:
|
||||
^python@3: 'python{^python.version}'
|
||||
^python@3: 'python{^python.version.up_to_2}'
|
||||
^openblas: 'openblas'
|
||||
|
||||
will add a ``python-3.12.1`` version string to any packages compiled with
|
||||
Python matching the spec, ``python@3``. This is useful to know which
|
||||
version of Python a set of Python extensions is associated with. Likewise, the
|
||||
``openblas`` string is attached to any program that has openblas in the spec,
|
||||
most likely via the ``+blas`` variant specification.
|
||||
will add a ``python3.12`` to module names of packages compiled with Python 3.12, and similarly for
|
||||
all specs depending on ``python@3``. This is useful to know which version of Python a set of Python
|
||||
extensions is associated with. Likewise, the ``openblas`` string is attached to any program that
|
||||
has openblas in the spec, most likely via the ``+blas`` variant specification.
|
||||
|
||||
The most heavyweight solution to module naming is to change the entire
|
||||
naming convention for module files. This uses the projections format
|
||||
|
@@ -4,7 +4,7 @@ sphinx_design==0.6.1
|
||||
sphinx-rtd-theme==3.0.2
|
||||
python-levenshtein==0.26.1
|
||||
docutils==0.21.2
|
||||
pygments==2.18.0
|
||||
pygments==2.19.1
|
||||
urllib3==2.3.0
|
||||
pytest==8.3.4
|
||||
isort==5.13.2
|
||||
|
@@ -1740,8 +1740,7 @@ def find(
|
||||
|
||||
|
||||
def _log_file_access_issue(e: OSError, path: str) -> None:
|
||||
errno_name = errno.errorcode.get(e.errno, "UNKNOWN")
|
||||
tty.debug(f"find must skip {path}: {errno_name} {e}")
|
||||
tty.debug(f"find must skip {path}: {e}")
|
||||
|
||||
|
||||
def _file_id(s: os.stat_result) -> Tuple[int, int]:
|
||||
|
@@ -1356,14 +1356,8 @@ def _test_detection_by_executable(pkgs, debug_log, error_cls):
|
||||
|
||||
def _compare_extra_attribute(_expected, _detected, *, _spec):
|
||||
result = []
|
||||
# Check items are of the same type
|
||||
if not isinstance(_detected, type(_expected)):
|
||||
_summary = f'{pkg_name}: error when trying to detect "{_expected}"'
|
||||
_details = [f"{_detected} was detected instead"]
|
||||
return [error_cls(summary=_summary, details=_details)]
|
||||
|
||||
# If they are string expected is a regex
|
||||
if isinstance(_expected, str):
|
||||
if isinstance(_expected, str) and isinstance(_detected, str):
|
||||
try:
|
||||
_regex = re.compile(_expected)
|
||||
except re.error:
|
||||
@@ -1379,7 +1373,7 @@ def _compare_extra_attribute(_expected, _detected, *, _spec):
|
||||
_details = [f"{_detected} does not match the regex"]
|
||||
return [error_cls(summary=_summary, details=_details)]
|
||||
|
||||
if isinstance(_expected, dict):
|
||||
elif isinstance(_expected, dict) and isinstance(_detected, dict):
|
||||
_not_detected = set(_expected.keys()) - set(_detected.keys())
|
||||
if _not_detected:
|
||||
_summary = f"{pkg_name}: cannot detect some attributes for spec {_spec}"
|
||||
@@ -1394,6 +1388,10 @@ def _compare_extra_attribute(_expected, _detected, *, _spec):
|
||||
result.extend(
|
||||
_compare_extra_attribute(_expected[_key], _detected[_key], _spec=_spec)
|
||||
)
|
||||
else:
|
||||
_summary = f'{pkg_name}: error when trying to detect "{_expected}"'
|
||||
_details = [f"{_detected} was detected instead"]
|
||||
return [error_cls(summary=_summary, details=_details)]
|
||||
|
||||
return result
|
||||
|
||||
|
@@ -23,7 +23,7 @@
|
||||
import urllib.request
|
||||
import warnings
|
||||
from contextlib import closing
|
||||
from typing import IO, Dict, Iterable, List, NamedTuple, Optional, Set, Tuple, Union
|
||||
from typing import IO, Callable, Dict, Iterable, List, NamedTuple, Optional, Set, Tuple, Union
|
||||
|
||||
import llnl.util.filesystem as fsys
|
||||
import llnl.util.lang
|
||||
@@ -591,32 +591,18 @@ def file_matches(f: IO[bytes], regex: llnl.util.lang.PatternBytes) -> bool:
|
||||
f.seek(0)
|
||||
|
||||
|
||||
def deps_to_relocate(spec):
|
||||
"""Return the transitive link and direct run dependencies of the spec.
|
||||
|
||||
This is a special traversal for dependencies we need to consider when relocating a package.
|
||||
|
||||
Package binaries, scripts, and other files may refer to the prefixes of dependencies, so
|
||||
we need to rewrite those locations when dependencies are in a different place at install time
|
||||
than they were at build time.
|
||||
|
||||
This traversal covers transitive link dependencies and direct run dependencies because:
|
||||
|
||||
1. Spack adds RPATHs for transitive link dependencies so that packages can find needed
|
||||
dependency libraries.
|
||||
2. Packages may call any of their *direct* run dependencies (and may bake their paths into
|
||||
binaries or scripts), so we also need to search for run dependency prefixes when relocating.
|
||||
|
||||
This returns a deduplicated list of transitive link dependencies and direct run dependencies.
|
||||
"""
|
||||
deps = [
|
||||
def specs_to_relocate(spec: spack.spec.Spec) -> List[spack.spec.Spec]:
|
||||
"""Return the set of specs that may be referenced in the install prefix of the provided spec.
|
||||
We currently include non-external transitive link and direct run dependencies."""
|
||||
specs = [
|
||||
s
|
||||
for s in itertools.chain(
|
||||
spec.traverse(root=True, deptype="link"), spec.dependencies(deptype="run")
|
||||
spec.traverse(root=True, deptype="link", order="breadth", key=traverse.by_dag_hash),
|
||||
spec.dependencies(deptype="run"),
|
||||
)
|
||||
if not s.external
|
||||
]
|
||||
return llnl.util.lang.dedupe(deps, key=lambda s: s.dag_hash())
|
||||
return list(llnl.util.lang.dedupe(specs, key=lambda s: s.dag_hash()))
|
||||
|
||||
|
||||
def get_buildinfo_dict(spec):
|
||||
@@ -630,7 +616,7 @@ def get_buildinfo_dict(spec):
|
||||
# "relocate_binaries": [],
|
||||
# "relocate_links": [],
|
||||
"hardlinks_deduped": True,
|
||||
"hash_to_prefix": {d.dag_hash(): str(d.prefix) for d in deps_to_relocate(spec)},
|
||||
"hash_to_prefix": {d.dag_hash(): str(d.prefix) for d in specs_to_relocate(spec)},
|
||||
}
|
||||
|
||||
|
||||
@@ -683,19 +669,24 @@ def sign_specfile(key: str, specfile_path: str) -> str:
|
||||
|
||||
|
||||
def _read_specs_and_push_index(
|
||||
file_list, read_method, cache_prefix, db: BuildCacheDatabase, temp_dir, concurrency
|
||||
file_list: List[str],
|
||||
read_method: Callable,
|
||||
cache_prefix: str,
|
||||
db: BuildCacheDatabase,
|
||||
temp_dir: str,
|
||||
concurrency: int,
|
||||
):
|
||||
"""Read all the specs listed in the provided list, using thread given thread parallelism,
|
||||
generate the index, and push it to the mirror.
|
||||
|
||||
Args:
|
||||
file_list (list(str)): List of urls or file paths pointing at spec files to read
|
||||
file_list: List of urls or file paths pointing at spec files to read
|
||||
read_method: A function taking a single argument, either a url or a file path,
|
||||
and which reads the spec file at that location, and returns the spec.
|
||||
cache_prefix (str): prefix of the build cache on s3 where index should be pushed.
|
||||
cache_prefix: prefix of the build cache on s3 where index should be pushed.
|
||||
db: A spack database used for adding specs and then writing the index.
|
||||
temp_dir (str): Location to write index.json and hash for pushing
|
||||
concurrency (int): Number of parallel processes to use when fetching
|
||||
temp_dir: Location to write index.json and hash for pushing
|
||||
concurrency: Number of parallel processes to use when fetching
|
||||
"""
|
||||
for file in file_list:
|
||||
contents = read_method(file)
|
||||
@@ -875,9 +866,12 @@ def _url_generate_package_index(url: str, tmpdir: str, concurrency: int = 32):
|
||||
tty.debug(f"Retrieving spec descriptor files from {url} to build index")
|
||||
|
||||
db = BuildCacheDatabase(tmpdir)
|
||||
db._write()
|
||||
|
||||
try:
|
||||
_read_specs_and_push_index(file_list, read_fn, url, db, db.database_directory, concurrency)
|
||||
_read_specs_and_push_index(
|
||||
file_list, read_fn, url, db, str(db.database_directory), concurrency
|
||||
)
|
||||
except Exception as e:
|
||||
raise GenerateIndexError(f"Encountered problem pushing package index to {url}: {e}") from e
|
||||
|
||||
@@ -1112,7 +1106,7 @@ def _exists_in_buildcache(spec: spack.spec.Spec, tmpdir: str, out_url: str) -> E
|
||||
|
||||
|
||||
def prefixes_to_relocate(spec):
|
||||
prefixes = [s.prefix for s in deps_to_relocate(spec)]
|
||||
prefixes = [s.prefix for s in specs_to_relocate(spec)]
|
||||
prefixes.append(spack.hooks.sbang.sbang_install_path())
|
||||
prefixes.append(str(spack.store.STORE.layout.root))
|
||||
return prefixes
|
||||
@@ -2139,10 +2133,9 @@ def fetch_url_to_mirror(url):
|
||||
|
||||
|
||||
def dedupe_hardlinks_if_necessary(root, buildinfo):
|
||||
"""Updates a buildinfo dict for old archives that did
|
||||
not dedupe hardlinks. De-duping hardlinks is necessary
|
||||
when relocating files in parallel and in-place. This
|
||||
means we must preserve inodes when relocating."""
|
||||
"""Updates a buildinfo dict for old archives that did not dedupe hardlinks. De-duping hardlinks
|
||||
is necessary when relocating files in parallel and in-place. This means we must preserve inodes
|
||||
when relocating."""
|
||||
|
||||
# New archives don't need this.
|
||||
if buildinfo.get("hardlinks_deduped", False):
|
||||
@@ -2171,65 +2164,47 @@ def dedupe_hardlinks_if_necessary(root, buildinfo):
|
||||
buildinfo[key] = new_list
|
||||
|
||||
|
||||
def relocate_package(spec):
|
||||
"""
|
||||
Relocate the given package
|
||||
"""
|
||||
workdir = str(spec.prefix)
|
||||
buildinfo = read_buildinfo_file(workdir)
|
||||
new_layout_root = str(spack.store.STORE.layout.root)
|
||||
new_prefix = str(spec.prefix)
|
||||
new_rel_prefix = str(os.path.relpath(new_prefix, new_layout_root))
|
||||
new_spack_prefix = str(spack.paths.prefix)
|
||||
|
||||
old_sbang_install_path = None
|
||||
if "sbang_install_path" in buildinfo:
|
||||
old_sbang_install_path = str(buildinfo["sbang_install_path"])
|
||||
def relocate_package(spec: spack.spec.Spec) -> None:
|
||||
"""Relocate binaries and text files in the given spec prefix, based on its buildinfo file."""
|
||||
buildinfo = read_buildinfo_file(spec.prefix)
|
||||
old_layout_root = str(buildinfo["buildpath"])
|
||||
old_spack_prefix = str(buildinfo.get("spackprefix"))
|
||||
old_rel_prefix = buildinfo.get("relative_prefix")
|
||||
old_prefix = os.path.join(old_layout_root, old_rel_prefix)
|
||||
rel = buildinfo.get("relative_rpaths", False)
|
||||
|
||||
# In the past prefix_to_hash was the default and externals were not dropped, so prefixes
|
||||
# were not unique.
|
||||
# Warn about old style tarballs created with the --rel flag (removed in Spack v0.20)
|
||||
if buildinfo.get("relative_rpaths", False):
|
||||
tty.warn(
|
||||
f"Tarball for {spec} uses relative rpaths, which can cause library loading issues."
|
||||
)
|
||||
|
||||
# In Spack 0.19 and older prefix_to_hash was the default and externals were not dropped, so
|
||||
# prefixes were not unique.
|
||||
if "hash_to_prefix" in buildinfo:
|
||||
hash_to_old_prefix = buildinfo["hash_to_prefix"]
|
||||
elif "prefix_to_hash" in buildinfo:
|
||||
hash_to_old_prefix = dict((v, k) for (k, v) in buildinfo["prefix_to_hash"].items())
|
||||
hash_to_old_prefix = {v: k for (k, v) in buildinfo["prefix_to_hash"].items()}
|
||||
else:
|
||||
hash_to_old_prefix = dict()
|
||||
raise NewLayoutException(
|
||||
"Package tarball was created from an install prefix with a different directory layout "
|
||||
"and an older buildcache create implementation. It cannot be relocated."
|
||||
)
|
||||
|
||||
if old_rel_prefix != new_rel_prefix and not hash_to_old_prefix:
|
||||
msg = "Package tarball was created from an install "
|
||||
msg += "prefix with a different directory layout and an older "
|
||||
msg += "buildcache create implementation. It cannot be relocated."
|
||||
raise NewLayoutException(msg)
|
||||
prefix_to_prefix = {}
|
||||
|
||||
# Spurious replacements (e.g. sbang) will cause issues with binaries
|
||||
# For example, the new sbang can be longer than the old one.
|
||||
# Hence 2 dictionaries are maintained here.
|
||||
prefix_to_prefix_text = collections.OrderedDict()
|
||||
prefix_to_prefix_bin = collections.OrderedDict()
|
||||
if "sbang_install_path" in buildinfo:
|
||||
old_sbang_install_path = str(buildinfo["sbang_install_path"])
|
||||
prefix_to_prefix[old_sbang_install_path] = spack.hooks.sbang.sbang_install_path()
|
||||
|
||||
if old_sbang_install_path:
|
||||
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.
|
||||
|
||||
# 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.
|
||||
#
|
||||
# If the spec is spliced, we need to handle the simultaneous mapping
|
||||
# from the old install_tree to the new install_tree and from the build_spec
|
||||
# to the spliced spec.
|
||||
# Because foo.build_spec is foo for any non-spliced spec, we can simplify
|
||||
# by checking for spliced-in nodes by checking for nodes not in the build_spec
|
||||
# without any explicit check for whether the spec is spliced.
|
||||
# An analog in this algorithm is any spec that shares a name or provides the same virtuals
|
||||
# in the context of the relevant root spec. This ensures that the analog for a spec s
|
||||
# is the spec that s replaced when we spliced.
|
||||
relocation_specs = deps_to_relocate(spec)
|
||||
# If the spec is spliced, we need to handle the simultaneous mapping from the old install_tree
|
||||
# to the new install_tree and from the build_spec to the spliced spec. Because foo.build_spec
|
||||
# is foo for any non-spliced spec, we can simplify by checking for spliced-in nodes by checking
|
||||
# for nodes not in the build_spec without any explicit check for whether the spec is spliced.
|
||||
# An analog in this algorithm is any spec that shares a name or provides the same virtuals in
|
||||
# the context of the relevant root spec. This ensures that the analog for a spec s is the spec
|
||||
# that s replaced when we spliced.
|
||||
relocation_specs = specs_to_relocate(spec)
|
||||
build_spec_ids = set(id(s) for s in spec.build_spec.traverse(deptype=dt.ALL & ~dt.BUILD))
|
||||
for s in relocation_specs:
|
||||
analog = s
|
||||
@@ -2248,98 +2223,48 @@ def relocate_package(spec):
|
||||
lookup_dag_hash = analog.dag_hash()
|
||||
if lookup_dag_hash in hash_to_old_prefix:
|
||||
old_dep_prefix = hash_to_old_prefix[lookup_dag_hash]
|
||||
prefix_to_prefix_bin[old_dep_prefix] = str(s.prefix)
|
||||
prefix_to_prefix_text[old_dep_prefix] = str(s.prefix)
|
||||
prefix_to_prefix[old_dep_prefix] = str(s.prefix)
|
||||
|
||||
# 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
|
||||
prefix_to_prefix[old_layout_root] = str(spack.store.STORE.layout.root)
|
||||
|
||||
# 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
|
||||
# will have the old sbang location in their shebangs.
|
||||
orig_sbang = "#!/bin/bash {0}/bin/sbang".format(old_spack_prefix)
|
||||
new_sbang = spack.hooks.sbang.sbang_shebang_line()
|
||||
prefix_to_prefix_text[orig_sbang] = new_sbang
|
||||
# Delete identity mappings from prefix_to_prefix
|
||||
prefix_to_prefix = {k: v for k, v in prefix_to_prefix.items() if k != v}
|
||||
|
||||
tty.debug("Relocating package from", "%s to %s." % (old_layout_root, new_layout_root))
|
||||
# If there's nothing to relocate, we're done.
|
||||
if not prefix_to_prefix:
|
||||
return
|
||||
|
||||
# Old archives maybe have hardlinks repeated.
|
||||
dedupe_hardlinks_if_necessary(workdir, buildinfo)
|
||||
for old, new in prefix_to_prefix.items():
|
||||
tty.debug(f"Relocating: {old} => {new}.")
|
||||
|
||||
def is_backup_file(file):
|
||||
return file.endswith("~")
|
||||
# Old archives may have hardlinks repeated.
|
||||
dedupe_hardlinks_if_necessary(spec.prefix, buildinfo)
|
||||
|
||||
# Text files containing the prefix text
|
||||
text_names = list()
|
||||
for filename in buildinfo["relocate_textfiles"]:
|
||||
text_name = os.path.join(workdir, filename)
|
||||
# Don't add backup files generated by filter_file during install step.
|
||||
if not is_backup_file(text_name):
|
||||
text_names.append(text_name)
|
||||
textfiles = [os.path.join(spec.prefix, f) for f in buildinfo["relocate_textfiles"]]
|
||||
binaries = [os.path.join(spec.prefix, f) for f in buildinfo.get("relocate_binaries")]
|
||||
links = [os.path.join(spec.prefix, f) for f in buildinfo.get("relocate_links", [])]
|
||||
|
||||
# If we are not installing back to the same install tree do the relocation
|
||||
if old_prefix != new_prefix:
|
||||
files_to_relocate = [
|
||||
os.path.join(workdir, filename) for filename in buildinfo.get("relocate_binaries")
|
||||
]
|
||||
# If the buildcache was not created with relativized rpaths
|
||||
# do the relocation of path in binaries
|
||||
platform = spack.platforms.by_name(spec.platform)
|
||||
if "macho" in platform.binary_formats:
|
||||
relocate.relocate_macho_binaries(
|
||||
files_to_relocate,
|
||||
old_layout_root,
|
||||
new_layout_root,
|
||||
prefix_to_prefix_bin,
|
||||
rel,
|
||||
old_prefix,
|
||||
new_prefix,
|
||||
)
|
||||
elif "elf" in platform.binary_formats and not rel:
|
||||
# The new ELF dynamic section relocation logic only handles absolute to
|
||||
# absolute relocation.
|
||||
relocate.new_relocate_elf_binaries(files_to_relocate, prefix_to_prefix_bin)
|
||||
elif "elf" in platform.binary_formats and rel:
|
||||
relocate.relocate_elf_binaries(
|
||||
files_to_relocate,
|
||||
old_layout_root,
|
||||
new_layout_root,
|
||||
prefix_to_prefix_bin,
|
||||
rel,
|
||||
old_prefix,
|
||||
new_prefix,
|
||||
)
|
||||
platform = spack.platforms.by_name(spec.platform)
|
||||
if "macho" in platform.binary_formats:
|
||||
relocate.relocate_macho_binaries(binaries, prefix_to_prefix)
|
||||
elif "elf" in platform.binary_formats:
|
||||
relocate.relocate_elf_binaries(binaries, prefix_to_prefix)
|
||||
|
||||
# Relocate links to the new install prefix
|
||||
links = [os.path.join(workdir, f) for f in buildinfo.get("relocate_links", [])]
|
||||
relocate.relocate_links(links, prefix_to_prefix_bin)
|
||||
relocate.relocate_links(links, prefix_to_prefix)
|
||||
relocate.relocate_text(textfiles, prefix_to_prefix)
|
||||
changed_files = relocate.relocate_text_bin(binaries, prefix_to_prefix)
|
||||
|
||||
# For all buildcaches
|
||||
# relocate the install prefixes in text files including dependencies
|
||||
relocate.relocate_text(text_names, prefix_to_prefix_text)
|
||||
|
||||
# relocate the install prefixes in binary files including dependencies
|
||||
changed_files = relocate.relocate_text_bin(files_to_relocate, prefix_to_prefix_bin)
|
||||
|
||||
# Add ad-hoc signatures to patched macho files when on macOS.
|
||||
if "macho" in platform.binary_formats and sys.platform == "darwin":
|
||||
codesign = which("codesign")
|
||||
if not codesign:
|
||||
return
|
||||
for binary in changed_files:
|
||||
# preserve the original inode by running codesign on a copy
|
||||
with fsys.edit_in_place_through_temporary_file(binary) as tmp_binary:
|
||||
codesign("-fs-", tmp_binary)
|
||||
|
||||
# If we are installing back to the same location
|
||||
# relocate the sbang location if the spack directory changed
|
||||
else:
|
||||
if old_spack_prefix != new_spack_prefix:
|
||||
relocate.relocate_text(text_names, prefix_to_prefix_text)
|
||||
# Add ad-hoc signatures to patched macho files when on macOS.
|
||||
if "macho" in platform.binary_formats and sys.platform == "darwin":
|
||||
codesign = which("codesign")
|
||||
if not codesign:
|
||||
return
|
||||
for binary in changed_files:
|
||||
# preserve the original inode by running codesign on a copy
|
||||
with fsys.edit_in_place_through_temporary_file(binary) as tmp_binary:
|
||||
codesign("-fs-", tmp_binary)
|
||||
|
||||
|
||||
def _extract_inner_tarball(spec, filename, extract_to, signature_required: bool, remote_checksum):
|
||||
|
@@ -10,7 +10,9 @@
|
||||
import sys
|
||||
import sysconfig
|
||||
import warnings
|
||||
from typing import Dict, Optional, Sequence, Union
|
||||
from typing import Optional, Sequence, Union
|
||||
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
import archspec.cpu
|
||||
|
||||
@@ -18,13 +20,17 @@
|
||||
from llnl.util import tty
|
||||
|
||||
import spack.platforms
|
||||
import spack.spec
|
||||
import spack.store
|
||||
import spack.util.environment
|
||||
import spack.util.executable
|
||||
|
||||
from .config import spec_for_current_python
|
||||
|
||||
QueryInfo = Dict[str, "spack.spec.Spec"]
|
||||
|
||||
class QueryInfo(TypedDict, total=False):
|
||||
spec: spack.spec.Spec
|
||||
command: spack.util.executable.Executable
|
||||
|
||||
|
||||
def _python_import(module: str) -> bool:
|
||||
@@ -211,7 +217,9 @@ def _executables_in_store(
|
||||
):
|
||||
spack.util.environment.path_put_first("PATH", [bin_dir])
|
||||
if query_info is not None:
|
||||
query_info["command"] = spack.util.executable.which(*executables, path=bin_dir)
|
||||
query_info["command"] = spack.util.executable.which(
|
||||
*executables, path=bin_dir, required=True
|
||||
)
|
||||
query_info["spec"] = concrete_spec
|
||||
return True
|
||||
return False
|
||||
|
@@ -34,6 +34,7 @@
|
||||
from llnl.util.lang import GroupedExceptionHandler
|
||||
|
||||
import spack.binary_distribution
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.detection
|
||||
import spack.mirrors.mirror
|
||||
@@ -47,7 +48,13 @@
|
||||
import spack.version
|
||||
from spack.installer import PackageInstaller
|
||||
|
||||
from ._common import _executables_in_store, _python_import, _root_spec, _try_import_from_store
|
||||
from ._common import (
|
||||
QueryInfo,
|
||||
_executables_in_store,
|
||||
_python_import,
|
||||
_root_spec,
|
||||
_try_import_from_store,
|
||||
)
|
||||
from .clingo import ClingoBootstrapConcretizer
|
||||
from .config import spack_python_interpreter, spec_for_current_python
|
||||
|
||||
@@ -134,7 +141,7 @@ class BuildcacheBootstrapper(Bootstrapper):
|
||||
|
||||
def __init__(self, conf) -> None:
|
||||
super().__init__(conf)
|
||||
self.last_search: Optional[ConfigDictionary] = None
|
||||
self.last_search: Optional[QueryInfo] = None
|
||||
self.config_scope_name = f"bootstrap_buildcache-{uuid.uuid4()}"
|
||||
|
||||
@staticmethod
|
||||
@@ -211,14 +218,14 @@ def _install_and_test(
|
||||
for _, pkg_hash, pkg_sha256 in item["binaries"]:
|
||||
self._install_by_hash(pkg_hash, pkg_sha256, bincache_platform)
|
||||
|
||||
info: ConfigDictionary = {}
|
||||
info: QueryInfo = {}
|
||||
if test_fn(query_spec=abstract_spec, query_info=info):
|
||||
self.last_search = info
|
||||
return True
|
||||
return False
|
||||
|
||||
def try_import(self, module: str, abstract_spec_str: str) -> bool:
|
||||
info: ConfigDictionary
|
||||
info: QueryInfo
|
||||
test_fn, info = functools.partial(_try_import_from_store, module), {}
|
||||
if test_fn(query_spec=abstract_spec_str, query_info=info):
|
||||
return True
|
||||
@@ -231,7 +238,7 @@ def try_import(self, module: str, abstract_spec_str: str) -> bool:
|
||||
return self._install_and_test(abstract_spec, bincache_platform, data, test_fn)
|
||||
|
||||
def try_search_path(self, executables: Tuple[str], abstract_spec_str: str) -> bool:
|
||||
info: ConfigDictionary
|
||||
info: QueryInfo
|
||||
test_fn, info = functools.partial(_executables_in_store, executables), {}
|
||||
if test_fn(query_spec=abstract_spec_str, query_info=info):
|
||||
self.last_search = info
|
||||
@@ -249,11 +256,11 @@ class SourceBootstrapper(Bootstrapper):
|
||||
|
||||
def __init__(self, conf) -> None:
|
||||
super().__init__(conf)
|
||||
self.last_search: Optional[ConfigDictionary] = None
|
||||
self.last_search: Optional[QueryInfo] = None
|
||||
self.config_scope_name = f"bootstrap_source-{uuid.uuid4()}"
|
||||
|
||||
def try_import(self, module: str, abstract_spec_str: str) -> bool:
|
||||
info: ConfigDictionary = {}
|
||||
info: QueryInfo = {}
|
||||
if _try_import_from_store(module, abstract_spec_str, query_info=info):
|
||||
self.last_search = info
|
||||
return True
|
||||
@@ -270,10 +277,10 @@ def try_import(self, module: str, abstract_spec_str: str) -> bool:
|
||||
bootstrapper = ClingoBootstrapConcretizer(configuration=spack.config.CONFIG)
|
||||
concrete_spec = bootstrapper.concretize()
|
||||
else:
|
||||
concrete_spec = spack.spec.Spec(
|
||||
abstract_spec = spack.spec.Spec(
|
||||
abstract_spec_str + " ^" + spec_for_current_python()
|
||||
)
|
||||
concrete_spec.concretize()
|
||||
concrete_spec = spack.concretize.concretize_one(abstract_spec)
|
||||
|
||||
msg = "[BOOTSTRAP MODULE {0}] Try installing '{1}' from sources"
|
||||
tty.debug(msg.format(module, abstract_spec_str))
|
||||
@@ -288,7 +295,7 @@ def try_import(self, module: str, abstract_spec_str: str) -> bool:
|
||||
return False
|
||||
|
||||
def try_search_path(self, executables: Tuple[str], abstract_spec_str: str) -> bool:
|
||||
info: ConfigDictionary = {}
|
||||
info: QueryInfo = {}
|
||||
if _executables_in_store(executables, abstract_spec_str, query_info=info):
|
||||
self.last_search = info
|
||||
return True
|
||||
@@ -299,7 +306,7 @@ def try_search_path(self, executables: Tuple[str], abstract_spec_str: str) -> bo
|
||||
# might reduce compilation time by a fair amount
|
||||
_add_externals_if_missing()
|
||||
|
||||
concrete_spec = spack.spec.Spec(abstract_spec_str).concretized()
|
||||
concrete_spec = spack.concretize.concretize_one(abstract_spec_str)
|
||||
msg = "[BOOTSTRAP] Try installing '{0}' from sources"
|
||||
tty.debug(msg.format(abstract_spec_str))
|
||||
with spack.config.override(self.mirror_scope):
|
||||
@@ -414,6 +421,7 @@ def ensure_executables_in_path_or_raise(
|
||||
current_bootstrapper.last_search["spec"],
|
||||
current_bootstrapper.last_search["command"],
|
||||
)
|
||||
assert cmd is not None, "expected an Executable"
|
||||
cmd.add_default_envmod(
|
||||
spack.user_environment.environment_modifications_for_specs(
|
||||
concrete_spec, set_package_py_globals=False
|
||||
|
@@ -44,7 +44,19 @@
|
||||
from enum import Flag, auto
|
||||
from itertools import chain
|
||||
from multiprocessing.connection import Connection
|
||||
from typing import Callable, Dict, List, Optional, Set, Tuple
|
||||
from typing import (
|
||||
Callable,
|
||||
Dict,
|
||||
List,
|
||||
Optional,
|
||||
Sequence,
|
||||
Set,
|
||||
TextIO,
|
||||
Tuple,
|
||||
Type,
|
||||
Union,
|
||||
overload,
|
||||
)
|
||||
|
||||
import archspec.cpu
|
||||
|
||||
@@ -146,48 +158,128 @@ def get_effective_jobs(jobs, parallel=True, supports_jobserver=False):
|
||||
|
||||
|
||||
class MakeExecutable(Executable):
|
||||
"""Special callable executable object for make so the user can specify
|
||||
parallelism options on a per-invocation basis. Specifying
|
||||
'parallel' to the call will override whatever the package's
|
||||
global setting is, so you can either default to true or false and
|
||||
override particular calls. Specifying 'jobs_env' to a particular
|
||||
call will name an environment variable which will be set to the
|
||||
parallelism level (without affecting the normal invocation with
|
||||
-j).
|
||||
"""Special callable executable object for make so the user can specify parallelism options
|
||||
on a per-invocation basis.
|
||||
"""
|
||||
|
||||
def __init__(self, name, jobs, **kwargs):
|
||||
supports_jobserver = kwargs.pop("supports_jobserver", True)
|
||||
super().__init__(name, **kwargs)
|
||||
def __init__(self, name: str, *, jobs: int, supports_jobserver: bool = True) -> None:
|
||||
super().__init__(name)
|
||||
self.supports_jobserver = supports_jobserver
|
||||
self.jobs = jobs
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
"""parallel, and jobs_env from kwargs are swallowed and used here;
|
||||
remaining arguments are passed through to the superclass.
|
||||
"""
|
||||
parallel = kwargs.pop("parallel", True)
|
||||
jobs_env = kwargs.pop("jobs_env", None)
|
||||
jobs_env_supports_jobserver = kwargs.pop("jobs_env_supports_jobserver", False)
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
*args: str,
|
||||
parallel: bool = ...,
|
||||
jobs_env: Optional[str] = ...,
|
||||
jobs_env_supports_jobserver: bool = ...,
|
||||
fail_on_error: bool = ...,
|
||||
ignore_errors: Union[int, Sequence[int]] = ...,
|
||||
ignore_quotes: Optional[bool] = ...,
|
||||
timeout: Optional[int] = ...,
|
||||
env: Optional[Union[Dict[str, str], EnvironmentModifications]] = ...,
|
||||
extra_env: Optional[Union[Dict[str, str], EnvironmentModifications]] = ...,
|
||||
input: Optional[TextIO] = ...,
|
||||
output: Union[Optional[TextIO], str] = ...,
|
||||
error: Union[Optional[TextIO], str] = ...,
|
||||
_dump_env: Optional[Dict[str, str]] = ...,
|
||||
) -> None: ...
|
||||
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
*args: str,
|
||||
parallel: bool = ...,
|
||||
jobs_env: Optional[str] = ...,
|
||||
jobs_env_supports_jobserver: bool = ...,
|
||||
fail_on_error: bool = ...,
|
||||
ignore_errors: Union[int, Sequence[int]] = ...,
|
||||
ignore_quotes: Optional[bool] = ...,
|
||||
timeout: Optional[int] = ...,
|
||||
env: Optional[Union[Dict[str, str], EnvironmentModifications]] = ...,
|
||||
extra_env: Optional[Union[Dict[str, str], EnvironmentModifications]] = ...,
|
||||
input: Optional[TextIO] = ...,
|
||||
output: Union[Type[str], Callable] = ...,
|
||||
error: Union[Optional[TextIO], str, Type[str], Callable] = ...,
|
||||
_dump_env: Optional[Dict[str, str]] = ...,
|
||||
) -> str: ...
|
||||
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
*args: str,
|
||||
parallel: bool = ...,
|
||||
jobs_env: Optional[str] = ...,
|
||||
jobs_env_supports_jobserver: bool = ...,
|
||||
fail_on_error: bool = ...,
|
||||
ignore_errors: Union[int, Sequence[int]] = ...,
|
||||
ignore_quotes: Optional[bool] = ...,
|
||||
timeout: Optional[int] = ...,
|
||||
env: Optional[Union[Dict[str, str], EnvironmentModifications]] = ...,
|
||||
extra_env: Optional[Union[Dict[str, str], EnvironmentModifications]] = ...,
|
||||
input: Optional[TextIO] = ...,
|
||||
output: Union[Optional[TextIO], str, Type[str], Callable] = ...,
|
||||
error: Union[Type[str], Callable] = ...,
|
||||
_dump_env: Optional[Dict[str, str]] = ...,
|
||||
) -> str: ...
|
||||
|
||||
def __call__(
|
||||
self,
|
||||
*args: str,
|
||||
parallel: bool = True,
|
||||
jobs_env: Optional[str] = None,
|
||||
jobs_env_supports_jobserver: bool = False,
|
||||
**kwargs,
|
||||
) -> Optional[str]:
|
||||
"""Runs this "make" executable in a subprocess.
|
||||
|
||||
Args:
|
||||
parallel: if False, parallelism is disabled
|
||||
jobs_env: environment variable that will be set to the current level of parallelism
|
||||
jobs_env_supports_jobserver: whether the jobs env supports a job server
|
||||
|
||||
For all the other **kwargs, refer to the base class.
|
||||
"""
|
||||
jobs = get_effective_jobs(
|
||||
self.jobs, parallel=parallel, supports_jobserver=self.supports_jobserver
|
||||
)
|
||||
if jobs is not None:
|
||||
args = ("-j{0}".format(jobs),) + args
|
||||
args = (f"-j{jobs}",) + args
|
||||
|
||||
if jobs_env:
|
||||
# Caller wants us to set an environment variable to
|
||||
# control the parallelism.
|
||||
# Caller wants us to set an environment variable to control the parallelism
|
||||
jobs_env_jobs = get_effective_jobs(
|
||||
self.jobs, parallel=parallel, supports_jobserver=jobs_env_supports_jobserver
|
||||
)
|
||||
if jobs_env_jobs is not None:
|
||||
kwargs["extra_env"] = {jobs_env: str(jobs_env_jobs)}
|
||||
extra_env = kwargs.setdefault("extra_env", {})
|
||||
extra_env.update({jobs_env: str(jobs_env_jobs)})
|
||||
|
||||
return super().__call__(*args, **kwargs)
|
||||
|
||||
|
||||
class UndeclaredDependencyError(spack.error.SpackError):
|
||||
"""Raised if a dependency is invoking an executable through a module global, without
|
||||
declaring a dependency on it.
|
||||
"""
|
||||
|
||||
|
||||
class DeprecatedExecutable:
|
||||
def __init__(self, pkg: str, exe: str, exe_pkg: str) -> None:
|
||||
self.pkg = pkg
|
||||
self.exe = exe
|
||||
self.exe_pkg = exe_pkg
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
raise UndeclaredDependencyError(
|
||||
f"{self.pkg} is using {self.exe} without declaring a dependency on {self.exe_pkg}"
|
||||
)
|
||||
|
||||
def add_default_env(self, key: str, value: str):
|
||||
self.__call__()
|
||||
|
||||
|
||||
def clean_environment():
|
||||
# Stuff in here sanitizes the build environment to eliminate
|
||||
# anything the user has set that may interfere. We apply it immediately
|
||||
@@ -621,10 +713,9 @@ def set_package_py_globals(pkg, context: Context = Context.BUILD):
|
||||
module.std_meson_args = spack.build_systems.meson.MesonBuilder.std_args(pkg)
|
||||
module.std_pip_args = spack.build_systems.python.PythonPipBuilder.std_args(pkg)
|
||||
|
||||
# TODO: make these build deps that can be installed if not found.
|
||||
module.make = MakeExecutable("make", jobs)
|
||||
module.gmake = MakeExecutable("gmake", jobs)
|
||||
module.ninja = MakeExecutable("ninja", jobs, supports_jobserver=False)
|
||||
module.make = DeprecatedExecutable(pkg.name, "make", "gmake")
|
||||
module.gmake = DeprecatedExecutable(pkg.name, "gmake", "gmake")
|
||||
module.ninja = DeprecatedExecutable(pkg.name, "ninja", "ninja")
|
||||
# TODO: johnwparent: add package or builder support to define these build tools
|
||||
# for now there is no entrypoint for builders to define these on their
|
||||
# own
|
||||
|
@@ -298,7 +298,14 @@ def initconfig_hardware_entries(self):
|
||||
def std_initconfig_entries(self):
|
||||
cmake_prefix_path_env = os.environ["CMAKE_PREFIX_PATH"]
|
||||
cmake_prefix_path = cmake_prefix_path_env.replace(os.pathsep, ";")
|
||||
|
||||
complete_rpath_list = ";".join(
|
||||
[
|
||||
self.pkg.spec.prefix.lib,
|
||||
self.pkg.spec.prefix.lib64,
|
||||
*os.environ.get("SPACK_COMPILER_EXTRA_RPATHS", "").split(":"),
|
||||
*os.environ.get("SPACK_COMPILER_IMPLICIT_RPATHS", "").split(":"),
|
||||
]
|
||||
)
|
||||
return [
|
||||
"#------------------{0}".format("-" * 60),
|
||||
"# !!!! This is a generated file, edit at own risk !!!!",
|
||||
@@ -307,6 +314,8 @@ def std_initconfig_entries(self):
|
||||
"#------------------{0}\n".format("-" * 60),
|
||||
cmake_cache_string("CMAKE_PREFIX_PATH", cmake_prefix_path),
|
||||
cmake_cache_string("CMAKE_INSTALL_RPATH_USE_LINK_PATH", "ON"),
|
||||
cmake_cache_string("CMAKE_BUILD_RPATH", complete_rpath_list),
|
||||
cmake_cache_string("CMAKE_INSTALL_RPATH", complete_rpath_list),
|
||||
self.define_cmake_cache_from_variant("CMAKE_BUILD_TYPE", "build_type"),
|
||||
]
|
||||
|
||||
|
@@ -71,13 +71,16 @@ def build_directory(self):
|
||||
@property
|
||||
def build_args(self):
|
||||
"""Arguments for ``cargo build``."""
|
||||
return []
|
||||
return ["-j", str(self.pkg.module.make_jobs)]
|
||||
|
||||
@property
|
||||
def check_args(self):
|
||||
"""Argument for ``cargo test`` during check phase"""
|
||||
return []
|
||||
|
||||
def setup_build_environment(self, env):
|
||||
env.set("CARGO_HOME", self.stage.path)
|
||||
|
||||
def build(self, pkg, spec, prefix):
|
||||
"""Runs ``cargo install`` in the source directory"""
|
||||
with fs.working_dir(self.build_directory):
|
||||
|
@@ -10,8 +10,9 @@
|
||||
import spack.builder
|
||||
import spack.package_base
|
||||
import spack.phase_callbacks
|
||||
from spack.directives import build_system, extends
|
||||
from spack.directives import build_system, depends_on, extends
|
||||
from spack.install_test import SkipTest, test_part
|
||||
from spack.multimethod import when
|
||||
from spack.util.executable import Executable
|
||||
|
||||
from ._checks import BuilderWithDefaults, execute_build_time_tests
|
||||
@@ -28,7 +29,9 @@ class PerlPackage(spack.package_base.PackageBase):
|
||||
|
||||
build_system("perl")
|
||||
|
||||
extends("perl", when="build_system=perl")
|
||||
with when("build_system=perl"):
|
||||
extends("perl")
|
||||
depends_on("gmake", type="build")
|
||||
|
||||
@property
|
||||
@memoized
|
||||
|
@@ -27,6 +27,7 @@ class QMakePackage(spack.package_base.PackageBase):
|
||||
build_system("qmake")
|
||||
|
||||
depends_on("qmake", type="build", when="build_system=qmake")
|
||||
depends_on("gmake", type="build")
|
||||
|
||||
|
||||
@spack.builder.builder("qmake")
|
||||
|
@@ -94,7 +94,7 @@ def list_url(cls):
|
||||
if cls.cran:
|
||||
return f"https://cloud.r-project.org/src/contrib/Archive/{cls.cran}/"
|
||||
|
||||
@property
|
||||
def git(self):
|
||||
if self.bioc:
|
||||
return f"https://git.bioconductor.org/packages/{self.bioc}"
|
||||
@lang.classproperty
|
||||
def git(cls):
|
||||
if cls.bioc:
|
||||
return f"https://git.bioconductor.org/packages/{cls.bioc}"
|
||||
|
@@ -171,7 +171,9 @@ def quote_kvp(string: str) -> str:
|
||||
|
||||
|
||||
def parse_specs(
|
||||
args: Union[str, List[str]], concretize: bool = False, tests: bool = False
|
||||
args: Union[str, List[str]],
|
||||
concretize: bool = False,
|
||||
tests: spack.concretize.TestsType = False,
|
||||
) -> List[spack.spec.Spec]:
|
||||
"""Convenience function for parsing arguments from specs. Handles common
|
||||
exceptions and dies if there are errors.
|
||||
@@ -183,11 +185,13 @@ def parse_specs(
|
||||
if not concretize:
|
||||
return specs
|
||||
|
||||
to_concretize = [(s, None) for s in specs]
|
||||
to_concretize: List[spack.concretize.SpecPairInput] = [(s, None) for s in specs]
|
||||
return _concretize_spec_pairs(to_concretize, tests=tests)
|
||||
|
||||
|
||||
def _concretize_spec_pairs(to_concretize, tests=False):
|
||||
def _concretize_spec_pairs(
|
||||
to_concretize: List[spack.concretize.SpecPairInput], tests: spack.concretize.TestsType = False
|
||||
) -> List[spack.spec.Spec]:
|
||||
"""Helper method that concretizes abstract specs from a list of abstract,concrete pairs.
|
||||
|
||||
Any spec with a concrete spec associated with it will concretize to that spec. Any spec
|
||||
@@ -198,7 +202,7 @@ def _concretize_spec_pairs(to_concretize, tests=False):
|
||||
# Special case for concretizing a single spec
|
||||
if len(to_concretize) == 1:
|
||||
abstract, concrete = to_concretize[0]
|
||||
return [concrete or abstract.concretized()]
|
||||
return [concrete or spack.concretize.concretize_one(abstract, tests=tests)]
|
||||
|
||||
# Special case if every spec is either concrete or has an abstract hash
|
||||
if all(
|
||||
@@ -250,9 +254,9 @@ def matching_spec_from_env(spec):
|
||||
"""
|
||||
env = ev.active_environment()
|
||||
if env:
|
||||
return env.matching_spec(spec) or spec.concretized()
|
||||
return env.matching_spec(spec) or spack.concretize.concretize_one(spec)
|
||||
else:
|
||||
return spec.concretized()
|
||||
return spack.concretize.concretize_one(spec)
|
||||
|
||||
|
||||
def matching_specs_from_env(specs):
|
||||
@@ -293,7 +297,7 @@ def disambiguate_spec(
|
||||
|
||||
def disambiguate_spec_from_hashes(
|
||||
spec: spack.spec.Spec,
|
||||
hashes: List[str],
|
||||
hashes: Optional[List[str]],
|
||||
local: bool = False,
|
||||
installed: Union[bool, InstallRecordStatus] = True,
|
||||
first: bool = False,
|
||||
|
@@ -14,9 +14,9 @@
|
||||
import spack.bootstrap
|
||||
import spack.bootstrap.config
|
||||
import spack.bootstrap.core
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.mirrors.utils
|
||||
import spack.spec
|
||||
import spack.stage
|
||||
import spack.util.path
|
||||
import spack.util.spack_yaml
|
||||
@@ -397,7 +397,7 @@ def _mirror(args):
|
||||
llnl.util.tty.msg(msg.format(spec_str, mirror_dir))
|
||||
# Suppress tty from the call below for terser messages
|
||||
llnl.util.tty.set_msg_enabled(False)
|
||||
spec = spack.spec.Spec(spec_str).concretized()
|
||||
spec = spack.concretize.concretize_one(spec_str)
|
||||
for node in spec.traverse():
|
||||
spack.mirrors.utils.create(mirror_dir, [node])
|
||||
llnl.util.tty.set_msg_enabled(True)
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
import spack.binary_distribution as bindist
|
||||
import spack.cmd
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.deptypes as dt
|
||||
import spack.environment as ev
|
||||
@@ -554,8 +555,7 @@ def check_fn(args: argparse.Namespace):
|
||||
tty.msg("No specs provided, exiting.")
|
||||
return
|
||||
|
||||
for spec in specs:
|
||||
spec.concretize()
|
||||
specs = [spack.concretize.concretize_one(s) for s in specs]
|
||||
|
||||
# Next see if there are any configured binary mirrors
|
||||
configured_mirrors = spack.config.get("mirrors", scope=args.scope)
|
||||
@@ -623,7 +623,7 @@ def save_specfile_fn(args):
|
||||
root = specs[0]
|
||||
|
||||
if not root.concrete:
|
||||
root.concretize()
|
||||
root = spack.concretize.concretize_one(root)
|
||||
|
||||
save_dependency_specfiles(
|
||||
root, args.specfile_dir, dependencies=spack.cmd.parse_specs(args.specs)
|
||||
|
@@ -18,6 +18,7 @@
|
||||
from llnl.util.symlink import symlink
|
||||
|
||||
import spack.cmd
|
||||
import spack.concretize
|
||||
import spack.environment as ev
|
||||
import spack.installer
|
||||
import spack.store
|
||||
@@ -103,7 +104,7 @@ def deprecate(parser, args):
|
||||
)
|
||||
|
||||
if args.install:
|
||||
deprecator = specs[1].concretized()
|
||||
deprecator = spack.concretize.concretize_one(specs[1])
|
||||
else:
|
||||
deprecator = spack.cmd.disambiguate_spec(specs[1], env, local=True)
|
||||
|
||||
|
@@ -10,6 +10,7 @@
|
||||
import spack.build_environment
|
||||
import spack.cmd
|
||||
import spack.cmd.common.arguments
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.repo
|
||||
from spack.cmd.common import arguments
|
||||
@@ -114,7 +115,7 @@ def dev_build(self, args):
|
||||
|
||||
# Forces the build to run out of the source directory.
|
||||
spec.constrain("dev_path=%s" % source_path)
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one(spec)
|
||||
|
||||
if spec.installed:
|
||||
tty.error("Already installed in %s" % spec.prefix)
|
||||
|
@@ -13,6 +13,7 @@
|
||||
from llnl.util import lang, tty
|
||||
|
||||
import spack.cmd
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.environment as ev
|
||||
import spack.paths
|
||||
@@ -450,7 +451,7 @@ def concrete_specs_from_file(args):
|
||||
else:
|
||||
s = spack.spec.Spec.from_json(f)
|
||||
|
||||
concretized = s.concretized()
|
||||
concretized = spack.concretize.concretize_one(s)
|
||||
if concretized.dag_hash() != s.dag_hash():
|
||||
msg = 'skipped invalid file "{0}". '
|
||||
msg += "The file does not contain a concrete spec."
|
||||
|
@@ -7,9 +7,9 @@
|
||||
|
||||
from llnl.path import convert_to_posix_path
|
||||
|
||||
import spack.concretize
|
||||
import spack.paths
|
||||
import spack.util.executable
|
||||
from spack.spec import Spec
|
||||
|
||||
description = "generate Windows installer"
|
||||
section = "admin"
|
||||
@@ -65,8 +65,7 @@ def make_installer(parser, args):
|
||||
"""
|
||||
if sys.platform == "win32":
|
||||
output_dir = args.output_dir
|
||||
cmake_spec = Spec("cmake")
|
||||
cmake_spec.concretize()
|
||||
cmake_spec = spack.concretize.concretize_one("cmake")
|
||||
cmake_path = os.path.join(cmake_spec.prefix, "bin", "cmake.exe")
|
||||
cpack_path = os.path.join(cmake_spec.prefix, "bin", "cpack.exe")
|
||||
spack_source = args.spack_source
|
||||
|
@@ -492,7 +492,7 @@ def extend_with_additional_versions(specs, num_versions):
|
||||
mirror_specs = spack.mirrors.utils.get_all_versions(specs)
|
||||
else:
|
||||
mirror_specs = spack.mirrors.utils.get_matching_versions(specs, num_versions=num_versions)
|
||||
mirror_specs = [x.concretized() for x in mirror_specs]
|
||||
mirror_specs = [spack.concretize.concretize_one(x) for x in mirror_specs]
|
||||
return mirror_specs
|
||||
|
||||
|
||||
|
@@ -144,7 +144,7 @@ def is_installed(spec):
|
||||
record = spack.store.STORE.db.query_local_by_spec_hash(spec.dag_hash())
|
||||
return record and record.installed
|
||||
|
||||
specs = traverse.traverse_nodes(
|
||||
all_specs = traverse.traverse_nodes(
|
||||
specs,
|
||||
root=False,
|
||||
order="breadth",
|
||||
@@ -155,7 +155,7 @@ def is_installed(spec):
|
||||
)
|
||||
|
||||
with spack.store.STORE.db.read_transaction():
|
||||
return [spec for spec in specs if is_installed(spec)]
|
||||
return [spec for spec in all_specs if is_installed(spec)]
|
||||
|
||||
|
||||
def dependent_environments(
|
||||
|
@@ -749,12 +749,18 @@ def __init__(self, compiler, feature, flag_name, ver_string=None):
|
||||
class CompilerCacheEntry:
|
||||
"""Deserialized cache entry for a compiler"""
|
||||
|
||||
__slots__ = ["c_compiler_output", "real_version"]
|
||||
__slots__ = ("c_compiler_output", "real_version")
|
||||
|
||||
def __init__(self, c_compiler_output: Optional[str], real_version: str):
|
||||
self.c_compiler_output = c_compiler_output
|
||||
self.real_version = real_version
|
||||
|
||||
@property
|
||||
def empty(self) -> bool:
|
||||
"""Sometimes the compiler is temporarily broken, preventing us from getting output. The
|
||||
call site determines if that is a problem."""
|
||||
return self.c_compiler_output is None
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Optional[str]]):
|
||||
if not isinstance(data, dict):
|
||||
@@ -792,9 +798,10 @@ def __init__(self, cache: "FileCache") -> None:
|
||||
self.cache.init_entry(self.name)
|
||||
self._data: Dict[str, Dict[str, Optional[str]]] = {}
|
||||
|
||||
def _get_entry(self, key: str) -> Optional[CompilerCacheEntry]:
|
||||
def _get_entry(self, key: str, *, allow_empty: bool) -> Optional[CompilerCacheEntry]:
|
||||
try:
|
||||
return CompilerCacheEntry.from_dict(self._data[key])
|
||||
entry = CompilerCacheEntry.from_dict(self._data[key])
|
||||
return entry if allow_empty or not entry.empty else None
|
||||
except ValueError:
|
||||
del self._data[key]
|
||||
except KeyError:
|
||||
@@ -812,7 +819,7 @@ def get(self, compiler: Compiler) -> CompilerCacheEntry:
|
||||
self._data = {}
|
||||
|
||||
key = self._key(compiler)
|
||||
value = self._get_entry(key)
|
||||
value = self._get_entry(key, allow_empty=False)
|
||||
if value is not None:
|
||||
return value
|
||||
|
||||
@@ -826,7 +833,7 @@ def get(self, compiler: Compiler) -> CompilerCacheEntry:
|
||||
self._data = {}
|
||||
|
||||
# Use cache entry that may have been created by another process in the meantime.
|
||||
entry = self._get_entry(key)
|
||||
entry = self._get_entry(key, allow_empty=True)
|
||||
|
||||
# Finally compute the cache entry
|
||||
if entry is None:
|
||||
|
@@ -5,7 +5,7 @@
|
||||
import sys
|
||||
import time
|
||||
from contextlib import contextmanager
|
||||
from typing import Iterable, Optional, Sequence, Tuple, Union
|
||||
from typing import Iterable, List, Optional, Sequence, Tuple, Union
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
||||
@@ -35,14 +35,14 @@ def enable_compiler_existence_check():
|
||||
CHECK_COMPILER_EXISTENCE = saved
|
||||
|
||||
|
||||
SpecPairInput = Tuple[Spec, Optional[Spec]]
|
||||
SpecPair = Tuple[Spec, Spec]
|
||||
SpecLike = Union[Spec, str]
|
||||
TestsType = Union[bool, Iterable[str]]
|
||||
|
||||
|
||||
def concretize_specs_together(
|
||||
abstract_specs: Sequence[SpecLike], tests: TestsType = False
|
||||
) -> Sequence[Spec]:
|
||||
def _concretize_specs_together(
|
||||
abstract_specs: Sequence[Spec], tests: TestsType = False
|
||||
) -> List[Spec]:
|
||||
"""Given a number of specs as input, tries to concretize them together.
|
||||
|
||||
Args:
|
||||
@@ -50,17 +50,16 @@ def concretize_specs_together(
|
||||
tests: list of package names for which to consider tests dependencies. If True, all nodes
|
||||
will have test dependencies. If False, test dependencies will be disregarded.
|
||||
"""
|
||||
import spack.solver.asp
|
||||
from spack.solver.asp import Solver
|
||||
|
||||
allow_deprecated = spack.config.get("config:deprecated", False)
|
||||
solver = spack.solver.asp.Solver()
|
||||
result = solver.solve(abstract_specs, tests=tests, allow_deprecated=allow_deprecated)
|
||||
result = Solver().solve(abstract_specs, tests=tests, allow_deprecated=allow_deprecated)
|
||||
return [s.copy() for s in result.specs]
|
||||
|
||||
|
||||
def concretize_together(
|
||||
spec_list: Sequence[SpecPair], tests: TestsType = False
|
||||
) -> Sequence[SpecPair]:
|
||||
spec_list: Sequence[SpecPairInput], tests: TestsType = False
|
||||
) -> List[SpecPair]:
|
||||
"""Given a number of specs as input, tries to concretize them together.
|
||||
|
||||
Args:
|
||||
@@ -71,13 +70,13 @@ def concretize_together(
|
||||
"""
|
||||
to_concretize = [concrete if concrete else abstract for abstract, concrete in spec_list]
|
||||
abstract_specs = [abstract for abstract, _ in spec_list]
|
||||
concrete_specs = concretize_specs_together(to_concretize, tests=tests)
|
||||
concrete_specs = _concretize_specs_together(to_concretize, tests=tests)
|
||||
return list(zip(abstract_specs, concrete_specs))
|
||||
|
||||
|
||||
def concretize_together_when_possible(
|
||||
spec_list: Sequence[SpecPair], tests: TestsType = False
|
||||
) -> Sequence[SpecPair]:
|
||||
spec_list: Sequence[SpecPairInput], tests: TestsType = False
|
||||
) -> List[SpecPair]:
|
||||
"""Given a number of specs as input, tries to concretize them together to the extent possible.
|
||||
|
||||
See documentation for ``unify: when_possible`` concretization for the precise definition of
|
||||
@@ -89,7 +88,7 @@ def concretize_together_when_possible(
|
||||
tests: list of package names for which to consider tests dependencies. If True, all nodes
|
||||
will have test dependencies. If False, test dependencies will be disregarded.
|
||||
"""
|
||||
import spack.solver.asp
|
||||
from spack.solver.asp import Solver
|
||||
|
||||
to_concretize = [concrete if concrete else abstract for abstract, concrete in spec_list]
|
||||
old_concrete_to_abstract = {
|
||||
@@ -97,9 +96,8 @@ def concretize_together_when_possible(
|
||||
}
|
||||
|
||||
result_by_user_spec = {}
|
||||
solver = spack.solver.asp.Solver()
|
||||
allow_deprecated = spack.config.get("config:deprecated", False)
|
||||
for result in solver.solve_in_rounds(
|
||||
for result in Solver().solve_in_rounds(
|
||||
to_concretize, tests=tests, allow_deprecated=allow_deprecated
|
||||
):
|
||||
result_by_user_spec.update(result.specs_by_input)
|
||||
@@ -113,8 +111,8 @@ def concretize_together_when_possible(
|
||||
|
||||
|
||||
def concretize_separately(
|
||||
spec_list: Sequence[SpecPair], tests: TestsType = False
|
||||
) -> Sequence[SpecPair]:
|
||||
spec_list: Sequence[SpecPairInput], tests: TestsType = False
|
||||
) -> List[SpecPair]:
|
||||
"""Concretizes the input specs separately from each other.
|
||||
|
||||
Args:
|
||||
@@ -123,7 +121,7 @@ def concretize_separately(
|
||||
tests: list of package names for which to consider tests dependencies. If True, all nodes
|
||||
will have test dependencies. If False, test dependencies will be disregarded.
|
||||
"""
|
||||
import spack.bootstrap
|
||||
from spack.bootstrap import ensure_bootstrap_configuration, ensure_clingo_importable_or_raise
|
||||
|
||||
to_concretize = [abstract for abstract, concrete in spec_list if not concrete]
|
||||
args = [
|
||||
@@ -133,8 +131,8 @@ def concretize_separately(
|
||||
]
|
||||
ret = [(i, abstract) for i, abstract in enumerate(to_concretize) if abstract.concrete]
|
||||
# Ensure we don't try to bootstrap clingo in parallel
|
||||
with spack.bootstrap.ensure_bootstrap_configuration():
|
||||
spack.bootstrap.ensure_clingo_importable_or_raise()
|
||||
with ensure_bootstrap_configuration():
|
||||
ensure_clingo_importable_or_raise()
|
||||
|
||||
# Ensure all the indexes have been built or updated, since
|
||||
# otherwise the processes in the pool may timeout on waiting
|
||||
@@ -189,10 +187,52 @@ def _concretize_task(packed_arguments: Tuple[int, str, TestsType]) -> Tuple[int,
|
||||
index, spec_str, tests = packed_arguments
|
||||
with tty.SuppressOutput(msg_enabled=False):
|
||||
start = time.time()
|
||||
spec = Spec(spec_str).concretized(tests=tests)
|
||||
spec = concretize_one(Spec(spec_str), tests=tests)
|
||||
return index, spec, time.time() - start
|
||||
|
||||
|
||||
def concretize_one(spec: Union[str, Spec], tests: TestsType = False) -> Spec:
|
||||
"""Return a concretized copy of the given spec.
|
||||
|
||||
Args:
|
||||
tests: if False disregard 'test' dependencies, if a list of names activate them for
|
||||
the packages in the list, if True activate 'test' dependencies for all packages.
|
||||
"""
|
||||
from spack.solver.asp import Solver, SpecBuilder
|
||||
|
||||
if isinstance(spec, str):
|
||||
spec = Spec(spec)
|
||||
spec = spec.lookup_hash()
|
||||
|
||||
if spec.concrete:
|
||||
return spec.copy()
|
||||
|
||||
for node in spec.traverse():
|
||||
if not node.name:
|
||||
raise spack.error.SpecError(
|
||||
f"Spec {node} has no name; cannot concretize an anonymous spec"
|
||||
)
|
||||
|
||||
allow_deprecated = spack.config.get("config:deprecated", False)
|
||||
result = Solver().solve([spec], tests=tests, allow_deprecated=allow_deprecated)
|
||||
|
||||
# take the best answer
|
||||
opt, i, answer = min(result.answers)
|
||||
name = spec.name
|
||||
# TODO: Consolidate this code with similar code in solve.py
|
||||
if spec.virtual:
|
||||
providers = [s.name for s in answer.values() if s.package.provides(name)]
|
||||
name = providers[0]
|
||||
|
||||
node = SpecBuilder.make_node(pkg=name)
|
||||
assert (
|
||||
node in answer
|
||||
), f"cannot find {name} in the list of specs {','.join([n.pkg for n in answer.keys()])}"
|
||||
|
||||
concretized = answer[node]
|
||||
return concretized
|
||||
|
||||
|
||||
class UnavailableCompilerVersionError(spack.error.SpackError):
|
||||
"""Raised when there is no available compiler that satisfies a
|
||||
compiler spec."""
|
||||
|
@@ -951,12 +951,6 @@ def set(path: str, value: Any, scope: Optional[str] = None) -> None:
|
||||
return CONFIG.set(path, value, scope)
|
||||
|
||||
|
||||
def add_default_platform_scope(platform: str) -> None:
|
||||
plat_name = os.path.join("defaults", platform)
|
||||
plat_path = os.path.join(CONFIGURATION_DEFAULTS_PATH[1], platform)
|
||||
CONFIG.push_scope(DirectoryConfigScope(plat_name, plat_path))
|
||||
|
||||
|
||||
def scopes() -> Dict[str, ConfigScope]:
|
||||
"""Convenience function to get list of configuration scopes."""
|
||||
return CONFIG.scopes
|
||||
|
@@ -419,14 +419,25 @@ class FailureTracker:
|
||||
the likelihood of collision very low with no cleanup required.
|
||||
"""
|
||||
|
||||
#: root directory of the failure tracker
|
||||
dir: pathlib.Path
|
||||
|
||||
#: File for locking particular concrete spec hashes
|
||||
locker: SpecLocker
|
||||
|
||||
def __init__(self, root_dir: Union[str, pathlib.Path], default_timeout: Optional[float]):
|
||||
#: Ensure a persistent location for dealing with parallel installation
|
||||
#: failures (e.g., across near-concurrent processes).
|
||||
self.dir = pathlib.Path(root_dir) / _DB_DIRNAME / "failures"
|
||||
self.dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
self.locker = SpecLocker(failures_lock_path(root_dir), default_timeout=default_timeout)
|
||||
|
||||
def _ensure_parent_directories(self) -> None:
|
||||
"""Ensure that parent directories of the FailureTracker exist.
|
||||
|
||||
Accesses the filesystem only once, the first time it's called on a given FailureTracker.
|
||||
"""
|
||||
self.dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def clear(self, spec: "spack.spec.Spec", force: bool = False) -> None:
|
||||
"""Removes any persistent and cached failure tracking for the spec.
|
||||
|
||||
@@ -469,13 +480,18 @@ def clear_all(self) -> None:
|
||||
|
||||
tty.debug("Removing prefix failure tracking files")
|
||||
try:
|
||||
for fail_mark in os.listdir(str(self.dir)):
|
||||
try:
|
||||
(self.dir / fail_mark).unlink()
|
||||
except OSError as exc:
|
||||
tty.warn(f"Unable to remove failure marking file {fail_mark}: {str(exc)}")
|
||||
marks = os.listdir(str(self.dir))
|
||||
except FileNotFoundError:
|
||||
return # directory doesn't exist yet
|
||||
except OSError as exc:
|
||||
tty.warn(f"Unable to remove failure marking files: {str(exc)}")
|
||||
return
|
||||
|
||||
for fail_mark in marks:
|
||||
try:
|
||||
(self.dir / fail_mark).unlink()
|
||||
except OSError as exc:
|
||||
tty.warn(f"Unable to remove failure marking file {fail_mark}: {str(exc)}")
|
||||
|
||||
def mark(self, spec: "spack.spec.Spec") -> lk.Lock:
|
||||
"""Marks a spec as failing to install.
|
||||
@@ -483,6 +499,8 @@ def mark(self, spec: "spack.spec.Spec") -> lk.Lock:
|
||||
Args:
|
||||
spec: spec that failed to install
|
||||
"""
|
||||
self._ensure_parent_directories()
|
||||
|
||||
# Dump the spec to the failure file for (manual) debugging purposes
|
||||
path = self._path(spec)
|
||||
path.write_text(spec.to_json())
|
||||
@@ -567,17 +585,13 @@ def __init__(
|
||||
Relevant only if the repository is not an upstream.
|
||||
"""
|
||||
self.root = root
|
||||
self.database_directory = os.path.join(self.root, _DB_DIRNAME)
|
||||
self.database_directory = pathlib.Path(self.root) / _DB_DIRNAME
|
||||
self.layout = layout
|
||||
|
||||
# Set up layout of database files within the db dir
|
||||
self._index_path = os.path.join(self.database_directory, "index.json")
|
||||
self._verifier_path = os.path.join(self.database_directory, "index_verifier")
|
||||
self._lock_path = os.path.join(self.database_directory, "lock")
|
||||
|
||||
# Create needed directories and files
|
||||
if not is_upstream and not os.path.exists(self.database_directory):
|
||||
fs.mkdirp(self.database_directory)
|
||||
self._index_path = self.database_directory / "index.json"
|
||||
self._verifier_path = self.database_directory / "index_verifier"
|
||||
self._lock_path = self.database_directory / "lock"
|
||||
|
||||
self.is_upstream = is_upstream
|
||||
self.last_seen_verifier = ""
|
||||
@@ -599,7 +613,7 @@ def __init__(
|
||||
self.lock = ForbiddenLock()
|
||||
else:
|
||||
self.lock = lk.Lock(
|
||||
self._lock_path,
|
||||
str(self._lock_path),
|
||||
default_timeout=self.db_lock_timeout,
|
||||
desc="database",
|
||||
enable=lock_cfg.enable,
|
||||
@@ -616,6 +630,11 @@ def __init__(
|
||||
self._write_transaction_impl = lk.WriteTransaction
|
||||
self._read_transaction_impl = lk.ReadTransaction
|
||||
|
||||
def _ensure_parent_directories(self):
|
||||
"""Create the parent directory for the DB, if necessary."""
|
||||
if not self.is_upstream:
|
||||
self.database_directory.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def write_transaction(self):
|
||||
"""Get a write lock context manager for use in a `with` block."""
|
||||
return self._write_transaction_impl(self.lock, acquire=self._read, release=self._write)
|
||||
@@ -630,6 +649,8 @@ def _write_to_file(self, stream):
|
||||
|
||||
This function does not do any locking or transactions.
|
||||
"""
|
||||
self._ensure_parent_directories()
|
||||
|
||||
# map from per-spec hash code to installation record.
|
||||
installs = dict(
|
||||
(k, v.to_dict(include_fields=self.record_fields)) for k, v in self._data.items()
|
||||
@@ -759,7 +780,7 @@ def _read_from_file(self, filename):
|
||||
Does not do any locking.
|
||||
"""
|
||||
try:
|
||||
with open(filename, "r", encoding="utf-8") as f:
|
||||
with open(str(filename), "r", encoding="utf-8") as f:
|
||||
# In the future we may use a stream of JSON objects, hence `raw_decode` for compat.
|
||||
fdata, _ = JSONDecoder().raw_decode(f.read())
|
||||
except Exception as e:
|
||||
@@ -860,11 +881,13 @@ def reindex(self):
|
||||
if self.is_upstream:
|
||||
raise UpstreamDatabaseLockingError("Cannot reindex an upstream database")
|
||||
|
||||
self._ensure_parent_directories()
|
||||
|
||||
# Special transaction to avoid recursive reindex calls and to
|
||||
# ignore errors if we need to rebuild a corrupt database.
|
||||
def _read_suppress_error():
|
||||
try:
|
||||
if os.path.isfile(self._index_path):
|
||||
if self._index_path.is_file():
|
||||
self._read_from_file(self._index_path)
|
||||
except CorruptDatabaseError as e:
|
||||
tty.warn(f"Reindexing corrupt database, error was: {e}")
|
||||
@@ -1007,7 +1030,7 @@ def _check_ref_counts(self):
|
||||
% (key, found, expected, self._index_path)
|
||||
)
|
||||
|
||||
def _write(self, type, value, traceback):
|
||||
def _write(self, type=None, value=None, traceback=None):
|
||||
"""Write the in-memory database index to its file path.
|
||||
|
||||
This is a helper function called by the WriteTransaction context
|
||||
@@ -1018,6 +1041,8 @@ def _write(self, type, value, traceback):
|
||||
|
||||
This routine does no locking.
|
||||
"""
|
||||
self._ensure_parent_directories()
|
||||
|
||||
# Do not write if exceptions were raised
|
||||
if type is not None:
|
||||
# A failure interrupted a transaction, so we should record that
|
||||
@@ -1026,16 +1051,16 @@ def _write(self, type, value, traceback):
|
||||
self._state_is_inconsistent = True
|
||||
return
|
||||
|
||||
temp_file = self._index_path + (".%s.%s.temp" % (_getfqdn(), os.getpid()))
|
||||
temp_file = str(self._index_path) + (".%s.%s.temp" % (_getfqdn(), os.getpid()))
|
||||
|
||||
# Write a temporary database file them move it into place
|
||||
try:
|
||||
with open(temp_file, "w", encoding="utf-8") as f:
|
||||
self._write_to_file(f)
|
||||
fs.rename(temp_file, self._index_path)
|
||||
fs.rename(temp_file, str(self._index_path))
|
||||
|
||||
if _use_uuid:
|
||||
with open(self._verifier_path, "w", encoding="utf-8") as f:
|
||||
with self._verifier_path.open("w", encoding="utf-8") as f:
|
||||
new_verifier = str(uuid.uuid4())
|
||||
f.write(new_verifier)
|
||||
self.last_seen_verifier = new_verifier
|
||||
@@ -1048,11 +1073,11 @@ def _write(self, type, value, traceback):
|
||||
|
||||
def _read(self):
|
||||
"""Re-read Database from the data in the set location. This does no locking."""
|
||||
if os.path.isfile(self._index_path):
|
||||
if self._index_path.is_file():
|
||||
current_verifier = ""
|
||||
if _use_uuid:
|
||||
try:
|
||||
with open(self._verifier_path, "r", encoding="utf-8") as f:
|
||||
with self._verifier_path.open("r", encoding="utf-8") as f:
|
||||
current_verifier = f.read()
|
||||
except BaseException:
|
||||
pass
|
||||
@@ -1330,7 +1355,7 @@ def deprecate(self, spec: "spack.spec.Spec", deprecator: "spack.spec.Spec") -> N
|
||||
def installed_relatives(
|
||||
self,
|
||||
spec: "spack.spec.Spec",
|
||||
direction: str = "children",
|
||||
direction: tr.DirectionType = "children",
|
||||
transitive: bool = True,
|
||||
deptype: Union[dt.DepFlag, dt.DepTypes] = dt.ALL,
|
||||
) -> Set["spack.spec.Spec"]:
|
||||
@@ -1681,7 +1706,7 @@ def query(
|
||||
)
|
||||
|
||||
results = list(local_results) + list(x for x in upstream_results if x not in local_results)
|
||||
results.sort()
|
||||
results.sort() # type: ignore[call-overload]
|
||||
return results
|
||||
|
||||
def query_one(
|
||||
|
@@ -8,7 +8,7 @@
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List, Optional, Tuple
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
from llnl.util.symlink import readlink
|
||||
@@ -17,7 +17,6 @@
|
||||
import spack.hash_types as ht
|
||||
import spack.projections
|
||||
import spack.spec
|
||||
import spack.store
|
||||
import spack.util.spack_json as sjson
|
||||
from spack.error import SpackError
|
||||
|
||||
@@ -69,10 +68,9 @@ def specs_from_metadata_dirs(root: str) -> List["spack.spec.Spec"]:
|
||||
|
||||
|
||||
class DirectoryLayout:
|
||||
"""A directory layout is used to associate unique paths with specs.
|
||||
Different installations are going to want different layouts for their
|
||||
install, and they can use this to customize the nesting structure of
|
||||
spack installs. The default layout is:
|
||||
"""A directory layout is used to associate unique paths with specs. Different installations are
|
||||
going to want different layouts for their install, and they can use this to customize the
|
||||
nesting structure of spack installs. The default layout is:
|
||||
|
||||
* <install root>/
|
||||
|
||||
@@ -82,35 +80,30 @@ class DirectoryLayout:
|
||||
|
||||
* <name>-<version>-<hash>
|
||||
|
||||
The hash here is a SHA-1 hash for the full DAG plus the build
|
||||
spec.
|
||||
The installation directory projections can be modified with the projections argument."""
|
||||
|
||||
The installation directory projections can be modified with the
|
||||
projections argument.
|
||||
"""
|
||||
|
||||
def __init__(self, root, **kwargs):
|
||||
def __init__(
|
||||
self,
|
||||
root,
|
||||
*,
|
||||
projections: Optional[Dict[str, str]] = None,
|
||||
hash_length: Optional[int] = None,
|
||||
) -> None:
|
||||
self.root = root
|
||||
self.check_upstream = True
|
||||
projections = kwargs.get("projections") or default_projections
|
||||
self.projections = dict(
|
||||
(key, projection.lower()) for key, projection in projections.items()
|
||||
)
|
||||
projections = projections or default_projections
|
||||
self.projections = {key: projection.lower() for key, projection in projections.items()}
|
||||
|
||||
# apply hash length as appropriate
|
||||
self.hash_length = kwargs.get("hash_length", None)
|
||||
self.hash_length = hash_length
|
||||
if self.hash_length is not None:
|
||||
for when_spec, projection in self.projections.items():
|
||||
if "{hash}" not in projection:
|
||||
if "{hash" in projection:
|
||||
raise InvalidDirectoryLayoutParametersError(
|
||||
"Conflicting options for installation layout hash" " length"
|
||||
)
|
||||
else:
|
||||
raise InvalidDirectoryLayoutParametersError(
|
||||
"Cannot specify hash length when the hash is not"
|
||||
" part of all install_tree projections"
|
||||
)
|
||||
raise InvalidDirectoryLayoutParametersError(
|
||||
"Conflicting options for installation layout hash length"
|
||||
if "{hash" in projection
|
||||
else "Cannot specify hash length when the hash is not part of all "
|
||||
"install_tree projections"
|
||||
)
|
||||
self.projections[when_spec] = projection.replace(
|
||||
"{hash}", "{hash:%d}" % self.hash_length
|
||||
)
|
||||
@@ -279,13 +272,6 @@ def path_for_spec(self, spec):
|
||||
|
||||
if spec.external:
|
||||
return spec.external_path
|
||||
if self.check_upstream:
|
||||
upstream, record = spack.store.STORE.db.query_by_spec_hash(spec.dag_hash())
|
||||
if upstream:
|
||||
raise SpackError(
|
||||
"Internal error: attempted to call path_for_spec on"
|
||||
" upstream-installed package."
|
||||
)
|
||||
|
||||
path = self.relative_path_for_spec(spec)
|
||||
assert not path.startswith(self.root)
|
||||
|
@@ -15,6 +15,10 @@
|
||||
SHOW_BACKTRACE = False
|
||||
|
||||
|
||||
class SpackAPIWarning(UserWarning):
|
||||
"""Warning that formats with file and line number."""
|
||||
|
||||
|
||||
class SpackError(Exception):
|
||||
"""This is the superclass for all Spack errors.
|
||||
Subclasses can be found in the modules they have to do with.
|
||||
|
@@ -35,7 +35,6 @@
|
||||
|
||||
import spack.config
|
||||
import spack.directory_layout
|
||||
import spack.paths
|
||||
import spack.projections
|
||||
import spack.relocate
|
||||
import spack.schema.projections
|
||||
@@ -44,7 +43,6 @@
|
||||
import spack.util.spack_json as s_json
|
||||
import spack.util.spack_yaml as s_yaml
|
||||
from spack.error import SpackError
|
||||
from spack.hooks import sbang
|
||||
|
||||
__all__ = ["FilesystemView", "YamlFilesystemView"]
|
||||
|
||||
@@ -94,12 +92,6 @@ def view_copy(
|
||||
spack.relocate.relocate_text_bin(binaries=[dst], prefixes=prefix_to_projection)
|
||||
else:
|
||||
prefix_to_projection[spack.store.STORE.layout.root] = view._root
|
||||
|
||||
# This is vestigial code for the *old* location of sbang.
|
||||
prefix_to_projection[f"#!/bin/bash {spack.paths.spack_root}/bin/sbang"] = (
|
||||
sbang.sbang_shebang_line()
|
||||
)
|
||||
|
||||
spack.relocate.relocate_text(files=[dst], prefixes=prefix_to_projection)
|
||||
|
||||
# The os module on Windows does not have a chown function.
|
||||
|
@@ -275,7 +275,7 @@ def _do_fake_install(pkg: "spack.package_base.PackageBase") -> None:
|
||||
fs.mkdirp(pkg.prefix.bin)
|
||||
fs.touch(os.path.join(pkg.prefix.bin, command))
|
||||
if sys.platform != "win32":
|
||||
chmod = which("chmod")
|
||||
chmod = which("chmod", required=True)
|
||||
chmod("+x", os.path.join(pkg.prefix.bin, command))
|
||||
|
||||
# Install fake header file
|
||||
@@ -539,7 +539,7 @@ def dump_packages(spec: "spack.spec.Spec", path: str) -> None:
|
||||
# Note that we copy them in as they are in the *install* directory
|
||||
# NOT as they are in the repository, because we want a snapshot of
|
||||
# how *this* particular build was done.
|
||||
for node in spec.traverse(deptype=all):
|
||||
for node in spec.traverse(deptype="all"):
|
||||
if node is not spec:
|
||||
# Locate the dependency package in the install tree and find
|
||||
# its provenance information.
|
||||
|
@@ -503,16 +503,16 @@ def make_argument_parser(**kwargs):
|
||||
return parser
|
||||
|
||||
|
||||
def send_warning_to_tty(message, *args):
|
||||
def showwarning(message, category, filename, lineno, file=None, line=None):
|
||||
"""Redirects messages to tty.warn."""
|
||||
tty.warn(message)
|
||||
if category is spack.error.SpackAPIWarning:
|
||||
tty.warn(f"{filename}:{lineno}: {message}")
|
||||
else:
|
||||
tty.warn(message)
|
||||
|
||||
|
||||
def setup_main_options(args):
|
||||
"""Configure spack globals based on the basic options."""
|
||||
# Assign a custom function to show warnings
|
||||
warnings.showwarning = send_warning_to_tty
|
||||
|
||||
# Set up environment based on args.
|
||||
tty.set_verbose(args.verbose)
|
||||
tty.set_debug(args.debug)
|
||||
@@ -903,9 +903,10 @@ def _main(argv=None):
|
||||
# main() is tricky to get right, so be careful where you put things.
|
||||
#
|
||||
# Things in this first part of `main()` should *not* require any
|
||||
# configuration. This doesn't include much -- setting up th parser,
|
||||
# configuration. This doesn't include much -- setting up the parser,
|
||||
# restoring some key environment variables, very simple CLI options, etc.
|
||||
# ------------------------------------------------------------------------
|
||||
warnings.showwarning = showwarning
|
||||
|
||||
# Create a parser with a simple positional argument first. We'll
|
||||
# lazily load the subcommand(s) we need later. This allows us to
|
||||
|
@@ -106,8 +106,16 @@
|
||||
from spack.variant import any_combination_of, auto_or_any_combination_of, disjoint_sets
|
||||
from spack.version import Version, ver
|
||||
|
||||
# These are just here for editor support; they will be replaced when the build env
|
||||
# is set up.
|
||||
make = MakeExecutable("make", jobs=1)
|
||||
ninja = MakeExecutable("ninja", jobs=1)
|
||||
configure = Executable(join_path(".", "configure"))
|
||||
# These are just here for editor support; they may be set when the build env is set up.
|
||||
configure: Executable
|
||||
make_jobs: int
|
||||
make: MakeExecutable
|
||||
ninja: MakeExecutable
|
||||
python_include: str
|
||||
python_platlib: str
|
||||
python_purelib: str
|
||||
python: Executable
|
||||
spack_cc: str
|
||||
spack_cxx: str
|
||||
spack_f77: str
|
||||
spack_fc: str
|
||||
|
@@ -767,6 +767,9 @@ def __init__(self, spec):
|
||||
self.win_rpath = fsys.WindowsSimulatedRPath(self)
|
||||
super().__init__()
|
||||
|
||||
def __getitem__(self, key: str) -> "PackageBase":
|
||||
return self.spec[key].package
|
||||
|
||||
@classmethod
|
||||
def dependency_names(cls):
|
||||
return _subkeys(cls.dependencies)
|
||||
@@ -1816,12 +1819,6 @@ def _has_make_target(self, target):
|
||||
Returns:
|
||||
bool: True if 'target' is found, else False
|
||||
"""
|
||||
# Prevent altering LC_ALL for 'make' outside this function
|
||||
make = copy.deepcopy(self.module.make)
|
||||
|
||||
# Use English locale for missing target message comparison
|
||||
make.add_default_env("LC_ALL", "C")
|
||||
|
||||
# Check if we have a Makefile
|
||||
for makefile in ["GNUmakefile", "Makefile", "makefile"]:
|
||||
if os.path.exists(makefile):
|
||||
@@ -1830,6 +1827,12 @@ def _has_make_target(self, target):
|
||||
tty.debug("No Makefile found in the build directory")
|
||||
return False
|
||||
|
||||
# Prevent altering LC_ALL for 'make' outside this function
|
||||
make = copy.deepcopy(self.module.make)
|
||||
|
||||
# Use English locale for missing target message comparison
|
||||
make.add_default_env("LC_ALL", "C")
|
||||
|
||||
# Check if 'target' is a valid target.
|
||||
#
|
||||
# `make -n target` performs a "dry run". It prints the commands that
|
||||
|
@@ -54,144 +54,11 @@ def _patchelf() -> Optional[executable.Executable]:
|
||||
return spack.bootstrap.ensure_patchelf_in_path_or_raise()
|
||||
|
||||
|
||||
def _elf_rpaths_for(path):
|
||||
"""Return the RPATHs for an executable or a library.
|
||||
|
||||
Args:
|
||||
path (str): full path to the executable or library
|
||||
|
||||
Return:
|
||||
RPATHs as a list of strings. Returns an empty array
|
||||
on ELF parsing errors, or when the ELF file simply
|
||||
has no rpaths.
|
||||
"""
|
||||
return elf.get_rpaths(path) or []
|
||||
|
||||
|
||||
def _make_relative(reference_file, path_root, paths):
|
||||
"""Return a list where any path in ``paths`` that starts with
|
||||
``path_root`` is made relative to the directory in which the
|
||||
reference file is stored.
|
||||
|
||||
After a path is made relative it is prefixed with the ``$ORIGIN``
|
||||
string.
|
||||
|
||||
Args:
|
||||
reference_file (str): file from which the reference directory
|
||||
is computed
|
||||
path_root (str): root of the relative paths
|
||||
paths: (list) paths to be examined
|
||||
|
||||
Returns:
|
||||
List of relative paths
|
||||
"""
|
||||
start_directory = os.path.dirname(reference_file)
|
||||
pattern = re.compile(path_root)
|
||||
relative_paths = []
|
||||
|
||||
for path in paths:
|
||||
if pattern.match(path):
|
||||
rel = os.path.relpath(path, start=start_directory)
|
||||
path = os.path.join("$ORIGIN", rel)
|
||||
|
||||
relative_paths.append(path)
|
||||
|
||||
return relative_paths
|
||||
|
||||
|
||||
def _normalize_relative_paths(start_path, relative_paths):
|
||||
"""Normalize the relative paths with respect to the original path name
|
||||
of the file (``start_path``).
|
||||
|
||||
The paths that are passed to this function existed or were relevant
|
||||
on another filesystem, so os.path.abspath cannot be used.
|
||||
|
||||
A relative path may contain the signifier $ORIGIN. Assuming that
|
||||
``start_path`` is absolute, this implies that the relative path
|
||||
(relative to start_path) should be replaced with an absolute path.
|
||||
|
||||
Args:
|
||||
start_path (str): path from which the starting directory
|
||||
is extracted
|
||||
relative_paths (str): list of relative paths as obtained by a
|
||||
call to :ref:`_make_relative`
|
||||
|
||||
Returns:
|
||||
List of normalized paths
|
||||
"""
|
||||
normalized_paths = []
|
||||
pattern = re.compile(re.escape("$ORIGIN"))
|
||||
start_directory = os.path.dirname(start_path)
|
||||
|
||||
for path in relative_paths:
|
||||
if path.startswith("$ORIGIN"):
|
||||
sub = pattern.sub(start_directory, path)
|
||||
path = os.path.normpath(sub)
|
||||
normalized_paths.append(path)
|
||||
|
||||
return normalized_paths
|
||||
|
||||
|
||||
def _decode_macho_data(bytestring):
|
||||
return bytestring.rstrip(b"\x00").decode("ascii")
|
||||
|
||||
|
||||
def macho_make_paths_relative(path_name, old_layout_root, rpaths, deps, idpath):
|
||||
"""
|
||||
Return a dictionary mapping the original rpaths to the relativized rpaths.
|
||||
This dictionary is used to replace paths in mach-o binaries.
|
||||
Replace old_dir with relative path from dirname of path name
|
||||
in rpaths and deps; idpath is replaced with @rpath/libname.
|
||||
"""
|
||||
paths_to_paths = dict()
|
||||
if idpath:
|
||||
paths_to_paths[idpath] = os.path.join("@rpath", "%s" % os.path.basename(idpath))
|
||||
for rpath in rpaths:
|
||||
if re.match(old_layout_root, rpath):
|
||||
rel = os.path.relpath(rpath, start=os.path.dirname(path_name))
|
||||
paths_to_paths[rpath] = os.path.join("@loader_path", "%s" % rel)
|
||||
else:
|
||||
paths_to_paths[rpath] = rpath
|
||||
for dep in deps:
|
||||
if re.match(old_layout_root, dep):
|
||||
rel = os.path.relpath(dep, start=os.path.dirname(path_name))
|
||||
paths_to_paths[dep] = os.path.join("@loader_path", "%s" % rel)
|
||||
else:
|
||||
paths_to_paths[dep] = dep
|
||||
return paths_to_paths
|
||||
|
||||
|
||||
def macho_make_paths_normal(orig_path_name, rpaths, deps, idpath):
|
||||
"""
|
||||
Return a dictionary mapping the relativized rpaths to the original rpaths.
|
||||
This dictionary is used to replace paths in mach-o binaries.
|
||||
Replace '@loader_path' with the dirname of the origname path name
|
||||
in rpaths and deps; idpath is replaced with the original path name
|
||||
"""
|
||||
rel_to_orig = dict()
|
||||
if idpath:
|
||||
rel_to_orig[idpath] = orig_path_name
|
||||
|
||||
for rpath in rpaths:
|
||||
if re.match("@loader_path", rpath):
|
||||
norm = os.path.normpath(
|
||||
re.sub(re.escape("@loader_path"), os.path.dirname(orig_path_name), rpath)
|
||||
)
|
||||
rel_to_orig[rpath] = norm
|
||||
else:
|
||||
rel_to_orig[rpath] = rpath
|
||||
for dep in deps:
|
||||
if re.match("@loader_path", dep):
|
||||
norm = os.path.normpath(
|
||||
re.sub(re.escape("@loader_path"), os.path.dirname(orig_path_name), dep)
|
||||
)
|
||||
rel_to_orig[dep] = norm
|
||||
else:
|
||||
rel_to_orig[dep] = dep
|
||||
return rel_to_orig
|
||||
|
||||
|
||||
def macho_find_paths(orig_rpaths, deps, idpath, old_layout_root, prefix_to_prefix):
|
||||
def macho_find_paths(orig_rpaths, deps, idpath, prefix_to_prefix):
|
||||
"""
|
||||
Inputs
|
||||
original rpaths from mach-o binaries
|
||||
@@ -207,13 +74,12 @@ def macho_find_paths(orig_rpaths, deps, idpath, old_layout_root, prefix_to_prefi
|
||||
# Sort from longest path to shortest, to ensure we try /foo/bar/baz before /foo/bar
|
||||
prefix_iteration_order = sorted(prefix_to_prefix, key=len, reverse=True)
|
||||
for orig_rpath in orig_rpaths:
|
||||
if orig_rpath.startswith(old_layout_root):
|
||||
for old_prefix in prefix_iteration_order:
|
||||
new_prefix = prefix_to_prefix[old_prefix]
|
||||
if orig_rpath.startswith(old_prefix):
|
||||
new_rpath = re.sub(re.escape(old_prefix), new_prefix, orig_rpath)
|
||||
paths_to_paths[orig_rpath] = new_rpath
|
||||
break
|
||||
for old_prefix in prefix_iteration_order:
|
||||
new_prefix = prefix_to_prefix[old_prefix]
|
||||
if orig_rpath.startswith(old_prefix):
|
||||
new_rpath = re.sub(re.escape(old_prefix), new_prefix, orig_rpath)
|
||||
paths_to_paths[orig_rpath] = new_rpath
|
||||
break
|
||||
else:
|
||||
paths_to_paths[orig_rpath] = orig_rpath
|
||||
|
||||
@@ -348,9 +214,7 @@ def _set_elf_rpaths_and_interpreter(
|
||||
return None
|
||||
|
||||
|
||||
def relocate_macho_binaries(
|
||||
path_names, old_layout_root, new_layout_root, prefix_to_prefix, rel, old_prefix, new_prefix
|
||||
):
|
||||
def relocate_macho_binaries(path_names, prefix_to_prefix):
|
||||
"""
|
||||
Use macholib python package to get the rpaths, depedent libraries
|
||||
and library identity for libraries from the MachO object. Modify them
|
||||
@@ -363,77 +227,15 @@ def relocate_macho_binaries(
|
||||
# Corner case where macho object file ended up in the path name list
|
||||
if path_name.endswith(".o"):
|
||||
continue
|
||||
if rel:
|
||||
# get the relativized paths
|
||||
rpaths, deps, idpath = macholib_get_paths(path_name)
|
||||
# get the file path name in the original prefix
|
||||
orig_path_name = re.sub(re.escape(new_prefix), old_prefix, path_name)
|
||||
# get the mapping of the relativized paths to the original
|
||||
# normalized paths
|
||||
rel_to_orig = macho_make_paths_normal(orig_path_name, rpaths, deps, idpath)
|
||||
# replace the relativized paths with normalized paths
|
||||
modify_macho_object(path_name, rpaths, deps, idpath, rel_to_orig)
|
||||
# get the normalized paths in the mach-o binary
|
||||
rpaths, deps, idpath = macholib_get_paths(path_name)
|
||||
# get the mapping of paths in old prefix to path in new prefix
|
||||
paths_to_paths = macho_find_paths(
|
||||
rpaths, deps, idpath, old_layout_root, prefix_to_prefix
|
||||
)
|
||||
# replace the old paths with new paths
|
||||
modify_macho_object(path_name, rpaths, deps, idpath, paths_to_paths)
|
||||
# get the new normalized path in the mach-o binary
|
||||
rpaths, deps, idpath = macholib_get_paths(path_name)
|
||||
# get the mapping of paths to relative paths in the new prefix
|
||||
paths_to_paths = macho_make_paths_relative(
|
||||
path_name, new_layout_root, rpaths, deps, idpath
|
||||
)
|
||||
# replace the new paths with relativized paths in the new prefix
|
||||
modify_macho_object(path_name, rpaths, deps, idpath, paths_to_paths)
|
||||
else:
|
||||
# get the paths in the old prefix
|
||||
rpaths, deps, idpath = macholib_get_paths(path_name)
|
||||
# get the mapping of paths in the old prerix to the new prefix
|
||||
paths_to_paths = macho_find_paths(
|
||||
rpaths, deps, idpath, old_layout_root, prefix_to_prefix
|
||||
)
|
||||
# replace the old paths with new paths
|
||||
modify_macho_object(path_name, rpaths, deps, idpath, paths_to_paths)
|
||||
# get the paths in the old prefix
|
||||
rpaths, deps, idpath = macholib_get_paths(path_name)
|
||||
# get the mapping of paths in the old prerix to the new prefix
|
||||
paths_to_paths = macho_find_paths(rpaths, deps, idpath, prefix_to_prefix)
|
||||
# replace the old paths with new paths
|
||||
modify_macho_object(path_name, rpaths, deps, idpath, paths_to_paths)
|
||||
|
||||
|
||||
def _transform_rpaths(orig_rpaths, orig_root, new_prefixes):
|
||||
"""Return an updated list of RPATHs where each entry in the original list
|
||||
starting with the old root is relocated to another place according to the
|
||||
mapping passed as argument.
|
||||
|
||||
Args:
|
||||
orig_rpaths (list): list of the original RPATHs
|
||||
orig_root (str): original root to be substituted
|
||||
new_prefixes (dict): dictionary that maps the original prefixes to
|
||||
where they should be relocated
|
||||
|
||||
Returns:
|
||||
List of paths
|
||||
"""
|
||||
new_rpaths = []
|
||||
for orig_rpath in orig_rpaths:
|
||||
# If the original RPATH doesn't start with the target root
|
||||
# append it verbatim and proceed
|
||||
if not orig_rpath.startswith(orig_root):
|
||||
new_rpaths.append(orig_rpath)
|
||||
continue
|
||||
|
||||
# Otherwise inspect the mapping and transform + append any prefix
|
||||
# that starts with a registered key
|
||||
# avoiding duplicates
|
||||
for old_prefix, new_prefix in new_prefixes.items():
|
||||
if orig_rpath.startswith(old_prefix):
|
||||
new_rpath = re.sub(re.escape(old_prefix), new_prefix, orig_rpath)
|
||||
if new_rpath not in new_rpaths:
|
||||
new_rpaths.append(new_rpath)
|
||||
return new_rpaths
|
||||
|
||||
|
||||
def new_relocate_elf_binaries(binaries, prefix_to_prefix):
|
||||
def relocate_elf_binaries(binaries, prefix_to_prefix):
|
||||
"""Take a list of binaries, and an ordered dictionary of
|
||||
prefix to prefix mapping, and update the rpaths accordingly."""
|
||||
|
||||
@@ -452,98 +254,6 @@ def new_relocate_elf_binaries(binaries, prefix_to_prefix):
|
||||
_set_elf_rpaths_and_interpreter(path, rpaths=rpaths, interpreter=interpreter)
|
||||
|
||||
|
||||
def relocate_elf_binaries(
|
||||
binaries, orig_root, new_root, new_prefixes, rel, orig_prefix, new_prefix
|
||||
):
|
||||
"""Relocate the binaries passed as arguments by changing their RPATHs.
|
||||
|
||||
Use patchelf to get the original RPATHs and then replace them with
|
||||
rpaths in the new directory layout.
|
||||
|
||||
New RPATHs are determined from a dictionary mapping the prefixes in the
|
||||
old directory layout to the prefixes in the new directory layout if the
|
||||
rpath was in the old layout root, i.e. system paths are not replaced.
|
||||
|
||||
Args:
|
||||
binaries (list): list of binaries that might need relocation, located
|
||||
in the new prefix
|
||||
orig_root (str): original root to be substituted
|
||||
new_root (str): new root to be used, only relevant for relative RPATHs
|
||||
new_prefixes (dict): dictionary that maps the original prefixes to
|
||||
where they should be relocated
|
||||
rel (bool): True if the RPATHs are relative, False if they are absolute
|
||||
orig_prefix (str): prefix where the executable was originally located
|
||||
new_prefix (str): prefix where we want to relocate the executable
|
||||
"""
|
||||
for new_binary in binaries:
|
||||
orig_rpaths = _elf_rpaths_for(new_binary)
|
||||
# TODO: Can we deduce `rel` from the original RPATHs?
|
||||
if rel:
|
||||
# Get the file path in the original prefix
|
||||
orig_binary = re.sub(re.escape(new_prefix), orig_prefix, new_binary)
|
||||
|
||||
# Get the normalized RPATHs in the old prefix using the file path
|
||||
# in the orig prefix
|
||||
orig_norm_rpaths = _normalize_relative_paths(orig_binary, orig_rpaths)
|
||||
# Get the normalize RPATHs in the new prefix
|
||||
new_norm_rpaths = _transform_rpaths(orig_norm_rpaths, orig_root, new_prefixes)
|
||||
# Get the relative RPATHs in the new prefix
|
||||
new_rpaths = _make_relative(new_binary, new_root, new_norm_rpaths)
|
||||
# check to see if relative rpaths are changed before rewriting
|
||||
if sorted(new_rpaths) != sorted(orig_rpaths):
|
||||
_set_elf_rpaths_and_interpreter(new_binary, new_rpaths)
|
||||
else:
|
||||
new_rpaths = _transform_rpaths(orig_rpaths, orig_root, new_prefixes)
|
||||
_set_elf_rpaths_and_interpreter(new_binary, new_rpaths)
|
||||
|
||||
|
||||
def make_link_relative(new_links, orig_links):
|
||||
"""Compute the relative target from the original link and
|
||||
make the new link relative.
|
||||
|
||||
Args:
|
||||
new_links (list): new links to be made relative
|
||||
orig_links (list): original links
|
||||
"""
|
||||
for new_link, orig_link in zip(new_links, orig_links):
|
||||
target = readlink(orig_link)
|
||||
relative_target = os.path.relpath(target, os.path.dirname(orig_link))
|
||||
os.unlink(new_link)
|
||||
symlink(relative_target, new_link)
|
||||
|
||||
|
||||
def make_macho_binaries_relative(cur_path_names, orig_path_names, old_layout_root):
|
||||
"""
|
||||
Replace old RPATHs with paths relative to old_dir in binary files
|
||||
"""
|
||||
if not sys.platform == "darwin":
|
||||
return
|
||||
|
||||
for cur_path, orig_path in zip(cur_path_names, orig_path_names):
|
||||
(rpaths, deps, idpath) = macholib_get_paths(cur_path)
|
||||
paths_to_paths = macho_make_paths_relative(
|
||||
orig_path, old_layout_root, rpaths, deps, idpath
|
||||
)
|
||||
modify_macho_object(cur_path, rpaths, deps, idpath, paths_to_paths)
|
||||
|
||||
|
||||
def make_elf_binaries_relative(new_binaries, orig_binaries, orig_layout_root):
|
||||
"""Replace the original RPATHs in the new binaries making them
|
||||
relative to the original layout root.
|
||||
|
||||
Args:
|
||||
new_binaries (list): new binaries whose RPATHs is to be made relative
|
||||
orig_binaries (list): original binaries
|
||||
orig_layout_root (str): path to be used as a base for making
|
||||
RPATHs relative
|
||||
"""
|
||||
for new_binary, orig_binary in zip(new_binaries, orig_binaries):
|
||||
orig_rpaths = _elf_rpaths_for(new_binary)
|
||||
if orig_rpaths:
|
||||
new_rpaths = _make_relative(orig_binary, orig_layout_root, orig_rpaths)
|
||||
_set_elf_rpaths_and_interpreter(new_binary, new_rpaths)
|
||||
|
||||
|
||||
def warn_if_link_cant_be_relocated(link, target):
|
||||
if not os.path.isabs(target):
|
||||
return
|
||||
|
@@ -208,7 +208,7 @@ def _apply_to_file(self, f):
|
||||
# but it's nasty to deal with matches across boundaries, so let's stick to
|
||||
# something simple.
|
||||
|
||||
modified = True
|
||||
modified = False
|
||||
|
||||
for match in self.regex.finditer(f.read()):
|
||||
# The matching prefix (old) and its replacement (new)
|
||||
|
@@ -48,7 +48,7 @@ def rewire_node(spec, explicit):
|
||||
# spec
|
||||
prefix_to_prefix = {spec.build_spec.prefix: spec.prefix}
|
||||
build_spec_ids = set(id(s) for s in spec.build_spec.traverse(deptype=dt.ALL & ~dt.BUILD))
|
||||
for s in bindist.deps_to_relocate(spec):
|
||||
for s in bindist.specs_to_relocate(spec):
|
||||
analog = s
|
||||
if id(s) not in build_spec_ids:
|
||||
analogs = [
|
||||
@@ -77,25 +77,9 @@ def rewire_node(spec, explicit):
|
||||
]
|
||||
if bins_to_relocate:
|
||||
if "macho" in platform.binary_formats:
|
||||
relocate.relocate_macho_binaries(
|
||||
bins_to_relocate,
|
||||
str(spack.store.STORE.layout.root),
|
||||
str(spack.store.STORE.layout.root),
|
||||
prefix_to_prefix,
|
||||
False,
|
||||
spec.build_spec.prefix,
|
||||
spec.prefix,
|
||||
)
|
||||
relocate.relocate_macho_binaries(bins_to_relocate, prefix_to_prefix)
|
||||
if "elf" in platform.binary_formats:
|
||||
relocate.relocate_elf_binaries(
|
||||
bins_to_relocate,
|
||||
str(spack.store.STORE.layout.root),
|
||||
str(spack.store.STORE.layout.root),
|
||||
prefix_to_prefix,
|
||||
False,
|
||||
spec.build_spec.prefix,
|
||||
spec.prefix,
|
||||
)
|
||||
relocate.relocate_elf_binaries(bins_to_relocate, prefix_to_prefix)
|
||||
relocate.relocate_text_bin(binaries=bins_to_relocate, prefixes=prefix_to_prefix)
|
||||
shutil.rmtree(tempdir)
|
||||
install_manifest = os.path.join(
|
||||
|
@@ -106,10 +106,17 @@
|
||||
{
|
||||
"names": ["install_missing_compilers"],
|
||||
"message": "The config:install_missing_compilers option has been deprecated in "
|
||||
"Spack v0.23, and is currently ignored. It will be removed from config after "
|
||||
"Spack v0.23, and is currently ignored. It will be removed from config in "
|
||||
"Spack v1.0.",
|
||||
"error": False,
|
||||
},
|
||||
{
|
||||
"names": ["install_path_scheme"],
|
||||
"message": "The config:install_path_scheme option was deprecated in Spack v0.16 "
|
||||
"in favor of config:install_tree:projections:all. It will be removed in Spack "
|
||||
"v1.0.",
|
||||
"error": False,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
@@ -37,6 +37,7 @@
|
||||
import spack.package_prefs
|
||||
import spack.platforms
|
||||
import spack.repo
|
||||
import spack.solver.splicing
|
||||
import spack.spec
|
||||
import spack.store
|
||||
import spack.util.crypto
|
||||
@@ -67,7 +68,7 @@
|
||||
|
||||
GitOrStandardVersion = Union[spack.version.GitVersion, spack.version.StandardVersion]
|
||||
|
||||
TransformFunction = Callable[["spack.spec.Spec", List[AspFunction]], List[AspFunction]]
|
||||
TransformFunction = Callable[[spack.spec.Spec, List[AspFunction]], List[AspFunction]]
|
||||
|
||||
#: Enable the addition of a runtime node
|
||||
WITH_RUNTIME = sys.platform != "win32"
|
||||
@@ -127,8 +128,8 @@ def __str__(self):
|
||||
|
||||
@contextmanager
|
||||
def named_spec(
|
||||
spec: Optional["spack.spec.Spec"], name: Optional[str]
|
||||
) -> Iterator[Optional["spack.spec.Spec"]]:
|
||||
spec: Optional[spack.spec.Spec], name: Optional[str]
|
||||
) -> Iterator[Optional[spack.spec.Spec]]:
|
||||
"""Context manager to temporarily set the name of a spec"""
|
||||
if spec is None or name is None:
|
||||
yield spec
|
||||
@@ -747,11 +748,11 @@ def on_model(model):
|
||||
class KnownCompiler(NamedTuple):
|
||||
"""Data class to collect information on compilers"""
|
||||
|
||||
spec: "spack.spec.Spec"
|
||||
spec: spack.spec.Spec
|
||||
os: str
|
||||
target: str
|
||||
target: Optional[str]
|
||||
available: bool
|
||||
compiler_obj: Optional["spack.compiler.Compiler"]
|
||||
compiler_obj: Optional[spack.compiler.Compiler]
|
||||
|
||||
def _key(self):
|
||||
return self.spec, self.os, self.target
|
||||
@@ -1132,7 +1133,7 @@ def __init__(self, tests: bool = False):
|
||||
set
|
||||
)
|
||||
|
||||
self.possible_compilers: List = []
|
||||
self.possible_compilers: List[KnownCompiler] = []
|
||||
self.possible_oses: Set = set()
|
||||
self.variant_values_from_specs: Set = set()
|
||||
self.version_constraints: Set = set()
|
||||
@@ -1386,7 +1387,7 @@ def effect_rules(self):
|
||||
|
||||
def define_variant(
|
||||
self,
|
||||
pkg: "Type[spack.package_base.PackageBase]",
|
||||
pkg: Type[spack.package_base.PackageBase],
|
||||
name: str,
|
||||
when: spack.spec.Spec,
|
||||
variant_def: vt.Variant,
|
||||
@@ -1490,7 +1491,7 @@ def define_auto_variant(self, name: str, multi: bool):
|
||||
)
|
||||
)
|
||||
|
||||
def variant_rules(self, pkg: "Type[spack.package_base.PackageBase]"):
|
||||
def variant_rules(self, pkg: Type[spack.package_base.PackageBase]):
|
||||
for name in pkg.variant_names():
|
||||
self.gen.h3(f"Variant {name} in package {pkg.name}")
|
||||
for when, variant_def in pkg.variant_definitions(name):
|
||||
@@ -1681,8 +1682,8 @@ def dependency_holds(input_spec, requirements):
|
||||
def _gen_match_variant_splice_constraints(
|
||||
self,
|
||||
pkg,
|
||||
cond_spec: "spack.spec.Spec",
|
||||
splice_spec: "spack.spec.Spec",
|
||||
cond_spec: spack.spec.Spec,
|
||||
splice_spec: spack.spec.Spec,
|
||||
hash_asp_var: "AspVar",
|
||||
splice_node,
|
||||
match_variants: List[str],
|
||||
@@ -1740,7 +1741,7 @@ def package_splice_rules(self, pkg):
|
||||
if any(
|
||||
v in cond.variants or v in spec_to_splice.variants for v in match_variants
|
||||
):
|
||||
raise Exception(
|
||||
raise spack.error.PackageError(
|
||||
"Overlap between match_variants and explicitly set variants"
|
||||
)
|
||||
variant_constraints = self._gen_match_variant_splice_constraints(
|
||||
@@ -2977,7 +2978,7 @@ def _specs_from_requires(self, pkg_name, section):
|
||||
for s in spec_group[key]:
|
||||
yield _spec_with_default_name(s, pkg_name)
|
||||
|
||||
def pkg_class(self, pkg_name: str) -> typing.Type["spack.package_base.PackageBase"]:
|
||||
def pkg_class(self, pkg_name: str) -> typing.Type[spack.package_base.PackageBase]:
|
||||
request = pkg_name
|
||||
if pkg_name in self.explicitly_required_namespaces:
|
||||
namespace = self.explicitly_required_namespaces[pkg_name]
|
||||
@@ -3096,7 +3097,7 @@ def __init__(self, configuration) -> None:
|
||||
|
||||
self.compilers.add(candidate)
|
||||
|
||||
def with_input_specs(self, input_specs: List["spack.spec.Spec"]) -> "CompilerParser":
|
||||
def with_input_specs(self, input_specs: List[spack.spec.Spec]) -> "CompilerParser":
|
||||
"""Accounts for input specs when building the list of possible compilers.
|
||||
|
||||
Args:
|
||||
@@ -3136,7 +3137,7 @@ def with_input_specs(self, input_specs: List["spack.spec.Spec"]) -> "CompilerPar
|
||||
|
||||
return self
|
||||
|
||||
def add_compiler_from_concrete_spec(self, spec: "spack.spec.Spec") -> None:
|
||||
def add_compiler_from_concrete_spec(self, spec: spack.spec.Spec) -> None:
|
||||
"""Account for compilers that are coming from concrete specs, through reuse.
|
||||
|
||||
Args:
|
||||
@@ -3374,14 +3375,6 @@ def consume_facts(self):
|
||||
self._setup.effect_rules()
|
||||
|
||||
|
||||
# This should be a dataclass, but dataclasses don't work on Python 3.6
|
||||
class Splice:
|
||||
def __init__(self, splice_node: NodeArgument, child_name: str, child_hash: str):
|
||||
self.splice_node = splice_node
|
||||
self.child_name = child_name
|
||||
self.child_hash = child_hash
|
||||
|
||||
|
||||
class SpecBuilder:
|
||||
"""Class with actions to rebuild a spec from ASP results."""
|
||||
|
||||
@@ -3421,7 +3414,7 @@ def __init__(self, specs, hash_lookup=None):
|
||||
self._specs: Dict[NodeArgument, spack.spec.Spec] = {}
|
||||
|
||||
# Matches parent nodes to splice node
|
||||
self._splices: Dict[NodeArgument, List[Splice]] = {}
|
||||
self._splices: Dict[spack.spec.Spec, List[spack.solver.splicing.Splice]] = {}
|
||||
self._result = None
|
||||
self._command_line_specs = specs
|
||||
self._flag_sources: Dict[Tuple[NodeArgument, str], Set[str]] = collections.defaultdict(
|
||||
@@ -3540,15 +3533,13 @@ def reorder_flags(self):
|
||||
)
|
||||
cmd_specs = dict((s.name, s) for spec in self._command_line_specs for s in spec.traverse())
|
||||
|
||||
for spec in self._specs.values():
|
||||
for node, spec in self._specs.items():
|
||||
# if bootstrapping, compiler is not in config and has no flags
|
||||
flagmap_from_compiler = {}
|
||||
if spec.compiler in compilers:
|
||||
flagmap_from_compiler = compilers[spec.compiler].flags
|
||||
|
||||
for flag_type in spec.compiler_flags.valid_compiler_flags():
|
||||
node = SpecBuilder.make_node(pkg=spec.name)
|
||||
|
||||
ordered_flags = []
|
||||
|
||||
# 1. Put compiler flags first
|
||||
@@ -3630,49 +3621,12 @@ def splice_at_hash(
|
||||
child_name: str,
|
||||
child_hash: str,
|
||||
):
|
||||
splice = Splice(splice_node, child_name=child_name, child_hash=child_hash)
|
||||
self._splices.setdefault(parent_node, []).append(splice)
|
||||
|
||||
def _resolve_automatic_splices(self):
|
||||
"""After all of the specs have been concretized, apply all immediate splices.
|
||||
|
||||
Use reverse topological order to ensure that all dependencies are resolved
|
||||
before their parents, allowing for maximal sharing and minimal copying.
|
||||
|
||||
"""
|
||||
fixed_specs = {}
|
||||
|
||||
# create a mapping from dag hash to an integer representing position in reverse topo order.
|
||||
specs = self._specs.values()
|
||||
topo_order = list(traverse.traverse_nodes(specs, order="topo", key=traverse.by_dag_hash))
|
||||
topo_lookup = {spec.dag_hash(): index for index, spec in enumerate(reversed(topo_order))}
|
||||
|
||||
# iterate over specs, children before parents
|
||||
for node, spec in sorted(self._specs.items(), key=lambda x: topo_lookup[x[1].dag_hash()]):
|
||||
immediate = self._splices.get(node, [])
|
||||
if not immediate and not any(
|
||||
edge.spec in fixed_specs for edge in spec.edges_to_dependencies()
|
||||
):
|
||||
continue
|
||||
new_spec = spec.copy(deps=False)
|
||||
new_spec.build_spec = spec
|
||||
for edge in spec.edges_to_dependencies():
|
||||
depflag = edge.depflag & ~dt.BUILD
|
||||
if any(edge.spec.dag_hash() == splice.child_hash for splice in immediate):
|
||||
splice = [s for s in immediate if s.child_hash == edge.spec.dag_hash()][0]
|
||||
new_spec.add_dependency_edge(
|
||||
self._specs[splice.splice_node], depflag=depflag, virtuals=edge.virtuals
|
||||
)
|
||||
elif edge.spec in fixed_specs:
|
||||
new_spec.add_dependency_edge(
|
||||
fixed_specs[edge.spec], depflag=depflag, virtuals=edge.virtuals
|
||||
)
|
||||
else:
|
||||
new_spec.add_dependency_edge(
|
||||
edge.spec, depflag=depflag, virtuals=edge.virtuals
|
||||
)
|
||||
self._specs[node] = new_spec
|
||||
fixed_specs[spec] = new_spec
|
||||
parent_spec = self._specs[parent_node]
|
||||
splice_spec = self._specs[splice_node]
|
||||
splice = spack.solver.splicing.Splice(
|
||||
splice_spec, child_name=child_name, child_hash=child_hash
|
||||
)
|
||||
self._splices.setdefault(parent_spec, []).append(splice)
|
||||
|
||||
@staticmethod
|
||||
def sort_fn(function_tuple) -> Tuple[int, int]:
|
||||
@@ -3765,7 +3719,15 @@ def build_specs(self, function_tuples):
|
||||
for root in roots.values():
|
||||
root._finalize_concretization()
|
||||
|
||||
self._resolve_automatic_splices()
|
||||
# Only attempt to resolve automatic splices if the solver produced any
|
||||
if self._splices:
|
||||
resolved_splices = spack.solver.splicing._resolve_collected_splices(
|
||||
list(self._specs.values()), self._splices
|
||||
)
|
||||
new_specs = {}
|
||||
for node, spec in self._specs.items():
|
||||
new_specs[node] = resolved_splices.get(spec, spec)
|
||||
self._specs = new_specs
|
||||
|
||||
for s in self._specs.values():
|
||||
spack.spec.Spec.ensure_no_deprecated(s)
|
||||
|
73
lib/spack/spack/solver/splicing.py
Normal file
73
lib/spack/spack/solver/splicing.py
Normal file
@@ -0,0 +1,73 @@
|
||||
# Copyright Spack Project Developers. See COPYRIGHT file for details.
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
from functools import cmp_to_key
|
||||
from typing import Dict, List, NamedTuple
|
||||
|
||||
import spack.deptypes as dt
|
||||
from spack.spec import Spec
|
||||
from spack.traverse import by_dag_hash, traverse_nodes
|
||||
|
||||
|
||||
class Splice(NamedTuple):
|
||||
#: The spec being spliced into a parent
|
||||
splice_spec: Spec
|
||||
#: The name of the child that splice spec is replacing
|
||||
child_name: str
|
||||
#: The hash of the child that `splice_spec` is replacing
|
||||
child_hash: str
|
||||
|
||||
|
||||
def _resolve_collected_splices(
|
||||
specs: List[Spec], splices: Dict[Spec, List[Splice]]
|
||||
) -> Dict[Spec, Spec]:
|
||||
"""After all of the specs have been concretized, apply all immediate splices.
|
||||
Returns a dict mapping original specs to their resolved counterparts
|
||||
"""
|
||||
|
||||
def splice_cmp(s1: Spec, s2: Spec):
|
||||
"""This function can be used to sort a list of specs such that that any
|
||||
spec which will be spliced into a parent comes after the parent it will
|
||||
be spliced into. This order ensures that transitive splices will be
|
||||
executed in the correct order.
|
||||
"""
|
||||
|
||||
s1_splices = splices.get(s1, [])
|
||||
s2_splices = splices.get(s2, [])
|
||||
if any([s2.dag_hash() == splice.splice_spec.dag_hash() for splice in s1_splices]):
|
||||
return -1
|
||||
elif any([s1.dag_hash() == splice.splice_spec.dag_hash() for splice in s2_splices]):
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
splice_order = sorted(specs, key=cmp_to_key(splice_cmp))
|
||||
reverse_topo_order = reversed(
|
||||
[x for x in traverse_nodes(splice_order, order="topo", key=by_dag_hash) if x in specs]
|
||||
)
|
||||
|
||||
already_resolved: Dict[Spec, Spec] = {}
|
||||
for spec in reverse_topo_order:
|
||||
immediate = splices.get(spec, [])
|
||||
if not immediate and not any(
|
||||
edge.spec in already_resolved for edge in spec.edges_to_dependencies()
|
||||
):
|
||||
continue
|
||||
new_spec = spec.copy(deps=False)
|
||||
new_spec.clear_caches(ignore=("package_hash",))
|
||||
new_spec.build_spec = spec
|
||||
for edge in spec.edges_to_dependencies():
|
||||
depflag = edge.depflag & ~dt.BUILD
|
||||
if any(edge.spec.dag_hash() == splice.child_hash for splice in immediate):
|
||||
splice = [s for s in immediate if s.child_hash == edge.spec.dag_hash()][0]
|
||||
# If the spec being splice in is also spliced
|
||||
splice_spec = already_resolved.get(splice.splice_spec, splice.splice_spec)
|
||||
new_spec.add_dependency_edge(splice_spec, depflag=depflag, virtuals=edge.virtuals)
|
||||
elif edge.spec in already_resolved:
|
||||
new_spec.add_dependency_edge(
|
||||
already_resolved[edge.spec], depflag=depflag, virtuals=edge.virtuals
|
||||
)
|
||||
else:
|
||||
new_spec.add_dependency_edge(edge.spec, depflag=depflag, virtuals=edge.virtuals)
|
||||
already_resolved[spec] = new_spec
|
||||
return already_resolved
|
@@ -58,7 +58,21 @@
|
||||
import re
|
||||
import socket
|
||||
import warnings
|
||||
from typing import Any, Callable, Dict, Iterable, List, Match, Optional, Set, Tuple, Union
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
Iterable,
|
||||
List,
|
||||
Match,
|
||||
Optional,
|
||||
Set,
|
||||
Tuple,
|
||||
Union,
|
||||
overload,
|
||||
)
|
||||
|
||||
from typing_extensions import Literal
|
||||
|
||||
import archspec.cpu
|
||||
|
||||
@@ -72,7 +86,6 @@
|
||||
import spack
|
||||
import spack.compiler
|
||||
import spack.compilers
|
||||
import spack.config
|
||||
import spack.deptypes as dt
|
||||
import spack.error
|
||||
import spack.hash_types as ht
|
||||
@@ -80,10 +93,9 @@
|
||||
import spack.platforms
|
||||
import spack.provider_index
|
||||
import spack.repo
|
||||
import spack.solver
|
||||
import spack.spec_parser
|
||||
import spack.store
|
||||
import spack.traverse as traverse
|
||||
import spack.traverse
|
||||
import spack.util.executable
|
||||
import spack.util.hash
|
||||
import spack.util.module_cmd as md
|
||||
@@ -1339,16 +1351,16 @@ def tree(
|
||||
depth: bool = False,
|
||||
hashes: bool = False,
|
||||
hashlen: Optional[int] = None,
|
||||
cover: str = "nodes",
|
||||
cover: spack.traverse.CoverType = "nodes",
|
||||
indent: int = 0,
|
||||
format: str = DEFAULT_FORMAT,
|
||||
deptypes: Union[Tuple[str, ...], str] = "all",
|
||||
deptypes: Union[dt.DepFlag, dt.DepTypes] = dt.ALL,
|
||||
show_types: bool = False,
|
||||
depth_first: bool = False,
|
||||
recurse_dependencies: bool = True,
|
||||
status_fn: Optional[Callable[["Spec"], InstallStatus]] = None,
|
||||
prefix: Optional[Callable[["Spec"], str]] = None,
|
||||
key=id,
|
||||
key: Callable[["Spec"], Any] = id,
|
||||
) -> str:
|
||||
"""Prints out specs and their dependencies, tree-formatted with indentation.
|
||||
|
||||
@@ -1380,11 +1392,16 @@ def tree(
|
||||
# reduce deptypes over all in-edges when covering nodes
|
||||
if show_types and cover == "nodes":
|
||||
deptype_lookup: Dict[str, dt.DepFlag] = collections.defaultdict(dt.DepFlag)
|
||||
for edge in traverse.traverse_edges(specs, cover="edges", deptype=deptypes, root=False):
|
||||
for edge in spack.traverse.traverse_edges(
|
||||
specs, cover="edges", deptype=deptypes, root=False
|
||||
):
|
||||
deptype_lookup[edge.spec.dag_hash()] |= edge.depflag
|
||||
|
||||
for d, dep_spec in traverse.traverse_tree(
|
||||
sorted(specs), cover=cover, deptype=deptypes, depth_first=depth_first, key=key
|
||||
# SupportsRichComparisonT issue with List[Spec]
|
||||
sorted_specs: List["Spec"] = sorted(specs) # type: ignore[type-var]
|
||||
|
||||
for d, dep_spec in spack.traverse.traverse_tree(
|
||||
sorted_specs, cover=cover, deptype=deptypes, depth_first=depth_first, key=key
|
||||
):
|
||||
node = dep_spec.spec
|
||||
|
||||
@@ -1927,13 +1944,125 @@ def installed_upstream(self):
|
||||
upstream, _ = spack.store.STORE.db.query_by_spec_hash(self.dag_hash())
|
||||
return upstream
|
||||
|
||||
def traverse(self, **kwargs):
|
||||
"""Shorthand for :meth:`~spack.traverse.traverse_nodes`"""
|
||||
return traverse.traverse_nodes([self], **kwargs)
|
||||
@overload
|
||||
def traverse(
|
||||
self,
|
||||
*,
|
||||
root: bool = ...,
|
||||
order: spack.traverse.OrderType = ...,
|
||||
cover: spack.traverse.CoverType = ...,
|
||||
direction: spack.traverse.DirectionType = ...,
|
||||
deptype: Union[dt.DepFlag, dt.DepTypes] = ...,
|
||||
depth: Literal[False] = False,
|
||||
key: Callable[["Spec"], Any] = ...,
|
||||
visited: Optional[Set[Any]] = ...,
|
||||
) -> Iterable["Spec"]: ...
|
||||
|
||||
def traverse_edges(self, **kwargs):
|
||||
@overload
|
||||
def traverse(
|
||||
self,
|
||||
*,
|
||||
root: bool = ...,
|
||||
order: spack.traverse.OrderType = ...,
|
||||
cover: spack.traverse.CoverType = ...,
|
||||
direction: spack.traverse.DirectionType = ...,
|
||||
deptype: Union[dt.DepFlag, dt.DepTypes] = ...,
|
||||
depth: Literal[True],
|
||||
key: Callable[["Spec"], Any] = ...,
|
||||
visited: Optional[Set[Any]] = ...,
|
||||
) -> Iterable[Tuple[int, "Spec"]]: ...
|
||||
|
||||
def traverse(
|
||||
self,
|
||||
*,
|
||||
root: bool = True,
|
||||
order: spack.traverse.OrderType = "pre",
|
||||
cover: spack.traverse.CoverType = "nodes",
|
||||
direction: spack.traverse.DirectionType = "children",
|
||||
deptype: Union[dt.DepFlag, dt.DepTypes] = "all",
|
||||
depth: bool = False,
|
||||
key: Callable[["Spec"], Any] = id,
|
||||
visited: Optional[Set[Any]] = None,
|
||||
) -> Iterable[Union["Spec", Tuple[int, "Spec"]]]:
|
||||
"""Shorthand for :meth:`~spack.traverse.traverse_nodes`"""
|
||||
return spack.traverse.traverse_nodes(
|
||||
[self],
|
||||
root=root,
|
||||
order=order,
|
||||
cover=cover,
|
||||
direction=direction,
|
||||
deptype=deptype,
|
||||
depth=depth,
|
||||
key=key,
|
||||
visited=visited,
|
||||
)
|
||||
|
||||
@overload
|
||||
def traverse_edges(
|
||||
self,
|
||||
*,
|
||||
root: bool = ...,
|
||||
order: spack.traverse.OrderType = ...,
|
||||
cover: spack.traverse.CoverType = ...,
|
||||
direction: spack.traverse.DirectionType = ...,
|
||||
deptype: Union[dt.DepFlag, dt.DepTypes] = ...,
|
||||
depth: Literal[False] = False,
|
||||
key: Callable[["Spec"], Any] = ...,
|
||||
visited: Optional[Set[Any]] = ...,
|
||||
) -> Iterable[DependencySpec]: ...
|
||||
|
||||
@overload
|
||||
def traverse_edges(
|
||||
self,
|
||||
*,
|
||||
root: bool = ...,
|
||||
order: spack.traverse.OrderType = ...,
|
||||
cover: spack.traverse.CoverType = ...,
|
||||
direction: spack.traverse.DirectionType = ...,
|
||||
deptype: Union[dt.DepFlag, dt.DepTypes] = ...,
|
||||
depth: Literal[True],
|
||||
key: Callable[["Spec"], Any] = ...,
|
||||
visited: Optional[Set[Any]] = ...,
|
||||
) -> Iterable[Tuple[int, DependencySpec]]: ...
|
||||
|
||||
def traverse_edges(
|
||||
self,
|
||||
*,
|
||||
root: bool = True,
|
||||
order: spack.traverse.OrderType = "pre",
|
||||
cover: spack.traverse.CoverType = "nodes",
|
||||
direction: spack.traverse.DirectionType = "children",
|
||||
deptype: Union[dt.DepFlag, dt.DepTypes] = "all",
|
||||
depth: bool = False,
|
||||
key: Callable[["Spec"], Any] = id,
|
||||
visited: Optional[Set[Any]] = None,
|
||||
) -> Iterable[Union[DependencySpec, Tuple[int, DependencySpec]]]:
|
||||
"""Shorthand for :meth:`~spack.traverse.traverse_edges`"""
|
||||
return traverse.traverse_edges([self], **kwargs)
|
||||
return spack.traverse.traverse_edges(
|
||||
[self],
|
||||
root=root,
|
||||
order=order,
|
||||
cover=cover,
|
||||
direction=direction,
|
||||
deptype=deptype,
|
||||
depth=depth,
|
||||
key=key,
|
||||
visited=visited,
|
||||
)
|
||||
|
||||
@property
|
||||
def long_spec(self):
|
||||
"""Returns a string of the spec with the dependencies completely
|
||||
enumerated."""
|
||||
root_str = [self.format()]
|
||||
sorted_dependencies = sorted(
|
||||
self.traverse(root=False), key=lambda x: (x.name, x.abstract_hash)
|
||||
)
|
||||
sorted_dependencies = [
|
||||
d.format("{edge_attributes} " + DEFAULT_FORMAT) for d in sorted_dependencies
|
||||
]
|
||||
spec_str = " ^".join(root_str + sorted_dependencies)
|
||||
return spec_str.strip()
|
||||
|
||||
@property
|
||||
def short_spec(self):
|
||||
@@ -2203,11 +2332,16 @@ def to_node_dict(self, hash=ht.dag_hash):
|
||||
)
|
||||
|
||||
if self.external:
|
||||
if self.extra_attributes:
|
||||
extra_attributes = syaml.sorted_dict(self.extra_attributes)
|
||||
else:
|
||||
extra_attributes = None
|
||||
|
||||
d["external"] = syaml.syaml_dict(
|
||||
[
|
||||
("path", self.external_path),
|
||||
("module", self.external_modules),
|
||||
("extra_attributes", self.extra_attributes),
|
||||
("extra_attributes", extra_attributes),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -2818,44 +2952,16 @@ def ensure_no_deprecated(root):
|
||||
raise SpecDeprecatedError(msg)
|
||||
|
||||
def concretize(self, tests: Union[bool, Iterable[str]] = False) -> None:
|
||||
"""Concretize the current spec.
|
||||
from spack.concretize import concretize_one
|
||||
|
||||
Args:
|
||||
tests: if False disregard 'test' dependencies, if a list of names activate them for
|
||||
the packages in the list, if True activate 'test' dependencies for all packages.
|
||||
"""
|
||||
import spack.solver.asp
|
||||
warnings.warn(
|
||||
"`Spec.concretize` is deprecated and will be removed in version 1.0.0. Use "
|
||||
"`spack.concretize.concretize_one` instead.",
|
||||
category=spack.error.SpackAPIWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
self.replace_hash()
|
||||
|
||||
for node in self.traverse():
|
||||
if not node.name:
|
||||
raise spack.error.SpecError(
|
||||
f"Spec {node} has no name; cannot concretize an anonymous spec"
|
||||
)
|
||||
|
||||
if self._concrete:
|
||||
return
|
||||
|
||||
allow_deprecated = spack.config.get("config:deprecated", False)
|
||||
solver = spack.solver.asp.Solver()
|
||||
result = solver.solve([self], tests=tests, allow_deprecated=allow_deprecated)
|
||||
|
||||
# take the best answer
|
||||
opt, i, answer = min(result.answers)
|
||||
name = self.name
|
||||
# TODO: Consolidate this code with similar code in solve.py
|
||||
if self.virtual:
|
||||
providers = [spec.name for spec in answer.values() if spec.package.provides(name)]
|
||||
name = providers[0]
|
||||
|
||||
node = spack.solver.asp.SpecBuilder.make_node(pkg=name)
|
||||
assert (
|
||||
node in answer
|
||||
), f"cannot find {name} in the list of specs {','.join([n.pkg for n in answer.keys()])}"
|
||||
|
||||
concretized = answer[node]
|
||||
self._dup(concretized)
|
||||
self._dup(concretize_one(self, tests))
|
||||
|
||||
def _mark_root_concrete(self, value=True):
|
||||
"""Mark just this spec (not dependencies) concrete."""
|
||||
@@ -2944,20 +3050,17 @@ def _finalize_concretization(self):
|
||||
for spec in self.traverse():
|
||||
spec._cached_hash(ht.dag_hash)
|
||||
|
||||
def concretized(self, tests: Union[bool, Iterable[str]] = False) -> "spack.spec.Spec":
|
||||
"""This is a non-destructive version of concretize().
|
||||
def concretized(self, tests: Union[bool, Iterable[str]] = False) -> "Spec":
|
||||
from spack.concretize import concretize_one
|
||||
|
||||
First clones, then returns a concrete version of this package
|
||||
without modifying this package.
|
||||
warnings.warn(
|
||||
"`Spec.concretized` is deprecated and will be removed in version 1.0.0. Use "
|
||||
"`spack.concretize.concretize_one` instead.",
|
||||
category=spack.error.SpackAPIWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
Args:
|
||||
tests (bool or list): if False disregard 'test' dependencies,
|
||||
if a list of names activate them for the packages in the list,
|
||||
if True activate 'test' dependencies for all packages.
|
||||
"""
|
||||
clone = self.copy()
|
||||
clone.concretize(tests=tests)
|
||||
return clone
|
||||
return concretize_one(self, tests)
|
||||
|
||||
def index(self, deptype="all"):
|
||||
"""Return a dictionary that points to all the dependencies in this
|
||||
@@ -3493,25 +3596,16 @@ def patches(self):
|
||||
|
||||
return self._patches
|
||||
|
||||
def _dup(self, other, deps: Union[bool, dt.DepTypes, dt.DepFlag] = True, cleardeps=True):
|
||||
"""Copy the spec other into self. This is an overwriting
|
||||
copy. It does not copy any dependents (parents), but by default
|
||||
copies dependencies.
|
||||
|
||||
To duplicate an entire DAG, call _dup() on the root of the DAG.
|
||||
def _dup(self, other: "Spec", deps: Union[bool, dt.DepTypes, dt.DepFlag] = True) -> bool:
|
||||
"""Copies "other" into self, by overwriting all attributes.
|
||||
|
||||
Args:
|
||||
other (Spec): spec to be copied onto ``self``
|
||||
deps: if True copies all the dependencies. If
|
||||
False copies None. If deptype/depflag, copy matching types.
|
||||
cleardeps (bool): if True clears the dependencies of ``self``,
|
||||
before possibly copying the dependencies of ``other`` onto
|
||||
``self``
|
||||
other: spec to be copied onto ``self``
|
||||
deps: if True copies all the dependencies. If False copies None.
|
||||
If deptype, or depflag, copy matching types.
|
||||
|
||||
Returns:
|
||||
True if ``self`` changed because of the copy operation,
|
||||
False otherwise.
|
||||
|
||||
True if ``self`` changed because of the copy operation, False otherwise.
|
||||
"""
|
||||
# We don't count dependencies as changes here
|
||||
changed = True
|
||||
@@ -3536,14 +3630,15 @@ def _dup(self, other, deps: Union[bool, dt.DepTypes, dt.DepFlag] = True, clearde
|
||||
self.versions = other.versions.copy()
|
||||
self.architecture = other.architecture.copy() if other.architecture else None
|
||||
self.compiler = other.compiler.copy() if other.compiler else None
|
||||
if cleardeps:
|
||||
self._dependents = _EdgeMap(store_by_child=False)
|
||||
self._dependencies = _EdgeMap(store_by_child=True)
|
||||
self.compiler_flags = other.compiler_flags.copy()
|
||||
self.compiler_flags.spec = self
|
||||
self.variants = other.variants.copy()
|
||||
self._build_spec = other._build_spec
|
||||
|
||||
# Clear dependencies
|
||||
self._dependents = _EdgeMap(store_by_child=False)
|
||||
self._dependencies = _EdgeMap(store_by_child=True)
|
||||
|
||||
# FIXME: we manage _patches_in_order_of_appearance specially here
|
||||
# to keep it from leaking out of spec.py, but we should figure
|
||||
# out how to handle it more elegantly in the Variant classes.
|
||||
@@ -4048,15 +4143,7 @@ def __str__(self):
|
||||
if not self._dependencies:
|
||||
return self.format()
|
||||
|
||||
root_str = [self.format()]
|
||||
sorted_dependencies = sorted(
|
||||
self.traverse(root=False), key=lambda x: (x.name, x.abstract_hash)
|
||||
)
|
||||
sorted_dependencies = [
|
||||
d.format("{edge_attributes} " + DEFAULT_FORMAT) for d in sorted_dependencies
|
||||
]
|
||||
spec_str = " ^".join(root_str + sorted_dependencies)
|
||||
return spec_str.strip()
|
||||
return self.long_spec
|
||||
|
||||
@property
|
||||
def colored_str(self):
|
||||
@@ -4105,10 +4192,10 @@ def tree(
|
||||
depth: bool = False,
|
||||
hashes: bool = False,
|
||||
hashlen: Optional[int] = None,
|
||||
cover: str = "nodes",
|
||||
cover: spack.traverse.CoverType = "nodes",
|
||||
indent: int = 0,
|
||||
format: str = DEFAULT_FORMAT,
|
||||
deptypes: Union[Tuple[str, ...], str] = "all",
|
||||
deptypes: Union[dt.DepTypes, dt.DepFlag] = dt.ALL,
|
||||
show_types: bool = False,
|
||||
depth_first: bool = False,
|
||||
recurse_dependencies: bool = True,
|
||||
@@ -4434,7 +4521,7 @@ def mask_build_deps(in_spec):
|
||||
|
||||
return spec
|
||||
|
||||
def clear_caches(self, ignore=()):
|
||||
def clear_caches(self, ignore: Tuple[str, ...] = ()) -> None:
|
||||
"""
|
||||
Clears all cached hashes in a Spec, while preserving other properties.
|
||||
"""
|
||||
|
@@ -7,35 +7,14 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.deptypes as dt
|
||||
import spack.solver.asp
|
||||
from spack.installer import PackageInstaller
|
||||
from spack.solver.asp import SolverError
|
||||
from spack.spec import Spec
|
||||
|
||||
|
||||
class CacheManager:
|
||||
def __init__(self, specs: List[str]) -> None:
|
||||
self.req_specs = specs
|
||||
self.concr_specs: List[Spec]
|
||||
self.concr_specs = []
|
||||
|
||||
def __enter__(self):
|
||||
self.concr_specs = [Spec(s).concretized() for s in self.req_specs]
|
||||
for s in self.concr_specs:
|
||||
PackageInstaller([s.package], fake=True, explicit=True).install()
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
for s in self.concr_specs:
|
||||
s.package.do_uninstall()
|
||||
|
||||
|
||||
# MacOS and Windows only work if you pass this function pointer rather than a
|
||||
# closure
|
||||
def _mock_has_runtime_dependencies(_x):
|
||||
return True
|
||||
|
||||
|
||||
def _make_specs_non_buildable(specs: List[str]):
|
||||
output_config = {}
|
||||
for spec in specs:
|
||||
@@ -44,203 +23,262 @@ def _make_specs_non_buildable(specs: List[str]):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def splicing_setup(mutable_database, mock_packages, monkeypatch):
|
||||
spack.config.set("concretizer:reuse", True)
|
||||
monkeypatch.setattr(
|
||||
spack.solver.asp, "_has_runtime_dependencies", _mock_has_runtime_dependencies
|
||||
)
|
||||
def install_specs(
|
||||
mutable_database,
|
||||
mock_packages,
|
||||
mutable_config,
|
||||
do_not_check_runtimes_on_reuse,
|
||||
install_mockery,
|
||||
):
|
||||
"""Returns a function that concretizes and installs a list of abstract specs"""
|
||||
mutable_config.set("concretizer:reuse", True)
|
||||
|
||||
def _impl(*specs_str):
|
||||
concrete_specs = [Spec(s).concretized() for s in specs_str]
|
||||
PackageInstaller([s.package for s in concrete_specs], fake=True, explicit=True).install()
|
||||
return concrete_specs
|
||||
|
||||
return _impl
|
||||
|
||||
|
||||
def _enable_splicing():
|
||||
spack.config.set("concretizer:splice", {"automatic": True})
|
||||
|
||||
|
||||
def _has_build_dependency(spec: Spec, name: str):
|
||||
return any(s.name == name for s in spec.dependencies(None, dt.BUILD))
|
||||
@pytest.mark.parametrize("spec_str", ["splice-z", "splice-h@1"])
|
||||
def test_spec_reuse(spec_str, install_specs, mutable_config):
|
||||
"""Tests reuse of splice-z, without splicing, as a root and as a dependency of splice-h"""
|
||||
splice_z = install_specs("splice-z@1.0.0+compat")[0]
|
||||
mutable_config.set("packages", _make_specs_non_buildable(["splice-z"]))
|
||||
concrete = spack.concretize.concretize_one(spec_str)
|
||||
assert concrete["splice-z"].satisfies(splice_z)
|
||||
|
||||
|
||||
def test_simple_reuse(splicing_setup):
|
||||
with CacheManager(["splice-z@1.0.0+compat"]):
|
||||
spack.config.set("packages", _make_specs_non_buildable(["splice-z"]))
|
||||
assert Spec("splice-z").concretized().satisfies(Spec("splice-z"))
|
||||
|
||||
|
||||
def test_simple_dep_reuse(splicing_setup):
|
||||
with CacheManager(["splice-z@1.0.0+compat"]):
|
||||
spack.config.set("packages", _make_specs_non_buildable(["splice-z"]))
|
||||
assert Spec("splice-h@1").concretized().satisfies(Spec("splice-h@1"))
|
||||
|
||||
|
||||
def test_splice_installed_hash(splicing_setup):
|
||||
cache = [
|
||||
@pytest.mark.regression("48578")
|
||||
def test_splice_installed_hash(install_specs, mutable_config):
|
||||
"""Tests splicing the dependency of an installed spec, for another installed spec"""
|
||||
splice_t, splice_h = install_specs(
|
||||
"splice-t@1 ^splice-h@1.0.0+compat ^splice-z@1.0.0",
|
||||
"splice-h@1.0.2+compat ^splice-z@1.0.0",
|
||||
]
|
||||
with CacheManager(cache):
|
||||
packages_config = _make_specs_non_buildable(["splice-t", "splice-h"])
|
||||
spack.config.set("packages", packages_config)
|
||||
goal_spec = Spec("splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.0")
|
||||
with pytest.raises(Exception):
|
||||
goal_spec.concretized()
|
||||
_enable_splicing()
|
||||
assert goal_spec.concretized().satisfies(goal_spec)
|
||||
)
|
||||
packages_config = _make_specs_non_buildable(["splice-t", "splice-h"])
|
||||
mutable_config.set("packages", packages_config)
|
||||
|
||||
goal_spec = "splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.0"
|
||||
with pytest.raises(SolverError):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
_enable_splicing()
|
||||
concrete = spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
# splice-t has a dependency that is changing, thus its hash should be different
|
||||
assert concrete.dag_hash() != splice_t.dag_hash()
|
||||
assert concrete.build_spec.satisfies(splice_t)
|
||||
assert not concrete.satisfies(splice_t)
|
||||
|
||||
# splice-h is reused, so the hash should stay the same
|
||||
assert concrete["splice-h"].satisfies(splice_h)
|
||||
assert concrete["splice-h"].build_spec.satisfies(splice_h)
|
||||
assert concrete["splice-h"].dag_hash() == splice_h.dag_hash()
|
||||
|
||||
|
||||
def test_splice_build_splice_node(splicing_setup):
|
||||
with CacheManager(["splice-t@1 ^splice-h@1.0.0+compat ^splice-z@1.0.0+compat"]):
|
||||
spack.config.set("packages", _make_specs_non_buildable(["splice-t"]))
|
||||
goal_spec = Spec("splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.0+compat")
|
||||
with pytest.raises(Exception):
|
||||
goal_spec.concretized()
|
||||
_enable_splicing()
|
||||
assert goal_spec.concretized().satisfies(goal_spec)
|
||||
def test_splice_build_splice_node(install_specs, mutable_config):
|
||||
"""Tests splicing the dependency of an installed spec, for a spec that is yet to be built"""
|
||||
splice_t = install_specs("splice-t@1 ^splice-h@1.0.0+compat ^splice-z@1.0.0+compat")[0]
|
||||
mutable_config.set("packages", _make_specs_non_buildable(["splice-t"]))
|
||||
|
||||
goal_spec = "splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.0+compat"
|
||||
with pytest.raises(SolverError):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
_enable_splicing()
|
||||
concrete = spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
# splice-t has a dependency that is changing, thus its hash should be different
|
||||
assert concrete.dag_hash() != splice_t.dag_hash()
|
||||
assert concrete.build_spec.satisfies(splice_t)
|
||||
assert not concrete.satisfies(splice_t)
|
||||
|
||||
# splice-h should be different
|
||||
assert concrete["splice-h"].dag_hash() != splice_t["splice-h"].dag_hash()
|
||||
assert concrete["splice-h"].build_spec.dag_hash() == concrete["splice-h"].dag_hash()
|
||||
|
||||
|
||||
def test_double_splice(splicing_setup):
|
||||
cache = [
|
||||
def test_double_splice(install_specs, mutable_config):
|
||||
"""Tests splicing two dependencies of an installed spec, for other installed specs"""
|
||||
splice_t, splice_h, splice_z = install_specs(
|
||||
"splice-t@1 ^splice-h@1.0.0+compat ^splice-z@1.0.0+compat",
|
||||
"splice-h@1.0.2+compat ^splice-z@1.0.1+compat",
|
||||
"splice-z@1.0.2+compat",
|
||||
]
|
||||
with CacheManager(cache):
|
||||
freeze_builds_config = _make_specs_non_buildable(["splice-t", "splice-h", "splice-z"])
|
||||
spack.config.set("packages", freeze_builds_config)
|
||||
goal_spec = Spec("splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.2+compat")
|
||||
with pytest.raises(Exception):
|
||||
goal_spec.concretized()
|
||||
_enable_splicing()
|
||||
assert goal_spec.concretized().satisfies(goal_spec)
|
||||
)
|
||||
mutable_config.set("packages", _make_specs_non_buildable(["splice-t", "splice-h", "splice-z"]))
|
||||
|
||||
goal_spec = "splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.2+compat"
|
||||
with pytest.raises(SolverError):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
_enable_splicing()
|
||||
concrete = spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
# splice-t and splice-h have a dependency that is changing, thus its hash should be different
|
||||
assert concrete.dag_hash() != splice_t.dag_hash()
|
||||
assert concrete.build_spec.satisfies(splice_t)
|
||||
assert not concrete.satisfies(splice_t)
|
||||
|
||||
assert concrete["splice-h"].dag_hash() != splice_h.dag_hash()
|
||||
assert concrete["splice-h"].build_spec.satisfies(splice_h)
|
||||
assert not concrete["splice-h"].satisfies(splice_h)
|
||||
|
||||
# splice-z is reused, so the hash should stay the same
|
||||
assert concrete["splice-z"].dag_hash() == splice_z.dag_hash()
|
||||
|
||||
|
||||
# The next two tests are mirrors of one another
|
||||
def test_virtual_multi_splices_in(splicing_setup):
|
||||
cache = [
|
||||
"depends-on-virtual-with-abi ^virtual-abi-1",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-2",
|
||||
]
|
||||
goal_specs = [
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=one",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=two",
|
||||
]
|
||||
with CacheManager(cache):
|
||||
spack.config.set("packages", _make_specs_non_buildable(["depends-on-virtual-with-abi"]))
|
||||
for gs in goal_specs:
|
||||
with pytest.raises(Exception):
|
||||
Spec(gs).concretized()
|
||||
_enable_splicing()
|
||||
for gs in goal_specs:
|
||||
assert Spec(gs).concretized().satisfies(gs)
|
||||
@pytest.mark.parametrize(
|
||||
"original_spec,goal_spec",
|
||||
[
|
||||
# `virtual-abi-1` can be spliced for `virtual-abi-multi abi=one` and vice-versa
|
||||
(
|
||||
"depends-on-virtual-with-abi ^virtual-abi-1",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=one",
|
||||
),
|
||||
(
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=one",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-1",
|
||||
),
|
||||
# `virtual-abi-2` can be spliced for `virtual-abi-multi abi=two` and vice-versa
|
||||
(
|
||||
"depends-on-virtual-with-abi ^virtual-abi-2",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=two",
|
||||
),
|
||||
(
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=two",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-2",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_virtual_multi_splices_in(original_spec, goal_spec, install_specs, mutable_config):
|
||||
"""Tests that we can splice a virtual dependency with a different, but compatible, provider."""
|
||||
original = install_specs(original_spec)[0]
|
||||
mutable_config.set("packages", _make_specs_non_buildable(["depends-on-virtual-with-abi"]))
|
||||
|
||||
with pytest.raises(SolverError):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
_enable_splicing()
|
||||
spliced = spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
assert spliced.dag_hash() != original.dag_hash()
|
||||
assert spliced.build_spec.dag_hash() == original.dag_hash()
|
||||
assert spliced["virtual-with-abi"].name != spliced.build_spec["virtual-with-abi"].name
|
||||
|
||||
|
||||
def test_virtual_multi_can_be_spliced(splicing_setup):
|
||||
cache = [
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=one",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=two",
|
||||
]
|
||||
goal_specs = [
|
||||
"depends-on-virtual-with-abi ^virtual-abi-1",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-2",
|
||||
]
|
||||
with CacheManager(cache):
|
||||
spack.config.set("packages", _make_specs_non_buildable(["depends-on-virtual-with-abi"]))
|
||||
with pytest.raises(Exception):
|
||||
for gs in goal_specs:
|
||||
Spec(gs).concretized()
|
||||
_enable_splicing()
|
||||
for gs in goal_specs:
|
||||
assert Spec(gs).concretized().satisfies(gs)
|
||||
|
||||
|
||||
def test_manyvariant_star_matching_variant_splice(splicing_setup):
|
||||
cache = [
|
||||
@pytest.mark.parametrize(
|
||||
"original_spec,goal_spec",
|
||||
[
|
||||
# can_splice("manyvariants@1.0.0", when="@1.0.1", match_variants="*")
|
||||
"depends-on-manyvariants ^manyvariants@1.0.0+a+b c=v1 d=v2",
|
||||
"depends-on-manyvariants ^manyvariants@1.0.0~a~b c=v3 d=v3",
|
||||
]
|
||||
goal_specs = [
|
||||
Spec("depends-on-manyvariants ^manyvariants@1.0.1+a+b c=v1 d=v2"),
|
||||
Spec("depends-on-manyvariants ^manyvariants@1.0.1~a~b c=v3 d=v3"),
|
||||
]
|
||||
with CacheManager(cache):
|
||||
freeze_build_config = {"depends-on-manyvariants": {"buildable": False}}
|
||||
spack.config.set("packages", freeze_build_config)
|
||||
for goal in goal_specs:
|
||||
with pytest.raises(Exception):
|
||||
goal.concretized()
|
||||
_enable_splicing()
|
||||
for goal in goal_specs:
|
||||
assert goal.concretized().satisfies(goal)
|
||||
|
||||
|
||||
def test_manyvariant_limited_matching(splicing_setup):
|
||||
cache = [
|
||||
(
|
||||
"depends-on-manyvariants ^manyvariants@1.0.0+a+b c=v1 d=v2",
|
||||
"depends-on-manyvariants ^manyvariants@1.0.1+a+b c=v1 d=v2",
|
||||
),
|
||||
(
|
||||
"depends-on-manyvariants ^manyvariants@1.0.0~a~b c=v3 d=v3",
|
||||
"depends-on-manyvariants ^manyvariants@1.0.1~a~b c=v3 d=v3",
|
||||
),
|
||||
# can_splice("manyvariants@2.0.0+a~b", when="@2.0.1~a+b", match_variants=["c", "d"])
|
||||
"depends-on-manyvariants@2.0 ^manyvariants@2.0.0+a~b c=v3 d=v2",
|
||||
(
|
||||
"depends-on-manyvariants@2.0 ^manyvariants@2.0.0+a~b c=v3 d=v2",
|
||||
"depends-on-manyvariants@2.0 ^manyvariants@2.0.1~a+b c=v3 d=v2",
|
||||
),
|
||||
# can_splice("manyvariants@2.0.0 c=v1 d=v1", when="@2.0.1+a+b")
|
||||
"depends-on-manyvariants@2.0 ^manyvariants@2.0.0~a~b c=v1 d=v1",
|
||||
]
|
||||
goal_specs = [
|
||||
Spec("depends-on-manyvariants@2.0 ^manyvariants@2.0.1~a+b c=v3 d=v2"),
|
||||
Spec("depends-on-manyvariants@2.0 ^manyvariants@2.0.1+a+b c=v3 d=v3"),
|
||||
]
|
||||
with CacheManager(cache):
|
||||
freeze_build_config = {"depends-on-manyvariants": {"buildable": False}}
|
||||
spack.config.set("packages", freeze_build_config)
|
||||
for s in goal_specs:
|
||||
with pytest.raises(Exception):
|
||||
s.concretized()
|
||||
_enable_splicing()
|
||||
for s in goal_specs:
|
||||
assert s.concretized().satisfies(s)
|
||||
(
|
||||
"depends-on-manyvariants@2.0 ^manyvariants@2.0.0~a~b c=v1 d=v1",
|
||||
"depends-on-manyvariants@2.0 ^manyvariants@2.0.1+a+b c=v3 d=v3",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_manyvariant_matching_variant_splice(
|
||||
original_spec, goal_spec, install_specs, mutable_config
|
||||
):
|
||||
"""Tests splicing with different kind of matching on variants"""
|
||||
original = install_specs(original_spec)[0]
|
||||
mutable_config.set("packages", {"depends-on-manyvariants": {"buildable": False}})
|
||||
|
||||
with pytest.raises(SolverError):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
_enable_splicing()
|
||||
spliced = spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
assert spliced.dag_hash() != original.dag_hash()
|
||||
assert spliced.build_spec.dag_hash() == original.dag_hash()
|
||||
|
||||
# The spliced 'manyvariants' is yet to be built
|
||||
assert spliced["manyvariants"].dag_hash() != original["manyvariants"].dag_hash()
|
||||
assert spliced["manyvariants"].build_spec.dag_hash() == spliced["manyvariants"].dag_hash()
|
||||
|
||||
|
||||
def test_external_splice_same_name(splicing_setup):
|
||||
cache = [
|
||||
def test_external_splice_same_name(install_specs, mutable_config):
|
||||
"""Tests that externals can be spliced for non-external specs"""
|
||||
original_splice_h, original_splice_t = install_specs(
|
||||
"splice-h@1.0.0 ^splice-z@1.0.0+compat",
|
||||
"splice-t@1.0 ^splice-h@1.0.1 ^splice-z@1.0.1+compat",
|
||||
]
|
||||
packages_yaml = {
|
||||
"splice-z": {"externals": [{"spec": "splice-z@1.0.2+compat", "prefix": "/usr"}]}
|
||||
}
|
||||
goal_specs = [
|
||||
Spec("splice-h@1.0.0 ^splice-z@1.0.2"),
|
||||
Spec("splice-t@1.0 ^splice-h@1.0.1 ^splice-z@1.0.2"),
|
||||
]
|
||||
with CacheManager(cache):
|
||||
spack.config.set("packages", packages_yaml)
|
||||
_enable_splicing()
|
||||
for s in goal_specs:
|
||||
assert s.concretized().satisfies(s)
|
||||
)
|
||||
mutable_config.set("packages", _make_specs_non_buildable(["splice-t", "splice-h"]))
|
||||
mutable_config.set(
|
||||
"packages",
|
||||
{
|
||||
"splice-z": {
|
||||
"externals": [{"spec": "splice-z@1.0.2+compat", "prefix": "/usr"}],
|
||||
"buildable": False,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
_enable_splicing()
|
||||
concrete_splice_h = spack.concretize.concretize_one("splice-h@1.0.0 ^splice-z@1.0.2")
|
||||
concrete_splice_t = spack.concretize.concretize_one(
|
||||
"splice-t@1.0 ^splice-h@1.0.1 ^splice-z@1.0.2"
|
||||
)
|
||||
|
||||
assert concrete_splice_h.dag_hash() != original_splice_h.dag_hash()
|
||||
assert concrete_splice_h.build_spec.dag_hash() == original_splice_h.dag_hash()
|
||||
assert concrete_splice_h["splice-z"].external
|
||||
|
||||
assert concrete_splice_t.dag_hash() != original_splice_t.dag_hash()
|
||||
assert concrete_splice_t.build_spec.dag_hash() == original_splice_t.dag_hash()
|
||||
assert concrete_splice_t["splice-z"].external
|
||||
|
||||
assert concrete_splice_t["splice-z"].dag_hash() == concrete_splice_h["splice-z"].dag_hash()
|
||||
|
||||
|
||||
def test_spliced_build_deps_only_in_build_spec(splicing_setup):
|
||||
cache = ["splice-t@1.0 ^splice-h@1.0.1 ^splice-z@1.0.0"]
|
||||
goal_spec = Spec("splice-t@1.0 ^splice-h@1.0.2 ^splice-z@1.0.0")
|
||||
def test_spliced_build_deps_only_in_build_spec(install_specs):
|
||||
"""Tests that build specs are not reported in the spliced spec"""
|
||||
install_specs("splice-t@1.0 ^splice-h@1.0.1 ^splice-z@1.0.0")
|
||||
|
||||
with CacheManager(cache):
|
||||
_enable_splicing()
|
||||
concr_goal = goal_spec.concretized()
|
||||
build_spec = concr_goal._build_spec
|
||||
# Spec has been spliced
|
||||
assert build_spec is not None
|
||||
# Build spec has spliced build dependencies
|
||||
assert _has_build_dependency(build_spec, "splice-h")
|
||||
assert _has_build_dependency(build_spec, "splice-z")
|
||||
# Spliced build dependencies are removed
|
||||
assert len(concr_goal.dependencies(None, dt.BUILD)) == 0
|
||||
_enable_splicing()
|
||||
spliced = spack.concretize.concretize_one("splice-t@1.0 ^splice-h@1.0.2 ^splice-z@1.0.0")
|
||||
build_spec = spliced.build_spec
|
||||
|
||||
# Spec has been spliced
|
||||
assert build_spec.dag_hash() != spliced.dag_hash()
|
||||
# Build spec has spliced build dependencies
|
||||
assert build_spec.dependencies("splice-h", dt.BUILD)
|
||||
assert build_spec.dependencies("splice-z", dt.BUILD)
|
||||
# Spliced build dependencies are removed
|
||||
assert len(spliced.dependencies(None, dt.BUILD)) == 0
|
||||
|
||||
|
||||
def test_spliced_transitive_dependency(splicing_setup):
|
||||
cache = ["splice-depends-on-t@1.0 ^splice-h@1.0.1"]
|
||||
goal_spec = Spec("splice-depends-on-t^splice-h@1.0.2")
|
||||
def test_spliced_transitive_dependency(install_specs, mutable_config):
|
||||
"""Tests that build specs are not reported, even for spliced transitive dependencies"""
|
||||
install_specs("splice-depends-on-t@1.0 ^splice-h@1.0.1")
|
||||
mutable_config.set("packages", _make_specs_non_buildable(["splice-depends-on-t"]))
|
||||
|
||||
with CacheManager(cache):
|
||||
spack.config.set("packages", _make_specs_non_buildable(["splice-depends-on-t"]))
|
||||
_enable_splicing()
|
||||
concr_goal = goal_spec.concretized()
|
||||
# Spec has been spliced
|
||||
assert concr_goal._build_spec is not None
|
||||
assert concr_goal["splice-t"]._build_spec is not None
|
||||
assert concr_goal.satisfies(goal_spec)
|
||||
# Spliced build dependencies are removed
|
||||
assert len(concr_goal.dependencies(None, dt.BUILD)) == 0
|
||||
_enable_splicing()
|
||||
spliced = spack.concretize.concretize_one("splice-depends-on-t^splice-h@1.0.2")
|
||||
|
||||
# Spec has been spliced
|
||||
assert spliced.build_spec.dag_hash() != spliced.dag_hash()
|
||||
assert spliced["splice-t"].build_spec.dag_hash() != spliced["splice-t"].dag_hash()
|
||||
|
||||
# Spliced build dependencies are removed
|
||||
assert len(spliced.dependencies(None, dt.BUILD)) == 0
|
||||
assert len(spliced["splice-t"].dependencies(None, dt.BUILD)) == 0
|
||||
|
@@ -133,5 +133,5 @@ def test_concretize_target_ranges(root_target_range, dep_target_range, result, m
|
||||
f"pkg-a %gcc@10 foobar=bar target={root_target_range} ^pkg-b target={dep_target_range}"
|
||||
)
|
||||
with spack.concretize.disable_compiler_existence_check():
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one(spec)
|
||||
assert spec.target == spec["pkg-b"].target == result
|
||||
|
@@ -28,6 +28,7 @@
|
||||
import spack.binary_distribution as bindist
|
||||
import spack.caches
|
||||
import spack.compilers
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.fetch_strategy
|
||||
import spack.hooks.sbang as sbang
|
||||
@@ -36,14 +37,13 @@
|
||||
import spack.oci.image
|
||||
import spack.paths
|
||||
import spack.spec
|
||||
import spack.stage
|
||||
import spack.store
|
||||
import spack.util.gpg
|
||||
import spack.util.spack_yaml as syaml
|
||||
import spack.util.url as url_util
|
||||
import spack.util.web as web_util
|
||||
from spack.binary_distribution import CannotListKeys, GenerateIndexError
|
||||
from spack.directory_layout import DirectoryLayout
|
||||
from spack.installer import PackageInstaller
|
||||
from spack.paths import test_path
|
||||
from spack.spec import Spec
|
||||
|
||||
@@ -136,35 +136,28 @@ def default_config(tmp_path, config_directory, monkeypatch, install_mockery):
|
||||
@pytest.fixture(scope="function")
|
||||
def install_dir_default_layout(tmpdir):
|
||||
"""Hooks a fake install directory with a default layout"""
|
||||
scheme = os.path.join(
|
||||
"${architecture}", "${compiler.name}-${compiler.version}", "${name}-${version}-${hash}"
|
||||
)
|
||||
real_store, real_layout = spack.store.STORE, spack.store.STORE.layout
|
||||
opt_dir = tmpdir.join("opt")
|
||||
spack.store.STORE = spack.store.Store(str(opt_dir))
|
||||
spack.store.STORE.layout = DirectoryLayout(str(opt_dir), path_scheme=scheme)
|
||||
original_store, spack.store.STORE = spack.store.STORE, spack.store.Store(str(opt_dir))
|
||||
try:
|
||||
yield spack.store
|
||||
finally:
|
||||
spack.store.STORE = real_store
|
||||
spack.store.STORE.layout = real_layout
|
||||
spack.store.STORE = original_store
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def install_dir_non_default_layout(tmpdir):
|
||||
"""Hooks a fake install directory with a non-default layout"""
|
||||
scheme = os.path.join(
|
||||
"${name}", "${version}", "${architecture}-${compiler.name}-${compiler.version}-${hash}"
|
||||
)
|
||||
real_store, real_layout = spack.store.STORE, spack.store.STORE.layout
|
||||
opt_dir = tmpdir.join("opt")
|
||||
spack.store.STORE = spack.store.Store(str(opt_dir))
|
||||
spack.store.STORE.layout = DirectoryLayout(str(opt_dir), path_scheme=scheme)
|
||||
original_store, spack.store.STORE = spack.store.STORE, spack.store.Store(
|
||||
str(opt_dir),
|
||||
projections={
|
||||
"all": "{name}/{version}/{architecture}-{compiler.name}-{compiler.version}-{hash}"
|
||||
},
|
||||
)
|
||||
try:
|
||||
yield spack.store
|
||||
finally:
|
||||
spack.store.STORE = real_store
|
||||
spack.store.STORE.layout = real_layout
|
||||
spack.store.STORE = original_store
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
@@ -213,8 +206,9 @@ def test_default_rpaths_create_install_default_layout(temporary_mirror_dir):
|
||||
Test the creation and installation of buildcaches with default rpaths
|
||||
into the default directory layout scheme.
|
||||
"""
|
||||
gspec, cspec = Spec("garply").concretized(), Spec("corge").concretized()
|
||||
sy_spec = Spec("symly").concretized()
|
||||
gspec = spack.concretize.concretize_one("garply")
|
||||
cspec = spack.concretize.concretize_one("corge")
|
||||
sy_spec = spack.concretize.concretize_one("symly")
|
||||
|
||||
# Install 'corge' without using a cache
|
||||
install_cmd("--no-cache", cspec.name)
|
||||
@@ -261,9 +255,9 @@ def test_default_rpaths_install_nondefault_layout(temporary_mirror_dir):
|
||||
Test the creation and installation of buildcaches with default rpaths
|
||||
into the non-default directory layout scheme.
|
||||
"""
|
||||
cspec = Spec("corge").concretized()
|
||||
cspec = spack.concretize.concretize_one("corge")
|
||||
# This guy tests for symlink relocation
|
||||
sy_spec = Spec("symly").concretized()
|
||||
sy_spec = spack.concretize.concretize_one("symly")
|
||||
|
||||
# Install some packages with dependent packages
|
||||
# test install in non-default install path scheme
|
||||
@@ -284,7 +278,8 @@ def test_relative_rpaths_install_default_layout(temporary_mirror_dir):
|
||||
Test the creation and installation of buildcaches with relative
|
||||
rpaths into the default directory layout scheme.
|
||||
"""
|
||||
gspec, cspec = Spec("garply").concretized(), Spec("corge").concretized()
|
||||
gspec = spack.concretize.concretize_one("garply")
|
||||
cspec = spack.concretize.concretize_one("corge")
|
||||
|
||||
# Install buildcache created with relativized rpaths
|
||||
buildcache_cmd("install", "-uf", cspec.name)
|
||||
@@ -313,7 +308,7 @@ def test_relative_rpaths_install_nondefault(temporary_mirror_dir):
|
||||
Test the installation of buildcaches with relativized rpaths
|
||||
into the non-default directory layout scheme.
|
||||
"""
|
||||
cspec = Spec("corge").concretized()
|
||||
cspec = spack.concretize.concretize_one("corge")
|
||||
|
||||
# Test install in non-default install path scheme and relative path
|
||||
buildcache_cmd("install", "-uf", cspec.name)
|
||||
@@ -366,7 +361,8 @@ def test_built_spec_cache(temporary_mirror_dir):
|
||||
that cache from a buildcache index."""
|
||||
buildcache_cmd("list", "-a", "-l")
|
||||
|
||||
gspec, cspec = Spec("garply").concretized(), Spec("corge").concretized()
|
||||
gspec = spack.concretize.concretize_one("garply")
|
||||
cspec = spack.concretize.concretize_one("corge")
|
||||
|
||||
for s in [gspec, cspec]:
|
||||
results = bindist.get_mirrors_for_spec(s)
|
||||
@@ -389,7 +385,7 @@ def test_spec_needs_rebuild(monkeypatch, tmpdir):
|
||||
mirror_dir = tmpdir.join("mirror_dir")
|
||||
mirror_url = url_util.path_to_file_url(mirror_dir.strpath)
|
||||
|
||||
s = Spec("libdwarf").concretized()
|
||||
s = spack.concretize.concretize_one("libdwarf")
|
||||
|
||||
# Install a package
|
||||
install_cmd(s.name)
|
||||
@@ -418,7 +414,7 @@ def test_generate_index_missing(monkeypatch, tmpdir, mutable_config):
|
||||
mirror_url = url_util.path_to_file_url(mirror_dir.strpath)
|
||||
spack.config.set("mirrors", {"test": mirror_url})
|
||||
|
||||
s = Spec("libdwarf").concretized()
|
||||
s = spack.concretize.concretize_one("libdwarf")
|
||||
|
||||
# Install a package
|
||||
install_cmd("--no-cache", s.name)
|
||||
@@ -500,74 +496,40 @@ def mock_list_url(url, recursive=False):
|
||||
assert f"Encountered problem listing packages at {url}" in capfd.readouterr().err
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_fetch", "install_mockery")
|
||||
def test_update_sbang(tmpdir, temporary_mirror):
|
||||
"""Test the creation and installation of buildcaches with default rpaths
|
||||
into the non-default directory layout scheme, triggering an update of the
|
||||
sbang.
|
||||
"""
|
||||
spec_str = "old-sbang"
|
||||
# Concretize a package with some old-fashioned sbang lines.
|
||||
old_spec = Spec(spec_str).concretized()
|
||||
old_spec_hash_str = "/{0}".format(old_spec.dag_hash())
|
||||
def test_update_sbang(tmp_path, temporary_mirror, mock_fetch, install_mockery):
|
||||
"""Test relocation of the sbang shebang line in a package script"""
|
||||
s = spack.concretize.concretize_one("old-sbang")
|
||||
PackageInstaller([s.package]).install()
|
||||
old_prefix, old_sbang_shebang = s.prefix, sbang.sbang_shebang_line()
|
||||
old_contents = f"""\
|
||||
{old_sbang_shebang}
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Need a fake mirror with *function* scope.
|
||||
mirror_dir = temporary_mirror
|
||||
|
||||
# Assume all commands will concretize old_spec the same way.
|
||||
install_cmd("--no-cache", old_spec.name)
|
||||
{s.prefix.bin}
|
||||
"""
|
||||
with open(os.path.join(s.prefix.bin, "script.sh"), encoding="utf-8") as f:
|
||||
assert f.read() == old_contents
|
||||
|
||||
# Create a buildcache with the installed spec.
|
||||
buildcache_cmd("push", "-u", mirror_dir, old_spec_hash_str)
|
||||
|
||||
# Need to force an update of the buildcache index
|
||||
buildcache_cmd("update-index", mirror_dir)
|
||||
|
||||
# Uninstall the original package.
|
||||
uninstall_cmd("-y", old_spec_hash_str)
|
||||
buildcache_cmd("push", "--update-index", "--unsigned", temporary_mirror, f"/{s.dag_hash()}")
|
||||
|
||||
# Switch the store to the new install tree locations
|
||||
newtree_dir = tmpdir.join("newtree")
|
||||
with spack.store.use_store(str(newtree_dir)):
|
||||
new_spec = Spec("old-sbang").concretized()
|
||||
assert new_spec.dag_hash() == old_spec.dag_hash()
|
||||
with spack.store.use_store(str(tmp_path)):
|
||||
s._prefix = None # clear the cached old prefix
|
||||
new_prefix, new_sbang_shebang = s.prefix, sbang.sbang_shebang_line()
|
||||
assert old_prefix != new_prefix
|
||||
assert old_sbang_shebang != new_sbang_shebang
|
||||
PackageInstaller([s.package], cache_only=True, unsigned=True).install()
|
||||
|
||||
# Install package from buildcache
|
||||
buildcache_cmd("install", "-u", "-f", new_spec.name)
|
||||
# Check that the sbang line refers to the new install tree
|
||||
new_contents = f"""\
|
||||
{sbang.sbang_shebang_line()}
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Continue blowing away caches
|
||||
bindist.clear_spec_cache()
|
||||
spack.stage.purge()
|
||||
|
||||
# test that the sbang was updated by the move
|
||||
sbang_style_1_expected = """{0}
|
||||
#!/usr/bin/env python
|
||||
|
||||
{1}
|
||||
""".format(
|
||||
sbang.sbang_shebang_line(), new_spec.prefix.bin
|
||||
)
|
||||
sbang_style_2_expected = """{0}
|
||||
#!/usr/bin/env python
|
||||
|
||||
{1}
|
||||
""".format(
|
||||
sbang.sbang_shebang_line(), new_spec.prefix.bin
|
||||
)
|
||||
|
||||
installed_script_style_1_path = new_spec.prefix.bin.join("sbang-style-1.sh")
|
||||
assert (
|
||||
sbang_style_1_expected
|
||||
== open(str(installed_script_style_1_path), encoding="utf-8").read()
|
||||
)
|
||||
|
||||
installed_script_style_2_path = new_spec.prefix.bin.join("sbang-style-2.sh")
|
||||
assert (
|
||||
sbang_style_2_expected
|
||||
== open(str(installed_script_style_2_path), encoding="utf-8").read()
|
||||
)
|
||||
|
||||
uninstall_cmd("-y", "/%s" % new_spec.dag_hash())
|
||||
{s.prefix.bin}
|
||||
"""
|
||||
with open(os.path.join(s.prefix.bin, "script.sh"), encoding="utf-8") as f:
|
||||
assert f.read() == new_contents
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
|
@@ -8,15 +8,15 @@
|
||||
import pytest
|
||||
|
||||
import spack.binary_distribution as bd
|
||||
import spack.concretize
|
||||
import spack.mirrors.mirror
|
||||
import spack.spec
|
||||
from spack.installer import PackageInstaller
|
||||
|
||||
pytestmark = pytest.mark.not_on_windows("does not run on windows")
|
||||
|
||||
|
||||
def test_build_tarball_overwrite(install_mockery, mock_fetch, monkeypatch, tmp_path):
|
||||
spec = spack.spec.Spec("trivial-install-test-package").concretized()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
PackageInstaller([spec.package], fake=True).install()
|
||||
|
||||
specs = [spec]
|
||||
|
@@ -16,6 +16,7 @@
|
||||
import spack.build_environment
|
||||
import spack.compiler
|
||||
import spack.compilers
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.deptypes as dt
|
||||
import spack.package_base
|
||||
@@ -163,8 +164,7 @@ def test_static_to_shared_library(build_environment):
|
||||
@pytest.mark.regression("8345")
|
||||
@pytest.mark.usefixtures("config", "mock_packages")
|
||||
def test_cc_not_changed_by_modules(monkeypatch, working_env):
|
||||
s = spack.spec.Spec("cmake")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("cmake")
|
||||
pkg = s.package
|
||||
|
||||
def _set_wrong_cc(x):
|
||||
@@ -184,7 +184,7 @@ def test_setup_dependent_package_inherited_modules(
|
||||
working_env, mock_packages, install_mockery, mock_fetch
|
||||
):
|
||||
# This will raise on regression
|
||||
s = spack.spec.Spec("cmake-client-inheritor").concretized()
|
||||
s = spack.concretize.concretize_one("cmake-client-inheritor")
|
||||
PackageInstaller([s.package]).install()
|
||||
|
||||
|
||||
@@ -277,7 +277,7 @@ def platform_pathsep(pathlist):
|
||||
return convert_to_platform_path(pathlist)
|
||||
|
||||
# Monkeypatch a pkg.compiler.environment with the required modifications
|
||||
pkg = spack.spec.Spec("cmake").concretized().package
|
||||
pkg = spack.concretize.concretize_one("cmake").package
|
||||
monkeypatch.setattr(pkg.compiler, "environment", modifications)
|
||||
# Trigger the modifications
|
||||
spack.build_environment.setup_package(pkg, False)
|
||||
@@ -301,7 +301,7 @@ def custom_env(pkg, env):
|
||||
env.prepend_path("PATH", test_path)
|
||||
env.append_flags("ENV_CUSTOM_CC_FLAGS", "--custom-env-flag1")
|
||||
|
||||
pkg = spack.spec.Spec("cmake").concretized().package
|
||||
pkg = spack.concretize.concretize_one("cmake").package
|
||||
monkeypatch.setattr(pkg.compiler, "setup_custom_environment", custom_env)
|
||||
spack.build_environment.setup_package(pkg, False)
|
||||
|
||||
@@ -322,7 +322,7 @@ def test_external_config_env(mock_packages, mutable_config, working_env):
|
||||
}
|
||||
spack.config.set("packages:cmake", cmake_config)
|
||||
|
||||
cmake_client = spack.spec.Spec("cmake-client").concretized()
|
||||
cmake_client = spack.concretize.concretize_one("cmake-client")
|
||||
spack.build_environment.setup_package(cmake_client.package, False)
|
||||
|
||||
assert os.environ["TEST_ENV_VAR_SET"] == "yes it's set"
|
||||
@@ -330,8 +330,7 @@ def test_external_config_env(mock_packages, mutable_config, working_env):
|
||||
|
||||
@pytest.mark.regression("9107")
|
||||
def test_spack_paths_before_module_paths(config, mock_packages, monkeypatch, working_env):
|
||||
s = spack.spec.Spec("cmake")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("cmake")
|
||||
pkg = s.package
|
||||
|
||||
module_path = os.path.join("path", "to", "module")
|
||||
@@ -352,8 +351,7 @@ def _set_wrong_cc(x):
|
||||
|
||||
|
||||
def test_package_inheritance_module_setup(config, mock_packages, working_env):
|
||||
s = spack.spec.Spec("multimodule-inheritance")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("multimodule-inheritance")
|
||||
pkg = s.package
|
||||
|
||||
spack.build_environment.setup_package(pkg, False)
|
||||
@@ -387,8 +385,7 @@ def test_wrapper_variables(
|
||||
not in cuda_include_dirs
|
||||
)
|
||||
|
||||
root = spack.spec.Spec("dt-diamond")
|
||||
root.concretize()
|
||||
root = spack.concretize.concretize_one("dt-diamond")
|
||||
|
||||
for s in root.traverse():
|
||||
s.prefix = "/{0}-prefix/".format(s.name)
|
||||
@@ -453,7 +450,7 @@ def test_external_prefixes_last(mutable_config, mock_packages, working_env, monk
|
||||
"""
|
||||
)
|
||||
spack.config.set("packages", cfg_data)
|
||||
top = spack.spec.Spec("dt-diamond").concretized()
|
||||
top = spack.concretize.concretize_one("dt-diamond")
|
||||
|
||||
def _trust_me_its_a_dir(path):
|
||||
return True
|
||||
@@ -500,8 +497,7 @@ def test_parallel_false_is_not_propagating(default_mock_concretization):
|
||||
)
|
||||
def test_setting_dtags_based_on_config(config_setting, expected_flag, config, mock_packages):
|
||||
# Pick a random package to be able to set compiler's variables
|
||||
s = spack.spec.Spec("cmake")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("cmake")
|
||||
pkg = s.package
|
||||
|
||||
env = EnvironmentModifications()
|
||||
@@ -533,7 +529,7 @@ def setup_dependent_package(module, dependent_spec):
|
||||
assert dependent_module.ninja is not None
|
||||
dependent_spec.package.test_attr = True
|
||||
|
||||
externaltool = spack.spec.Spec("externaltest").concretized()
|
||||
externaltool = spack.concretize.concretize_one("externaltest")
|
||||
monkeypatch.setattr(
|
||||
externaltool["externaltool"].package, "setup_dependent_package", setup_dependent_package
|
||||
)
|
||||
@@ -728,7 +724,7 @@ def test_build_system_globals_only_set_on_root_during_build(default_mock_concret
|
||||
But obviously it can lead to very hard to find bugs... We should get rid of those globals and
|
||||
define them instead as a property on the package instance.
|
||||
"""
|
||||
root = spack.spec.Spec("mpileaks").concretized()
|
||||
root = spack.concretize.concretize_one("mpileaks")
|
||||
build_variables = ("std_cmake_args", "std_meson_args", "std_pip_args")
|
||||
|
||||
# See todo above, we clear out any properties that may have been set by the previous test.
|
||||
|
@@ -15,12 +15,13 @@
|
||||
import spack.build_systems.autotools
|
||||
import spack.build_systems.cmake
|
||||
import spack.builder
|
||||
import spack.concretize
|
||||
import spack.environment
|
||||
import spack.error
|
||||
import spack.paths
|
||||
import spack.platforms
|
||||
import spack.platforms.test
|
||||
from spack.build_environment import ChildError, setup_package
|
||||
from spack.build_environment import ChildError, MakeExecutable, setup_package
|
||||
from spack.installer import PackageInstaller
|
||||
from spack.spec import Spec
|
||||
from spack.util.executable import which
|
||||
@@ -29,10 +30,12 @@
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def concretize_and_setup(default_mock_concretization):
|
||||
def concretize_and_setup(default_mock_concretization, monkeypatch):
|
||||
def _func(spec_str):
|
||||
s = default_mock_concretization(spec_str)
|
||||
setup_package(s.package, False)
|
||||
monkeypatch.setattr(s.package.module, "make", MakeExecutable("make", jobs=1))
|
||||
monkeypatch.setattr(s.package.module, "ninja", MakeExecutable("ninja", jobs=1))
|
||||
return s
|
||||
|
||||
return _func
|
||||
@@ -144,7 +147,7 @@ def test_none_is_allowed(self, default_mock_concretization):
|
||||
|
||||
def test_libtool_archive_files_are_deleted_by_default(self, mutable_database):
|
||||
# Install a package that creates a mock libtool archive
|
||||
s = Spec("libtool-deletion").concretized()
|
||||
s = spack.concretize.concretize_one("libtool-deletion")
|
||||
PackageInstaller([s.package], explicit=True).install()
|
||||
|
||||
# Assert the libtool archive is not there and we have
|
||||
@@ -159,7 +162,7 @@ def test_libtool_archive_files_might_be_installed_on_demand(
|
||||
):
|
||||
# Install a package that creates a mock libtool archive,
|
||||
# patch its package to preserve the installation
|
||||
s = Spec("libtool-deletion").concretized()
|
||||
s = spack.concretize.concretize_one("libtool-deletion")
|
||||
monkeypatch.setattr(
|
||||
type(spack.builder.create(s.package)), "install_libtool_archives", True
|
||||
)
|
||||
@@ -173,7 +176,9 @@ def test_autotools_gnuconfig_replacement(self, mutable_database):
|
||||
Tests whether only broken config.sub and config.guess are replaced with
|
||||
files from working alternatives from the gnuconfig package.
|
||||
"""
|
||||
s = Spec("autotools-config-replacement +patch_config_files +gnuconfig").concretized()
|
||||
s = spack.concretize.concretize_one(
|
||||
Spec("autotools-config-replacement +patch_config_files +gnuconfig")
|
||||
)
|
||||
PackageInstaller([s.package]).install()
|
||||
|
||||
with open(os.path.join(s.prefix.broken, "config.sub"), encoding="utf-8") as f:
|
||||
@@ -192,7 +197,9 @@ def test_autotools_gnuconfig_replacement_disabled(self, mutable_database):
|
||||
"""
|
||||
Tests whether disabling patch_config_files
|
||||
"""
|
||||
s = Spec("autotools-config-replacement ~patch_config_files +gnuconfig").concretized()
|
||||
s = spack.concretize.concretize_one(
|
||||
Spec("autotools-config-replacement ~patch_config_files +gnuconfig")
|
||||
)
|
||||
PackageInstaller([s.package]).install()
|
||||
|
||||
with open(os.path.join(s.prefix.broken, "config.sub"), encoding="utf-8") as f:
|
||||
@@ -217,8 +224,9 @@ def test_autotools_gnuconfig_replacement_no_gnuconfig(self, mutable_database, mo
|
||||
enabled, but gnuconfig is not listed as a direct build dependency.
|
||||
"""
|
||||
monkeypatch.setattr(spack.platforms.test.Test, "default", "x86_64")
|
||||
s = Spec("autotools-config-replacement +patch_config_files ~gnuconfig")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one(
|
||||
Spec("autotools-config-replacement +patch_config_files ~gnuconfig")
|
||||
)
|
||||
|
||||
msg = "Cannot patch config files: missing dependencies: gnuconfig"
|
||||
with pytest.raises(ChildError, match=msg):
|
||||
@@ -298,7 +306,7 @@ def test_define(self, default_mock_concretization):
|
||||
assert define("SINGLE", "red") == "-DSINGLE:STRING=red"
|
||||
|
||||
def test_define_from_variant(self):
|
||||
s = Spec("cmake-client multi=up,right ~truthy single=red").concretized()
|
||||
s = spack.concretize.concretize_one("cmake-client multi=up,right ~truthy single=red")
|
||||
|
||||
arg = s.package.define_from_variant("MULTI")
|
||||
assert arg == "-DMULTI:STRING=right;up"
|
||||
|
@@ -8,9 +8,9 @@
|
||||
from llnl.util.filesystem import touch
|
||||
|
||||
import spack.builder
|
||||
import spack.concretize
|
||||
import spack.paths
|
||||
import spack.repo
|
||||
import spack.spec
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@@ -78,7 +78,7 @@ def builder_test_repository():
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_callbacks_and_installation_procedure(spec_str, expected_values, working_env):
|
||||
"""Test the correct execution of callbacks and installation procedures for packages."""
|
||||
s = spack.spec.Spec(spec_str).concretized()
|
||||
s = spack.concretize.concretize_one(spec_str)
|
||||
builder = spack.builder.create(s.package)
|
||||
for phase_fn in builder:
|
||||
phase_fn.execute()
|
||||
@@ -101,7 +101,7 @@ def test_callbacks_and_installation_procedure(spec_str, expected_values, working
|
||||
],
|
||||
)
|
||||
def test_old_style_compatibility_with_super(spec_str, method_name, expected):
|
||||
s = spack.spec.Spec(spec_str).concretized()
|
||||
s = spack.concretize.concretize_one(spec_str)
|
||||
builder = spack.builder.create(s.package)
|
||||
value = getattr(builder, method_name)()
|
||||
assert value == expected
|
||||
@@ -112,7 +112,7 @@ def test_old_style_compatibility_with_super(spec_str, method_name, expected):
|
||||
@pytest.mark.usefixtures("builder_test_repository", "config", "working_env")
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_build_time_tests_are_executed_from_default_builder():
|
||||
s = spack.spec.Spec("old-style-autotools").concretized()
|
||||
s = spack.concretize.concretize_one("old-style-autotools")
|
||||
builder = spack.builder.create(s.package)
|
||||
builder.pkg.run_tests = True
|
||||
for phase_fn in builder:
|
||||
@@ -126,7 +126,7 @@ def test_build_time_tests_are_executed_from_default_builder():
|
||||
@pytest.mark.usefixtures("builder_test_repository", "config", "working_env")
|
||||
def test_monkey_patching_wrapped_pkg():
|
||||
"""Confirm 'run_tests' is accessible through wrappers."""
|
||||
s = spack.spec.Spec("old-style-autotools").concretized()
|
||||
s = spack.concretize.concretize_one("old-style-autotools")
|
||||
builder = spack.builder.create(s.package)
|
||||
assert s.package.run_tests is False
|
||||
assert builder.pkg.run_tests is False
|
||||
@@ -141,7 +141,7 @@ def test_monkey_patching_wrapped_pkg():
|
||||
@pytest.mark.usefixtures("builder_test_repository", "config", "working_env")
|
||||
def test_monkey_patching_test_log_file():
|
||||
"""Confirm 'test_log_file' is accessible through wrappers."""
|
||||
s = spack.spec.Spec("old-style-autotools").concretized()
|
||||
s = spack.concretize.concretize_one("old-style-autotools")
|
||||
builder = spack.builder.create(s.package)
|
||||
|
||||
s.package.tester.test_log_file = "/some/file"
|
||||
@@ -154,7 +154,7 @@ def test_monkey_patching_test_log_file():
|
||||
@pytest.mark.not_on_windows("Does not run on windows")
|
||||
def test_install_time_test_callback(tmpdir, config, mock_packages, mock_stage):
|
||||
"""Confirm able to run stand-alone test as a post-install callback."""
|
||||
s = spack.spec.Spec("py-test-callback").concretized()
|
||||
s = spack.concretize.concretize_one("py-test-callback")
|
||||
builder = spack.builder.create(s.package)
|
||||
builder.pkg.run_tests = True
|
||||
s.package.tester.test_log_file = tmpdir.join("install_test.log")
|
||||
@@ -174,7 +174,7 @@ def test_mixins_with_builders(working_env):
|
||||
"""Tests that run_after and run_before callbacks are accumulated correctly,
|
||||
when mixins are used with builders.
|
||||
"""
|
||||
s = spack.spec.Spec("builder-and-mixins").concretized()
|
||||
s = spack.concretize.concretize_one("builder-and-mixins")
|
||||
builder = spack.builder.create(s.package)
|
||||
|
||||
# Check that callbacks added by the mixin are in the list
|
||||
|
@@ -4,6 +4,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.concretize
|
||||
import spack.deptypes as dt
|
||||
import spack.installer as inst
|
||||
import spack.repo
|
||||
@@ -21,8 +22,7 @@ def test_build_request_errors(install_mockery):
|
||||
|
||||
|
||||
def test_build_request_basics(install_mockery):
|
||||
spec = spack.spec.Spec("dependent-install")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("dependent-install")
|
||||
assert spec.concrete
|
||||
|
||||
# Ensure key properties match expectations
|
||||
@@ -39,8 +39,7 @@ def test_build_request_basics(install_mockery):
|
||||
def test_build_request_strings(install_mockery):
|
||||
"""Tests of BuildRequest repr and str for coverage purposes."""
|
||||
# Using a package with one dependency
|
||||
spec = spack.spec.Spec("dependent-install")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("dependent-install")
|
||||
assert spec.concrete
|
||||
|
||||
# Ensure key properties match expectations
|
||||
@@ -72,7 +71,7 @@ def test_build_request_deptypes(
|
||||
package_deptypes,
|
||||
dependencies_deptypes,
|
||||
):
|
||||
s = spack.spec.Spec("dependent-install").concretized()
|
||||
s = spack.concretize.concretize_one("dependent-install")
|
||||
|
||||
build_request = inst.BuildRequest(
|
||||
s.package,
|
||||
|
@@ -4,6 +4,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.concretize
|
||||
import spack.error
|
||||
import spack.installer as inst
|
||||
import spack.repo
|
||||
@@ -24,7 +25,7 @@ def test_build_task_errors(install_mockery):
|
||||
inst.BuildTask(pkg_cls(spec), None)
|
||||
|
||||
# Using a concretized package now means the request argument is checked.
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one(spec)
|
||||
assert spec.concrete
|
||||
|
||||
with pytest.raises(TypeError, match="is not a valid build request"):
|
||||
@@ -47,8 +48,7 @@ def test_build_task_errors(install_mockery):
|
||||
|
||||
|
||||
def test_build_task_basics(install_mockery):
|
||||
spec = spack.spec.Spec("dependent-install")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("dependent-install")
|
||||
assert spec.concrete
|
||||
|
||||
# Ensure key properties match expectations
|
||||
@@ -69,8 +69,7 @@ def test_build_task_basics(install_mockery):
|
||||
def test_build_task_strings(install_mockery):
|
||||
"""Tests of build_task repr and str for coverage purposes."""
|
||||
# Using a package with one dependency
|
||||
spec = spack.spec.Spec("dependent-install")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("dependent-install")
|
||||
assert spec.concrete
|
||||
|
||||
# Ensure key properties match expectations
|
||||
|
@@ -9,13 +9,12 @@
|
||||
import llnl.util.filesystem as fs
|
||||
|
||||
import spack.ci as ci
|
||||
import spack.concretize
|
||||
import spack.environment as ev
|
||||
import spack.error
|
||||
import spack.paths as spack_paths
|
||||
import spack.repo as repo
|
||||
import spack.spec
|
||||
import spack.util.git
|
||||
from spack.spec import Spec
|
||||
|
||||
pytestmark = [pytest.mark.usefixtures("mock_packages")]
|
||||
|
||||
@@ -54,7 +53,7 @@ def test_pipeline_dag(config, tmpdir):
|
||||
builder.add_package("pkg-a", dependencies=[("pkg-b", None, None), ("pkg-c", None, None)])
|
||||
|
||||
with repo.use_repositories(builder.root):
|
||||
spec_a = Spec("pkg-a").concretized()
|
||||
spec_a = spack.concretize.concretize_one("pkg-a")
|
||||
|
||||
key_a = ci.common.PipelineDag.key(spec_a)
|
||||
key_b = ci.common.PipelineDag.key(spec_a["pkg-b"])
|
||||
@@ -449,7 +448,7 @@ def test_ci_run_standalone_tests_not_installed_junit(
|
||||
log_file = tmp_path / "junit.xml"
|
||||
args = {
|
||||
"log_file": str(log_file),
|
||||
"job_spec": spack.spec.Spec("printing-package").concretized(),
|
||||
"job_spec": spack.concretize.concretize_one("printing-package"),
|
||||
"repro_dir": str(repro_dir),
|
||||
"fail_fast": True,
|
||||
}
|
||||
@@ -468,7 +467,7 @@ def test_ci_run_standalone_tests_not_installed_cdash(
|
||||
log_file = tmp_path / "junit.xml"
|
||||
args = {
|
||||
"log_file": str(log_file),
|
||||
"job_spec": spack.spec.Spec("printing-package").concretized(),
|
||||
"job_spec": spack.concretize.concretize_one("printing-package"),
|
||||
"repro_dir": str(repro_dir),
|
||||
}
|
||||
|
||||
@@ -501,7 +500,7 @@ def test_ci_run_standalone_tests_not_installed_cdash(
|
||||
def test_ci_skipped_report(tmpdir, mock_packages, config):
|
||||
"""Test explicit skipping of report as well as CI's 'package' arg."""
|
||||
pkg = "trivial-smoke-test"
|
||||
spec = spack.spec.Spec(pkg).concretized()
|
||||
spec = spack.concretize.concretize_one(pkg)
|
||||
ci_cdash = {
|
||||
"url": "file://fake",
|
||||
"build-group": "fake-group",
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
import spack.bootstrap
|
||||
import spack.bootstrap.core
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.environment as ev
|
||||
import spack.main
|
||||
@@ -183,7 +184,7 @@ def test_bootstrap_mirror_metadata(mutable_config, linux_os, monkeypatch, tmpdir
|
||||
"""
|
||||
old_create = spack.mirrors.utils.create
|
||||
monkeypatch.setattr(spack.mirrors.utils, "create", lambda p, s: old_create(p, []))
|
||||
monkeypatch.setattr(spack.spec.Spec, "concretized", lambda p: p)
|
||||
monkeypatch.setattr(spack.concretize, "concretize_one", lambda p: spack.spec.Spec(p))
|
||||
|
||||
# Create the mirror in a temporary folder
|
||||
compilers = [
|
||||
|
@@ -12,6 +12,7 @@
|
||||
|
||||
import spack.binary_distribution
|
||||
import spack.cmd.buildcache
|
||||
import spack.concretize
|
||||
import spack.environment as ev
|
||||
import spack.error
|
||||
import spack.main
|
||||
@@ -19,7 +20,6 @@
|
||||
import spack.spec
|
||||
import spack.util.url
|
||||
from spack.installer import PackageInstaller
|
||||
from spack.spec import Spec
|
||||
|
||||
buildcache = spack.main.SpackCommand("buildcache")
|
||||
install = spack.main.SpackCommand("install")
|
||||
@@ -81,7 +81,7 @@ def tests_buildcache_create(install_mockery, mock_fetch, monkeypatch, tmpdir):
|
||||
|
||||
buildcache("push", "--unsigned", str(tmpdir), pkg)
|
||||
|
||||
spec = Spec(pkg).concretized()
|
||||
spec = spack.concretize.concretize_one(pkg)
|
||||
tarball_path = spack.binary_distribution.tarball_path_name(spec, ".spack")
|
||||
tarball = spack.binary_distribution.tarball_name(spec, ".spec.json")
|
||||
assert os.path.exists(os.path.join(str(tmpdir), "build_cache", tarball_path))
|
||||
@@ -101,7 +101,7 @@ def tests_buildcache_create_env(
|
||||
|
||||
buildcache("push", "--unsigned", str(tmpdir))
|
||||
|
||||
spec = Spec(pkg).concretized()
|
||||
spec = spack.concretize.concretize_one(pkg)
|
||||
tarball_path = spack.binary_distribution.tarball_path_name(spec, ".spack")
|
||||
tarball = spack.binary_distribution.tarball_name(spec, ".spec.json")
|
||||
assert os.path.exists(os.path.join(str(tmpdir), "build_cache", tarball_path))
|
||||
@@ -145,7 +145,7 @@ def test_update_key_index(
|
||||
|
||||
gpg("create", "Test Signing Key", "nobody@nowhere.com")
|
||||
|
||||
s = Spec("libdwarf").concretized()
|
||||
s = spack.concretize.concretize_one("libdwarf")
|
||||
|
||||
# Install a package
|
||||
install(s.name)
|
||||
@@ -175,7 +175,7 @@ def test_buildcache_autopush(tmp_path, install_mockery, mock_fetch):
|
||||
mirror("add", "--unsigned", "mirror", mirror_dir.as_uri())
|
||||
mirror("add", "--autopush", "--unsigned", "mirror-autopush", mirror_autopush_dir.as_uri())
|
||||
|
||||
s = Spec("libdwarf").concretized()
|
||||
s = spack.concretize.concretize_one("libdwarf")
|
||||
|
||||
# Install and generate build cache index
|
||||
PackageInstaller([s.package], explicit=True).install()
|
||||
@@ -219,7 +219,7 @@ def verify_mirror_contents():
|
||||
assert False
|
||||
|
||||
# Install a package and put it in the buildcache
|
||||
s = Spec(out_env_pkg).concretized()
|
||||
s = spack.concretize.concretize_one(out_env_pkg)
|
||||
install(s.name)
|
||||
buildcache("push", "-u", "-f", src_mirror_url, s.name)
|
||||
|
||||
@@ -329,7 +329,7 @@ def test_buildcache_create_install(
|
||||
|
||||
buildcache("push", "--unsigned", str(tmpdir), pkg)
|
||||
|
||||
spec = Spec(pkg).concretized()
|
||||
spec = spack.concretize.concretize_one(pkg)
|
||||
tarball_path = spack.binary_distribution.tarball_path_name(spec, ".spack")
|
||||
tarball = spack.binary_distribution.tarball_name(spec, ".spec.json")
|
||||
assert os.path.exists(os.path.join(str(tmpdir), "build_cache", tarball_path))
|
||||
@@ -450,7 +450,7 @@ def test_push_and_install_with_mirror_marked_unsigned_does_not_require_extra_fla
|
||||
|
||||
|
||||
def test_skip_no_redistribute(mock_packages, config):
|
||||
specs = list(Spec("no-redistribute-dependent").concretized().traverse())
|
||||
specs = list(spack.concretize.concretize_one("no-redistribute-dependent").traverse())
|
||||
filtered = spack.cmd.buildcache._skip_no_redistribute_for_public(specs)
|
||||
assert not any(s.name == "no-redistribute" for s in filtered)
|
||||
assert any(s.name == "no-redistribute-dependent" for s in filtered)
|
||||
@@ -490,7 +490,7 @@ def test_push_without_build_deps(tmp_path, temporary_store, mock_packages, mutab
|
||||
|
||||
mirror("add", "--unsigned", "my-mirror", str(tmp_path))
|
||||
|
||||
s = spack.spec.Spec("dtrun3").concretized()
|
||||
s = spack.concretize.concretize_one("dtrun3")
|
||||
PackageInstaller([s.package], explicit=True, fake=True).install()
|
||||
s["dtbuild3"].package.do_uninstall()
|
||||
|
||||
|
@@ -7,10 +7,10 @@
|
||||
import pytest
|
||||
|
||||
import spack.cmd.checksum
|
||||
import spack.concretize
|
||||
import spack.error
|
||||
import spack.package_base
|
||||
import spack.repo
|
||||
import spack.spec
|
||||
import spack.stage
|
||||
import spack.util.web
|
||||
from spack.main import SpackCommand
|
||||
@@ -308,7 +308,7 @@ def test_checksum_url(mock_packages, config):
|
||||
|
||||
|
||||
def test_checksum_verification_fails(default_mock_concretization, capsys, can_fetch_versions):
|
||||
spec = spack.spec.Spec("zlib").concretized()
|
||||
spec = spack.concretize.concretize_one("zlib")
|
||||
pkg = spec.package
|
||||
versions = list(pkg.versions.keys())
|
||||
version_hashes = {versions[0]: "abadhash", Version("0.1"): "123456789"}
|
||||
|
@@ -18,6 +18,7 @@
|
||||
import spack.ci as ci
|
||||
import spack.cmd
|
||||
import spack.cmd.ci
|
||||
import spack.concretize
|
||||
import spack.environment as ev
|
||||
import spack.hash_types as ht
|
||||
import spack.main
|
||||
@@ -1056,7 +1057,7 @@ def test_ci_rebuild_index(
|
||||
with working_dir(tmp_path):
|
||||
env_cmd("create", "test", "./spack.yaml")
|
||||
with ev.read("test"):
|
||||
concrete_spec = Spec("callpath").concretized()
|
||||
concrete_spec = spack.concretize.concretize_one("callpath")
|
||||
with open(tmp_path / "spec.json", "w", encoding="utf-8") as f:
|
||||
f.write(concrete_spec.to_json(hash=ht.dag_hash))
|
||||
|
||||
@@ -1177,12 +1178,10 @@ def test_ci_generate_read_broken_specs_url(
|
||||
ci_base_environment,
|
||||
):
|
||||
"""Verify that `broken-specs-url` works as intended"""
|
||||
spec_a = Spec("pkg-a")
|
||||
spec_a.concretize()
|
||||
spec_a = spack.concretize.concretize_one("pkg-a")
|
||||
a_dag_hash = spec_a.dag_hash()
|
||||
|
||||
spec_flattendeps = Spec("flatten-deps")
|
||||
spec_flattendeps.concretize()
|
||||
spec_flattendeps = spack.concretize.concretize_one("flatten-deps")
|
||||
flattendeps_dag_hash = spec_flattendeps.dag_hash()
|
||||
|
||||
broken_specs_url = tmp_path.as_uri()
|
||||
@@ -1533,8 +1532,7 @@ def dynamic_mapping_setup(tmpdir):
|
||||
"""
|
||||
)
|
||||
|
||||
spec_a = Spec("pkg-a")
|
||||
spec_a.concretize()
|
||||
spec_a = spack.concretize.concretize_one("pkg-a")
|
||||
|
||||
return gitlab_generator.get_job_name(spec_a)
|
||||
|
||||
|
@@ -10,10 +10,8 @@
|
||||
|
||||
import spack.caches
|
||||
import spack.cmd.clean
|
||||
import spack.environment as ev
|
||||
import spack.main
|
||||
import spack.package_base
|
||||
import spack.spec
|
||||
import spack.stage
|
||||
import spack.store
|
||||
|
||||
@@ -69,20 +67,6 @@ def test_function_calls(command_line, effects, mock_calls_for_clean):
|
||||
assert mock_calls_for_clean[name] == (1 if name in effects else 0)
|
||||
|
||||
|
||||
def test_env_aware_clean(mock_stage, install_mockery, mutable_mock_env_path, monkeypatch):
|
||||
e = ev.create("test", with_view=False)
|
||||
e.add("mpileaks")
|
||||
e.concretize()
|
||||
|
||||
def fail(*args, **kwargs):
|
||||
raise Exception("This should not have been called")
|
||||
|
||||
monkeypatch.setattr(spack.spec.Spec, "concretize", fail)
|
||||
|
||||
with e:
|
||||
clean("mpileaks")
|
||||
|
||||
|
||||
def test_remove_python_cache(tmpdir, monkeypatch):
|
||||
cache_files = ["file1.pyo", "file2.pyc"]
|
||||
source_file = "file1.py"
|
||||
|
@@ -8,12 +8,12 @@
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.database
|
||||
import spack.environment as ev
|
||||
import spack.main
|
||||
import spack.schema.config
|
||||
import spack.spec
|
||||
import spack.store
|
||||
import spack.util.spack_yaml as syaml
|
||||
|
||||
@@ -593,8 +593,7 @@ def test_config_prefer_upstream(
|
||||
prepared_db = spack.database.Database(mock_db_root, layout=gen_mock_layout("/a/"))
|
||||
|
||||
for spec in ["hdf5 +mpi", "hdf5 ~mpi", "boost+debug~icu+graph", "dependency-install", "patch"]:
|
||||
dep = spack.spec.Spec(spec)
|
||||
dep.concretize()
|
||||
dep = spack.concretize.concretize_one(spec)
|
||||
prepared_db.add(dep)
|
||||
|
||||
downstream_db_root = str(tmpdir_factory.mktemp("mock_downstream_db_root"))
|
||||
|
@@ -4,6 +4,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.concretize
|
||||
import spack.spec
|
||||
import spack.store
|
||||
from spack.enums import InstallRecordStatus
|
||||
@@ -66,8 +67,8 @@ def test_deprecate_deps(mock_packages, mock_archive, mock_fetch, install_mockery
|
||||
install("libdwarf@20130729 ^libelf@0.8.13")
|
||||
install("libdwarf@20130207 ^libelf@0.8.10")
|
||||
|
||||
new_spec = spack.spec.Spec("libdwarf@20130729^libelf@0.8.13").concretized()
|
||||
old_spec = spack.spec.Spec("libdwarf@20130207^libelf@0.8.10").concretized()
|
||||
new_spec = spack.concretize.concretize_one("libdwarf@20130729^libelf@0.8.13")
|
||||
old_spec = spack.concretize.concretize_one("libdwarf@20130207^libelf@0.8.10")
|
||||
|
||||
all_installed = spack.store.STORE.db.query()
|
||||
|
||||
@@ -107,12 +108,12 @@ def test_deprecate_already_deprecated(mock_packages, mock_archive, mock_fetch, i
|
||||
install("libelf@0.8.12")
|
||||
install("libelf@0.8.10")
|
||||
|
||||
deprecated_spec = spack.spec.Spec("libelf@0.8.10").concretized()
|
||||
deprecated_spec = spack.concretize.concretize_one("libelf@0.8.10")
|
||||
|
||||
deprecate("-y", "libelf@0.8.10", "libelf@0.8.12")
|
||||
|
||||
deprecator = spack.store.STORE.db.deprecator(deprecated_spec)
|
||||
assert deprecator == spack.spec.Spec("libelf@0.8.12").concretized()
|
||||
assert deprecator == spack.concretize.concretize_one("libelf@0.8.12")
|
||||
|
||||
deprecate("-y", "libelf@0.8.10", "libelf@0.8.13")
|
||||
|
||||
@@ -122,7 +123,7 @@ def test_deprecate_already_deprecated(mock_packages, mock_archive, mock_fetch, i
|
||||
assert len(all_available) == 3
|
||||
|
||||
deprecator = spack.store.STORE.db.deprecator(deprecated_spec)
|
||||
assert deprecator == spack.spec.Spec("libelf@0.8.13").concretized()
|
||||
assert deprecator == spack.concretize.concretize_one("libelf@0.8.13")
|
||||
|
||||
|
||||
def test_deprecate_deprecator(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
@@ -132,9 +133,9 @@ def test_deprecate_deprecator(mock_packages, mock_archive, mock_fetch, install_m
|
||||
install("libelf@0.8.12")
|
||||
install("libelf@0.8.10")
|
||||
|
||||
first_deprecated_spec = spack.spec.Spec("libelf@0.8.10").concretized()
|
||||
second_deprecated_spec = spack.spec.Spec("libelf@0.8.12").concretized()
|
||||
final_deprecator = spack.spec.Spec("libelf@0.8.13").concretized()
|
||||
first_deprecated_spec = spack.concretize.concretize_one("libelf@0.8.10")
|
||||
second_deprecated_spec = spack.concretize.concretize_one("libelf@0.8.12")
|
||||
final_deprecator = spack.concretize.concretize_one("libelf@0.8.13")
|
||||
|
||||
deprecate("-y", "libelf@0.8.10", "libelf@0.8.12")
|
||||
|
||||
@@ -164,7 +165,7 @@ def test_concretize_deprecated(mock_packages, mock_archive, mock_fetch, install_
|
||||
|
||||
spec = spack.spec.Spec("libelf@0.8.10")
|
||||
with pytest.raises(spack.spec.SpecDeprecatedError):
|
||||
spec.concretize()
|
||||
spack.concretize.concretize_one(spec)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_packages", "mock_archive", "mock_fetch", "install_mockery")
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
|
||||
import spack.concretize
|
||||
import spack.environment as ev
|
||||
import spack.error
|
||||
import spack.repo
|
||||
@@ -23,7 +24,9 @@
|
||||
|
||||
|
||||
def test_dev_build_basics(tmpdir, install_mockery):
|
||||
spec = spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={tmpdir}").concretized()
|
||||
spec = spack.concretize.concretize_one(
|
||||
spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={tmpdir}")
|
||||
)
|
||||
|
||||
assert "dev_path" in spec.variants
|
||||
|
||||
@@ -41,7 +44,9 @@ def test_dev_build_basics(tmpdir, install_mockery):
|
||||
|
||||
|
||||
def test_dev_build_before(tmpdir, install_mockery):
|
||||
spec = spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={tmpdir}").concretized()
|
||||
spec = spack.concretize.concretize_one(
|
||||
spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={tmpdir}")
|
||||
)
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
with open(spec.package.filename, "w", encoding="utf-8") as f:
|
||||
@@ -57,7 +62,9 @@ def test_dev_build_before(tmpdir, install_mockery):
|
||||
|
||||
|
||||
def test_dev_build_until(tmpdir, install_mockery):
|
||||
spec = spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={tmpdir}").concretized()
|
||||
spec = spack.concretize.concretize_one(
|
||||
spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={tmpdir}")
|
||||
)
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
with open(spec.package.filename, "w", encoding="utf-8") as f:
|
||||
@@ -75,7 +82,9 @@ def test_dev_build_until(tmpdir, install_mockery):
|
||||
|
||||
def test_dev_build_until_last_phase(tmpdir, install_mockery):
|
||||
# Test that we ignore the last_phase argument if it is already last
|
||||
spec = spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={tmpdir}").concretized()
|
||||
spec = spack.concretize.concretize_one(
|
||||
spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={tmpdir}")
|
||||
)
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
with open(spec.package.filename, "w", encoding="utf-8") as f:
|
||||
@@ -93,7 +102,9 @@ def test_dev_build_until_last_phase(tmpdir, install_mockery):
|
||||
|
||||
|
||||
def test_dev_build_before_until(tmpdir, install_mockery):
|
||||
spec = spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={tmpdir}").concretized()
|
||||
spec = spack.concretize.concretize_one(
|
||||
spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={tmpdir}")
|
||||
)
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
with open(spec.package.filename, "w", encoding="utf-8") as f:
|
||||
@@ -129,8 +140,9 @@ def test_dev_build_drop_in(tmpdir, mock_packages, monkeypatch, install_mockery,
|
||||
|
||||
|
||||
def test_dev_build_fails_already_installed(tmpdir, install_mockery):
|
||||
spec = spack.spec.Spec("dev-build-test-install@0.0.0 dev_path=%s" % tmpdir)
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one(
|
||||
spack.spec.Spec("dev-build-test-install@0.0.0 dev_path=%s" % tmpdir)
|
||||
)
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
with open(spec.package.filename, "w", encoding="utf-8") as f:
|
||||
@@ -172,8 +184,9 @@ def test_dev_build_env(tmpdir, install_mockery, mutable_mock_env_path):
|
||||
"""Test Spack does dev builds for packages in develop section of env."""
|
||||
# setup dev-build-test-install package for dev build
|
||||
build_dir = tmpdir.mkdir("build")
|
||||
spec = spack.spec.Spec("dev-build-test-install@0.0.0 dev_path=%s" % build_dir)
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one(
|
||||
spack.spec.Spec("dev-build-test-install@0.0.0 dev_path=%s" % build_dir)
|
||||
)
|
||||
|
||||
with build_dir.as_cwd():
|
||||
with open(spec.package.filename, "w", encoding="utf-8") as f:
|
||||
@@ -208,8 +221,9 @@ def test_dev_build_env_with_vars(tmpdir, install_mockery, mutable_mock_env_path,
|
||||
"""Test Spack does dev builds for packages in develop section of env (path with variables)."""
|
||||
# setup dev-build-test-install package for dev build
|
||||
build_dir = tmpdir.mkdir("build")
|
||||
spec = spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={build_dir}")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one(
|
||||
spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={build_dir}")
|
||||
)
|
||||
|
||||
# store the build path in an environment variable that will be used in the environment
|
||||
monkeypatch.setenv("CUSTOM_BUILD_PATH", build_dir)
|
||||
@@ -246,8 +260,9 @@ def test_dev_build_env_version_mismatch(tmpdir, install_mockery, mutable_mock_en
|
||||
"""Test Spack constraints concretization by develop specs."""
|
||||
# setup dev-build-test-install package for dev build
|
||||
build_dir = tmpdir.mkdir("build")
|
||||
spec = spack.spec.Spec("dev-build-test-install@0.0.0 dev_path=%s" % tmpdir)
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one(
|
||||
spack.spec.Spec("dev-build-test-install@0.0.0 dev_path=%s" % tmpdir)
|
||||
)
|
||||
|
||||
with build_dir.as_cwd():
|
||||
with open(spec.package.filename, "w", encoding="utf-8") as f:
|
||||
@@ -327,8 +342,8 @@ def test_dev_build_multiple(tmpdir, install_mockery, mutable_mock_env_path, mock
|
||||
with ev.read("test"):
|
||||
# Do concretization inside environment for dev info
|
||||
# These specs are the source of truth to compare against the installs
|
||||
leaf_spec.concretize()
|
||||
root_spec.concretize()
|
||||
leaf_spec = spack.concretize.concretize_one(leaf_spec)
|
||||
root_spec = spack.concretize.concretize_one(root_spec)
|
||||
|
||||
# Do install
|
||||
install()
|
||||
@@ -374,8 +389,8 @@ def test_dev_build_env_dependency(tmpdir, install_mockery, mock_fetch, mutable_m
|
||||
# concretize in the environment to get the dev build info
|
||||
# equivalent to setting dev_build and dev_path variants
|
||||
# on all specs above
|
||||
spec.concretize()
|
||||
dep_spec.concretize()
|
||||
spec = spack.concretize.concretize_one(spec)
|
||||
dep_spec = spack.concretize.concretize_one(dep_spec)
|
||||
install()
|
||||
|
||||
# Ensure that both specs installed properly
|
||||
@@ -399,8 +414,9 @@ def test_dev_build_rebuild_on_source_changes(
|
||||
"""
|
||||
# setup dev-build-test-install package for dev build
|
||||
build_dir = tmpdir.mkdir("build")
|
||||
spec = spack.spec.Spec("dev-build-test-install@0.0.0 dev_path=%s" % build_dir)
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one(
|
||||
spack.spec.Spec("dev-build-test-install@0.0.0 dev_path=%s" % build_dir)
|
||||
)
|
||||
|
||||
def reset_string():
|
||||
with build_dir.as_cwd():
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.environment as ev
|
||||
import spack.package_base
|
||||
@@ -138,7 +139,8 @@ def check_path(stage, dest):
|
||||
self.check_develop(e, spack.spec.Spec("mpich@=1.0"), path)
|
||||
|
||||
# Check modifications actually worked
|
||||
assert spack.spec.Spec("mpich@1.0").concretized().satisfies("dev_path=%s" % abspath)
|
||||
result = spack.concretize.concretize_one("mpich@1.0")
|
||||
assert result.satisfies("dev_path=%s" % abspath)
|
||||
|
||||
def test_develop_canonicalize_path_no_args(self, monkeypatch):
|
||||
env("create", "test")
|
||||
@@ -165,7 +167,8 @@ def check_path(stage, dest):
|
||||
self.check_develop(e, spack.spec.Spec("mpich@=1.0"), path)
|
||||
|
||||
# Check modifications actually worked
|
||||
assert spack.spec.Spec("mpich@1.0").concretized().satisfies("dev_path=%s" % abspath)
|
||||
result = spack.concretize.concretize_one("mpich@1.0")
|
||||
assert result.satisfies("dev_path=%s" % abspath)
|
||||
|
||||
|
||||
def _git_commit_list(git_repo_dir):
|
||||
@@ -190,7 +193,7 @@ def test_develop_full_git_repo(
|
||||
spack.package_base.PackageBase, "git", "file://%s" % repo_path, raising=False
|
||||
)
|
||||
|
||||
spec = spack.spec.Spec("git-test-commit@1.2").concretized()
|
||||
spec = spack.concretize.concretize_one("git-test-commit@1.2")
|
||||
try:
|
||||
spec.package.do_stage()
|
||||
commits = _git_commit_list(spec.package.stage[0].source_path)
|
||||
|
@@ -5,9 +5,9 @@
|
||||
import pytest
|
||||
|
||||
import spack.cmd.diff
|
||||
import spack.concretize
|
||||
import spack.main
|
||||
import spack.repo
|
||||
import spack.spec
|
||||
import spack.util.spack_json as sjson
|
||||
from spack.test.conftest import create_test_repo
|
||||
|
||||
@@ -133,8 +133,8 @@ def test_repo(_create_test_repo, monkeypatch, mock_stage):
|
||||
|
||||
|
||||
def test_diff_ignore(test_repo):
|
||||
specA = spack.spec.Spec("p1+usev1").concretized()
|
||||
specB = spack.spec.Spec("p1~usev1").concretized()
|
||||
specA = spack.concretize.concretize_one("p1+usev1")
|
||||
specB = spack.concretize.concretize_one("p1~usev1")
|
||||
|
||||
c1 = spack.cmd.diff.compare_specs(specA, specB, to_string=False)
|
||||
|
||||
@@ -154,8 +154,8 @@ def find(function_list, name, args):
|
||||
|
||||
# Check ignoring changes on multiple packages
|
||||
|
||||
specA = spack.spec.Spec("p1+usev1 ^p3+p3var").concretized()
|
||||
specA = spack.spec.Spec("p1~usev1 ^p3~p3var").concretized()
|
||||
specA = spack.concretize.concretize_one("p1+usev1 ^p3+p3var")
|
||||
specA = spack.concretize.concretize_one("p1~usev1 ^p3~p3var")
|
||||
|
||||
c3 = spack.cmd.diff.compare_specs(specA, specB, to_string=False)
|
||||
assert find(c3["a_not_b"], "variant_value", ["p3", "p3var"])
|
||||
@@ -168,8 +168,8 @@ def find(function_list, name, args):
|
||||
def test_diff_cmd(install_mockery, mock_fetch, mock_archive, mock_packages):
|
||||
"""Test that we can install two packages and diff them"""
|
||||
|
||||
specA = spack.spec.Spec("mpileaks").concretized()
|
||||
specB = spack.spec.Spec("mpileaks+debug").concretized()
|
||||
specA = spack.concretize.concretize_one("mpileaks")
|
||||
specB = spack.concretize.concretize_one("mpileaks+debug")
|
||||
|
||||
# Specs should be the same as themselves
|
||||
c = spack.cmd.diff.compare_specs(specA, specA, to_string=True)
|
||||
|
@@ -19,6 +19,7 @@
|
||||
from llnl.util.symlink import readlink
|
||||
|
||||
import spack.cmd.env
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.environment as ev
|
||||
import spack.environment.depfile as depfile
|
||||
@@ -957,7 +958,7 @@ def test_lockfile_spliced_specs(environment_from_manifest, install_mockery):
|
||||
"""Test that an environment can round-trip a spliced spec."""
|
||||
# Create a local install for zmpi to splice in
|
||||
# Default concretization is not using zmpi
|
||||
zmpi = spack.spec.Spec("zmpi").concretized()
|
||||
zmpi = spack.concretize.concretize_one("zmpi")
|
||||
PackageInstaller([zmpi.package], fake=True).install()
|
||||
|
||||
e1 = environment_from_manifest(
|
||||
@@ -1320,39 +1321,43 @@ def test_config_change_existing(mutable_mock_env_path, tmp_path, mock_packages,
|
||||
with e:
|
||||
# List of requirements, flip a variant
|
||||
config("change", "packages:mpich:require:~debug")
|
||||
test_spec = spack.spec.Spec("mpich").concretized()
|
||||
test_spec = spack.concretize.concretize_one("mpich")
|
||||
assert test_spec.satisfies("@3.0.2~debug")
|
||||
|
||||
# List of requirements, change the version (in a different scope)
|
||||
config("change", "packages:mpich:require:@3.0.3")
|
||||
test_spec = spack.spec.Spec("mpich").concretized()
|
||||
test_spec = spack.concretize.concretize_one("mpich")
|
||||
assert test_spec.satisfies("@3.0.3")
|
||||
|
||||
# "require:" as a single string, also try specifying
|
||||
# a spec string that requires enclosing in quotes as
|
||||
# part of the config path
|
||||
config("change", 'packages:libelf:require:"@0.8.12:"')
|
||||
spack.spec.Spec("libelf@0.8.12").concretized()
|
||||
spack.concretize.concretize_one("libelf@0.8.12")
|
||||
# No need for assert, if there wasn't a failure, we
|
||||
# changed the requirement successfully.
|
||||
|
||||
# Use change to add a requirement for a package that
|
||||
# has no requirements defined
|
||||
config("change", "packages:fftw:require:+mpi")
|
||||
test_spec = spack.spec.Spec("fftw").concretized()
|
||||
test_spec = spack.concretize.concretize_one("fftw")
|
||||
assert test_spec.satisfies("+mpi")
|
||||
config("change", "packages:fftw:require:~mpi")
|
||||
test_spec = spack.spec.Spec("fftw").concretized()
|
||||
test_spec = spack.concretize.concretize_one("fftw")
|
||||
assert test_spec.satisfies("~mpi")
|
||||
config("change", "packages:fftw:require:@1.0")
|
||||
test_spec = spack.spec.Spec("fftw").concretized()
|
||||
test_spec = spack.concretize.concretize_one("fftw")
|
||||
assert test_spec.satisfies("@1.0~mpi")
|
||||
|
||||
# Use "--match-spec" to change one spec in a "one_of"
|
||||
# list
|
||||
config("change", "packages:bowtie:require:@1.2.2", "--match-spec", "@1.2.0")
|
||||
spack.spec.Spec("bowtie@1.3.0").concretize()
|
||||
spack.spec.Spec("bowtie@1.2.2").concretized()
|
||||
# confirm that we can concretize to either value
|
||||
spack.concretize.concretize_one("bowtie@1.3.0")
|
||||
spack.concretize.concretize_one("bowtie@1.2.2")
|
||||
# confirm that we cannot concretize to the old value
|
||||
with pytest.raises(spack.solver.asp.UnsatisfiableSpecError):
|
||||
spack.concretize.concretize_one("bowtie@1.2.0")
|
||||
|
||||
|
||||
def test_config_change_new(mutable_mock_env_path, tmp_path, mock_packages, mutable_config):
|
||||
@@ -1367,8 +1372,8 @@ def test_config_change_new(mutable_mock_env_path, tmp_path, mock_packages, mutab
|
||||
with ev.Environment(tmp_path):
|
||||
config("change", "packages:mpich:require:~debug")
|
||||
with pytest.raises(spack.solver.asp.UnsatisfiableSpecError):
|
||||
spack.spec.Spec("mpich+debug").concretized()
|
||||
spack.spec.Spec("mpich~debug").concretized()
|
||||
spack.concretize.concretize_one("mpich+debug")
|
||||
spack.concretize.concretize_one("mpich~debug")
|
||||
|
||||
# Now check that we raise an error if we need to add a require: constraint
|
||||
# when preexisting config manually specified it as a singular spec
|
||||
@@ -1382,7 +1387,7 @@ def test_config_change_new(mutable_mock_env_path, tmp_path, mock_packages, mutab
|
||||
"""
|
||||
)
|
||||
with ev.Environment(tmp_path):
|
||||
assert spack.spec.Spec("mpich").concretized().satisfies("@3.0.3")
|
||||
assert spack.concretize.concretize_one("mpich").satisfies("@3.0.3")
|
||||
with pytest.raises(spack.error.ConfigError, match="not a list"):
|
||||
config("change", "packages:mpich:require:~debug")
|
||||
|
||||
@@ -1690,7 +1695,7 @@ def test_stage(mock_stage, mock_fetch, install_mockery):
|
||||
root = str(mock_stage)
|
||||
|
||||
def check_stage(spec):
|
||||
spec = Spec(spec).concretized()
|
||||
spec = spack.concretize.concretize_one(spec)
|
||||
for dep in spec.traverse():
|
||||
stage_name = f"{stage_prefix}{dep.name}-{dep.version}-{dep.dag_hash()}"
|
||||
assert os.path.isdir(os.path.join(root, stage_name))
|
||||
@@ -1791,7 +1796,7 @@ def test_indirect_build_dep(tmp_path):
|
||||
|
||||
with spack.repo.use_repositories(builder.root):
|
||||
x_spec = Spec("x")
|
||||
x_concretized = x_spec.concretized()
|
||||
x_concretized = spack.concretize.concretize_one(x_spec)
|
||||
|
||||
_env_create("test", with_view=False)
|
||||
e = ev.read("test")
|
||||
@@ -1824,10 +1829,10 @@ def test_store_different_build_deps(tmp_path):
|
||||
|
||||
with spack.repo.use_repositories(builder.root):
|
||||
y_spec = Spec("y ^z@3")
|
||||
y_concretized = y_spec.concretized()
|
||||
y_concretized = spack.concretize.concretize_one(y_spec)
|
||||
|
||||
x_spec = Spec("x ^z@2")
|
||||
x_concretized = x_spec.concretized()
|
||||
x_concretized = spack.concretize.concretize_one(x_spec)
|
||||
|
||||
# Even though x chose a different 'z', the y it chooses should be identical
|
||||
# *aside* from the dependency on 'z'. The dag_hash() will show the difference
|
||||
@@ -2120,15 +2125,7 @@ def configure_reuse(reuse_mode, combined_env) -> Optional[ev.Environment]:
|
||||
"from_environment_raise",
|
||||
],
|
||||
)
|
||||
def test_env_include_concrete_reuse(monkeypatch, reuse_mode):
|
||||
|
||||
# The mock packages do not use the gcc-runtime
|
||||
def mock_has_runtime_dependencies(*args, **kwargs):
|
||||
return True
|
||||
|
||||
monkeypatch.setattr(
|
||||
spack.solver.asp, "_has_runtime_dependencies", mock_has_runtime_dependencies
|
||||
)
|
||||
def test_env_include_concrete_reuse(do_not_check_runtimes_on_reuse, reuse_mode):
|
||||
# The default mpi version is 3.x provided by mpich in the mock repo.
|
||||
# This test verifies that concretizing with an included concrete
|
||||
# environment with "concretizer:reuse:true" the included
|
||||
|
@@ -5,16 +5,18 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.concretize
|
||||
from spack.installer import PackageInstaller
|
||||
from spack.main import SpackCommand, SpackCommandError
|
||||
from spack.spec import Spec
|
||||
|
||||
extensions = SpackCommand("extensions")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def python_database(mock_packages, mutable_database):
|
||||
specs = [Spec(s).concretized() for s in ["python", "py-extension1", "py-extension2"]]
|
||||
specs = [
|
||||
spack.concretize.concretize_one(s) for s in ["python", "py-extension1", "py-extension2"]
|
||||
]
|
||||
PackageInstaller([s.package for s in specs], explicit=True, fake=True).install()
|
||||
yield
|
||||
|
||||
@@ -22,7 +24,7 @@ def python_database(mock_packages, mutable_database):
|
||||
@pytest.mark.not_on_windows("All Fetchers Failed")
|
||||
@pytest.mark.db
|
||||
def test_extensions(mock_packages, python_database, capsys):
|
||||
ext2 = Spec("py-extension2").concretized()
|
||||
ext2 = spack.concretize.concretize_one("py-extension2")
|
||||
|
||||
def check_output(ni):
|
||||
with capsys.disabled():
|
||||
|
@@ -12,13 +12,13 @@
|
||||
|
||||
import spack.cmd as cmd
|
||||
import spack.cmd.find
|
||||
import spack.concretize
|
||||
import spack.environment as ev
|
||||
import spack.repo
|
||||
import spack.store
|
||||
import spack.user_environment as uenv
|
||||
from spack.enums import InstallRecordStatus
|
||||
from spack.main import SpackCommand
|
||||
from spack.spec import Spec
|
||||
from spack.test.conftest import create_test_repo
|
||||
from spack.test.utilities import SpackCommandArgs
|
||||
from spack.util.pattern import Bunch
|
||||
@@ -201,7 +201,8 @@ def test_find_json_deps(database):
|
||||
@pytest.mark.db
|
||||
def test_display_json(database, capsys):
|
||||
specs = [
|
||||
Spec(s).concretized() for s in ["mpileaks ^zmpi", "mpileaks ^mpich", "mpileaks ^mpich2"]
|
||||
spack.concretize.concretize_one(s)
|
||||
for s in ["mpileaks ^zmpi", "mpileaks ^mpich", "mpileaks ^mpich2"]
|
||||
]
|
||||
|
||||
cmd.display_specs_as_json(specs)
|
||||
@@ -216,7 +217,8 @@ def test_display_json(database, capsys):
|
||||
@pytest.mark.db
|
||||
def test_display_json_deps(database, capsys):
|
||||
specs = [
|
||||
Spec(s).concretized() for s in ["mpileaks ^zmpi", "mpileaks ^mpich", "mpileaks ^mpich2"]
|
||||
spack.concretize.concretize_one(s)
|
||||
for s in ["mpileaks ^zmpi", "mpileaks ^mpich", "mpileaks ^mpich2"]
|
||||
]
|
||||
|
||||
cmd.display_specs_as_json(specs, deps=True)
|
||||
@@ -275,7 +277,7 @@ def test_find_format_deps(database, config):
|
||||
def test_find_format_deps_paths(database, config):
|
||||
output = find("-dp", "--format", "{name}-{version}", "mpileaks", "^zmpi")
|
||||
|
||||
spec = Spec("mpileaks ^zmpi").concretized()
|
||||
spec = spack.concretize.concretize_one("mpileaks ^zmpi")
|
||||
prefixes = [s.prefix for s in spec.traverse()]
|
||||
|
||||
assert (
|
||||
@@ -300,7 +302,8 @@ def test_find_very_long(database, config):
|
||||
output = find("-L", "--no-groups", "mpileaks")
|
||||
|
||||
specs = [
|
||||
Spec(s).concretized() for s in ["mpileaks ^zmpi", "mpileaks ^mpich", "mpileaks ^mpich2"]
|
||||
spack.concretize.concretize_one(s)
|
||||
for s in ["mpileaks ^zmpi", "mpileaks ^mpich", "mpileaks ^mpich2"]
|
||||
]
|
||||
|
||||
assert set(output.strip().split("\n")) == set(
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.concretize
|
||||
import spack.deptypes as dt
|
||||
import spack.environment as ev
|
||||
import spack.main
|
||||
@@ -25,8 +26,7 @@ def test_gc_without_build_dependency(mutable_database):
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_with_build_dependency(mutable_database):
|
||||
s = spack.spec.Spec("simple-inheritance")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("simple-inheritance")
|
||||
PackageInstaller([s.package], explicit=True, fake=True).install()
|
||||
|
||||
assert "There are no unused specs." in gc("-yb")
|
||||
@@ -36,8 +36,8 @@ def test_gc_with_build_dependency(mutable_database):
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_with_constraints(mutable_database):
|
||||
s_cmake1 = spack.spec.Spec("simple-inheritance ^cmake@3.4.3").concretized()
|
||||
s_cmake2 = spack.spec.Spec("simple-inheritance ^cmake@3.23.1").concretized()
|
||||
s_cmake1 = spack.concretize.concretize_one("simple-inheritance ^cmake@3.4.3")
|
||||
s_cmake2 = spack.concretize.concretize_one("simple-inheritance ^cmake@3.23.1")
|
||||
PackageInstaller([s_cmake1.package], explicit=True, fake=True).install()
|
||||
PackageInstaller([s_cmake2.package], explicit=True, fake=True).install()
|
||||
|
||||
@@ -52,8 +52,7 @@ def test_gc_with_constraints(mutable_database):
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_with_environment(mutable_database, mutable_mock_env_path):
|
||||
s = spack.spec.Spec("simple-inheritance")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("simple-inheritance")
|
||||
PackageInstaller([s.package], explicit=True, fake=True).install()
|
||||
|
||||
e = ev.create("test_gc")
|
||||
@@ -68,8 +67,7 @@ def test_gc_with_environment(mutable_database, mutable_mock_env_path):
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_with_build_dependency_in_environment(mutable_database, mutable_mock_env_path):
|
||||
s = spack.spec.Spec("simple-inheritance")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("simple-inheritance")
|
||||
PackageInstaller([s.package], explicit=True, fake=True).install()
|
||||
|
||||
e = ev.create("test_gc")
|
||||
@@ -120,8 +118,7 @@ def test_gc_except_any_environments(mutable_database, mutable_mock_env_path):
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_except_specific_environments(mutable_database, mutable_mock_env_path):
|
||||
s = spack.spec.Spec("simple-inheritance")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("simple-inheritance")
|
||||
PackageInstaller([s.package], explicit=True, fake=True).install()
|
||||
|
||||
assert mutable_database.query_local("zmpi")
|
||||
@@ -147,8 +144,7 @@ def test_gc_except_nonexisting_dir_env(mutable_database, mutable_mock_env_path,
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_except_specific_dir_env(mutable_database, mutable_mock_env_path, tmpdir):
|
||||
s = spack.spec.Spec("simple-inheritance")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("simple-inheritance")
|
||||
PackageInstaller([s.package], explicit=True, fake=True).install()
|
||||
|
||||
assert mutable_database.query_local("zmpi")
|
||||
|
@@ -19,6 +19,7 @@
|
||||
import spack.build_environment
|
||||
import spack.cmd.common.arguments
|
||||
import spack.cmd.install
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.environment as ev
|
||||
import spack.error
|
||||
@@ -134,7 +135,7 @@ def test_package_output(tmpdir, capsys, install_mockery, mock_fetch):
|
||||
# we can't use output capture here because it interferes with Spack's
|
||||
# logging. TODO: see whether we can get multiple log_outputs to work
|
||||
# when nested AND in pytest
|
||||
spec = Spec("printing-package").concretized()
|
||||
spec = spack.concretize.concretize_one("printing-package")
|
||||
pkg = spec.package
|
||||
PackageInstaller([pkg], explicit=True, verbose=True).install()
|
||||
|
||||
@@ -174,7 +175,7 @@ def test_install_output_on_python_error(mock_packages, mock_archive, mock_fetch,
|
||||
def test_install_with_source(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
"""Verify that source has been copied into place."""
|
||||
install("--source", "--keep-stage", "trivial-install-test-package")
|
||||
spec = Spec("trivial-install-test-package").concretized()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
src = os.path.join(spec.prefix.share, "trivial-install-test-package", "src")
|
||||
assert filecmp.cmp(
|
||||
os.path.join(mock_archive.path, "configure"), os.path.join(src, "configure")
|
||||
@@ -182,8 +183,7 @@ def test_install_with_source(mock_packages, mock_archive, mock_fetch, install_mo
|
||||
|
||||
|
||||
def test_install_env_variables(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
spec = Spec("libdwarf")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("libdwarf")
|
||||
install("libdwarf")
|
||||
assert os.path.isfile(spec.package.install_env_path)
|
||||
|
||||
@@ -204,8 +204,7 @@ def test_show_log_on_error(mock_packages, mock_archive, mock_fetch, install_mock
|
||||
|
||||
def test_install_overwrite(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
# Try to install a spec and then to reinstall it.
|
||||
spec = Spec("libdwarf")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("libdwarf")
|
||||
|
||||
install("libdwarf")
|
||||
|
||||
@@ -238,8 +237,7 @@ def test_install_overwrite(mock_packages, mock_archive, mock_fetch, install_mock
|
||||
|
||||
def test_install_overwrite_not_installed(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
# Try to install a spec and then to reinstall it.
|
||||
spec = Spec("libdwarf")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("libdwarf")
|
||||
|
||||
assert not os.path.exists(spec.prefix)
|
||||
|
||||
@@ -260,7 +258,7 @@ def test_install_commit(mock_git_version_info, install_mockery, mock_packages, m
|
||||
monkeypatch.setattr(spack.package_base.PackageBase, "git", file_url, raising=False)
|
||||
|
||||
# Use the earliest commit in the respository
|
||||
spec = Spec(f"git-test-commit@{commits[-1]}").concretized()
|
||||
spec = spack.concretize.concretize_one(f"git-test-commit@{commits[-1]}")
|
||||
PackageInstaller([spec.package], explicit=True).install()
|
||||
|
||||
# Ensure first commit file contents were written
|
||||
@@ -273,13 +271,11 @@ def test_install_commit(mock_git_version_info, install_mockery, mock_packages, m
|
||||
|
||||
def test_install_overwrite_multiple(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
# Try to install a spec and then to reinstall it.
|
||||
libdwarf = Spec("libdwarf")
|
||||
libdwarf.concretize()
|
||||
libdwarf = spack.concretize.concretize_one("libdwarf")
|
||||
|
||||
install("libdwarf")
|
||||
|
||||
cmake = Spec("cmake")
|
||||
cmake.concretize()
|
||||
cmake = spack.concretize.concretize_one("cmake")
|
||||
|
||||
install("cmake")
|
||||
|
||||
@@ -355,7 +351,7 @@ def test_install_invalid_spec():
|
||||
)
|
||||
def test_install_from_file(spec, concretize, error_code, tmpdir):
|
||||
if concretize:
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one(spec)
|
||||
|
||||
specfile = tmpdir.join("spec.yaml")
|
||||
|
||||
@@ -485,8 +481,7 @@ def test_install_mix_cli_and_files(clispecs, filespecs, tmpdir):
|
||||
for spec in filespecs:
|
||||
filepath = tmpdir.join(spec + ".yaml")
|
||||
args = ["-f", str(filepath)] + args
|
||||
s = Spec(spec)
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one(spec)
|
||||
with filepath.open("w") as f:
|
||||
s.to_yaml(f)
|
||||
|
||||
@@ -495,8 +490,7 @@ def test_install_mix_cli_and_files(clispecs, filespecs, tmpdir):
|
||||
|
||||
|
||||
def test_extra_files_are_archived(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
s = Spec("archive-files")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("archive-files")
|
||||
|
||||
install("archive-files")
|
||||
|
||||
@@ -615,8 +609,7 @@ def test_cdash_install_from_spec_json(
|
||||
with capfd.disabled(), tmpdir.as_cwd():
|
||||
spec_json_path = str(tmpdir.join("spec.json"))
|
||||
|
||||
pkg_spec = Spec("pkg-a")
|
||||
pkg_spec.concretize()
|
||||
pkg_spec = spack.concretize.concretize_one("pkg-a")
|
||||
|
||||
with open(spec_json_path, "w", encoding="utf-8") as fd:
|
||||
fd.write(pkg_spec.to_json(hash=ht.dag_hash))
|
||||
@@ -692,8 +685,8 @@ def test_cache_only_fails(tmpdir, mock_fetch, install_mockery, capfd):
|
||||
|
||||
|
||||
def test_install_only_dependencies(tmpdir, mock_fetch, install_mockery):
|
||||
dep = Spec("dependency-install").concretized()
|
||||
root = Spec("dependent-install").concretized()
|
||||
dep = spack.concretize.concretize_one("dependency-install")
|
||||
root = spack.concretize.concretize_one("dependent-install")
|
||||
|
||||
install("--only", "dependencies", "dependent-install")
|
||||
|
||||
@@ -714,8 +707,8 @@ def test_install_only_package(tmpdir, mock_fetch, install_mockery, capfd):
|
||||
|
||||
|
||||
def test_install_deps_then_package(tmpdir, mock_fetch, install_mockery):
|
||||
dep = Spec("dependency-install").concretized()
|
||||
root = Spec("dependent-install").concretized()
|
||||
dep = spack.concretize.concretize_one("dependency-install")
|
||||
root = spack.concretize.concretize_one("dependent-install")
|
||||
|
||||
install("--only", "dependencies", "dependent-install")
|
||||
assert os.path.exists(dep.prefix)
|
||||
@@ -733,8 +726,8 @@ def test_install_only_dependencies_in_env(
|
||||
env("create", "test")
|
||||
|
||||
with ev.read("test"):
|
||||
dep = Spec("dependency-install").concretized()
|
||||
root = Spec("dependent-install").concretized()
|
||||
dep = spack.concretize.concretize_one("dependency-install")
|
||||
root = spack.concretize.concretize_one("dependent-install")
|
||||
|
||||
install("-v", "--only", "dependencies", "--add", "dependent-install")
|
||||
|
||||
@@ -750,8 +743,8 @@ def test_install_only_dependencies_of_all_in_env(
|
||||
|
||||
with ev.read("test"):
|
||||
roots = [
|
||||
Spec("dependent-install@1.0").concretized(),
|
||||
Spec("dependent-install@2.0").concretized(),
|
||||
spack.concretize.concretize_one("dependent-install@1.0"),
|
||||
spack.concretize.concretize_one("dependent-install@2.0"),
|
||||
]
|
||||
|
||||
add("dependent-install@1.0")
|
||||
@@ -900,7 +893,7 @@ def test_cdash_configure_warning(tmpdir, mock_fetch, install_mockery, capfd):
|
||||
|
||||
# Ensure that even on non-x86_64 architectures, there are no
|
||||
# dependencies installed
|
||||
spec = Spec("configure-warning").concretized()
|
||||
spec = spack.concretize.concretize_one("configure-warning")
|
||||
spec.clear_dependencies()
|
||||
specfile = "./spec.json"
|
||||
with open(specfile, "w", encoding="utf-8") as f:
|
||||
@@ -946,7 +939,7 @@ def test_install_env_with_tests_all(
|
||||
):
|
||||
env("create", "test")
|
||||
with ev.read("test"):
|
||||
test_dep = Spec("test-dependency").concretized()
|
||||
test_dep = spack.concretize.concretize_one("test-dependency")
|
||||
add("depb")
|
||||
install("--test", "all")
|
||||
assert os.path.exists(test_dep.prefix)
|
||||
@@ -958,7 +951,7 @@ def test_install_env_with_tests_root(
|
||||
):
|
||||
env("create", "test")
|
||||
with ev.read("test"):
|
||||
test_dep = Spec("test-dependency").concretized()
|
||||
test_dep = spack.concretize.concretize_one("test-dependency")
|
||||
add("depb")
|
||||
install("--test", "root")
|
||||
assert not os.path.exists(test_dep.prefix)
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.spec
|
||||
import spack.concretize
|
||||
import spack.user_environment as uenv
|
||||
from spack.main import SpackCommand
|
||||
|
||||
@@ -49,7 +49,7 @@ def test_load_shell(shell, set_command):
|
||||
"""Test that `spack load` applies prefix inspections of its required runtime deps in
|
||||
topo-order"""
|
||||
install("mpileaks")
|
||||
mpileaks_spec = spack.spec.Spec("mpileaks").concretized()
|
||||
mpileaks_spec = spack.concretize.concretize_one("mpileaks")
|
||||
|
||||
# Ensure our reference variable is clean.
|
||||
os.environ["CMAKE_PREFIX_PATH"] = "/hello" + os.pathsep + "/world"
|
||||
@@ -166,7 +166,7 @@ def test_unload(
|
||||
"""Tests that any variables set in the user environment are undone by the
|
||||
unload command"""
|
||||
install("mpileaks")
|
||||
mpileaks_spec = spack.spec.Spec("mpileaks").concretized()
|
||||
mpileaks_spec = spack.concretize.concretize_one("mpileaks")
|
||||
|
||||
# Set so unload has something to do
|
||||
os.environ["FOOBAR"] = "mpileaks"
|
||||
@@ -187,7 +187,7 @@ def test_unload_fails_no_shell(
|
||||
):
|
||||
"""Test that spack unload prints an error message without a shell."""
|
||||
install("mpileaks")
|
||||
mpileaks_spec = spack.spec.Spec("mpileaks").concretized()
|
||||
mpileaks_spec = spack.concretize.concretize_one("mpileaks")
|
||||
os.environ[uenv.spack_loaded_hashes_var] = mpileaks_spec.dag_hash()
|
||||
|
||||
out = unload("mpileaks", fail_on_error=False)
|
||||
|
@@ -8,9 +8,9 @@
|
||||
|
||||
from llnl.util.filesystem import mkdirp
|
||||
|
||||
import spack.concretize
|
||||
import spack.environment as ev
|
||||
import spack.paths
|
||||
import spack.spec
|
||||
import spack.stage
|
||||
from spack.main import SpackCommand, SpackCommandError
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
@pytest.fixture
|
||||
def mock_spec():
|
||||
# Make it look like the source was actually expanded.
|
||||
s = spack.spec.Spec("externaltest").concretized()
|
||||
s = spack.concretize.concretize_one("externaltest")
|
||||
source_path = s.package.stage.source_path
|
||||
mkdirp(source_path)
|
||||
yield s, s.package
|
||||
|
@@ -13,6 +13,7 @@
|
||||
|
||||
import spack
|
||||
import spack.cmd.logs
|
||||
import spack.concretize
|
||||
import spack.main
|
||||
import spack.spec
|
||||
from spack.main import SpackCommand
|
||||
@@ -53,7 +54,7 @@ def disable_capture(capfd):
|
||||
|
||||
|
||||
def test_logs_cmd_errors(install_mockery, mock_fetch, mock_archive, mock_packages):
|
||||
spec = spack.spec.Spec("libelf").concretized()
|
||||
spec = spack.concretize.concretize_one("libelf")
|
||||
assert not spec.installed
|
||||
|
||||
with pytest.raises(spack.main.SpackCommandError, match="is not installed or staged"):
|
||||
@@ -82,7 +83,7 @@ def test_dump_logs(install_mockery, mock_fetch, mock_archive, mock_packages, dis
|
||||
decompress them.
|
||||
"""
|
||||
cmdline_spec = spack.spec.Spec("libelf")
|
||||
concrete_spec = cmdline_spec.concretized()
|
||||
concrete_spec = spack.concretize.concretize_one(cmdline_spec)
|
||||
|
||||
# Sanity check, make sure this test is checking what we want: to
|
||||
# start with
|
||||
|
@@ -7,6 +7,7 @@
|
||||
import pytest
|
||||
|
||||
import spack.cmd.mirror
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.environment as ev
|
||||
import spack.error
|
||||
@@ -60,7 +61,7 @@ def test_mirror_from_env(tmp_path, mock_packages, mock_fetch, mutable_mock_env_p
|
||||
|
||||
@pytest.fixture
|
||||
def source_for_pkg_with_hash(mock_packages, tmpdir):
|
||||
s = spack.spec.Spec("trivial-pkg-with-valid-hash").concretized()
|
||||
s = spack.concretize.concretize_one("trivial-pkg-with-valid-hash")
|
||||
local_url_basename = os.path.basename(s.package.url)
|
||||
local_path = os.path.join(str(tmpdir), local_url_basename)
|
||||
with open(local_path, "w", encoding="utf-8") as f:
|
||||
@@ -72,7 +73,9 @@ def source_for_pkg_with_hash(mock_packages, tmpdir):
|
||||
def test_mirror_skip_unstable(tmpdir_factory, mock_packages, config, source_for_pkg_with_hash):
|
||||
mirror_dir = str(tmpdir_factory.mktemp("mirror-dir"))
|
||||
|
||||
specs = [spack.spec.Spec(x).concretized() for x in ["git-test", "trivial-pkg-with-valid-hash"]]
|
||||
specs = [
|
||||
spack.concretize.concretize_one(x) for x in ["git-test", "trivial-pkg-with-valid-hash"]
|
||||
]
|
||||
spack.mirrors.utils.create(mirror_dir, specs, skip_unstable_versions=True)
|
||||
|
||||
assert set(os.listdir(mirror_dir)) - set(["_source-cache"]) == set(
|
||||
@@ -111,7 +114,7 @@ def test_exclude_specs(mock_packages, config):
|
||||
|
||||
mirror_specs, _ = spack.cmd.mirror._specs_and_action(args)
|
||||
expected_include = set(
|
||||
spack.spec.Spec(x).concretized() for x in ["mpich@3.0.3", "mpich@3.0.4", "mpich@3.0"]
|
||||
spack.concretize.concretize_one(x) for x in ["mpich@3.0.3", "mpich@3.0.4", "mpich@3.0"]
|
||||
)
|
||||
expected_exclude = set(spack.spec.Spec(x) for x in ["mpich@3.0.1", "mpich@3.0.2", "mpich@1.0"])
|
||||
assert expected_include <= set(mirror_specs)
|
||||
@@ -145,7 +148,7 @@ def test_exclude_file(mock_packages, tmpdir, config):
|
||||
|
||||
mirror_specs, _ = spack.cmd.mirror._specs_and_action(args)
|
||||
expected_include = set(
|
||||
spack.spec.Spec(x).concretized() for x in ["mpich@3.0.3", "mpich@3.0.4", "mpich@3.0"]
|
||||
spack.concretize.concretize_one(x) for x in ["mpich@3.0.3", "mpich@3.0.4", "mpich@3.0"]
|
||||
)
|
||||
expected_exclude = set(spack.spec.Spec(x) for x in ["mpich@3.0.1", "mpich@3.0.2", "mpich@1.0"])
|
||||
assert expected_include <= set(mirror_specs)
|
||||
|
@@ -7,12 +7,12 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.main
|
||||
import spack.modules
|
||||
import spack.modules.lmod
|
||||
import spack.repo
|
||||
import spack.spec
|
||||
import spack.store
|
||||
from spack.installer import PackageInstaller
|
||||
|
||||
@@ -33,7 +33,7 @@ def ensure_module_files_are_there(mock_repo_path, mock_store, mock_configuration
|
||||
|
||||
|
||||
def _module_files(module_type, *specs):
|
||||
specs = [spack.spec.Spec(x).concretized() for x in specs]
|
||||
specs = [spack.concretize.concretize_one(x) for x in specs]
|
||||
writer_cls = spack.modules.module_types[module_type]
|
||||
return [writer_cls(spec, "default").layout.filename for spec in specs]
|
||||
|
||||
@@ -184,12 +184,15 @@ def test_setdefault_command(mutable_database, mutable_config):
|
||||
# Install two different versions of pkg-a
|
||||
other_spec, preferred = "pkg-a@1.0", "pkg-a@2.0"
|
||||
|
||||
specs = [spack.spec.Spec(other_spec).concretized(), spack.spec.Spec(preferred).concretized()]
|
||||
specs = [
|
||||
spack.concretize.concretize_one(other_spec),
|
||||
spack.concretize.concretize_one(preferred),
|
||||
]
|
||||
PackageInstaller([s.package for s in specs], explicit=True, fake=True).install()
|
||||
|
||||
writers = {
|
||||
preferred: writer_cls(spack.spec.Spec(preferred).concretized(), "default"),
|
||||
other_spec: writer_cls(spack.spec.Spec(other_spec).concretized(), "default"),
|
||||
preferred: writer_cls(specs[1], "default"),
|
||||
other_spec: writer_cls(specs[0], "default"),
|
||||
}
|
||||
|
||||
# Create two module files for the same software
|
||||
|
@@ -2,9 +2,9 @@
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import spack.concretize
|
||||
import spack.main
|
||||
import spack.repo
|
||||
import spack.spec
|
||||
from spack.installer import PackageInstaller
|
||||
|
||||
tags = spack.main.SpackCommand("tags")
|
||||
@@ -47,7 +47,7 @@ class tag_path:
|
||||
|
||||
|
||||
def test_tags_installed(install_mockery, mock_fetch):
|
||||
s = spack.spec.Spec("mpich").concretized()
|
||||
s = spack.concretize.concretize_one("mpich")
|
||||
PackageInstaller([s.package], explicit=True, fake=True).install()
|
||||
|
||||
out = tags("-i")
|
||||
|
@@ -11,10 +11,10 @@
|
||||
|
||||
import spack.cmd.common.arguments
|
||||
import spack.cmd.test
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.install_test
|
||||
import spack.paths
|
||||
import spack.spec
|
||||
from spack.install_test import TestStatus
|
||||
from spack.main import SpackCommand
|
||||
|
||||
@@ -240,7 +240,7 @@ def test_read_old_results(mock_packages, mock_test_stage):
|
||||
|
||||
def test_test_results_none(mock_packages, mock_test_stage):
|
||||
name = "trivial"
|
||||
spec = spack.spec.Spec("trivial-smoke-test").concretized()
|
||||
spec = spack.concretize.concretize_one("trivial-smoke-test")
|
||||
suite = spack.install_test.TestSuite([spec], name)
|
||||
suite.ensure_stage()
|
||||
spack.install_test.write_test_suite_file(suite)
|
||||
@@ -255,7 +255,7 @@ def test_test_results_none(mock_packages, mock_test_stage):
|
||||
def test_test_results_status(mock_packages, mock_test_stage, status):
|
||||
"""Confirm 'spack test results' returns expected status."""
|
||||
name = "trivial"
|
||||
spec = spack.spec.Spec("trivial-smoke-test").concretized()
|
||||
spec = spack.concretize.concretize_one("trivial-smoke-test")
|
||||
suite = spack.install_test.TestSuite([spec], name)
|
||||
suite.ensure_stage()
|
||||
spack.install_test.write_test_suite_file(suite)
|
||||
@@ -278,7 +278,7 @@ def test_test_results_status(mock_packages, mock_test_stage, status):
|
||||
def test_report_filename_for_cdash(install_mockery, mock_fetch):
|
||||
"""Test that the temporary file used to write Testing.xml for CDash is not the upload URL"""
|
||||
name = "trivial"
|
||||
spec = spack.spec.Spec("trivial-smoke-test").concretized()
|
||||
spec = spack.concretize.concretize_one("trivial-smoke-test")
|
||||
suite = spack.install_test.TestSuite([spec], name)
|
||||
suite.ensure_stage()
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
# Copyright Spack Project Developers. See COPYRIGHT file for details.
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
import spack.concretize
|
||||
import spack.environment as ev
|
||||
import spack.spec
|
||||
from spack.main import SpackCommand
|
||||
|
||||
undevelop = SpackCommand("undevelop")
|
||||
@@ -30,9 +30,9 @@ def test_undevelop(tmpdir, mutable_config, mock_packages, mutable_mock_env_path)
|
||||
|
||||
env("create", "test", "./spack.yaml")
|
||||
with ev.read("test"):
|
||||
before = spack.spec.Spec("mpich").concretized()
|
||||
before = spack.concretize.concretize_one("mpich")
|
||||
undevelop("mpich")
|
||||
after = spack.spec.Spec("mpich").concretized()
|
||||
after = spack.concretize.concretize_one("mpich")
|
||||
|
||||
# Removing dev spec from environment changes concretization
|
||||
assert before.satisfies("dev_path=*")
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
|
||||
import spack.spec
|
||||
import spack.concretize
|
||||
import spack.store
|
||||
import spack.util.spack_json as sjson
|
||||
import spack.verify
|
||||
@@ -65,7 +65,7 @@ def test_single_file_verify_cmd(tmpdir):
|
||||
def test_single_spec_verify_cmd(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
# Test the verify command interface to verify a single spec
|
||||
install("libelf")
|
||||
s = spack.spec.Spec("libelf").concretized()
|
||||
s = spack.concretize.concretize_one("libelf")
|
||||
prefix = s.prefix
|
||||
hash = s.dag_hash()
|
||||
|
||||
|
@@ -9,10 +9,10 @@
|
||||
|
||||
from llnl.util.symlink import _windows_can_symlink
|
||||
|
||||
import spack.concretize
|
||||
import spack.util.spack_yaml as s_yaml
|
||||
from spack.installer import PackageInstaller
|
||||
from spack.main import SpackCommand
|
||||
from spack.spec import Spec
|
||||
|
||||
extensions = SpackCommand("extensions")
|
||||
install = SpackCommand("install")
|
||||
@@ -190,7 +190,7 @@ def test_view_fails_with_missing_projections_file(tmpdir):
|
||||
def test_view_files_not_ignored(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery, cmd, with_projection
|
||||
):
|
||||
spec = Spec("view-not-ignored").concretized()
|
||||
spec = spack.concretize.concretize_one("view-not-ignored")
|
||||
pkg = spec.package
|
||||
PackageInstaller([pkg], explicit=True).install()
|
||||
pkg.assert_installed(spec.prefix)
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
import archspec.cpu
|
||||
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.paths
|
||||
import spack.repo
|
||||
@@ -20,7 +21,7 @@
|
||||
|
||||
|
||||
def _concretize_with_reuse(*, root_str, reused_str):
|
||||
reused_spec = spack.spec.Spec(reused_str).concretized()
|
||||
reused_spec = spack.concretize.concretize_one(reused_str)
|
||||
setup = spack.solver.asp.SpackSolverSetup(tests=False)
|
||||
driver = spack.solver.asp.PyclingoDriver()
|
||||
result, _, _ = driver.solve(setup, [spack.spec.Spec(f"{root_str}")], reuse=[reused_spec])
|
||||
@@ -44,7 +45,7 @@ def enable_runtimes():
|
||||
|
||||
|
||||
def test_correct_gcc_runtime_is_injected_as_dependency(runtime_repo):
|
||||
s = spack.spec.Spec("pkg-a%gcc@10.2.1 ^pkg-b%gcc@9.4.0").concretized()
|
||||
s = spack.concretize.concretize_one("pkg-a%gcc@10.2.1 ^pkg-b%gcc@9.4.0")
|
||||
a, b = s["pkg-a"], s["pkg-b"]
|
||||
|
||||
# Both a and b should depend on the same gcc-runtime directly
|
||||
@@ -61,7 +62,7 @@ def test_external_nodes_do_not_have_runtimes(runtime_repo, mutable_config, tmp_p
|
||||
packages_yaml = {"pkg-b": {"externals": [{"spec": "pkg-b@1.0", "prefix": f"{str(tmp_path)}"}]}}
|
||||
spack.config.set("packages", packages_yaml)
|
||||
|
||||
s = spack.spec.Spec("pkg-a%gcc@10.2.1").concretized()
|
||||
s = spack.concretize.concretize_one("pkg-a%gcc@10.2.1")
|
||||
|
||||
a, b = s["pkg-a"], s["pkg-b"]
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -4,9 +4,9 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.solver.asp
|
||||
import spack.spec
|
||||
|
||||
version_error_messages = [
|
||||
"Cannot satisfy 'fftw@:1.0' and 'fftw@1.1:",
|
||||
@@ -57,7 +57,7 @@ def test_error_messages(error_messages, config_set, spec, mock_packages, mutable
|
||||
spack.config.set(path, conf)
|
||||
|
||||
with pytest.raises(spack.solver.asp.UnsatisfiableSpecError) as e:
|
||||
_ = spack.spec.Spec(spec).concretized()
|
||||
_ = spack.concretize.concretize_one(spec)
|
||||
|
||||
for em in error_messages:
|
||||
assert em in str(e.value)
|
||||
|
@@ -5,12 +5,13 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.environment as ev
|
||||
import spack.paths
|
||||
import spack.repo
|
||||
import spack.spec
|
||||
import spack.util.spack_yaml as syaml
|
||||
from spack.spec import Spec
|
||||
|
||||
"""
|
||||
These tests include the following package DAGs:
|
||||
@@ -62,12 +63,12 @@ def test_mix_spec_and_requirements(concretize_scope, test_repo):
|
||||
"""
|
||||
update_concretize_scope(conf_str, "packages")
|
||||
|
||||
s1 = Spec('y cflags="-a"').concretized()
|
||||
s1 = spack.concretize.concretize_one('y cflags="-a"')
|
||||
assert s1.satisfies('cflags="-a -c"')
|
||||
|
||||
|
||||
def test_mix_spec_and_dependent(concretize_scope, test_repo):
|
||||
s1 = Spec('x ^y cflags="-a"').concretized()
|
||||
s1 = spack.concretize.concretize_one('x ^y cflags="-a"')
|
||||
assert s1["y"].satisfies('cflags="-a -d1"')
|
||||
|
||||
|
||||
@@ -92,10 +93,22 @@ def test_mix_spec_and_compiler_cfg(concretize_scope, test_repo):
|
||||
conf_str = _compiler_cfg_one_entry_with_cflags("-Wall")
|
||||
update_concretize_scope(conf_str, "compilers")
|
||||
|
||||
s1 = Spec('y %gcc@12.100.100 cflags="-O2"').concretized()
|
||||
s1 = spack.concretize.concretize_one('y %gcc@12.100.100 cflags="-O2"')
|
||||
assert s1.satisfies('cflags="-Wall -O2"')
|
||||
|
||||
|
||||
def test_pkg_flags_from_compiler_and_none(concretize_scope, mock_packages):
|
||||
conf_str = _compiler_cfg_one_entry_with_cflags("-Wall")
|
||||
update_concretize_scope(conf_str, "compilers")
|
||||
|
||||
s1 = spack.spec.Spec("cmake%gcc@12.100.100")
|
||||
s2 = spack.spec.Spec("cmake-client^cmake%clang")
|
||||
concrete = dict(spack.concretize.concretize_together([(s1, None), (s2, None)]))
|
||||
|
||||
assert concrete[s1].compiler_flags["cflags"] == ["-Wall"]
|
||||
assert concrete[s2].compiler_flags["cflags"] == []
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"cmd_flags,req_flags,cmp_flags,dflags,expected_order",
|
||||
[
|
||||
@@ -147,7 +160,7 @@ def test_flag_order_and_grouping(
|
||||
if cmd_flags:
|
||||
spec_str += f' cflags="{cmd_flags}"'
|
||||
|
||||
root_spec = Spec(spec_str).concretized()
|
||||
root_spec = spack.concretize.concretize_one(spec_str)
|
||||
spec = root_spec["y"]
|
||||
satisfy_flags = " ".join(x for x in [cmd_flags, req_flags, cmp_flags, expected_dflags] if x)
|
||||
assert spec.satisfies(f'cflags="{satisfy_flags}"')
|
||||
@@ -155,11 +168,11 @@ def test_flag_order_and_grouping(
|
||||
|
||||
|
||||
def test_two_dependents_flag_mixing(concretize_scope, test_repo):
|
||||
root_spec1 = Spec("w~moveflaglater").concretized()
|
||||
root_spec1 = spack.concretize.concretize_one("w~moveflaglater")
|
||||
spec1 = root_spec1["y"]
|
||||
assert spec1.compiler_flags["cflags"] == "-d0 -d1 -d2".split()
|
||||
|
||||
root_spec2 = Spec("w+moveflaglater").concretized()
|
||||
root_spec2 = spack.concretize.concretize_one("w+moveflaglater")
|
||||
spec2 = root_spec2["y"]
|
||||
assert spec2.compiler_flags["cflags"] == "-d3 -d1 -d2".split()
|
||||
|
||||
@@ -168,7 +181,7 @@ def test_propagate_and_compiler_cfg(concretize_scope, test_repo):
|
||||
conf_str = _compiler_cfg_one_entry_with_cflags("-f2")
|
||||
update_concretize_scope(conf_str, "compilers")
|
||||
|
||||
root_spec = Spec("v %gcc@12.100.100 cflags=='-f1'").concretized()
|
||||
root_spec = spack.concretize.concretize_one("v %gcc@12.100.100 cflags=='-f1'")
|
||||
assert root_spec["y"].satisfies("cflags='-f1 -f2'")
|
||||
|
||||
|
||||
@@ -177,7 +190,7 @@ def test_propagate_and_compiler_cfg(concretize_scope, test_repo):
|
||||
|
||||
|
||||
def test_propagate_and_pkg_dep(concretize_scope, test_repo):
|
||||
root_spec1 = Spec("x ~activatemultiflag cflags=='-f1'").concretized()
|
||||
root_spec1 = spack.concretize.concretize_one("x ~activatemultiflag cflags=='-f1'")
|
||||
assert root_spec1["y"].satisfies("cflags='-f1 -d1'")
|
||||
|
||||
|
||||
@@ -189,7 +202,7 @@ def test_propagate_and_require(concretize_scope, test_repo):
|
||||
"""
|
||||
update_concretize_scope(conf_str, "packages")
|
||||
|
||||
root_spec1 = Spec("v cflags=='-f1'").concretized()
|
||||
root_spec1 = spack.concretize.concretize_one("v cflags=='-f1'")
|
||||
assert root_spec1["y"].satisfies("cflags='-f1 -f2'")
|
||||
|
||||
# Next, check that a requirement does not "undo" a request for
|
||||
@@ -201,7 +214,7 @@ def test_propagate_and_require(concretize_scope, test_repo):
|
||||
"""
|
||||
update_concretize_scope(conf_str, "packages")
|
||||
|
||||
root_spec2 = Spec("v cflags=='-f1'").concretized()
|
||||
root_spec2 = spack.concretize.concretize_one("v cflags=='-f1'")
|
||||
assert root_spec2["y"].satisfies("cflags='-f1'")
|
||||
|
||||
# Note: requirements cannot enforce propagation: any attempt to do
|
||||
@@ -245,7 +258,7 @@ def test_diamond_dep_flag_mixing(concretize_scope, test_repo):
|
||||
nodes of the diamond always appear in the same order).
|
||||
`Spec.traverse` is responsible for handling both of these needs.
|
||||
"""
|
||||
root_spec1 = Spec("t").concretized()
|
||||
root_spec1 = spack.concretize.concretize_one("t")
|
||||
spec1 = root_spec1["y"]
|
||||
assert spec1.satisfies('cflags="-c1 -c2 -d1 -d2 -e1 -e2"')
|
||||
assert spec1.compiler_flags["cflags"] == "-c1 -c2 -e1 -e2 -d1 -d2".split()
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.package_prefs
|
||||
import spack.repo
|
||||
@@ -46,7 +47,7 @@ def configure_permissions():
|
||||
|
||||
|
||||
def concretize(abstract_spec):
|
||||
return Spec(abstract_spec).concretized()
|
||||
return spack.concretize.concretize_one(abstract_spec)
|
||||
|
||||
|
||||
def update_packages(pkgname, section, value):
|
||||
@@ -111,7 +112,7 @@ def test_preferred_variants_from_wildcard(self):
|
||||
def test_preferred_compilers(self, compiler_str, spec_str):
|
||||
"""Test preferred compilers are applied correctly"""
|
||||
update_packages("all", "compiler", [compiler_str])
|
||||
spec = spack.spec.Spec(spec_str).concretized()
|
||||
spec = spack.concretize.concretize_one(spec_str)
|
||||
assert spec.compiler == CompilerSpec(compiler_str)
|
||||
|
||||
def test_preferred_target(self, mutable_mock_repo):
|
||||
@@ -213,15 +214,13 @@ def test_config_set_pkg_property_new(self, mock_repo_path):
|
||||
|
||||
def test_preferred(self):
|
||||
""" "Test packages with some version marked as preferred=True"""
|
||||
spec = Spec("python")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("python")
|
||||
assert spec.version == Version("2.7.11")
|
||||
|
||||
# now add packages.yaml with versions other than preferred
|
||||
# ensure that once config is in place, non-preferred version is used
|
||||
update_packages("python", "version", ["3.5.0"])
|
||||
spec = Spec("python")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("python")
|
||||
assert spec.version == Version("3.5.0")
|
||||
|
||||
def test_preferred_undefined_raises(self):
|
||||
@@ -229,7 +228,7 @@ def test_preferred_undefined_raises(self):
|
||||
update_packages("python", "version", ["3.5.0.1"])
|
||||
spec = Spec("python")
|
||||
with pytest.raises(ConfigError):
|
||||
spec.concretize()
|
||||
spack.concretize.concretize_one(spec)
|
||||
|
||||
def test_preferred_truncated(self):
|
||||
"""Versions without "=" are treated as version ranges: if there is
|
||||
@@ -237,35 +236,29 @@ def test_preferred_truncated(self):
|
||||
(don't define a new version).
|
||||
"""
|
||||
update_packages("python", "version", ["3.5"])
|
||||
spec = Spec("python")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("python")
|
||||
assert spec.satisfies("@3.5.1")
|
||||
|
||||
def test_develop(self):
|
||||
"""Test concretization with develop-like versions"""
|
||||
spec = Spec("develop-test")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("develop-test")
|
||||
assert spec.version == Version("0.2.15")
|
||||
spec = Spec("develop-test2")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("develop-test2")
|
||||
assert spec.version == Version("0.2.15")
|
||||
|
||||
# now add packages.yaml with develop-like versions
|
||||
# ensure that once config is in place, develop-like version is used
|
||||
update_packages("develop-test", "version", ["develop"])
|
||||
spec = Spec("develop-test")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("develop-test")
|
||||
assert spec.version == Version("develop")
|
||||
|
||||
update_packages("develop-test2", "version", ["0.2.15.develop"])
|
||||
spec = Spec("develop-test2")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("develop-test2")
|
||||
assert spec.version == Version("0.2.15.develop")
|
||||
|
||||
def test_external_mpi(self):
|
||||
# make sure this doesn't give us an external first.
|
||||
spec = Spec("mpi")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("mpi")
|
||||
assert not spec["mpi"].external
|
||||
|
||||
# load config
|
||||
@@ -284,8 +277,7 @@ def test_external_mpi(self):
|
||||
spack.config.set("packages", conf, scope="concretize")
|
||||
|
||||
# ensure that once config is in place, external is used
|
||||
spec = Spec("mpi")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("mpi")
|
||||
assert spec["mpich"].external_path == os.path.sep + os.path.join("dummy", "path")
|
||||
|
||||
def test_external_module(self, monkeypatch):
|
||||
@@ -300,8 +292,7 @@ def mock_module(cmd, module):
|
||||
|
||||
monkeypatch.setattr(spack.util.module_cmd, "module", mock_module)
|
||||
|
||||
spec = Spec("mpi")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("mpi")
|
||||
assert not spec["mpi"].external
|
||||
|
||||
# load config
|
||||
@@ -320,8 +311,7 @@ def mock_module(cmd, module):
|
||||
spack.config.set("packages", conf, scope="concretize")
|
||||
|
||||
# ensure that once config is in place, external is used
|
||||
spec = Spec("mpi")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("mpi")
|
||||
assert spec["mpich"].external_path == os.path.sep + os.path.join("dummy", "path")
|
||||
|
||||
def test_buildable_false(self):
|
||||
@@ -467,7 +457,7 @@ def test_variant_not_flipped_to_pull_externals(self):
|
||||
"""Test that a package doesn't prefer pulling in an
|
||||
external to using the default value of a variant.
|
||||
"""
|
||||
s = Spec("vdefault-or-external-root").concretized()
|
||||
s = spack.concretize.concretize_one("vdefault-or-external-root")
|
||||
|
||||
assert "~external" in s["vdefault-or-external"]
|
||||
assert "externaltool" not in s
|
||||
@@ -479,7 +469,7 @@ def test_dependencies_cant_make_version_parent_score_better(self):
|
||||
that makes the overall version score even or better and maybe
|
||||
has a better score in some lower priority criteria.
|
||||
"""
|
||||
s = Spec("version-test-root").concretized()
|
||||
s = spack.concretize.concretize_one("version-test-root")
|
||||
|
||||
assert s.satisfies("^version-test-pkg@2.4.6")
|
||||
assert "version-test-dependency-preferred" not in s
|
||||
@@ -497,13 +487,13 @@ def test_multivalued_variants_are_lower_priority_than_providers(self):
|
||||
with spack.config.override(
|
||||
"packages:all", {"providers": {"somevirtual": ["some-virtual-preferred"]}}
|
||||
):
|
||||
s = Spec("somevirtual").concretized()
|
||||
s = spack.concretize.concretize_one("somevirtual")
|
||||
assert s.name == "some-virtual-preferred"
|
||||
|
||||
@pytest.mark.regression("26721,19736")
|
||||
def test_sticky_variant_accounts_for_packages_yaml(self):
|
||||
with spack.config.override("packages:sticky-variant", {"variants": "+allow-gcc"}):
|
||||
s = Spec("sticky-variant %gcc").concretized()
|
||||
s = spack.concretize.concretize_one("sticky-variant %gcc")
|
||||
assert s.satisfies("%gcc") and s.satisfies("+allow-gcc")
|
||||
|
||||
@pytest.mark.regression("41134")
|
||||
@@ -512,5 +502,5 @@ def test_default_preference_variant_different_type_does_not_error(self):
|
||||
packages.yaml doesn't fail with an error.
|
||||
"""
|
||||
with spack.config.override("packages:all", {"variants": "+foo"}):
|
||||
s = Spec("pkg-a").concretized()
|
||||
s = spack.concretize.concretize_one("pkg-a")
|
||||
assert s.satisfies("foo=bar")
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.error
|
||||
import spack.package_base
|
||||
@@ -42,7 +43,7 @@ def test_one_package_multiple_reqs(concretize_scope, test_repo):
|
||||
- "~shared"
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
y_spec = Spec("y").concretized()
|
||||
y_spec = spack.concretize.concretize_one("y")
|
||||
assert y_spec.satisfies("@2.4~shared")
|
||||
|
||||
|
||||
@@ -57,7 +58,7 @@ def test_requirement_isnt_optional(concretize_scope, test_repo):
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
with pytest.raises(UnsatisfiableSpecError):
|
||||
Spec("x@1.1").concretize()
|
||||
spack.concretize.concretize_one("x@1.1")
|
||||
|
||||
|
||||
def test_require_undefined_version(concretize_scope, test_repo):
|
||||
@@ -74,7 +75,7 @@ def test_require_undefined_version(concretize_scope, test_repo):
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
with pytest.raises(spack.error.ConfigError):
|
||||
Spec("x").concretize()
|
||||
spack.concretize.concretize_one("x")
|
||||
|
||||
|
||||
def test_require_truncated(concretize_scope, test_repo):
|
||||
@@ -89,7 +90,7 @@ def test_require_truncated(concretize_scope, test_repo):
|
||||
require: "@1"
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
xspec = Spec("x").concretized()
|
||||
xspec = spack.concretize.concretize_one("x")
|
||||
assert xspec.satisfies("@1.1")
|
||||
|
||||
|
||||
@@ -159,7 +160,7 @@ def test_requirement_adds_new_version(
|
||||
)
|
||||
update_packages_config(conf_str)
|
||||
|
||||
s1 = Spec("v").concretized()
|
||||
s1 = spack.concretize.concretize_one("v")
|
||||
assert s1.satisfies("@2.2")
|
||||
# Make sure the git commit info is retained
|
||||
assert isinstance(s1.version, spack.version.GitVersion)
|
||||
@@ -180,7 +181,7 @@ def test_requirement_adds_version_satisfies(
|
||||
)
|
||||
|
||||
# Sanity check: early version of T does not include U
|
||||
s0 = Spec("t@2.0").concretized()
|
||||
s0 = spack.concretize.concretize_one("t@2.0")
|
||||
assert not ("u" in s0)
|
||||
|
||||
conf_str = """\
|
||||
@@ -192,7 +193,7 @@ def test_requirement_adds_version_satisfies(
|
||||
)
|
||||
update_packages_config(conf_str)
|
||||
|
||||
s1 = Spec("t").concretized()
|
||||
s1 = spack.concretize.concretize_one("t")
|
||||
assert "u" in s1
|
||||
assert s1.satisfies("@2.2")
|
||||
|
||||
@@ -218,7 +219,7 @@ def test_requirement_adds_git_hash_version(
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
s1 = Spec("v").concretized()
|
||||
s1 = spack.concretize.concretize_one("v")
|
||||
assert isinstance(s1.version, spack.version.GitVersion)
|
||||
assert s1.satisfies(f"v@{a_commit_hash}")
|
||||
|
||||
@@ -239,8 +240,8 @@ def test_requirement_adds_multiple_new_versions(
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
assert Spec("v").concretized().satisfies(f"@{commits[0]}=2.2")
|
||||
assert Spec("v@2.3").concretized().satisfies(f"v@{commits[1]}=2.3")
|
||||
assert spack.concretize.concretize_one("v").satisfies(f"@{commits[0]}=2.2")
|
||||
assert spack.concretize.concretize_one("v@2.3").satisfies(f"v@{commits[1]}=2.3")
|
||||
|
||||
|
||||
# TODO: this belongs in the concretize_preferences test module but uses
|
||||
@@ -263,11 +264,11 @@ def test_preference_adds_new_version(
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
assert Spec("v").concretized().satisfies(f"@{commits[0]}=2.2")
|
||||
assert Spec("v@2.3").concretized().satisfies(f"@{commits[1]}=2.3")
|
||||
assert spack.concretize.concretize_one("v").satisfies(f"@{commits[0]}=2.2")
|
||||
assert spack.concretize.concretize_one("v@2.3").satisfies(f"@{commits[1]}=2.3")
|
||||
|
||||
# When installing by hash, a lookup is triggered, so it's not mapped to =2.3.
|
||||
s3 = Spec(f"v@{commits[1]}").concretized()
|
||||
s3 = spack.concretize.concretize_one(f"v@{commits[1]}")
|
||||
assert s3.satisfies(f"v@{commits[1]}")
|
||||
assert not s3.satisfies("@2.3")
|
||||
|
||||
@@ -287,7 +288,7 @@ def test_external_adds_new_version_that_is_preferred(concretize_scope, test_repo
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
spec = Spec("x").concretized()
|
||||
spec = spack.concretize.concretize_one("x")
|
||||
assert spec["y"].satisfies("@2.7")
|
||||
assert spack.version.Version("2.7") not in spec["y"].package.versions
|
||||
|
||||
@@ -296,7 +297,7 @@ def test_requirement_is_successfully_applied(concretize_scope, test_repo):
|
||||
"""If a simple requirement can be satisfied, make sure the
|
||||
concretization succeeds and the requirement spec is applied.
|
||||
"""
|
||||
s1 = Spec("x").concretized()
|
||||
s1 = spack.concretize.concretize_one("x")
|
||||
# Without any requirements/preferences, the later version is preferred
|
||||
assert s1.satisfies("@1.1")
|
||||
|
||||
@@ -306,7 +307,7 @@ def test_requirement_is_successfully_applied(concretize_scope, test_repo):
|
||||
require: "@1.0"
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
s2 = Spec("x").concretized()
|
||||
s2 = spack.concretize.concretize_one("x")
|
||||
# The requirement forces choosing the eariler version
|
||||
assert s2.satisfies("@1.0")
|
||||
|
||||
@@ -323,7 +324,7 @@ def test_multiple_packages_requirements_are_respected(concretize_scope, test_rep
|
||||
require: "@2.4"
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
spec = Spec("x").concretized()
|
||||
spec = spack.concretize.concretize_one("x")
|
||||
assert spec["x"].satisfies("@1.0")
|
||||
assert spec["y"].satisfies("@2.4")
|
||||
|
||||
@@ -339,7 +340,7 @@ def test_oneof(concretize_scope, test_repo):
|
||||
- one_of: ["@2.4", "~shared"]
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
spec = Spec("x").concretized()
|
||||
spec = spack.concretize.concretize_one("x")
|
||||
# The concretizer only has to satisfy one of @2.4/~shared, and @2.4
|
||||
# comes first so it is prioritized
|
||||
assert spec["y"].satisfies("@2.4+shared")
|
||||
@@ -358,10 +359,10 @@ def test_one_package_multiple_oneof_groups(concretize_scope, test_repo):
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
s1 = Spec("y@2.5").concretized()
|
||||
s1 = spack.concretize.concretize_one("y@2.5")
|
||||
assert s1.satisfies("%clang~shared")
|
||||
|
||||
s2 = Spec("y@2.4").concretized()
|
||||
s2 = spack.concretize.concretize_one("y@2.4")
|
||||
assert s2.satisfies("%gcc+shared")
|
||||
|
||||
|
||||
@@ -377,10 +378,10 @@ def test_require_cflags(concretize_scope, mock_packages):
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
spec_mpich2 = Spec("mpich2").concretized()
|
||||
spec_mpich2 = spack.concretize.concretize_one("mpich2")
|
||||
assert spec_mpich2.satisfies("cflags=-g")
|
||||
|
||||
spec_mpi = Spec("mpi").concretized()
|
||||
spec_mpi = spack.concretize.concretize_one("mpi")
|
||||
assert spec_mpi.satisfies("mpich cflags=-O1")
|
||||
|
||||
|
||||
@@ -403,7 +404,7 @@ def test_requirements_for_package_that_is_not_needed(concretize_scope, test_repo
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
s1 = Spec("v").concretized()
|
||||
s1 = spack.concretize.concretize_one("v")
|
||||
assert s1.satisfies("@2.1")
|
||||
|
||||
|
||||
@@ -420,10 +421,10 @@ def test_oneof_ordering(concretize_scope, test_repo):
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
s1 = Spec("y").concretized()
|
||||
s1 = spack.concretize.concretize_one("y")
|
||||
assert s1.satisfies("@2.4")
|
||||
|
||||
s2 = Spec("y@2.5").concretized()
|
||||
s2 = spack.concretize.concretize_one("y@2.5")
|
||||
assert s2.satisfies("@2.5")
|
||||
|
||||
|
||||
@@ -437,14 +438,14 @@ def test_reuse_oneof(concretize_scope, test_repo, tmp_path, mock_fetch):
|
||||
|
||||
store_dir = tmp_path / "store"
|
||||
with spack.store.use_store(str(store_dir)):
|
||||
s1 = Spec("y@2.5 ~shared").concretized()
|
||||
s1 = spack.concretize.concretize_one("y@2.5~shared")
|
||||
PackageInstaller([s1.package], fake=True, explicit=True).install()
|
||||
|
||||
update_packages_config(conf_str)
|
||||
|
||||
with spack.config.override("concretizer:reuse", True):
|
||||
s2 = Spec("y").concretized()
|
||||
assert not s2.satisfies("@2.5 ~shared")
|
||||
s2 = spack.concretize.concretize_one("y")
|
||||
assert not s2.satisfies("@2.5~shared")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -472,7 +473,7 @@ def test_requirements_and_deprecated_versions(
|
||||
update_packages_config(conf_str)
|
||||
|
||||
with spack.config.override("config:deprecated", allow_deprecated):
|
||||
s1 = Spec("y").concretized()
|
||||
s1 = spack.concretize.concretize_one("y")
|
||||
for constrain in expected:
|
||||
assert s1.satisfies(constrain)
|
||||
|
||||
@@ -490,7 +491,7 @@ def test_default_requirements_with_all(spec_str, requirement_str, concretize_sco
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
spec = Spec(spec_str).concretized()
|
||||
spec = spack.concretize.concretize_one(spec_str)
|
||||
for s in spec.traverse():
|
||||
assert s.satisfies(requirement_str)
|
||||
|
||||
@@ -499,7 +500,7 @@ def test_default_requirements_with_all(spec_str, requirement_str, concretize_sco
|
||||
"requirements,expectations",
|
||||
[
|
||||
(("%gcc", "%clang"), ("%gcc", "%clang")),
|
||||
(("%gcc ~shared", "@1.0"), ("%gcc ~shared", "@1.0 +shared")),
|
||||
(("%gcc~shared", "@1.0"), ("%gcc~shared", "@1.0+shared")),
|
||||
],
|
||||
)
|
||||
def test_default_and_package_specific_requirements(
|
||||
@@ -517,7 +518,7 @@ def test_default_and_package_specific_requirements(
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
spec = Spec("x").concretized()
|
||||
spec = spack.concretize.concretize_one("x")
|
||||
assert spec.satisfies(specific_exp)
|
||||
for s in spec.traverse(root=False):
|
||||
assert s.satisfies(generic_exp)
|
||||
@@ -532,7 +533,7 @@ def test_requirements_on_virtual(mpi_requirement, concretize_scope, mock_package
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
spec = Spec("callpath").concretized()
|
||||
spec = spack.concretize.concretize_one("callpath")
|
||||
assert "mpi" in spec
|
||||
assert mpi_requirement in spec
|
||||
|
||||
@@ -553,7 +554,7 @@ def test_requirements_on_virtual_and_on_package(
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
spec = Spec("callpath").concretized()
|
||||
spec = spack.concretize.concretize_one("callpath")
|
||||
assert "mpi" in spec
|
||||
assert mpi_requirement in spec
|
||||
assert spec["mpi"].satisfies(specific_requirement)
|
||||
@@ -567,10 +568,10 @@ def test_incompatible_virtual_requirements_raise(concretize_scope, mock_packages
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
spec = Spec("callpath ^zmpi")
|
||||
spec = Spec("callpath^zmpi")
|
||||
# TODO (multiple nodes): recover a better error message later
|
||||
with pytest.raises((UnsatisfiableSpecError, InternalConcretizerError)):
|
||||
spec.concretize()
|
||||
spack.concretize.concretize_one(spec)
|
||||
|
||||
|
||||
def test_non_existing_variants_under_all(concretize_scope, mock_packages):
|
||||
@@ -582,7 +583,7 @@ def test_non_existing_variants_under_all(concretize_scope, mock_packages):
|
||||
"""
|
||||
update_packages_config(conf_str)
|
||||
|
||||
spec = Spec("callpath ^zmpi").concretized()
|
||||
spec = spack.concretize.concretize_one("callpath^zmpi")
|
||||
assert "~foo" not in spec
|
||||
|
||||
|
||||
@@ -657,7 +658,7 @@ def test_conditional_requirements_from_packages_yaml(
|
||||
and optional when the condition is not met.
|
||||
"""
|
||||
update_packages_config(packages_yaml)
|
||||
spec = Spec(spec_str).concretized()
|
||||
spec = spack.concretize.concretize_one(spec_str)
|
||||
for match_str, expected in expected_satisfies:
|
||||
assert spec.satisfies(match_str) is expected
|
||||
|
||||
@@ -733,7 +734,7 @@ def test_requirements_fail_with_custom_message(
|
||||
"""
|
||||
update_packages_config(packages_yaml)
|
||||
with pytest.raises(spack.error.SpackError, match=expected_message):
|
||||
Spec(spec_str).concretized()
|
||||
spack.concretize.concretize_one(spec_str)
|
||||
|
||||
|
||||
def test_skip_requirement_when_default_requirement_condition_cannot_be_met(
|
||||
@@ -752,9 +753,9 @@ def test_skip_requirement_when_default_requirement_condition_cannot_be_met(
|
||||
when: "+shared"
|
||||
"""
|
||||
update_packages_config(packages_yaml)
|
||||
s = Spec("mpileaks").concretized()
|
||||
s = spack.concretize.concretize_one("mpileaks")
|
||||
|
||||
assert s.satisfies("%clang +shared")
|
||||
assert s.satisfies("%clang+shared")
|
||||
# Sanity checks that 'callpath' doesn't have the shared variant, but that didn't
|
||||
# cause failures during concretization.
|
||||
assert "shared" not in s["callpath"].variants
|
||||
@@ -781,12 +782,12 @@ def test_requires_directive(concretize_scope, mock_packages):
|
||||
spack.config.CONFIG.clear_caches()
|
||||
|
||||
# This package requires either clang or gcc
|
||||
s = Spec("requires_clang_or_gcc").concretized()
|
||||
s = spack.concretize.concretize_one("requires_clang_or_gcc")
|
||||
assert s.satisfies("%gcc@12.0.0")
|
||||
|
||||
# This package can only be compiled with clang
|
||||
with pytest.raises(spack.error.SpackError, match="can only be compiled with Clang"):
|
||||
Spec("requires_clang").concretized()
|
||||
spack.concretize.concretize_one("requires_clang")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -839,20 +840,20 @@ def test_default_requirements_semantic(packages_yaml, concretize_scope, mock_pac
|
||||
"""
|
||||
update_packages_config(packages_yaml)
|
||||
|
||||
# Regular zlib concretize to +shared
|
||||
s = Spec("zlib").concretized()
|
||||
# Regular zlib concretize to+shared
|
||||
s = spack.concretize.concretize_one("zlib")
|
||||
assert s.satisfies("+shared")
|
||||
|
||||
# If we specify the variant we can concretize only the one matching the constraint
|
||||
s = Spec("zlib +shared").concretized()
|
||||
s = spack.concretize.concretize_one("zlib+shared")
|
||||
assert s.satisfies("+shared")
|
||||
with pytest.raises(UnsatisfiableSpecError):
|
||||
Spec("zlib ~shared").concretized()
|
||||
spack.concretize.concretize_one("zlib~shared")
|
||||
|
||||
# A spec without the shared variant still concretize
|
||||
s = Spec("pkg-a").concretized()
|
||||
assert not s.satisfies("pkg-a +shared")
|
||||
assert not s.satisfies("pkg-a ~shared")
|
||||
s = spack.concretize.concretize_one("pkg-a")
|
||||
assert not s.satisfies("pkg-a+shared")
|
||||
assert not s.satisfies("pkg-a~shared")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -896,7 +897,7 @@ def test_default_requirements_semantic(packages_yaml, concretize_scope, mock_pac
|
||||
"""
|
||||
packages:
|
||||
all:
|
||||
require: "libs=static +feefoo"
|
||||
require: "libs=static+feefoo"
|
||||
""",
|
||||
"multivalue-variant",
|
||||
["libs=shared"],
|
||||
@@ -911,7 +912,7 @@ def test_default_requirements_semantic_with_mv_variants(
|
||||
from MV variants.
|
||||
"""
|
||||
update_packages_config(packages_yaml)
|
||||
s = Spec(spec_str).concretized()
|
||||
s = spack.concretize.concretize_one(spec_str)
|
||||
|
||||
for constraint in expected:
|
||||
assert s.satisfies(constraint), constraint
|
||||
@@ -936,7 +937,7 @@ def test_requiring_package_on_multiple_virtuals(concretize_scope, mock_packages)
|
||||
require: intel-parallel-studio
|
||||
"""
|
||||
)
|
||||
s = Spec("dla-future").concretized()
|
||||
s = spack.concretize.concretize_one("dla-future")
|
||||
|
||||
assert s["blas"].name == "intel-parallel-studio"
|
||||
assert s["lapack"].name == "intel-parallel-studio"
|
||||
@@ -989,7 +990,7 @@ def test_strong_preferences_packages_yaml(
|
||||
):
|
||||
"""Tests that "preferred" specs are stronger than usual preferences, but can be overridden."""
|
||||
update_packages_config(packages_yaml)
|
||||
s = Spec(spec_str).concretized()
|
||||
s = spack.concretize.concretize_one(spec_str)
|
||||
|
||||
for constraint in expected:
|
||||
assert s.satisfies(constraint), constraint
|
||||
@@ -1038,29 +1039,29 @@ def test_conflict_packages_yaml(packages_yaml, spec_str, concretize_scope, mock_
|
||||
"""Tests conflicts that are specified from configuration files."""
|
||||
update_packages_config(packages_yaml)
|
||||
with pytest.raises(UnsatisfiableSpecError):
|
||||
Spec(spec_str).concretized()
|
||||
spack.concretize.concretize_one(spec_str)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"spec_str,expected,not_expected",
|
||||
[
|
||||
(
|
||||
"forward-multi-value +cuda cuda_arch=10 ^dependency-mv~cuda",
|
||||
"forward-multi-value+cuda cuda_arch=10^dependency-mv~cuda",
|
||||
["cuda_arch=10", "^dependency-mv~cuda"],
|
||||
["cuda_arch=11", "^dependency-mv cuda_arch=10", "^dependency-mv cuda_arch=11"],
|
||||
),
|
||||
(
|
||||
"forward-multi-value +cuda cuda_arch=10 ^dependency-mv+cuda",
|
||||
"forward-multi-value+cuda cuda_arch=10^dependency-mv+cuda",
|
||||
["cuda_arch=10", "^dependency-mv cuda_arch=10"],
|
||||
["cuda_arch=11", "^dependency-mv cuda_arch=11"],
|
||||
),
|
||||
(
|
||||
"forward-multi-value +cuda cuda_arch=11 ^dependency-mv+cuda",
|
||||
"forward-multi-value+cuda cuda_arch=11^dependency-mv+cuda",
|
||||
["cuda_arch=11", "^dependency-mv cuda_arch=11"],
|
||||
["cuda_arch=10", "^dependency-mv cuda_arch=10"],
|
||||
),
|
||||
(
|
||||
"forward-multi-value +cuda cuda_arch=10,11 ^dependency-mv+cuda",
|
||||
"forward-multi-value+cuda cuda_arch=10,11^dependency-mv+cuda",
|
||||
["cuda_arch=10,11", "^dependency-mv cuda_arch=10,11"],
|
||||
[],
|
||||
),
|
||||
@@ -1073,9 +1074,9 @@ def test_forward_multi_valued_variant_using_requires(
|
||||
`requires` directives of the form:
|
||||
|
||||
for _val in ("shared", "static"):
|
||||
requires(f"^some-virtual-mv libs={_val}", when=f"libs={_val} ^some-virtual-mv")
|
||||
requires(f"^some-virtual-mv libs={_val}", when=f"libs={_val}^some-virtual-mv")
|
||||
"""
|
||||
s = Spec(spec_str).concretized()
|
||||
s = spack.concretize.concretize_one(spec_str)
|
||||
|
||||
for constraint in expected:
|
||||
assert s.satisfies(constraint)
|
||||
@@ -1086,7 +1087,7 @@ def test_forward_multi_valued_variant_using_requires(
|
||||
|
||||
def test_strong_preferences_higher_priority_than_reuse(concretize_scope, mock_packages):
|
||||
"""Tests that strong preferences have a higher priority than reusing specs."""
|
||||
reused_spec = Spec("adios2~bzip2").concretized()
|
||||
reused_spec = spack.concretize.concretize_one("adios2~bzip2")
|
||||
reuse_nodes = list(reused_spec.traverse())
|
||||
root_specs = [Spec("ascent+adios2")]
|
||||
|
||||
@@ -1121,7 +1122,7 @@ def test_strong_preferences_higher_priority_than_reuse(concretize_scope, mock_pa
|
||||
solver = spack.solver.asp.Solver()
|
||||
setup = spack.solver.asp.SpackSolverSetup()
|
||||
result, _, _ = solver.driver.solve(
|
||||
setup, [Spec("ascent+adios2 ^adios2~bzip2")], reuse=reuse_nodes
|
||||
setup, [Spec("ascent+adios2^adios2~bzip2")], reuse=reuse_nodes
|
||||
)
|
||||
ascent = result.specs[0]
|
||||
assert ascent["adios2"].dag_hash() == reused_spec.dag_hash(), ascent
|
||||
|
@@ -4,7 +4,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.spec
|
||||
import spack.concretize
|
||||
import spack.store
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
def test_set_install_hash_length(hash_length, mutable_config, tmpdir):
|
||||
mutable_config.set("config:install_hash_length", hash_length)
|
||||
with spack.store.use_store(str(tmpdir)):
|
||||
spec = spack.spec.Spec("libelf").concretized()
|
||||
spec = spack.concretize.concretize_one("libelf")
|
||||
prefix = spec.prefix
|
||||
hash_str = prefix.rsplit("-")[-1]
|
||||
assert len(hash_str) == hash_length
|
||||
@@ -23,7 +23,7 @@ def test_set_install_hash_length(hash_length, mutable_config, tmpdir):
|
||||
def test_set_install_hash_length_upper_case(mutable_config, tmpdir):
|
||||
mutable_config.set("config:install_hash_length", 5)
|
||||
with spack.store.use_store(str(tmpdir), extra_data={"projections": {"all": "{name}-{HASH}"}}):
|
||||
spec = spack.spec.Spec("libelf").concretized()
|
||||
spec = spack.concretize.concretize_one("libelf")
|
||||
prefix = spec.prefix
|
||||
hash_str = prefix.rsplit("-")[-1]
|
||||
assert len(hash_str) == 5
|
||||
|
@@ -36,6 +36,7 @@
|
||||
import spack.caches
|
||||
import spack.compiler
|
||||
import spack.compilers
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.directives_meta
|
||||
import spack.environment as ev
|
||||
@@ -635,11 +636,6 @@ def ensure_debug(monkeypatch):
|
||||
tty.set_debug(current_debug_level)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=sys.platform == "win32", scope="session")
|
||||
def platform_config():
|
||||
spack.config.add_default_platform_scope(spack.platforms.real_host().name)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def default_config():
|
||||
"""Isolates the default configuration from the user configs.
|
||||
@@ -854,7 +850,7 @@ def _populate(mock_db):
|
||||
"""
|
||||
|
||||
def _install(spec):
|
||||
s = spack.spec.Spec(spec).concretized()
|
||||
s = spack.concretize.concretize_one(spec)
|
||||
PackageInstaller([s.package], fake=True, explicit=True).install()
|
||||
|
||||
_install("mpileaks ^mpich")
|
||||
@@ -892,21 +888,26 @@ def mock_store(
|
||||
"""
|
||||
store_path, store_cache = _store_dir_and_cache
|
||||
|
||||
# Make the DB filesystem read-only to ensure constructors don't modify anything in it.
|
||||
# We want Spack to be able to point to a DB on a read-only filesystem easily.
|
||||
store_path.chmod(mode=0o555, rec=1)
|
||||
|
||||
# If the cache does not exist populate the store and create it
|
||||
if not os.path.exists(str(store_cache.join(".spack-db"))):
|
||||
with spack.config.use_configuration(*mock_configuration_scopes):
|
||||
with spack.store.use_store(str(store_path)) as store:
|
||||
with spack.repo.use_repositories(mock_repo_path):
|
||||
# make the DB filesystem writable only while we populate it
|
||||
store_path.chmod(mode=0o755, rec=1)
|
||||
_populate(store.db)
|
||||
copy_tree(str(store_path), str(store_cache))
|
||||
store_path.chmod(mode=0o555, rec=1)
|
||||
|
||||
# Make the DB filesystem read-only to ensure we can't modify entries
|
||||
store_path.join(".spack-db").chmod(mode=0o555, rec=1)
|
||||
store_cache.chmod(mode=0o755, rec=1)
|
||||
copy_tree(str(store_path), str(store_cache))
|
||||
store_cache.chmod(mode=0o555, rec=1)
|
||||
|
||||
yield store_path
|
||||
|
||||
store_path.join(".spack-db").chmod(mode=0o755, rec=1)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def database(mock_store, mock_packages, config):
|
||||
@@ -932,7 +933,7 @@ def mutable_database(database_mutable_config, _store_dir_and_cache):
|
||||
"""
|
||||
# Make the database writeable, as we are going to modify it
|
||||
store_path, store_cache = _store_dir_and_cache
|
||||
store_path.join(".spack-db").chmod(mode=0o755, rec=1)
|
||||
store_path.chmod(mode=0o755, rec=1)
|
||||
|
||||
yield database_mutable_config
|
||||
|
||||
@@ -940,7 +941,7 @@ def mutable_database(database_mutable_config, _store_dir_and_cache):
|
||||
# the store and making the database read-only
|
||||
store_path.remove(rec=1)
|
||||
copy_tree(str(store_cache), str(store_path))
|
||||
store_path.join(".spack-db").chmod(mode=0o555, rec=1)
|
||||
store_path.chmod(mode=0o555, rec=1)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@@ -1044,7 +1045,8 @@ def temporary_store(tmpdir, request):
|
||||
temporary_store_path = tmpdir.join("opt")
|
||||
with spack.store.use_store(str(temporary_store_path)) as s:
|
||||
yield s
|
||||
temporary_store_path.remove()
|
||||
if temporary_store_path.exists():
|
||||
temporary_store_path.remove()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@@ -1982,7 +1984,9 @@ def default_mock_concretization(config, mock_packages, concretized_specs_cache):
|
||||
def _func(spec_str, tests=False):
|
||||
key = spec_str, tests
|
||||
if key not in concretized_specs_cache:
|
||||
concretized_specs_cache[key] = spack.spec.Spec(spec_str).concretized(tests=tests)
|
||||
concretized_specs_cache[key] = spack.concretize.concretize_one(
|
||||
spack.spec.Spec(spec_str), tests=tests
|
||||
)
|
||||
return concretized_specs_cache[key].copy()
|
||||
|
||||
return _func
|
||||
|
@@ -8,8 +8,8 @@
|
||||
|
||||
from llnl.util.filesystem import mkdirp, touch, working_dir
|
||||
|
||||
import spack.concretize
|
||||
from spack.fetch_strategy import CvsFetchStrategy
|
||||
from spack.spec import Spec
|
||||
from spack.stage import Stage
|
||||
from spack.util.executable import which
|
||||
from spack.version import Version
|
||||
@@ -37,7 +37,7 @@ def test_fetch(type_of_test, mock_cvs_repository, config, mutable_mock_repo):
|
||||
get_date = mock_cvs_repository.get_date
|
||||
|
||||
# Construct the package under test
|
||||
spec = Spec("cvs-test").concretized()
|
||||
spec = spack.concretize.concretize_one("cvs-test")
|
||||
spec.package.versions[Version("cvs")] = test.args
|
||||
|
||||
# Enter the stage directory and check some properties
|
||||
|
@@ -2,10 +2,12 @@
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
"""Check the database is functioning properly, both in memory and in its file."""
|
||||
import contextlib
|
||||
import datetime
|
||||
import functools
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
@@ -26,12 +28,14 @@
|
||||
import llnl.util.lock as lk
|
||||
from llnl.util.tty.colify import colify
|
||||
|
||||
import spack.concretize
|
||||
import spack.database
|
||||
import spack.deptypes as dt
|
||||
import spack.package_base
|
||||
import spack.repo
|
||||
import spack.spec
|
||||
import spack.store
|
||||
import spack.util.lock
|
||||
import spack.version as vn
|
||||
from spack.enums import InstallRecordStatus
|
||||
from spack.installer import PackageInstaller
|
||||
@@ -41,24 +45,51 @@
|
||||
pytestmark = pytest.mark.db
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def writable(database):
|
||||
"""Allow a database to be written inside this context manager."""
|
||||
old_lock, old_is_upstream = database.lock, database.is_upstream
|
||||
db_root = pathlib.Path(database.root)
|
||||
|
||||
try:
|
||||
# this is safe on all platforms during tests (tests get their own tmpdirs)
|
||||
database.lock = spack.util.lock.Lock(str(database._lock_path), enable=False)
|
||||
database.is_upstream = False
|
||||
db_root.chmod(mode=0o755)
|
||||
with database.write_transaction():
|
||||
yield
|
||||
finally:
|
||||
db_root.chmod(mode=0o555)
|
||||
database.lock = old_lock
|
||||
database.is_upstream = old_is_upstream
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def upstream_and_downstream_db(tmpdir, gen_mock_layout):
|
||||
mock_db_root = str(tmpdir.mkdir("mock_db_root"))
|
||||
upstream_layout = gen_mock_layout("/a/")
|
||||
upstream_write_db = spack.database.Database(mock_db_root, layout=upstream_layout)
|
||||
upstream_db = spack.database.Database(mock_db_root, is_upstream=True, layout=upstream_layout)
|
||||
# Generate initial DB file to avoid reindex
|
||||
with open(upstream_write_db._index_path, "w", encoding="utf-8") as db_file:
|
||||
upstream_write_db._write_to_file(db_file)
|
||||
"""Fixture for a pair of stores: upstream and downstream.
|
||||
|
||||
downstream_db_root = str(tmpdir.mkdir("mock_downstream_db_root"))
|
||||
downstream_db = spack.database.Database(
|
||||
downstream_db_root, upstream_dbs=[upstream_db], layout=gen_mock_layout("/b/")
|
||||
Upstream API prohibits writing to an upstream, so we also return a writable version
|
||||
of the upstream DB for tests to use.
|
||||
|
||||
"""
|
||||
mock_db_root = tmpdir.mkdir("mock_db_root")
|
||||
mock_db_root.chmod(0o555)
|
||||
|
||||
upstream_db = spack.database.Database(
|
||||
str(mock_db_root), is_upstream=True, layout=gen_mock_layout("/a/")
|
||||
)
|
||||
with open(downstream_db._index_path, "w", encoding="utf-8") as db_file:
|
||||
downstream_db._write_to_file(db_file)
|
||||
with writable(upstream_db):
|
||||
upstream_db._write()
|
||||
|
||||
yield upstream_write_db, upstream_db, downstream_db
|
||||
downstream_db_root = tmpdir.mkdir("mock_downstream_db_root")
|
||||
downstream_db_root.chmod(0o755)
|
||||
|
||||
downstream_db = spack.database.Database(
|
||||
str(downstream_db_root), upstream_dbs=[upstream_db], layout=gen_mock_layout("/b/")
|
||||
)
|
||||
downstream_db._write()
|
||||
|
||||
yield upstream_db, downstream_db
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -70,16 +101,18 @@ def upstream_and_downstream_db(tmpdir, gen_mock_layout):
|
||||
("{u}", ["pkg-c"]),
|
||||
("{d}", ["pkg-b"]),
|
||||
],
|
||||
ids=["all", "upstream", "local", "upstream_path", "downstream_path"],
|
||||
)
|
||||
def test_query_by_install_tree(
|
||||
install_tree, result, upstream_and_downstream_db, mock_packages, monkeypatch, config
|
||||
):
|
||||
up_write_db, up_db, down_db = upstream_and_downstream_db
|
||||
up_db, down_db = upstream_and_downstream_db
|
||||
|
||||
# Set the upstream DB to contain "pkg-c" and downstream to contain "pkg-b")
|
||||
b = spack.spec.Spec("pkg-b").concretized()
|
||||
c = spack.spec.Spec("pkg-c").concretized()
|
||||
up_write_db.add(c)
|
||||
b = spack.concretize.concretize_one("pkg-b")
|
||||
c = spack.concretize.concretize_one("pkg-c")
|
||||
with writable(up_db):
|
||||
up_db.add(c)
|
||||
up_db._read()
|
||||
down_db.add(b)
|
||||
|
||||
@@ -91,15 +124,16 @@ def test_spec_installed_upstream(
|
||||
upstream_and_downstream_db, mock_custom_repository, config, monkeypatch
|
||||
):
|
||||
"""Test whether Spec.installed_upstream() works."""
|
||||
upstream_write_db, upstream_db, downstream_db = upstream_and_downstream_db
|
||||
upstream_db, downstream_db = upstream_and_downstream_db
|
||||
|
||||
# a known installed spec should say that it's installed
|
||||
with spack.repo.use_repositories(mock_custom_repository):
|
||||
spec = spack.spec.Spec("pkg-c").concretized()
|
||||
spec = spack.concretize.concretize_one("pkg-c")
|
||||
assert not spec.installed
|
||||
assert not spec.installed_upstream
|
||||
|
||||
upstream_write_db.add(spec)
|
||||
with writable(upstream_db):
|
||||
upstream_db.add(spec)
|
||||
upstream_db._read()
|
||||
|
||||
monkeypatch.setattr(spack.store.STORE, "db", downstream_db)
|
||||
@@ -115,7 +149,7 @@ def test_spec_installed_upstream(
|
||||
|
||||
@pytest.mark.usefixtures("config")
|
||||
def test_installed_upstream(upstream_and_downstream_db, tmpdir):
|
||||
upstream_write_db, upstream_db, downstream_db = upstream_and_downstream_db
|
||||
upstream_db, downstream_db = upstream_and_downstream_db
|
||||
|
||||
builder = spack.repo.MockRepositoryBuilder(tmpdir.mkdir("mock.repo"))
|
||||
builder.add_package("x")
|
||||
@@ -124,9 +158,10 @@ def test_installed_upstream(upstream_and_downstream_db, tmpdir):
|
||||
builder.add_package("w", dependencies=[("x", None, None), ("y", None, None)])
|
||||
|
||||
with spack.repo.use_repositories(builder.root):
|
||||
spec = spack.spec.Spec("w").concretized()
|
||||
for dep in spec.traverse(root=False):
|
||||
upstream_write_db.add(dep)
|
||||
spec = spack.concretize.concretize_one("w")
|
||||
with writable(upstream_db):
|
||||
for dep in spec.traverse(root=False):
|
||||
upstream_db.add(dep)
|
||||
upstream_db._read()
|
||||
|
||||
for dep in spec.traverse(root=False):
|
||||
@@ -135,7 +170,7 @@ def test_installed_upstream(upstream_and_downstream_db, tmpdir):
|
||||
with pytest.raises(spack.database.ForbiddenLockError):
|
||||
upstream_db.get_by_hash(dep.dag_hash())
|
||||
|
||||
new_spec = spack.spec.Spec("w").concretized()
|
||||
new_spec = spack.concretize.concretize_one("w")
|
||||
downstream_db.add(new_spec)
|
||||
for dep in new_spec.traverse(root=False):
|
||||
upstream, record = downstream_db.query_by_spec_hash(dep.dag_hash())
|
||||
@@ -150,23 +185,25 @@ def test_installed_upstream(upstream_and_downstream_db, tmpdir):
|
||||
|
||||
|
||||
def test_removed_upstream_dep(upstream_and_downstream_db, tmpdir, capsys, config):
|
||||
upstream_write_db, upstream_db, downstream_db = upstream_and_downstream_db
|
||||
upstream_db, downstream_db = upstream_and_downstream_db
|
||||
|
||||
builder = spack.repo.MockRepositoryBuilder(tmpdir.mkdir("mock.repo"))
|
||||
builder.add_package("z")
|
||||
builder.add_package("y", dependencies=[("z", None, None)])
|
||||
|
||||
with spack.repo.use_repositories(builder):
|
||||
y = spack.spec.Spec("y").concretized()
|
||||
y = spack.concretize.concretize_one("y")
|
||||
z = y["z"]
|
||||
|
||||
# add dependency to upstream, dependents to downstream
|
||||
upstream_write_db.add(z)
|
||||
with writable(upstream_db):
|
||||
upstream_db.add(z)
|
||||
upstream_db._read()
|
||||
downstream_db.add(y)
|
||||
|
||||
# remove the dependency from the upstream DB
|
||||
upstream_write_db.remove(z)
|
||||
with writable(upstream_db):
|
||||
upstream_db.remove(z)
|
||||
upstream_db._read()
|
||||
|
||||
# then rereading the downstream DB should warn about the missing dep
|
||||
@@ -183,16 +220,17 @@ def test_add_to_upstream_after_downstream(upstream_and_downstream_db, tmpdir):
|
||||
DB. When a package is recorded as installed in both, the results should
|
||||
refer to the downstream DB.
|
||||
"""
|
||||
upstream_write_db, upstream_db, downstream_db = upstream_and_downstream_db
|
||||
upstream_db, downstream_db = upstream_and_downstream_db
|
||||
|
||||
builder = spack.repo.MockRepositoryBuilder(tmpdir.mkdir("mock.repo"))
|
||||
builder.add_package("x")
|
||||
|
||||
with spack.repo.use_repositories(builder.root):
|
||||
spec = spack.spec.Spec("x").concretized()
|
||||
spec = spack.concretize.concretize_one("x")
|
||||
|
||||
downstream_db.add(spec)
|
||||
upstream_write_db.add(spec)
|
||||
with writable(upstream_db):
|
||||
upstream_db.add(spec)
|
||||
upstream_db._read()
|
||||
|
||||
upstream, record = downstream_db.query_by_spec_hash(spec.dag_hash())
|
||||
@@ -221,7 +259,7 @@ def test_cannot_write_upstream(tmp_path, mock_packages, config):
|
||||
db = spack.database.Database(str(tmp_path), is_upstream=True)
|
||||
|
||||
with pytest.raises(spack.database.ForbiddenLockError):
|
||||
db.add(spack.spec.Spec("pkg-a").concretized())
|
||||
db.add(spack.concretize.concretize_one("pkg-a"))
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config", "temporary_store")
|
||||
@@ -235,7 +273,7 @@ def test_recursive_upstream_dbs(tmpdir, gen_mock_layout):
|
||||
builder.add_package("x", dependencies=[("y", None, None)])
|
||||
|
||||
with spack.repo.use_repositories(builder.root):
|
||||
spec = spack.spec.Spec("x").concretized()
|
||||
spec = spack.concretize.concretize_one("x")
|
||||
db_c = spack.database.Database(roots[2], layout=layouts[2])
|
||||
db_c.add(spec["z"])
|
||||
|
||||
@@ -385,7 +423,7 @@ def _check_remove_and_add_package(database: spack.database.Database, spec):
|
||||
|
||||
|
||||
def _mock_install(spec: str):
|
||||
s = spack.spec.Spec(spec).concretized()
|
||||
s = spack.concretize.concretize_one(spec)
|
||||
PackageInstaller([s.package], fake=True, explicit=True).install()
|
||||
|
||||
|
||||
@@ -730,8 +768,7 @@ def test_regression_issue_8036(mutable_database, usr_folder_exists):
|
||||
# existing. Even when the package prefix exists, the package should
|
||||
# not be considered installed until it is added to the database by
|
||||
# the installer with install().
|
||||
s = spack.spec.Spec("externaltool@0.9")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("externaltool@0.9")
|
||||
assert not s.installed
|
||||
|
||||
# Now install the external package and check again the `installed` property
|
||||
@@ -746,8 +783,7 @@ def test_old_external_entries_prefix(mutable_database):
|
||||
|
||||
jsonschema.validate(db_obj, schema)
|
||||
|
||||
s = spack.spec.Spec("externaltool")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("externaltool")
|
||||
|
||||
db_obj["database"]["installs"][s.dag_hash()]["path"] = "None"
|
||||
|
||||
@@ -776,8 +812,7 @@ def test_uninstall_by_spec(mutable_database):
|
||||
|
||||
def test_query_unused_specs(mutable_database):
|
||||
# This spec installs a fake cmake as a build only dependency
|
||||
s = spack.spec.Spec("simple-inheritance")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("simple-inheritance")
|
||||
PackageInstaller([s.package], fake=True, explicit=True).install()
|
||||
|
||||
si = s.dag_hash()
|
||||
@@ -819,8 +854,7 @@ def check_unused(roots, deptype, expected):
|
||||
def test_query_spec_with_conditional_dependency(mutable_database):
|
||||
# The issue is triggered by having dependencies that are
|
||||
# conditional on a Boolean variant
|
||||
s = spack.spec.Spec("hdf5~mpi")
|
||||
s.concretize()
|
||||
s = spack.concretize.concretize_one("hdf5~mpi")
|
||||
PackageInstaller([s.package], fake=True, explicit=True).install()
|
||||
|
||||
results = spack.store.STORE.db.query_local("hdf5 ^mpich")
|
||||
@@ -843,7 +877,7 @@ def test_query_virtual_spec(database):
|
||||
assert all(name in names for name in ["mpich", "mpich2", "zmpi"])
|
||||
|
||||
|
||||
def test_failed_spec_path_error(database):
|
||||
def test_failed_spec_path_error(mutable_database):
|
||||
"""Ensure spec not concrete check is covered."""
|
||||
s = spack.spec.Spec("pkg-a")
|
||||
with pytest.raises(AssertionError, match="concrete spec required"):
|
||||
@@ -860,7 +894,7 @@ def _is(self, spec):
|
||||
# Pretend the spec has been failure locked
|
||||
monkeypatch.setattr(spack.database.FailureTracker, "lock_taken", _is)
|
||||
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
s = spack.concretize.concretize_one("pkg-a")
|
||||
spack.store.STORE.failure_tracker.clear(s)
|
||||
out = capfd.readouterr()[0]
|
||||
assert "Retaining failure marking" in out
|
||||
@@ -878,7 +912,7 @@ def _is(self, spec):
|
||||
# Ensure raise OSError when try to remove the non-existent marking
|
||||
monkeypatch.setattr(spack.database.FailureTracker, "persistent_mark", _is)
|
||||
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
s = spack.concretize.concretize_one("pkg-a")
|
||||
spack.store.STORE.failure_tracker.clear(s, force=True)
|
||||
out = capfd.readouterr()[1]
|
||||
assert "Removing failure marking despite lock" in out
|
||||
@@ -893,7 +927,7 @@ def _raise_exc(lock):
|
||||
raise lk.LockTimeoutError("write", "/mock-lock", 1.234, 10)
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
s = spack.concretize.concretize_one("pkg-a")
|
||||
|
||||
# Ensure attempt to acquire write lock on the mark raises the exception
|
||||
monkeypatch.setattr(lk.Lock, "acquire_write", _raise_exc)
|
||||
@@ -909,7 +943,7 @@ def _raise_exc(lock):
|
||||
def test_prefix_failed(mutable_database, monkeypatch):
|
||||
"""Add coverage to failed operation."""
|
||||
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
s = spack.concretize.concretize_one("pkg-a")
|
||||
|
||||
# Confirm the spec is not already marked as failed
|
||||
assert not spack.store.STORE.failure_tracker.has_failed(s)
|
||||
@@ -933,7 +967,7 @@ def test_prefix_write_lock_error(mutable_database, monkeypatch):
|
||||
def _raise(db, spec):
|
||||
raise lk.LockError("Mock lock error")
|
||||
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
s = spack.concretize.concretize_one("pkg-a")
|
||||
|
||||
# Ensure subsequent lock operations fail
|
||||
monkeypatch.setattr(lk.Lock, "acquire_write", _raise)
|
||||
@@ -950,7 +984,7 @@ def test_database_works_with_empty_dir(tmpdir):
|
||||
db_dir = tmpdir.ensure_dir(".spack-db")
|
||||
db_dir.ensure("lock")
|
||||
db_dir.ensure_dir("failures")
|
||||
tmpdir.chmod(mode=0o555, rec=1)
|
||||
tmpdir.chmod(mode=0o555)
|
||||
db = spack.database.Database(str(tmpdir))
|
||||
with db.read_transaction():
|
||||
db.query()
|
||||
@@ -1105,6 +1139,8 @@ def test_error_message_when_using_too_new_db(database, monkeypatch):
|
||||
def test_database_construction_doesnt_use_globals(tmpdir, config, nullify_globals, lock_cfg):
|
||||
lock_cfg = lock_cfg or spack.database.lock_configuration(config)
|
||||
db = spack.database.Database(str(tmpdir), lock_cfg=lock_cfg)
|
||||
with db.write_transaction():
|
||||
pass # ensure the DB is written
|
||||
assert os.path.exists(db.database_directory)
|
||||
|
||||
|
||||
@@ -1125,15 +1161,13 @@ def test_database_read_works_with_trailing_data(tmp_path, default_mock_concretiz
|
||||
assert spack.database.Database(root).query_local() == specs_in_db
|
||||
|
||||
|
||||
def test_database_errors_with_just_a_version_key(tmp_path):
|
||||
root = str(tmp_path)
|
||||
db = spack.database.Database(root)
|
||||
def test_database_errors_with_just_a_version_key(mutable_database):
|
||||
next_version = f"{spack.database._DB_VERSION}.next"
|
||||
with open(db._index_path, "w", encoding="utf-8") as f:
|
||||
with open(mutable_database._index_path, "w", encoding="utf-8") as f:
|
||||
f.write(json.dumps({"database": {"version": next_version}}))
|
||||
|
||||
with pytest.raises(spack.database.InvalidDatabaseVersionError):
|
||||
spack.database.Database(root).query_local()
|
||||
spack.database.Database(mutable_database.root).query_local()
|
||||
|
||||
|
||||
def test_reindex_with_upstreams(tmp_path, monkeypatch, mock_packages, config):
|
||||
@@ -1141,7 +1175,7 @@ def test_reindex_with_upstreams(tmp_path, monkeypatch, mock_packages, config):
|
||||
# we install `mpileaks` locally with dependencies in the upstream. And we even install
|
||||
# `mpileaks` with the same hash in the upstream. After reindexing, `mpileaks` should still be
|
||||
# in the local db, and `callpath` should not.
|
||||
mpileaks = spack.spec.Spec("mpileaks").concretized()
|
||||
mpileaks = spack.concretize.concretize_one("mpileaks")
|
||||
callpath = mpileaks.dependencies("callpath")[0]
|
||||
|
||||
upstream_store = spack.store.create(
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.concretize
|
||||
import spack.directives
|
||||
import spack.repo
|
||||
import spack.spec
|
||||
@@ -59,8 +60,8 @@ def test_constraints_from_context_are_merged(mock_packages):
|
||||
|
||||
@pytest.mark.regression("27754")
|
||||
def test_extends_spec(config, mock_packages):
|
||||
extender = spack.spec.Spec("extends-spec").concretized()
|
||||
extendee = spack.spec.Spec("extendee").concretized()
|
||||
extender = spack.concretize.concretize_one("extends-spec")
|
||||
extendee = spack.concretize.concretize_one("extendee")
|
||||
|
||||
assert extender.dependencies
|
||||
assert extender.package.extends(extendee)
|
||||
@@ -206,7 +207,7 @@ def test_repo(_create_test_repo, monkeypatch, mock_stage):
|
||||
def test_redistribute_directive(test_repo, spec_str, distribute_src, distribute_bin):
|
||||
spec = spack.spec.Spec(spec_str)
|
||||
assert spec.package_class.redistribute_source(spec) == distribute_src
|
||||
concretized_spec = spec.concretized()
|
||||
concretized_spec = spack.concretize.concretize_one(spec)
|
||||
assert concretized_spec.package.redistribute_binary == distribute_bin
|
||||
|
||||
|
||||
|
@@ -13,6 +13,7 @@
|
||||
|
||||
from llnl.path import path_to_os_path
|
||||
|
||||
import spack.concretize
|
||||
import spack.hash_types
|
||||
import spack.paths
|
||||
import spack.repo
|
||||
@@ -59,7 +60,7 @@ def test_yaml_directory_layout_parameters(tmpdir, default_mock_concretization):
|
||||
assert package7 == path_package7
|
||||
|
||||
# Test separation of architecture or namespace
|
||||
spec2 = Spec("libelf").concretized()
|
||||
spec2 = spack.concretize.concretize_one("libelf")
|
||||
|
||||
arch_scheme = (
|
||||
"{architecture.platform}/{architecture.target}/{architecture.os}/{name}/{version}/{hash:7}"
|
||||
@@ -97,7 +98,7 @@ def test_read_and_write_spec(temporary_store, config, mock_packages):
|
||||
# If a spec fails to concretize, just skip it. If it is a
|
||||
# real error, it will be caught by concretization tests.
|
||||
try:
|
||||
spec = spack.spec.Spec(name).concretized()
|
||||
spec = spack.concretize.concretize_one(name)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
@@ -136,7 +137,7 @@ def test_read_and_write_spec(temporary_store, config, mock_packages):
|
||||
assert norm.eq_dag(spec_from_file)
|
||||
|
||||
# TODO: revise this when build deps are in dag_hash
|
||||
conc = read_separately.concretized().copy(deps=stored_deptypes)
|
||||
conc = spack.concretize.concretize_one(read_separately).copy(deps=stored_deptypes)
|
||||
assert conc == spec_from_file
|
||||
assert conc.eq_dag(spec_from_file)
|
||||
|
||||
@@ -172,12 +173,10 @@ def test_handle_unknown_package(temporary_store, config, mock_packages, tmp_path
|
||||
# Create all the packages that are not in mock.
|
||||
installed_specs = {}
|
||||
for pkg_name in packages:
|
||||
spec = spack.spec.Spec(pkg_name)
|
||||
|
||||
# If a spec fails to concretize, just skip it. If it is a
|
||||
# real error, it will be caught by concretization tests.
|
||||
try:
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one(pkg_name)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
@@ -209,7 +208,7 @@ def test_find(temporary_store, config, mock_packages):
|
||||
if name.startswith("external"):
|
||||
# External package tests cannot be installed
|
||||
continue
|
||||
spec = spack.spec.Spec(name).concretized()
|
||||
spec = spack.concretize.concretize_one(name)
|
||||
installed_specs[spec.name] = spec
|
||||
layout.create_install_directory(spec)
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
import pytest
|
||||
|
||||
import spack.build_environment
|
||||
import spack.spec
|
||||
import spack.concretize
|
||||
from spack.package import build_system_flags, env_flags, inject_flags
|
||||
|
||||
|
||||
@@ -30,10 +30,10 @@ def add_o3_to_build_system_cflags(pkg, name, flags):
|
||||
class TestFlagHandlers:
|
||||
def test_no_build_system_flags(self, temp_env):
|
||||
# Test that both autotools and cmake work getting no build_system flags
|
||||
s1 = spack.spec.Spec("cmake-client").concretized()
|
||||
s1 = spack.concretize.concretize_one("cmake-client")
|
||||
spack.build_environment.setup_package(s1.package, False)
|
||||
|
||||
s2 = spack.spec.Spec("patchelf").concretized()
|
||||
s2 = spack.concretize.concretize_one("patchelf")
|
||||
spack.build_environment.setup_package(s2.package, False)
|
||||
|
||||
# Use cppflags as a canary
|
||||
@@ -43,28 +43,28 @@ def test_no_build_system_flags(self, temp_env):
|
||||
def test_unbound_method(self, temp_env):
|
||||
# Other tests test flag_handlers set as bound methods and functions.
|
||||
# This tests an unbound method in python2 (no change in python3).
|
||||
s = spack.spec.Spec("mpileaks cppflags=-g").concretized()
|
||||
s = spack.concretize.concretize_one("mpileaks cppflags=-g")
|
||||
s.package.flag_handler = s.package.__class__.inject_flags
|
||||
spack.build_environment.setup_package(s.package, False)
|
||||
assert os.environ["SPACK_CPPFLAGS"] == "-g"
|
||||
assert "CPPFLAGS" not in os.environ
|
||||
|
||||
def test_inject_flags(self, temp_env):
|
||||
s = spack.spec.Spec("mpileaks cppflags=-g").concretized()
|
||||
s = spack.concretize.concretize_one("mpileaks cppflags=-g")
|
||||
s.package.flag_handler = inject_flags
|
||||
spack.build_environment.setup_package(s.package, False)
|
||||
assert os.environ["SPACK_CPPFLAGS"] == "-g"
|
||||
assert "CPPFLAGS" not in os.environ
|
||||
|
||||
def test_env_flags(self, temp_env):
|
||||
s = spack.spec.Spec("mpileaks cppflags=-g").concretized()
|
||||
s = spack.concretize.concretize_one("mpileaks cppflags=-g")
|
||||
s.package.flag_handler = env_flags
|
||||
spack.build_environment.setup_package(s.package, False)
|
||||
assert os.environ["CPPFLAGS"] == "-g"
|
||||
assert "SPACK_CPPFLAGS" not in os.environ
|
||||
|
||||
def test_build_system_flags_cmake(self, temp_env):
|
||||
s = spack.spec.Spec("cmake-client cppflags=-g").concretized()
|
||||
s = spack.concretize.concretize_one("cmake-client cppflags=-g")
|
||||
s.package.flag_handler = build_system_flags
|
||||
spack.build_environment.setup_package(s.package, False)
|
||||
assert "SPACK_CPPFLAGS" not in os.environ
|
||||
@@ -76,7 +76,7 @@ def test_build_system_flags_cmake(self, temp_env):
|
||||
}
|
||||
|
||||
def test_build_system_flags_autotools(self, temp_env):
|
||||
s = spack.spec.Spec("patchelf cppflags=-g").concretized()
|
||||
s = spack.concretize.concretize_one("patchelf cppflags=-g")
|
||||
s.package.flag_handler = build_system_flags
|
||||
spack.build_environment.setup_package(s.package, False)
|
||||
assert "SPACK_CPPFLAGS" not in os.environ
|
||||
@@ -85,7 +85,7 @@ def test_build_system_flags_autotools(self, temp_env):
|
||||
|
||||
def test_build_system_flags_not_implemented(self, temp_env):
|
||||
"""Test the command line flags method raises a NotImplementedError"""
|
||||
s = spack.spec.Spec("mpileaks cppflags=-g").concretized()
|
||||
s = spack.concretize.concretize_one("mpileaks cppflags=-g")
|
||||
s.package.flag_handler = build_system_flags
|
||||
try:
|
||||
spack.build_environment.setup_package(s.package, False)
|
||||
@@ -94,7 +94,7 @@ def test_build_system_flags_not_implemented(self, temp_env):
|
||||
assert True
|
||||
|
||||
def test_add_build_system_flags_autotools(self, temp_env):
|
||||
s = spack.spec.Spec("patchelf cppflags=-g").concretized()
|
||||
s = spack.concretize.concretize_one("patchelf cppflags=-g")
|
||||
s.package.flag_handler = add_o3_to_build_system_cflags
|
||||
spack.build_environment.setup_package(s.package, False)
|
||||
assert "-g" in os.environ["SPACK_CPPFLAGS"]
|
||||
@@ -102,7 +102,7 @@ def test_add_build_system_flags_autotools(self, temp_env):
|
||||
assert s.package.configure_flag_args == ["CFLAGS=-O3"]
|
||||
|
||||
def test_add_build_system_flags_cmake(self, temp_env):
|
||||
s = spack.spec.Spec("cmake-client cppflags=-g").concretized()
|
||||
s = spack.concretize.concretize_one("cmake-client cppflags=-g")
|
||||
s.package.flag_handler = add_o3_to_build_system_cflags
|
||||
spack.build_environment.setup_package(s.package, False)
|
||||
assert "-g" in os.environ["SPACK_CPPFLAGS"]
|
||||
@@ -110,7 +110,7 @@ def test_add_build_system_flags_cmake(self, temp_env):
|
||||
assert s.package.cmake_flag_args == ["-DCMAKE_C_FLAGS=-O3"]
|
||||
|
||||
def test_ld_flags_cmake(self, temp_env):
|
||||
s = spack.spec.Spec("cmake-client ldflags=-mthreads").concretized()
|
||||
s = spack.concretize.concretize_one("cmake-client ldflags=-mthreads")
|
||||
s.package.flag_handler = build_system_flags
|
||||
spack.build_environment.setup_package(s.package, False)
|
||||
assert "SPACK_LDFLAGS" not in os.environ
|
||||
@@ -122,7 +122,7 @@ def test_ld_flags_cmake(self, temp_env):
|
||||
}
|
||||
|
||||
def test_ld_libs_cmake(self, temp_env):
|
||||
s = spack.spec.Spec("cmake-client ldlibs=-lfoo").concretized()
|
||||
s = spack.concretize.concretize_one("cmake-client ldlibs=-lfoo")
|
||||
s.package.flag_handler = build_system_flags
|
||||
spack.build_environment.setup_package(s.package, False)
|
||||
assert "SPACK_LDLIBS" not in os.environ
|
||||
@@ -138,7 +138,7 @@ def test_flag_handler(self, name, flags):
|
||||
flags.append("-foo")
|
||||
return (flags, None, None)
|
||||
|
||||
s = spack.spec.Spec("cmake-client").concretized()
|
||||
s = spack.concretize.concretize_one("cmake-client")
|
||||
s.package.flag_handler = test_flag_handler
|
||||
spack.build_environment.setup_package(s.package, False)
|
||||
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
from llnl.util.filesystem import mkdirp, touch, working_dir
|
||||
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.error
|
||||
import spack.fetch_strategy
|
||||
@@ -185,8 +186,9 @@ def test_adhoc_version_submodules(
|
||||
monkeypatch.setitem(pkg_class.versions, Version("git"), t.args)
|
||||
monkeypatch.setattr(pkg_class, "git", "file://%s" % mock_git_repository.path, raising=False)
|
||||
|
||||
spec = Spec("git-test@{0}".format(mock_git_repository.unversioned_commit))
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one(
|
||||
Spec("git-test@{0}".format(mock_git_repository.unversioned_commit))
|
||||
)
|
||||
spec.package.do_stage()
|
||||
collected_fnames = set()
|
||||
for root, dirs, files in os.walk(spec.package.stage.source_path):
|
||||
|
@@ -3,8 +3,8 @@
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
import io
|
||||
|
||||
import spack.concretize
|
||||
import spack.graph
|
||||
import spack.spec
|
||||
|
||||
|
||||
def test_dynamic_dot_graph_mpileaks(default_mock_concretization):
|
||||
@@ -38,7 +38,7 @@ def test_dynamic_dot_graph_mpileaks(default_mock_concretization):
|
||||
|
||||
def test_ascii_graph_mpileaks(config, mock_packages, monkeypatch):
|
||||
monkeypatch.setattr(spack.graph.AsciiGraph, "_node_label", lambda self, node: node.name)
|
||||
s = spack.spec.Spec("mpileaks").concretized()
|
||||
s = spack.concretize.concretize_one("mpileaks")
|
||||
|
||||
stream = io.StringIO()
|
||||
graph = spack.graph.AsciiGraph()
|
||||
|
@@ -8,9 +8,9 @@
|
||||
|
||||
from llnl.util.filesystem import mkdirp, touch, working_dir
|
||||
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
from spack.fetch_strategy import HgFetchStrategy
|
||||
from spack.spec import Spec
|
||||
from spack.stage import Stage
|
||||
from spack.util.executable import which
|
||||
from spack.version import Version
|
||||
@@ -40,7 +40,7 @@ def test_fetch(type_of_test, secure, mock_hg_repository, config, mutable_mock_re
|
||||
h = mock_hg_repository.hash
|
||||
|
||||
# Construct the package under test
|
||||
s = Spec("hg-test").concretized()
|
||||
s = spack.concretize.concretize_one("hg-test")
|
||||
monkeypatch.setitem(s.package.versions, Version("hg"), t.args)
|
||||
|
||||
# Enter the stage directory and check some properties
|
||||
|
@@ -11,6 +11,7 @@
|
||||
import llnl.util.filesystem as fs
|
||||
|
||||
import spack.build_environment
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.database
|
||||
import spack.error
|
||||
@@ -41,7 +42,7 @@ def find_nothing(*args):
|
||||
|
||||
|
||||
def test_install_and_uninstall(install_mockery, mock_fetch, monkeypatch):
|
||||
spec = Spec("trivial-install-test-package").concretized()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
|
||||
PackageInstaller([spec.package], explicit=True).install()
|
||||
assert spec.installed
|
||||
@@ -53,7 +54,7 @@ def test_install_and_uninstall(install_mockery, mock_fetch, monkeypatch):
|
||||
@pytest.mark.regression("11870")
|
||||
def test_uninstall_non_existing_package(install_mockery, mock_fetch, monkeypatch):
|
||||
"""Ensure that we can uninstall a package that has been deleted from the repo"""
|
||||
spec = Spec("trivial-install-test-package").concretized()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
|
||||
PackageInstaller([spec.package], explicit=True).install()
|
||||
assert spec.installed
|
||||
@@ -71,8 +72,7 @@ def test_uninstall_non_existing_package(install_mockery, mock_fetch, monkeypatch
|
||||
|
||||
def test_pkg_attributes(install_mockery, mock_fetch, monkeypatch):
|
||||
# Get a basic concrete spec for the dummy package.
|
||||
spec = Spec("attributes-foo-app ^attributes-foo")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("attributes-foo-app ^attributes-foo")
|
||||
assert spec.concrete
|
||||
|
||||
pkg = spec.package
|
||||
@@ -127,7 +127,7 @@ def remove_prefix(self):
|
||||
|
||||
|
||||
def test_partial_install_delete_prefix_and_stage(install_mockery, mock_fetch, working_env):
|
||||
s = Spec("canfail").concretized()
|
||||
s = spack.concretize.concretize_one("canfail")
|
||||
|
||||
instance_rm_prefix = s.package.remove_prefix
|
||||
|
||||
@@ -157,7 +157,7 @@ def test_failing_overwrite_install_should_keep_previous_installation(
|
||||
the original install prefix instead of cleaning it.
|
||||
"""
|
||||
# Do a successful install
|
||||
s = Spec("canfail").concretized()
|
||||
s = spack.concretize.concretize_one("canfail")
|
||||
s.package.set_install_succeed()
|
||||
|
||||
# Do a failing overwrite install
|
||||
@@ -173,13 +173,11 @@ def test_failing_overwrite_install_should_keep_previous_installation(
|
||||
|
||||
|
||||
def test_dont_add_patches_to_installed_package(install_mockery, mock_fetch, monkeypatch):
|
||||
dependency = Spec("dependency-install")
|
||||
dependency.concretize()
|
||||
dependency = spack.concretize.concretize_one("dependency-install")
|
||||
PackageInstaller([dependency.package], explicit=True).install()
|
||||
|
||||
dependency_hash = dependency.dag_hash()
|
||||
dependent = Spec("dependent-install ^/" + dependency_hash)
|
||||
dependent.concretize()
|
||||
dependent = spack.concretize.concretize_one("dependent-install ^/" + dependency_hash)
|
||||
|
||||
monkeypatch.setitem(
|
||||
dependency.package.patches,
|
||||
@@ -191,20 +189,18 @@ def test_dont_add_patches_to_installed_package(install_mockery, mock_fetch, monk
|
||||
|
||||
|
||||
def test_installed_dependency_request_conflicts(install_mockery, mock_fetch, mutable_mock_repo):
|
||||
dependency = Spec("dependency-install")
|
||||
dependency.concretize()
|
||||
dependency = spack.concretize.concretize_one("dependency-install")
|
||||
PackageInstaller([dependency.package], explicit=True).install()
|
||||
|
||||
dependency_hash = dependency.dag_hash()
|
||||
dependent = Spec("conflicting-dependent ^/" + dependency_hash)
|
||||
with pytest.raises(spack.error.UnsatisfiableSpecError):
|
||||
dependent.concretize()
|
||||
spack.concretize.concretize_one(dependent)
|
||||
|
||||
|
||||
def test_install_dependency_symlinks_pkg(install_mockery, mock_fetch, mutable_mock_repo):
|
||||
"""Test dependency flattening/symlinks mock package."""
|
||||
spec = Spec("flatten-deps")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("flatten-deps")
|
||||
pkg = spec.package
|
||||
PackageInstaller([pkg], explicit=True).install()
|
||||
|
||||
@@ -215,7 +211,7 @@ def test_install_dependency_symlinks_pkg(install_mockery, mock_fetch, mutable_mo
|
||||
|
||||
def test_install_times(install_mockery, mock_fetch, mutable_mock_repo):
|
||||
"""Test install times added."""
|
||||
spec = Spec("dev-build-test-install-phases").concretized()
|
||||
spec = spack.concretize.concretize_one("dev-build-test-install-phases")
|
||||
PackageInstaller([spec.package], explicit=True).install()
|
||||
|
||||
# Ensure dependency directory exists after the installation.
|
||||
@@ -236,8 +232,7 @@ def test_flatten_deps(install_mockery, mock_fetch, mutable_mock_repo):
|
||||
"""Explicitly test the flattening code for coverage purposes."""
|
||||
# Unfortunately, executing the 'flatten-deps' spec's installation does
|
||||
# not affect code coverage results, so be explicit here.
|
||||
spec = Spec("dependent-install")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("dependent-install")
|
||||
pkg = spec.package
|
||||
PackageInstaller([pkg], explicit=True).install()
|
||||
|
||||
@@ -272,7 +267,7 @@ def install_upstream(tmpdir_factory, gen_mock_layout, install_mockery):
|
||||
|
||||
def _install_upstream(*specs):
|
||||
for spec_str in specs:
|
||||
prepared_db.add(Spec(spec_str).concretized())
|
||||
prepared_db.add(spack.concretize.concretize_one(spec_str))
|
||||
downstream_root = str(tmpdir_factory.mktemp("mock_downstream_db_root"))
|
||||
return downstream_root, upstream_layout
|
||||
|
||||
@@ -285,8 +280,7 @@ def test_installed_upstream_external(install_upstream, mock_fetch):
|
||||
"""
|
||||
store_root, _ = install_upstream("externaltool")
|
||||
with spack.store.use_store(store_root):
|
||||
dependent = Spec("externaltest")
|
||||
dependent.concretize()
|
||||
dependent = spack.concretize.concretize_one("externaltest")
|
||||
|
||||
new_dependency = dependent["externaltool"]
|
||||
assert new_dependency.external
|
||||
@@ -304,8 +298,8 @@ def test_installed_upstream(install_upstream, mock_fetch):
|
||||
"""
|
||||
store_root, upstream_layout = install_upstream("dependency-install")
|
||||
with spack.store.use_store(store_root):
|
||||
dependency = Spec("dependency-install").concretized()
|
||||
dependent = Spec("dependent-install").concretized()
|
||||
dependency = spack.concretize.concretize_one("dependency-install")
|
||||
dependent = spack.concretize.concretize_one("dependent-install")
|
||||
|
||||
new_dependency = dependent["dependency-install"]
|
||||
assert new_dependency.installed_upstream
|
||||
@@ -319,7 +313,7 @@ def test_installed_upstream(install_upstream, mock_fetch):
|
||||
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_partial_install_keep_prefix(install_mockery, mock_fetch, monkeypatch, working_env):
|
||||
s = Spec("canfail").concretized()
|
||||
s = spack.concretize.concretize_one("canfail")
|
||||
|
||||
# If remove_prefix is called at any point in this test, that is an error
|
||||
monkeypatch.setattr(spack.package_base.PackageBase, "remove_prefix", mock_remove_prefix)
|
||||
@@ -336,7 +330,7 @@ def test_partial_install_keep_prefix(install_mockery, mock_fetch, monkeypatch, w
|
||||
|
||||
|
||||
def test_second_install_no_overwrite_first(install_mockery, mock_fetch, monkeypatch):
|
||||
s = Spec("canfail").concretized()
|
||||
s = spack.concretize.concretize_one("canfail")
|
||||
monkeypatch.setattr(spack.package_base.PackageBase, "remove_prefix", mock_remove_prefix)
|
||||
|
||||
s.package.set_install_succeed()
|
||||
@@ -356,8 +350,8 @@ def test_install_prefix_collision_fails(config, mock_fetch, mock_packages, tmpdi
|
||||
projections = {"projections": {"all": "one-prefix-per-package-{name}"}}
|
||||
with spack.store.use_store(str(tmpdir), extra_data=projections):
|
||||
with spack.config.override("config:checksum", False):
|
||||
pkg_a = Spec("libelf@0.8.13").concretized().package
|
||||
pkg_b = Spec("libelf@0.8.12").concretized().package
|
||||
pkg_a = spack.concretize.concretize_one("libelf@0.8.13").package
|
||||
pkg_b = spack.concretize.concretize_one("libelf@0.8.12").package
|
||||
PackageInstaller([pkg_a], explicit=True, fake=True).install()
|
||||
|
||||
with pytest.raises(InstallError, match="Install prefix collision"):
|
||||
@@ -365,14 +359,14 @@ def test_install_prefix_collision_fails(config, mock_fetch, mock_packages, tmpdi
|
||||
|
||||
|
||||
def test_store(install_mockery, mock_fetch):
|
||||
spec = Spec("cmake-client").concretized()
|
||||
spec = spack.concretize.concretize_one("cmake-client")
|
||||
pkg = spec.package
|
||||
PackageInstaller([pkg], fake=True, explicit=True).install()
|
||||
|
||||
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_failing_build(install_mockery, mock_fetch, capfd):
|
||||
spec = Spec("failing-build").concretized()
|
||||
spec = spack.concretize.concretize_one("failing-build")
|
||||
pkg = spec.package
|
||||
|
||||
with pytest.raises(spack.build_environment.ChildError, match="Expected failure"):
|
||||
@@ -387,8 +381,7 @@ def test_uninstall_by_spec_errors(mutable_database):
|
||||
"""Test exceptional cases with the uninstall command."""
|
||||
|
||||
# Try to uninstall a spec that has not been installed
|
||||
spec = Spec("dependent-install")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("dependent-install")
|
||||
with pytest.raises(InstallError, match="is not installed"):
|
||||
PackageBase.uninstall_by_spec(spec)
|
||||
|
||||
@@ -401,7 +394,7 @@ def test_uninstall_by_spec_errors(mutable_database):
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_nosource_pkg_install(install_mockery, mock_fetch, mock_packages, capfd, ensure_debug):
|
||||
"""Test install phases with the nosource package."""
|
||||
spec = Spec("nosource").concretized()
|
||||
spec = spack.concretize.concretize_one("nosource")
|
||||
pkg = spec.package
|
||||
|
||||
# Make sure install works even though there is no associated code.
|
||||
@@ -418,7 +411,7 @@ def test_nosource_bundle_pkg_install(
|
||||
install_mockery, mock_fetch, mock_packages, capfd, ensure_debug
|
||||
):
|
||||
"""Test install phases with the nosource-bundle package."""
|
||||
spec = Spec("nosource-bundle").concretized()
|
||||
spec = spack.concretize.concretize_one("nosource-bundle")
|
||||
pkg = spec.package
|
||||
|
||||
# Make sure install works even though there is no associated code.
|
||||
@@ -432,7 +425,7 @@ def test_nosource_bundle_pkg_install(
|
||||
|
||||
def test_nosource_pkg_install_post_install(install_mockery, mock_fetch, mock_packages):
|
||||
"""Test install phases with the nosource package with post-install."""
|
||||
spec = Spec("nosource-install").concretized()
|
||||
spec = spack.concretize.concretize_one("nosource-install")
|
||||
pkg = spec.package
|
||||
|
||||
# Make sure both the install and post-install package methods work.
|
||||
@@ -449,14 +442,14 @@ def test_nosource_pkg_install_post_install(install_mockery, mock_fetch, mock_pac
|
||||
|
||||
def test_pkg_build_paths(install_mockery):
|
||||
# Get a basic concrete spec for the trivial install package.
|
||||
spec = Spec("trivial-install-test-package").concretized()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
assert spec.package.log_path.endswith(_spack_build_logfile)
|
||||
assert spec.package.env_path.endswith(_spack_build_envfile)
|
||||
|
||||
|
||||
def test_pkg_install_paths(install_mockery):
|
||||
# Get a basic concrete spec for the trivial install package.
|
||||
spec = Spec("trivial-install-test-package").concretized()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
|
||||
log_path = os.path.join(spec.prefix, ".spack", _spack_build_logfile + ".gz")
|
||||
assert spec.package.install_log_path == log_path
|
||||
@@ -493,7 +486,7 @@ def test_pkg_install_paths(install_mockery):
|
||||
def test_log_install_without_build_files(install_mockery):
|
||||
"""Test the installer log function when no build files are present."""
|
||||
# Get a basic concrete spec for the trivial install package.
|
||||
spec = Spec("trivial-install-test-package").concretized()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
|
||||
# Attempt installing log without the build log file
|
||||
with pytest.raises(IOError, match="No such file or directory"):
|
||||
@@ -515,7 +508,7 @@ def _install(src, dest):
|
||||
|
||||
monkeypatch.setattr(fs, "install", _install)
|
||||
|
||||
spec = Spec("trivial-install-test-package").concretized()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
|
||||
# Set up mock build files and try again to include archive failure
|
||||
log_path = spec.package.log_path
|
||||
@@ -587,7 +580,7 @@ def test_empty_install_sanity_check_prefix(
|
||||
monkeypatch, install_mockery, mock_fetch, mock_packages
|
||||
):
|
||||
"""Test empty install triggers sanity_check_prefix."""
|
||||
spec = Spec("failing-empty-install").concretized()
|
||||
spec = spack.concretize.concretize_one("failing-empty-install")
|
||||
with pytest.raises(spack.build_environment.ChildError, match="Nothing was installed"):
|
||||
PackageInstaller([spec.package], explicit=True).install()
|
||||
|
||||
@@ -599,7 +592,7 @@ def test_install_from_binary_with_missing_patch_succeeds(
|
||||
pushing the package to a binary cache, installation from that binary cache shouldn't error out
|
||||
because of the missing patch."""
|
||||
# Create a spec s with non-existing patches
|
||||
s = Spec("trivial-install-test-package").concretized()
|
||||
s = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
patches = ["a" * 64]
|
||||
s_dict = s.to_dict()
|
||||
s_dict["spec"]["nodes"][0]["patches"] = patches
|
||||
|
@@ -16,6 +16,7 @@
|
||||
import llnl.util.tty as tty
|
||||
|
||||
import spack.binary_distribution
|
||||
import spack.concretize
|
||||
import spack.database
|
||||
import spack.deptypes as dt
|
||||
import spack.error
|
||||
@@ -81,7 +82,7 @@ def create_installer(
|
||||
) -> inst.PackageInstaller:
|
||||
"""Create an installer instance for a list of specs or package names that will be
|
||||
concretized."""
|
||||
_specs = [spack.spec.Spec(s).concretized() if isinstance(s, str) else s for s in specs]
|
||||
_specs = [spack.concretize.concretize_one(s) if isinstance(s, str) else s for s in specs]
|
||||
_install_args = {} if install_args is None else install_args
|
||||
return inst.PackageInstaller([spec.package for spec in _specs], **_install_args)
|
||||
|
||||
@@ -96,8 +97,7 @@ def test_hms(sec, result):
|
||||
|
||||
def test_get_dependent_ids(install_mockery, mock_packages):
|
||||
# Concretize the parent package, which handle dependency too
|
||||
spec = spack.spec.Spec("pkg-a")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("pkg-a")
|
||||
assert spec.concrete
|
||||
|
||||
pkg_id = inst.package_id(spec)
|
||||
@@ -133,8 +133,7 @@ def test_install_msg(monkeypatch):
|
||||
|
||||
def test_install_from_cache_errors(install_mockery):
|
||||
"""Test to ensure cover install from cache errors."""
|
||||
spec = spack.spec.Spec("trivial-install-test-package")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
assert spec.concrete
|
||||
|
||||
# Check with cache-only
|
||||
@@ -153,8 +152,7 @@ def test_install_from_cache_errors(install_mockery):
|
||||
|
||||
def test_install_from_cache_ok(install_mockery, monkeypatch):
|
||||
"""Test to ensure cover _install_from_cache to the return."""
|
||||
spec = spack.spec.Spec("trivial-install-test-package")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
monkeypatch.setattr(inst, "_try_install_from_binary_cache", _true)
|
||||
monkeypatch.setattr(spack.hooks, "post_install", _noop)
|
||||
|
||||
@@ -163,8 +161,7 @@ def test_install_from_cache_ok(install_mockery, monkeypatch):
|
||||
|
||||
def test_process_external_package_module(install_mockery, monkeypatch, capfd):
|
||||
"""Test to simply cover the external module message path."""
|
||||
spec = spack.spec.Spec("trivial-install-test-package")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
assert spec.concrete
|
||||
|
||||
# Ensure take the external module path WITHOUT any changes to the database
|
||||
@@ -191,7 +188,7 @@ def _spec(spec, unsigned=False, mirrors_for_spec=None):
|
||||
# Skip database updates
|
||||
monkeypatch.setattr(spack.database.Database, "add", _noop)
|
||||
|
||||
spec = spack.spec.Spec("pkg-a").concretized()
|
||||
spec = spack.concretize.concretize_one("pkg-a")
|
||||
assert inst._process_binary_cache_tarball(spec.package, explicit=False, unsigned=False)
|
||||
|
||||
out = capfd.readouterr()[0]
|
||||
@@ -201,8 +198,7 @@ def _spec(spec, unsigned=False, mirrors_for_spec=None):
|
||||
|
||||
def test_try_install_from_binary_cache(install_mockery, mock_packages, monkeypatch):
|
||||
"""Test return false when no match exists in the mirror"""
|
||||
spec = spack.spec.Spec("mpich")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("mpich")
|
||||
result = inst._try_install_from_binary_cache(spec.package, False, False)
|
||||
assert not result
|
||||
|
||||
@@ -274,7 +270,7 @@ def _mock_installed(self):
|
||||
|
||||
|
||||
def test_check_before_phase_error(install_mockery):
|
||||
s = spack.spec.Spec("trivial-install-test-package").concretized()
|
||||
s = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
s.package.stop_before_phase = "beforephase"
|
||||
with pytest.raises(inst.BadInstallPhase) as exc_info:
|
||||
inst._check_last_phase(s.package)
|
||||
@@ -285,7 +281,7 @@ def test_check_before_phase_error(install_mockery):
|
||||
|
||||
|
||||
def test_check_last_phase_error(install_mockery):
|
||||
s = spack.spec.Spec("trivial-install-test-package").concretized()
|
||||
s = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
s.package.stop_before_phase = None
|
||||
s.package.last_phase = "badphase"
|
||||
with pytest.raises(inst.BadInstallPhase) as exc_info:
|
||||
@@ -420,15 +416,13 @@ def test_package_id_err(install_mockery):
|
||||
|
||||
|
||||
def test_package_id_ok(install_mockery):
|
||||
spec = spack.spec.Spec("trivial-install-test-package")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
assert spec.concrete
|
||||
assert spec.name in inst.package_id(spec)
|
||||
|
||||
|
||||
def test_fake_install(install_mockery):
|
||||
spec = spack.spec.Spec("trivial-install-test-package")
|
||||
spec.concretize()
|
||||
spec = spack.concretize.concretize_one("trivial-install-test-package")
|
||||
assert spec.concrete
|
||||
|
||||
pkg = spec.package
|
||||
@@ -440,7 +434,7 @@ def test_dump_packages_deps_ok(install_mockery, tmpdir, mock_packages):
|
||||
"""Test happy path for dump_packages with dependencies."""
|
||||
|
||||
spec_name = "simple-inheritance"
|
||||
spec = spack.spec.Spec(spec_name).concretized()
|
||||
spec = spack.concretize.concretize_one(spec_name)
|
||||
inst.dump_packages(spec, str(tmpdir))
|
||||
|
||||
repo = mock_packages.repos[0]
|
||||
@@ -471,7 +465,7 @@ def _repoerr(repo, name):
|
||||
# the try-except block
|
||||
monkeypatch.setattr(spack.store.STORE.layout, "build_packages_path", bpp_path)
|
||||
|
||||
spec = spack.spec.Spec("simple-inheritance").concretized()
|
||||
spec = spack.concretize.concretize_one("simple-inheritance")
|
||||
path = str(tmpdir)
|
||||
|
||||
# The call to install_tree will raise the exception since not mocking
|
||||
@@ -581,7 +575,7 @@ def test_check_deps_status_install_failure(install_mockery):
|
||||
"""Tests that checking the dependency status on a request to install
|
||||
'a' fails, if we mark the dependency as failed.
|
||||
"""
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
s = spack.concretize.concretize_one("pkg-a")
|
||||
for dep in s.traverse(root=False):
|
||||
spack.store.STORE.failure_tracker.mark(dep)
|
||||
|
||||
@@ -654,8 +648,8 @@ def test_installer_init_requests(install_mockery):
|
||||
@pytest.mark.parametrize("transitive", [True, False])
|
||||
def test_install_spliced(install_mockery, mock_fetch, monkeypatch, capsys, transitive):
|
||||
"""Test installing a spliced spec"""
|
||||
spec = spack.spec.Spec("splice-t").concretized()
|
||||
dep = spack.spec.Spec("splice-h+foo").concretized()
|
||||
spec = spack.concretize.concretize_one("splice-t")
|
||||
dep = spack.concretize.concretize_one("splice-h+foo")
|
||||
|
||||
# Do the splice.
|
||||
out = spec.splice(dep, transitive)
|
||||
@@ -669,8 +663,8 @@ def test_install_spliced(install_mockery, mock_fetch, monkeypatch, capsys, trans
|
||||
@pytest.mark.parametrize("transitive", [True, False])
|
||||
def test_install_spliced_build_spec_installed(install_mockery, capfd, mock_fetch, transitive):
|
||||
"""Test installing a spliced spec with the build spec already installed"""
|
||||
spec = spack.spec.Spec("splice-t").concretized()
|
||||
dep = spack.spec.Spec("splice-h+foo").concretized()
|
||||
spec = spack.concretize.concretize_one("splice-t")
|
||||
dep = spack.concretize.concretize_one("splice-h+foo")
|
||||
|
||||
# Do the splice.
|
||||
out = spec.splice(dep, transitive)
|
||||
@@ -696,8 +690,8 @@ def test_install_splice_root_from_binary(
|
||||
):
|
||||
"""Test installing a spliced spec with the root available in binary cache"""
|
||||
# Test splicing and rewiring a spec with the same name, different hash.
|
||||
original_spec = spack.spec.Spec(root_str).concretized()
|
||||
spec_to_splice = spack.spec.Spec("splice-h+foo").concretized()
|
||||
original_spec = spack.concretize.concretize_one(root_str)
|
||||
spec_to_splice = spack.concretize.concretize_one("splice-h+foo")
|
||||
|
||||
PackageInstaller([original_spec.package, spec_to_splice.package]).install()
|
||||
|
||||
@@ -853,7 +847,7 @@ def _chgrp(path, group, follow_symlinks=True):
|
||||
monkeypatch.setattr(fs, "chgrp", _chgrp)
|
||||
|
||||
build_task = create_build_task(
|
||||
spack.spec.Spec("trivial-install-test-package").concretized().package
|
||||
spack.concretize.concretize_one("trivial-install-test-package").package
|
||||
)
|
||||
spec = build_task.request.pkg.spec
|
||||
|
||||
@@ -1024,7 +1018,8 @@ def test_install_fail_multi(install_mockery, mock_fetch, monkeypatch):
|
||||
|
||||
def test_install_fail_fast_on_detect(install_mockery, monkeypatch, capsys):
|
||||
"""Test fail_fast install when an install failure is detected."""
|
||||
b, c = spack.spec.Spec("pkg-b").concretized(), spack.spec.Spec("pkg-c").concretized()
|
||||
b = spack.concretize.concretize_one("pkg-b")
|
||||
c = spack.concretize.concretize_one("pkg-c")
|
||||
b_id, c_id = inst.package_id(b), inst.package_id(c)
|
||||
|
||||
installer = create_installer([b, c], {"fail_fast": True})
|
||||
@@ -1093,7 +1088,7 @@ def _requeued(installer, task, install_status):
|
||||
|
||||
def test_install_lock_installed_requeue(install_mockery, monkeypatch, capfd):
|
||||
"""Cover basic install handling for installed package."""
|
||||
b = spack.spec.Spec("pkg-b").concretized()
|
||||
b = spack.concretize.concretize_one("pkg-b")
|
||||
b_pkg_id = inst.package_id(b)
|
||||
installer = create_installer([b])
|
||||
|
||||
@@ -1279,7 +1274,7 @@ def test_term_status_line():
|
||||
@pytest.mark.parametrize("explicit", [True, False])
|
||||
def test_single_external_implicit_install(install_mockery, explicit):
|
||||
pkg = "trivial-install-test-package"
|
||||
s = spack.spec.Spec(pkg).concretized()
|
||||
s = spack.concretize.concretize_one(pkg)
|
||||
s.external_path = "/usr"
|
||||
args = {"explicit": [s.dag_hash()] if explicit else []}
|
||||
create_installer([s], args).install()
|
||||
@@ -1288,7 +1283,7 @@ def test_single_external_implicit_install(install_mockery, explicit):
|
||||
|
||||
def test_overwrite_install_does_install_build_deps(install_mockery, mock_fetch):
|
||||
"""When overwrite installing something from sources, build deps should be installed."""
|
||||
s = spack.spec.Spec("dtrun3").concretized()
|
||||
s = spack.concretize.concretize_one("dtrun3")
|
||||
create_installer([s]).install()
|
||||
|
||||
# Verify there is a pure build dep
|
||||
@@ -1310,7 +1305,7 @@ def test_overwrite_install_does_install_build_deps(install_mockery, mock_fetch):
|
||||
def test_print_install_test_log_skipped(install_mockery, mock_packages, capfd, run_tests):
|
||||
"""Confirm printing of install log skipped if not run/no failures."""
|
||||
name = "trivial-install-test-package"
|
||||
s = spack.spec.Spec(name).concretized()
|
||||
s = spack.concretize.concretize_one(name)
|
||||
pkg = s.package
|
||||
|
||||
pkg.run_tests = run_tests
|
||||
@@ -1324,7 +1319,7 @@ def test_print_install_test_log_failures(
|
||||
):
|
||||
"""Confirm expected outputs when there are test failures."""
|
||||
name = "trivial-install-test-package"
|
||||
s = spack.spec.Spec(name).concretized()
|
||||
s = spack.concretize.concretize_one(name)
|
||||
pkg = s.package
|
||||
|
||||
# Missing test log is an error
|
||||
|
@@ -29,31 +29,31 @@ def make_executable(tmp_path, working_env):
|
||||
|
||||
|
||||
def test_make_normal():
|
||||
make = MakeExecutable("make", 8)
|
||||
make = MakeExecutable("make", jobs=8)
|
||||
assert make(output=str).strip() == "-j8"
|
||||
assert make("install", output=str).strip() == "-j8 install"
|
||||
|
||||
|
||||
def test_make_explicit():
|
||||
make = MakeExecutable("make", 8)
|
||||
make = MakeExecutable("make", jobs=8)
|
||||
assert make(parallel=True, output=str).strip() == "-j8"
|
||||
assert make("install", parallel=True, output=str).strip() == "-j8 install"
|
||||
|
||||
|
||||
def test_make_one_job():
|
||||
make = MakeExecutable("make", 1)
|
||||
make = MakeExecutable("make", jobs=1)
|
||||
assert make(output=str).strip() == "-j1"
|
||||
assert make("install", output=str).strip() == "-j1 install"
|
||||
|
||||
|
||||
def test_make_parallel_false():
|
||||
make = MakeExecutable("make", 8)
|
||||
make = MakeExecutable("make", jobs=8)
|
||||
assert make(parallel=False, output=str).strip() == "-j1"
|
||||
assert make("install", parallel=False, output=str).strip() == "-j1 install"
|
||||
|
||||
|
||||
def test_make_parallel_disabled(monkeypatch):
|
||||
make = MakeExecutable("make", 8)
|
||||
make = MakeExecutable("make", jobs=8)
|
||||
|
||||
monkeypatch.setenv("SPACK_NO_PARALLEL_MAKE", "true")
|
||||
assert make(output=str).strip() == "-j1"
|
||||
@@ -74,7 +74,7 @@ def test_make_parallel_disabled(monkeypatch):
|
||||
|
||||
|
||||
def test_make_parallel_precedence(monkeypatch):
|
||||
make = MakeExecutable("make", 8)
|
||||
make = MakeExecutable("make", jobs=8)
|
||||
|
||||
# These should work
|
||||
monkeypatch.setenv("SPACK_NO_PARALLEL_MAKE", "true")
|
||||
@@ -96,21 +96,21 @@ def test_make_parallel_precedence(monkeypatch):
|
||||
|
||||
|
||||
def test_make_jobs_env():
|
||||
make = MakeExecutable("make", 8)
|
||||
make = MakeExecutable("make", jobs=8)
|
||||
dump_env = {}
|
||||
assert make(output=str, jobs_env="MAKE_PARALLELISM", _dump_env=dump_env).strip() == "-j8"
|
||||
assert dump_env["MAKE_PARALLELISM"] == "8"
|
||||
|
||||
|
||||
def test_make_jobserver(monkeypatch):
|
||||
make = MakeExecutable("make", 8)
|
||||
make = MakeExecutable("make", jobs=8)
|
||||
monkeypatch.setenv("MAKEFLAGS", "--jobserver-auth=X,Y")
|
||||
assert make(output=str).strip() == ""
|
||||
assert make(parallel=False, output=str).strip() == "-j1"
|
||||
|
||||
|
||||
def test_make_jobserver_not_supported(monkeypatch):
|
||||
make = MakeExecutable("make", 8, supports_jobserver=False)
|
||||
make = MakeExecutable("make", jobs=8, supports_jobserver=False)
|
||||
monkeypatch.setenv("MAKEFLAGS", "--jobserver-auth=X,Y")
|
||||
# Currently fallback on default job count, Maybe it should force -j1 ?
|
||||
assert make(output=str).strip() == "-j8"
|
||||
|
@@ -11,6 +11,7 @@
|
||||
from llnl.util.symlink import resolve_link_target_relative_to_the_link
|
||||
|
||||
import spack.caches
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.fetch_strategy
|
||||
import spack.mirrors.layout
|
||||
@@ -43,7 +44,7 @@ def set_up_package(name, repository, url_attr):
|
||||
2. Point the package's version args at that repo.
|
||||
"""
|
||||
# Set up packages to point at mock repos.
|
||||
s = Spec(name).concretized()
|
||||
s = spack.concretize.concretize_one(name)
|
||||
repos[name] = repository
|
||||
|
||||
# change the fetch args of the first (only) version.
|
||||
@@ -60,7 +61,7 @@ def check_mirror():
|
||||
mirrors = {"spack-mirror-test": url_util.path_to_file_url(mirror_root)}
|
||||
with spack.config.override("mirrors", mirrors):
|
||||
with spack.config.override("config:checksum", False):
|
||||
specs = [Spec(x).concretized() for x in repos]
|
||||
specs = [spack.concretize.concretize_one(x) for x in repos]
|
||||
spack.mirrors.utils.create(mirror_root, specs)
|
||||
|
||||
# Stage directory exists
|
||||
@@ -77,7 +78,7 @@ def check_mirror():
|
||||
|
||||
# Now try to fetch each package.
|
||||
for name, mock_repo in repos.items():
|
||||
spec = Spec(name).concretized()
|
||||
spec = spack.concretize.concretize_one(name)
|
||||
pkg = spec.package
|
||||
|
||||
with spack.config.override("config:checksum", False):
|
||||
@@ -212,13 +213,15 @@ def test_invalid_json_mirror_collection(invalid_json, error_message):
|
||||
|
||||
|
||||
def test_mirror_archive_paths_no_version(mock_packages, mock_archive):
|
||||
spec = Spec("trivial-install-test-package@=nonexistingversion").concretized()
|
||||
spec = spack.concretize.concretize_one(
|
||||
Spec("trivial-install-test-package@=nonexistingversion")
|
||||
)
|
||||
fetcher = spack.fetch_strategy.URLFetchStrategy(url=mock_archive.url)
|
||||
spack.mirrors.layout.default_mirror_layout(fetcher, "per-package-ref", spec)
|
||||
|
||||
|
||||
def test_mirror_with_url_patches(mock_packages, monkeypatch):
|
||||
spec = Spec("patch-several-dependencies").concretized()
|
||||
spec = spack.concretize.concretize_one("patch-several-dependencies")
|
||||
files_cached_in_mirror = set()
|
||||
|
||||
def record_store(_class, fetcher, relative_dst, cosmetic_path=None):
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user