Compare commits

...

423 Commits

Author SHA1 Message Date
Harmen Stoppels
19ac70e149 builtin: add missing commit= to git versions 2025-03-10 16:48:52 +01:00
Robert Maaskant
7d66063bd9 go: v1.22.12, v1.23.7, v1.24.1 (#49389) 2025-03-10 09:24:52 -04:00
Massimiliano Culpo
47c6fb750a spfft: update to use oneapi packages (#49311)
Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-03-10 08:32:49 +01:00
Massimiliano Culpo
8c3ac352b7 suite-sparse: update to use oneapi packages (#49310)
Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-03-10 08:32:01 +01:00
Massimiliano Culpo
d6ac16ca16 dyhidrogen: update to use oneapi packages (#49303)
Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-03-10 08:29:47 +01:00
Peter Scheibel
75e37c6db5 use default modify scope if no scope contains key (#48777)
If you use `spack config change` to modify a `require:` section that did
not exist before, Spack was inserting the merged configuration into the
highest modification scope (which for example would clutter the
environment's `spack.yaml` with a bunch of configuration details 
from the defaults).
2025-03-09 21:31:56 -07:00
Tamara Dahlgren
3f8dcfc6ed Support independent includes with conditional, optional, and remote entries (#48784)
Supersedes #46792.
Closes #40018.
Closes #31026.
Closes #2700.

There were a number of feature requests for os-specific config. This enables os-specific
config without adding a lot of special sub-scopes.

Support `include:` as an independent configuration schema, allowing users to include
configuration scopes from files or directories. Includes can be:
* conditional (similar to definitions in environments), and/or
* optional (i.e., the include will be skipped if it does not exist).

Includes can be paths or URLs (`ftp`, `https`, `http` or `file`). Paths can be absolute or
relative . Environments can include configuration files using the same schema. Remote includes 
must be checked by `sha256`.

Includes can also be recursive, and this modifies the config system accordingly so that
we push included configuration scopes on the stack *before* their including scopes, and
we remove configuration scopes from the stack when their including scopes are removed.

For example, you could have an `include.yaml` file (e.g., under `$HOME/.spack`) to specify
global includes:

```
include:
- ./enable_debug.yaml
- path: https://github.com/spack/spack-configs/blob/main/NREL/configs/mac/config.yaml
  sha256: 37f982915b03de18cc4e722c42c5267bf04e46b6a6d6e0ef3a67871fcb1d258b
```

Or an environment `spack.yaml`:

```
spack:
  include:
  - path: "/path/to/a/config-dir-or-file"
    when: os == "ventura"
  - ./path/relative/to/containing/file/that/is/required
  - path: "/path/with/spack/variables/$os/$target"
    optional: true
  - path: https://raw.githubusercontent.com/spack/spack-configs/refs/heads/main/path/to/required/raw/config.yaml
    sha256: 26e871804a92cd07bb3d611b31b4156ae93d35b6a6d6e0ef3a67871fcb1d258b
```

Updated TODO:
- [x] Get existing unit tests to pass with Todd's changes
- [x] Resolve new (or old) circular imports
- [x] Ensure remote includes (global) work
- [x] Ensure remote includes for environments work (note: caches remote
      files under user cache root)
- [x] add sha256 field to include paths, validate, and require for remote includes
- [x] add sha256 remote file unit tests
- [x] revisit how diamond includes should work
- [x] support recursive includes
- [x] add recursive include unit tests
- [x] update docs and unit test to indicate ordering of recursive includes with
      conflicting options is deferred to follow-on work

---------

Signed-off-by: Todd Gamblin <tgamblin@llnl.gov>
Co-authored-by: Peter Scheibel <scheibel1@llnl.gov>
Co-authored-by: Todd Gamblin <tgamblin@llnl.gov>
2025-03-09 19:33:44 -07:00
Satish Balay
07d4915e82 petsc, py-petsc4py: add v3.22.4 (#49374) 2025-03-08 12:23:31 -06:00
Ryan Krattiger
77ff574d94 Revert "CI: Set the cache path for all platforms (#49373)" (#49381)
This reverts commit 50b56ee1ce.
2025-03-08 08:29:05 +01:00
Rémi Lacroix
5783f950cf google-cloud-cli: Install missing "platform" directory (#49367)
Ignore the bundled Python since it's provided by Spack.

This fixes the "gsutil" command.
2025-03-07 23:16:57 -06:00
Edoardo Zoni
1c76c88f2c WarpX & pyAMReX 25.03 (#49328)
* pyAMReX 25.03

* Adding EZoni to pyAMReX Spack package maintainers

* WarpX 25.03

* Fix SHA-256 checksums

---------

Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja>
2025-03-07 21:03:28 -08:00
Ryan Krattiger
50b56ee1ce CI: Set the cache path for all platforms (#49373)
The SPACK_USER_CACHE_PATH was being overwritten in the windows CI
before_script. This should set the path for all systems unless
explicitly overridden.
2025-03-07 17:07:56 -06:00
wspear
be521c441e Conflict bugged +comm variant (#49371)
This will be fixed in the next tau release. Conflicted up to current. @kwryankrattiger
2025-03-07 16:29:46 -06:00
Wouter Deconinck
61ffb87757 actsvg: add v0.4.51 (#49352) 2025-03-07 16:53:02 +01:00
Chris Marsh
950b4c5847 py-rpy2: add missing libiconv (#49355)
* add missing libiconv

* use the virtual provider
2025-03-07 08:16:39 -06:00
Piotr Sacharuk
ac078f262d raja: Apply workarounds for oneAPI compiler for problem with build (#49290) 2025-03-07 06:44:11 -05:00
Harmen Stoppels
fd62f0f3a8 repo create: set api: vX.Y (#49344) 2025-03-07 08:34:55 +01:00
Chris White
ca977ea9e1 Fix missing hipBlas symbol (#49298)
Co-authored-by: Eric B. Chin <chin23@llnl.gov>
Co-authored-by: Greg Becker <becker33@llnl.gov>
2025-03-06 13:43:18 -08:00
Robert Maaskant
0d2c624bcb glib: add v2.82.5 (#49281) 2025-03-06 17:49:14 +01:00
Alec Scott
765b6b7150 py-aiojobs: new-package (#49329)
* py-aiojobs: new-package

* Update var/spack/repos/builtin/packages/py-aiojobs/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* Fix minimum required python dependency based on feedback

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-03-06 07:11:06 -06:00
Seth R. Johnson
a91f96292c vecgeom: add development version of surface branch (#49313)
* vecgeom: add development version of surface branch

* Use tag on main branch

* Get full repo for versioning on master branch
2025-03-06 05:32:33 -05:00
Wouter Deconinck
18487a45ed xz: add v5.4.7, v5.6.2, v5.6.3 (#49330) 2025-03-06 09:47:25 +01:00
Wouter Deconinck
29485e2125 meson: add v1.5.2, v1.6.1, v1.7.0 (#49244) 2025-03-05 22:36:06 -06:00
dependabot[bot]
7674ea0b7d build(deps): bump types-six in /.github/workflows/requirements/style (#49295)
Bumps [types-six](https://github.com/python/typeshed) from 1.17.0.20241205 to 1.17.0.20250304.
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-six
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-05 22:34:49 -06:00
Wouter Deconinck
693376ea97 qt-*: add v6.8.2 (#49320) 2025-03-05 20:03:34 -07:00
Massimiliano Culpo
88bf2a8bcf globalarrays: add unconditional dep on C++ (#49317)
See https://gitlab.spack.io/spack/spack/-/jobs/15482194

Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-03-05 20:03:09 -07:00
Wouter Deconinck
03e9ca0a76 QtPackage: set QT_ADDITIONAL_SBOM_DOCUMENT_PATHS (#49319)
* QtPackage: set QT_ADDITIONAL_SBOM_DOCUMENT_PATHS

* QtPackage: self.spec.satisfies("@6.9:")

* QtPackage: if self.spec.satisfies("@6.9:")
2025-03-05 19:53:35 -07:00
Massimiliano Culpo
18399d0bd1 qt-svg: add dependency on C (#49316)
https://gitlab.spack.io/spack/spack/-/jobs/15482214

Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-03-05 19:53:10 -07:00
Dan Bonachea
3aabff77d7 GASNet 2025.2 update (#49327)
* gasnet: deprecate old versions
  GASNet versions more than 2 years old are not supported.
  Update description text.
* gasnet: add 2025.2.0-snapshot version
2025-03-05 19:48:31 -07:00
Chris Marsh
aa86342814 Ensure if TCL is already sourced on the system the lib paths don't interfere with spack's install step (#49325) 2025-03-05 19:48:04 -07:00
Weiqun Zhang
170a276f18 amrex: add v25.03 (#49252)
Starting from amrex-25.03, FFT is enabled by default in spack build.
2025-03-05 15:53:25 -08:00
Massimiliano Culpo
313524dc6d qrupdate: update to use oneapi packages (#49304)
Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-03-05 13:44:37 -05:00
Massimiliano Culpo
5aae6e25a5 arpack-ng: update to use oneapi packages (#49302)
Also, remove deprecated versions

Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-03-05 13:44:13 -05:00
Massimiliano Culpo
b58a52b6ce abinit: update to use oneapi packages (#49301)
Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-03-05 13:44:01 -05:00
Chris White
32760e2885 sundials: expand patch when rule (#49296) 2025-03-05 16:13:19 +01:00
Harmen Stoppels
125feb125c Define Package API version (#49274)
Defines `spack.package_api_version` and `spack.min_package_api_version` 
as tuples (major, minor). 

This defines resp. the current Package API version implemented by this version 
of Spack and the minimal Package API version it is backwards compatible with.

Repositories can optionally define:
```yaml
repo:
    namespace: my_repo
    api: v1.2
```
which indicates they are compatible with versions of Spack that implement 
Package API `>= 1.2` and `< 2.0`. When the `api` key is omitted, the default 
`v1.0` is assumed.
2025-03-05 15:42:48 +01:00
Wouter Deconinck
8677063142 QtPackage: modify QT_ADDITIONAL_PACKAGES_PREFIX_PATH handling (#49297)
* QtPackage: mv QT_ADDITIONAL_PACKAGES_PREFIX_PATH handling

* geomodel: support Qt6

* qt-base: rm import re
2025-03-05 09:09:32 -05:00
Massimiliano Culpo
f015b18230 hydrogen: update to use oneapi packages (#49293)
Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-03-05 09:06:32 +01:00
Massimiliano Culpo
aa9e610fa6 elemental: remove deprecated package (#49291)
This package has not been maintained since 2016.

We maintain an active fork in the hydrogen
package, so remove this one.

Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-03-05 08:36:05 +01:00
Wouter Deconinck
7d62045c30 py-networkx: add up to v3.4.2 (#49289)
* py-networkx: add new versions up to 3.4.2
* py-networkx: add more requirements
* py-networkx: fix typo
* py-networkx: fix python and py-setuptools dependencies

---------

Co-authored-by: Joseph C Wang <joequant@gmail.com>
2025-03-04 17:02:54 -08:00
Chris Marsh
5b03173b99 r-packages: add missing gettext dependencies (#48910)
* add gettext dependency

* typo

* style
2025-03-04 17:07:01 -06:00
mvlopri
36fcdb8cfa Update the incorrect sha for the SEACAS package.py (#49292)
The sha256sum for the 2025-02-27 version of SEACAS is incorrect
due to the movement of the tagged version.
2025-03-04 16:03:28 -07:00
Chris Marsh
7d5b17fbf2 py-rpy2: Add 3.5.17 (#48911)
* Update rpy2 to newest version and clean up package

* Add me as maintainer

* Update depends section as per review. Add ipython variant. Fix some ranges and add support for python 3.9. Deprecated outdated versions

* refine depends_on and remove redundant version info

* style
2025-03-04 15:58:12 -07:00
Piotr Sacharuk
d6e3292955 flux-sched: Apply workarounds for oneAPI compiler for problem with build (#49282) 2025-03-04 15:28:33 -07:00
Chris Marsh
60f54df964 Explicitly depend on gettext for libintl (#48908) 2025-03-04 16:25:31 -06:00
Wouter Deconinck
487df807cc veccore: add typo fix for clang (#49288)
* veccore: add typo for clang

* veccore: apply ScalarWrapper.h patch for all compilers

---------

Co-authored-by: Joseph C Wang <joequant@gmail.com>
2025-03-04 14:35:47 -07:00
Zack Galbreath
cacdf84964 ci: add support for high priority local mirror (#49264) 2025-03-04 14:47:37 -06:00
fbrechin
e2293c758f Adding ability for repo paths from a manifest file to be expanded when creating an environment. (#49084)
* Adding ability for repo paths from a manifest file to be expanded when creating an environment.

A unit test was added to check that an environment variable will be expanded.
Also, a bug was fixed in the expansion of develop paths where if an environment variable
was in the path that then produced an absolute path the path would not be extended.

* Fixing new unit test for env repo var substitution

* Adding ability for repo paths from a manifest file to be expanded when creating an environment.

A unit test was added to check that an environment variable will be expanded.
Also, a bug was fixed in the expansion of develop paths where if an environment variable
was in the path that then produced an absolute path the path would not be extended.

* Messed up resolving last rebase
2025-03-04 09:52:28 -08:00
Harmen Stoppels
f5a275adf5 gitignore: remove *_archive (#49278) 2025-03-04 18:37:18 +01:00
Paul
615ced32cd protobuf: add v3.29.3 (#49246) 2025-03-04 11:29:53 -06:00
Massimiliano Culpo
bc04d963e5 Remove debug print statements in unit-tests (#49280)
Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-03-04 18:29:45 +01:00
Taillefumier Mathieu
11051ce5c7 CP2K: Add GRPP support (#49232) 2025-03-04 06:54:27 -07:00
Adam J. Stewart
631bddc52e py-pyarrow: add v19.0.1 (#49149)
* py-pyarrow: add v19.0.1

* Environment variables no longer needed either

* Remove py-pyarrow variants
2025-03-04 13:20:52 +01:00
Adam J. Stewart
b5f40aa7fb OpenCV: fix +cuda build (#49146) 2025-03-04 13:19:57 +01:00
Adam J. Stewart
57e0798af2 py-pip: mark Python 3.12+ support (#49148) 2025-03-04 13:18:38 +01:00
Chris White
0161b662f7 conduit: do not pass link flags to ar (#49263) 2025-03-03 19:53:11 -07:00
afzpatel
aa55b19680 fix +asan in ROCm packages (#48745)
* fix asan for hsa-rocr-dev
* add libclang_rt.asan-x86_64.so to LD_LIBRARY_PATH
* fix +asan for hipsparselt
* fix rocm-openmp-extras asan and add rccl +asan support
* add missing comgr build env variables
* add missing rocm-smi-lib build env variables
* minor dependency change
* fix style
2025-03-03 17:57:34 -08:00
dependabot[bot]
8cfffd88fa build(deps): bump pytest from 8.3.4 to 8.3.5 in /lib/spack/docs (#49268)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.4 to 8.3.5.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.4...8.3.5)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 19:18:42 -06:00
dependabot[bot]
2f8dcb8097 build(deps): bump python-levenshtein in /lib/spack/docs (#49269)
Bumps [python-levenshtein](https://github.com/rapidfuzz/python-Levenshtein) from 0.26.1 to 0.27.1.
- [Release notes](https://github.com/rapidfuzz/python-Levenshtein/releases)
- [Changelog](https://github.com/rapidfuzz/python-Levenshtein/blob/main/HISTORY.md)
- [Commits](https://github.com/rapidfuzz/python-Levenshtein/compare/v0.26.1...v0.27.1)

---
updated-dependencies:
- dependency-name: python-levenshtein
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 19:17:48 -06:00
dependabot[bot]
5b70fa8cc8 build(deps): bump sphinx from 8.2.1 to 8.2.3 in /lib/spack/docs (#49270)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 8.2.1 to 8.2.3.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES.rst)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v8.2.1...v8.2.3)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 19:17:08 -06:00
Adam J. Stewart
b4025e89ed py-torchmetrics: add v1.6.2 (#49262) 2025-03-03 19:15:49 -06:00
Eric Berquist
8db74e1b2f tmux: add 3.5a, 3.5, and 3.3 (#49259)
* tmux: add 3.5a, 3.5, and 3.3

* tmux: patch is in releases from 3.5 onward

* tmux: versions 3.5 and newer can use jemalloc
2025-03-03 19:12:45 -06:00
Wouter Deconinck
1fcfbadba7 qwt: add v6.2.0, v6.3.0, support Qt6 (#45604)
* qwt: support building against Qt6

* qwt: fix style

* qwt: depends_on qt-base+opengl+widgets when +opengl

* visit: patch for missing cmath include

---------

Co-authored-by: Bernhard Kaindl <contact@bernhard.kaindl.dev>
2025-03-03 16:25:48 -08:00
Chris White
13ec35873f Axom: Changes from Axom repository (#49183)
* pull in new changes from axom project

* add new versions

* convert more conditionals to spec.satisfies

-------------
Co-authored-by: white238 <white238@users.noreply.github.com>
2025-03-03 15:47:45 -08:00
Philip Fackler
f96b6eac2b xolotl: new package (#48876)
* Adding xolotl package

* [@spackbot] updating style on behalf of PhilipFackler

* Removing redundant text

* Add blank line

* Update var/spack/repos/builtin/packages/xolotl/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* Update var/spack/repos/builtin/packages/xolotl/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* Switch to CudaPackage and remove source dir from runtime env

* [@spackbot] updating style on behalf of PhilipFackler

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-03-03 15:18:28 -06:00
Rocco Meli
933a1a5cd9 update (#49261) 2025-03-03 10:38:10 -07:00
Stephen Nicholas Swatman
b2b9914efc acts dependencies: new versions as of 2025/03/03 (#49253)
This commit adds ACTS version 39.2.0 and detray version 0.89.0.
2025-03-03 09:32:59 -07:00
Rocco Meli
9ce9596981 multicharge: add v0.3.1 (#49255)
* multicharge: add v0.3.1

* fix url
2025-03-03 15:32:29 +01:00
Wouter Deconinck
fc30fe1f6b librsvg: add v2.56.4, v2.57.3, v2.58.2 (#45734)
* librsvg: add v2.56.4, v2.57.3, v2.58.2

---------

Co-authored-by: Harmen Stoppels <me@harmenstoppels.nl>
2025-03-02 14:08:43 -08:00
Paul
25a4b98359 jacamar-ci: add v0.25.0 (#49248) 2025-03-02 14:50:43 -06:00
Adam J. Stewart
05c34b7312 py-pymc3: not compatible with numpy 2 (#49225) 2025-03-01 13:43:05 -06:00
Tahmid Khan
b22842af56 globalarrays: Add variant cxx which adds the --enable-cxx flag (#49241) 2025-03-01 13:16:04 -06:00
Vanessasaurus
0bef028692 Automated deployment to update package flux-sched 2025-02-28 (#49229)
Co-authored-by: github-actions <github-actions@users.noreply.github.com>
2025-03-01 08:48:41 -07:00
Vanessasaurus
935facd069 Automated deployment to update package flux-security 2025-02-28 (#49230)
Co-authored-by: github-actions <github-actions@users.noreply.github.com>
2025-03-01 08:47:19 -07:00
Adam J. Stewart
87e5255bbc py-matplotlib: add v3.10.1 (#49233) 2025-03-01 16:22:49 +01:00
dependabot[bot]
b42f0d793d build(deps): bump isort in /.github/workflows/requirements/style (#49212)
Bumps [isort](https://github.com/PyCQA/isort) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/PyCQA/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/PyCQA/isort/compare/6.0.0...6.0.1)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-01 08:18:06 -07:00
dependabot[bot]
ccca0d3354 build(deps): bump isort from 6.0.0 to 6.0.1 in /lib/spack/docs (#49213)
Bumps [isort](https://github.com/PyCQA/isort) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/PyCQA/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/PyCQA/isort/compare/6.0.0...6.0.1)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-01 08:17:39 -07:00
HELICS-bot
9699bbc7b9 helics: Add version 3.6.1 (#49231)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-03-01 08:16:21 -07:00
Raffaele Solcà
c7e251de9f Add dla-future v0.8.0 (#49235) 2025-03-01 08:14:52 -07:00
Robert Maaskant
d788b15529 libmd: add version 1.1.0 (#49239)
Release notes can be read at https://archive.hadrons.org/software/libmd/libmd-1.1.0.announce
2025-03-01 08:11:12 -07:00
Harmen Stoppels
8e7489bc17 Revert "Honor cmake_prefix_paths property if available (#42569)" (#49237)
This reverts commit fe171a560b.
2025-02-28 23:33:02 +01:00
John W. Parent
d234df62d7 Solver: Cache Concretization Results (#48198)
Concretizer caching for reusing solver results
2025-02-28 12:42:00 -06:00
Mikhail Titov
4a5922a0ec py-radical-*: new version 1.90 (#48586)
* rct: update packages (RE, RG, RP, RS, RU) with new version 1.90

* radical: added `url_for_version` for older versions

* radical: set latest versions for `radical.pilot` and `radical.utils`

* radical: fixed `url_for_version` setup

* radical: set the latest version for `radical.entk`

* radical: fixed style for `url_for_version`

* Apply suggestions from code review (python version dependency)

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-28 07:38:45 -07:00
John W. Parent
5bd184aaaf Windows Rpath: Allow package test rpaths (#47072)
On Windows, libraries search their directory for dependencies, and
we help libraries in Spack-built packages locate their dependencies
by symlinking them into the dependent's directory (we refer to this
as simulated RPATHing).

We extend the convenience functionality here to support base library
directories outside of the package prefix: this is primarily for
running tests in the build directory (which is not located inside
of the final install prefix chosen by spack).
2025-02-27 19:16:00 -08:00
Mikael Simberg
464c3b96fa fmt: Add 11.1.4 (#49218) 2025-02-27 19:12:26 -06:00
Scott Wittenburg
60544a4e84 ci: avoid py-mpi4py tests on darwin (#49227) 2025-02-27 18:07:59 -07:00
Greg Sjaardema
a664d98f37 seacas: new version with change set support (#49224)
This release contains modifications to most of the SEACAS applications to support ChangeSets to some degree.
See https://github.com/SandiaLabs/seacas/wiki/Dynamic_Topology for information about Change Sets and
See https://github.com/SandiaLabs/seacas/wiki/Supporting-Change-Sets for information about how the various seacas applications are supporting the use or creation of change sets.

The release also includes various other small changes including formatting, portability, intallation, TPL version updates, and spelling.
2025-02-27 18:02:51 -07:00
Sinan
0e3d7efb0f alps: add conflict (#48751)
Co-authored-by: Sinan81 <Sinan@world>
Co-authored-by: Sinan81 <Sinan81@users.noreply.github.com>
2025-02-27 17:57:55 -07:00
Chris Green
a8cd0b99f3 New recipes for PlantUML and py-sphinxcontrib-plantuml (#49204)
* new-recipe: plantuml
* new-recipe: py-sphinxcontrib-plantuml
2025-02-27 16:57:23 -08:00
Alec Scott
a43df598a1 rust: add v1.85.0 (#49158) 2025-02-27 13:18:23 -06:00
Alec Scott
a7163cd0fa gnutls: add master, improve styling (#49080) 2025-02-27 13:13:23 -06:00
Kyle Knoepfel
fe171a560b Honor cmake_prefix_paths property if available (#42569)
* Honor package-specified cmake_prefix_paths at runtime

* Add paths in the correct order and prune duplicates

* Normalize paths for windows' sake
2025-02-27 11:11:22 -07:00
Ritwik Patil
24abc3294a sendme: new package (#49133)
* add sendme package

* style fix

* add docstring for test function

* changed maintainer string, run test after install

* removed redundant test

* Follow the common package license header format

Co-authored-by: Alec Scott <hi@alecbcs.com>

---------

Co-authored-by: Alec Scott <hi@alecbcs.com>
2025-02-27 09:59:09 -07:00
MatthewLieber
2dea0073b2 mvapich-plus: new package (#48507)
* add mvapich-plus 4.0

* run spack style fix

* fix license issue

* change styling of mvapich-plus package based on review

* using spack style --fix

* fix more typos

* Apply suggestions from code review

Co-authored-by: Alec Scott <hi@alecbcs.com>

* Adding CudaPackage and RocmPackage Mixins

---------

Co-authored-by: Matt Lieber <lieber.31@osu.edu>
Co-authored-by: Alec Scott <hi@alecbcs.com>
2025-02-27 09:36:26 -07:00
Massimiliano Culpo
31ecefbfd2 heppdt: add dependency on C (#49219)
Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-02-27 08:10:19 -06:00
Harmen Stoppels
7363047b82 schema: additionalKeysAreSpecs (#49221)
Currently we validate all keys as specs, but it's meant to validate only additional keys in all cases.
2025-02-27 12:17:25 +01:00
Massimiliano Culpo
12fe7aef65 pipelines: extract changes from compiler as nodes (#49222)
* Split requirements to get better error messages in case of unsat solves.
* use list requirements instead of string
* activate static_analysis in a few pipelines

Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-02-27 12:13:34 +01:00
Harmen Stoppels
5da4f18188 schema/modules.py: remove lmod props from tcl schema (#49220) 2025-02-27 10:48:22 +01:00
Marc T. Henry de Frahan
61c54ed28b Remove FSI variant from Nalu-Wind (#49209)
* Remove fsi variant from Nalu-Wind

* fix exawind
2025-02-26 16:57:56 -07:00
eugeneswalker
677caec3c6 Ci reactivate darwin pipelines (#48453)
* ci: darwin stacks: update tags following system updates

* disable SPACK_CI_DISABLE_STACKS; only enable *darwin* stacks for testing

* manually chmod u+w tmp/ before cleanup due to issue#49147

* comment out failing specs for now

* re-enable logic for disabling stacks

* add explanatory comment for darwin after_script additions

* remove more darwin-only targetting

* restore build_stage to default location

* move build-job-remove out of individual darwin stacks into darwin top level config

* keep build_stage in $spack/tmp for now
2025-02-26 17:34:22 -06:00
eugeneswalker
b914bd6638 e4s oneapi ci stack: mpi: require intel-oneapi-mpi (#49043)
* e4s oneapi ci stack: mpi: require intel-oneapi-mpi

* nrm ^py-scipy cflags="-Wno-error=incompatible-function-pointer-types"

* add explanatory comment
2025-02-26 23:07:57 +00:00
Massimiliano Culpo
3caa3132aa python: allow it as a build-tool again (#49201)
Python was removed from being a build tool in #46980, due to issues
when reusing specs. This PR adds a new rule to match the interpreter
among different Python packages, in clingo.

It also adds a bunch of new "build-tools", so that specs like:
```
py-matplotlib backend=tkagg
```
can be concretized in one go.

Modifications:
- [x] Make `py-matplotlib backend=tkagg` concretizable
- [x] Add unit-tests to ensure situations like in #46980 do not happen

---------

Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-02-26 15:04:31 -08:00
Massimiliano Culpo
dbd531112c Assign priorities to configuration scopes (take 2) (#49187)
Currently, the custom config scopes are pushed at the top when constructing
configuration, and are demoted whenever a context manager activating an
environment is used - see #48414 for details. Workflows that rely on the order
in the [docs](https://spack.readthedocs.io/en/latest/configuration.html#custom-scopes)
are thus fragile, and may break

This PR allows to assign priorities to scopes, and ensures that scopes of lower priorities
are always "below" scopes of higher priorities. When scopes have the same priority,
what matters is the insertion order.

Modifications:
- [x] Add a mapping that iterates over keys according to priorities set when
      adding the key/value pair
- [x] Use that mapping to allow assigning priorities to configuration scopes
- [x] Assign different priorities for different kind of scopes, to fix a bug, and
      add a regression test
- [x] Simplify `Configuration` constructor
- [x] Remove `Configuration.pop_scope`

---------

Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-02-26 10:52:19 -08:00
psakievich
ae5e121502 Preserve --lines (#49194)
This does not propagate in parsing. Open to other ideas.
2025-02-26 17:48:01 +00:00
snehring
929cfc8e5a relion: add v5.0.0 (#49174)
Signed-off-by: Shane Nehring <snehring@iastate.edu>
2025-02-26 09:17:54 -08:00
Chris Marsh
bad28e7f9f py-natsort: add new variant +icu and dependent package (#48907)
* Add new package py-pyicu to support new py-natsort variant +icu

* note version req location

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* bound icu variant

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-26 10:42:13 -06:00
Patrick Lavin
3d63fe91b0 sst-elements: add support for --enable-ariel-mpi flag (#49135) 2025-02-26 07:30:51 -07:00
Mikhail Titov
95af020310 py-psij-python: new version 0.9.9 (#48610)
* py-psij-python: new version 0.9.9

* Update var/spack/repos/builtin/packages/py-psij-python/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* fixed py3.8 dependency

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-26 08:13:48 -06:00
Seth R. Johnson
2147b9d95e g4vg: new version 1.0.3 (#49195) 2025-02-25 16:27:41 -06:00
psakievich
68636e7c19 lua-lpeg inheritance fix (#49065)
The parent class function doesn't return the path to the config file. This is one potential fix, or we can add the return back to base builder.
2025-02-25 15:14:54 -07:00
Elsa Gonsiorowski, PhD
f56675648a mpifileutils: add v0.12 (#49132)
* mpifileutils: update for v0.12 release

* removed @adammoody from maintainers
2025-02-25 13:39:25 -07:00
Tara Drwenski
3a219d114d Petsc: add in hipblas dependency on hipblas-common (#49017) 2025-02-25 10:35:36 -06:00
Wouter Deconinck
3cefa7047c davix: add v0.8.8, v0.8.9, v0.8.10 (#49057)
* davix: add v0.8.8, v0.8.9, v0.8.10

* davix: url_for_version

* davix: depends on googletest when @0.8.8: (type test, maybe build)

* davix: define DAVIX_TESTS
2025-02-25 10:05:31 -06:00
Cédric Chevalier
35013773ba Fix setup.fish syntax (#49176)
* Fix setup.fish syntax

* Simplify conditional in share/spack/setup-env.fish

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-25 07:11:55 -06:00
AMD Toolchain Support
e28379e98b python: limit parallellism in compileall (#48441) 2025-02-25 13:54:59 +01:00
afzpatel
93329d7f99 add ck variant to miopen-hip (#49143) 2025-02-25 05:48:49 -07:00
Massimiliano Culpo
9e508b0321 Revert "Assign priorities to configuration scopes (#48420)" (#49185)
All the build jobs in pipelines are apparently relying on the bug that was fixed.

The issue was not caught in the PR because generation jobs were fine, and
there was nothing to rebuild.

Reverting to fix pipelines in a new PR.

This reverts commit 3ad99d75f9.
2025-02-25 02:33:41 -08:00
Adam J. Stewart
2c26c429a7 py-sphinx: add v8.2.0 (#49107) 2025-02-25 10:44:58 +01:00
dependabot[bot]
1cc63e2b7c build(deps): bump sphinx from 8.2.0 to 8.2.1 in /lib/spack/docs (#49180)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 8.2.0 to 8.2.1.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/v8.2.1/CHANGES.rst)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v8.2.0...v8.2.1)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 02:33:03 -07:00
Harmen Stoppels
4e311a22d0 spec.py: remove VariantMap.concrete (#49170)
VariantMap.concrete is unused, and would be incorrect if it were used
due to conditional variants.

Just let the Spec dictate what is concrete and what is not.
2025-02-25 10:18:06 +01:00
Massimiliano Culpo
3ad99d75f9 Assign priorities to configuration scopes (#48420)
Currently, environments can end up with higher priority than `-C` custom
config scopes and `-c` command line arguments sometimes. This shouldn't
happen -- those explicit CLI scopes should override active environments.

Up to now configuration behaved like a stack, where scopes could be only be
pushed at the top. This PR allows to assign priorities to scopes, and ensures
that scopes of lower priorities are always "below" scopes of higher priorities.

When scopes have the same priority, what matters is the insertion order.

Modifications:
- [x] Add a mapping that iterates over keys according to priorities set when
      adding the key/value pair
- [x] Use that mapping to allow assigning priorities to configuration scopes
- [x] Assign different priorities for different kind of scopes, to fix a bug, and
      add a regression test
- [x] Simplify `Configuration` constructor
- [x] Remove `Configuration.pop_scope`
- [x] Remove `unify:false` from custom `-C` scope in pipelines

On the last modification: on `develop`, pipelines are relying on the environment
being able to override `-C` scopes, which is a bug. After this fix, we need to be
explicit about the unification strategy in each stack, and remove the blanket
`unify:false` from the highest priority scope

Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-02-25 00:58:16 -08:00
Adam J. Stewart
b79c01077d py-sympy: add v1.13.1 (#48951)
* py-sympy: add v1.13.1
2025-02-24 15:09:00 -08:00
Jim Galarowicz
4385f36b8d survey: add latest releases and python path settings for building with autoload none. Ref issue: 42535 (#48050)
* Update survey package file with latest releases and python path settings for building with autoload none.
* Submitting reformatted file.
* update survey package file with libmonitor dependency changes, take out py-gpustat, and minor comment change.
* Trigger build.
2025-02-24 15:04:40 -08:00
Axel Huebl
a85f1cfa4b WarpX 25.02 (#48917)
* pyAMReX: 25.02
* PICMI: 0.33.0
* WarpX: 25.02
* `amrex +fft` depends on `pkgconfig`
* Updated CMake logic uses `pkgconfig`
2025-02-24 14:48:27 -08:00
Melven Roehrig-Zoellner
13524fa8ed gcc: fix package.py for gcc@:9 (#49173) 2025-02-24 15:44:04 -07:00
Mikael Simberg
738c73975e mimalloc: Add new versions (#49168) 2025-02-24 13:04:22 -07:00
Mikael Simberg
bf9d72f87b ut: Add 2.3.0 (#49169) 2025-02-24 12:59:31 -07:00
Mikael Simberg
674cca3c4a asio: add 1.32.0 (#49167) 2025-02-24 12:39:18 -07:00
Cory Quammen
7a95e2beb5 paraview: add patch for Intel Classic compilers (#49116)
ParaView 5.12.0 through 5.13.2 do not compile. See
https://gitlab.kitware.com/vtk/vtk/-/issues/19620.
2025-02-24 11:27:03 -06:00
Adam J. Stewart
5ab71814a9 py-torchgeo: correct pyvista dep (#49140) 2025-02-24 09:06:33 -08:00
Harmen Stoppels
e783a2851d Revert "Repo.packages_with_tags: do not construct a set of all packages (#49141)" (#49172)
This reverts commit 0da5bafaf2.
2025-02-24 16:46:41 +01:00
Stephen Nicholas Swatman
29e3a28071 vecmem: add v1.14.0 (#49166)
This commit adds version 1.14.0 of the vecmem package.
2025-02-24 08:08:52 -06:00
Harmen Stoppels
4e7a5e9362 spack verify libraries: verify dependencies of installed packages can be resolved (#49124)
Currently, we have `config:shared_linking:missing_library_policy` to error
or warn when shared libraries cannot be resolved upon install.

The new `spack verify libraries` command allows users to run this post
install hook at any point in time to check whether their current
installations can resolve shared libs in rpaths.
2025-02-24 11:28:06 +01:00
Harmen Stoppels
89d1dfa340 python: deprecate old patch versions, remove patches that do not apply (#48958) 2025-02-24 03:23:05 -07:00
Harmen Stoppels
974abc8067 Add typehints for directory_layout / Spec.prefix (#48652) 2025-02-24 09:47:07 +00:00
Massimiliano Culpo
2f9ad5f34d spec.py: fix virtual reconstruction for old specs (#49103)
Co-authored-by: Harmen Stoppels <me@harmenstoppels.nl>
2025-02-24 01:23:37 -07:00
Harmen Stoppels
9555ceeb8a glib: various fixes (#48840)
* remove preferred to allow seamless python@3.12 usage

* glib: remove deprecated versions

* glib: use extends because python-venv is pulled in from build deps and put into path

* dont patch patch versions, use new patch releases containing the fix instead

* restrict patch of shebangs, group relevant bits together

* simplify lowerbound

* fix pinned glib version

---------

Co-authored-by: Chris Marsh <chrismarsh.c2@gmail.com>
2025-02-24 09:17:45 +01:00
Harmen Stoppels
6cd74efa90 Spec.ensure_external_path_if_external, Spec.inject_patches_variant -> spack.solver.asp (#48988)
y
2025-02-24 08:36:23 +01:00
Wouter Deconinck
3b3735a2cc root: add v6.34.04 (#49163)
* root: add v6.34.04

* root: add conflict for gcc-15 with earlier versions

---------

Co-authored-by: Patrick Gartung <gartung@fnal.gov>
2025-02-23 22:17:47 -07:00
dependabot[bot]
2ffbc0d053 build(deps): bump mypy in /.github/workflows/requirements/style (#49165)
Bumps [mypy](https://github.com/python/mypy) from 1.11.2 to 1.15.0.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.11.2...v1.15.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-23 22:29:24 -06:00
Dom Heinzeller
a92419ffe4 Partial bug fix + conflict for compiling node-js@21: with gcc@11.2 (#48494)
* Bug fix for compiling node-js@21: with gcc@11.2 (var/spack/repos/builtin/packages/node-js/package.py var/spack/repos/builtin/packages/node-js/wasm-compiler-gcc11p2.patch)

Since this bug fix is not sufficient, add a conflict for node-js@21: with gcc@11.2

* In var/spack/repos/builtin/packages/node-js/package.py, restrict patch wasm-compiler-gcc11p2.patch to versions 21:22 for gcc@11.2
2025-02-23 19:13:56 -06:00
Juan Miguel Carceller
92c16d085f gtkplus: add conflict with GCC 14 (#48661)
* gtkplus: add conflict with GCC 14

* gtkplus: conflict gcc@14: when @:3.24.35

---------

Co-authored-by: jmcarcell <jmcarcell@users.noreply.github.com>
Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-23 15:28:55 -07:00
Adam J. Stewart
c94024d51d py-timm: add v1.0.15 (#49159) 2025-02-23 14:43:33 -07:00
Harmen Stoppels
11915ca568 apr-util: add missing libxcrypt (#49160) 2025-02-23 13:30:09 -07:00
Buldram
4729b6e837 chafa: new package (#49162)
* chafa: new package

* Require at least one of +shared/+static
2025-02-23 13:29:50 -07:00
Seth R. Johnson
2f1978cf2f celeritas: add 'develop' branch (#49004)
* Revert "REVERTME: move celeritas changes to another branch"

This reverts commit a063e43aaf.

* Use predicted g4vg version

* Use

* fixup! Use predicted g4vg version

* Use spec for versions and improve dependency specification
2025-02-23 13:29:31 -07:00
Chase Phelps
d4045c1ef3 py-perfdump: new package (#49035)
* py-perfdump: new package

* Update package.py

style

* package.py aktualisieren

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* package.py aktualisieren

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* package.py aktualisieren

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* package.py aktualisieren

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* package.py aktualisieren

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* package.py aktualisieren

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* package.py aktualisieren

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* package.py aktualisieren

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* package.py aktualisieren

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* Update package.py

remove unneeded rpath and pythonroot

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-23 13:29:13 -07:00
Pranav Sivaraman
a0f8aaf4e7 setup-env.fish: fix version checking for completions (#48806) 2025-02-23 20:28:51 +00:00
Wouter Deconinck
b7a5e9ca03 root: add v6.34.00, v6.34.02 (#48129)
* root: add v6.34.00, v6.34.02

* root: prefer 6.32.08

* root: updated variants

* root: treat v6.34 as stable, no preference for v6.32

* root: add variants geom, geombuilder

* delphes: depends on root +geom +opengl

* dd4hep: depends on root +geom

* pandoramonitoring: depends on root +geom

* root: actually pass geom, geombuilder to cmake

---------

Co-authored-by: Patrick Gartung <gartung@fnal.gov>
2025-02-23 12:18:10 -06:00
Adam J. Stewart
7e4b8aa020 py-pyproj: add v3.7.1 (#49066) 2025-02-22 20:46:00 +01:00
Derek Ryan Strong
f5aa15034e Add fpart v1.7.0 (#49119) 2025-02-22 10:54:52 -06:00
Phil Tooley
f210be30d8 LLVM,GCC: Keep stable-series releases a bit longer (#49113) 2025-02-22 09:54:36 -06:00
Richard Berger
c63741a089 py-sphinx-rtd-dark-mode: add version 1.3.0 (#49136) 2025-02-22 08:31:13 -06:00
Andrey Perestoronin
4c99ffd81f new impi intel package 2021.14.2 release (#49114) 2025-02-22 08:02:53 -05:00
Nils Vu
1331332dcf libxsmm: update URL (#49155) 2025-02-22 02:04:49 -07:00
dmagdavector
910a4e6d22 slirp4netns: add v1.2.3, v1.3.1 (#48569) 2025-02-21 16:00:28 -08:00
Piotr Sacharuk
93f1ec20aa Update openturns versions (#48872) 2025-02-21 15:59:23 -08:00
Harmen Stoppels
9edbe5aed1 liburing: requires(...) (#49041)
* liburing: requires

* Update var/spack/repos/builtin/packages/liburing/package.py

Co-authored-by: Alec Scott <hi@alecbcs.com>

---------

Co-authored-by: Alec Scott <hi@alecbcs.com>
2025-02-21 15:45:54 -08:00
Krishna Chilleri
a574c7610b py-schema-salad: add v8.7.20241021092521 and py-mypy: add v1.12.1 (#49127)
* add new versions of dependencies

* modify pypi url for newest version

* add option for url depending on version number

* add version ranges of dependencies

* [@spackbot] updating style on behalf of kchilleri

* remove unnecessary py-cache-control version number
2025-02-21 16:07:32 -07:00
Alec Scott
4742f053af emacs: improve gui variant to cover both linux and macos (#49054)
* emacs: improve gui variant to cover both linux and macos

* emacs: fix optional deps type
2025-02-21 16:16:44 -06:00
Alec Scott
b06c5c7e81 fzf: fix go cache protection to allow delete (#49151) 2025-02-21 13:52:33 -07:00
Tobias Ribizel
03fa150185 typst: add v0.13.0 (#49134)
* spack: add version 0.13

* typst: fix version order

Co-authored-by: Alec Scott <hi@alecbcs.com>

* typst: more precise version requirements

* typst: use build_directory

---------

Co-authored-by: Alec Scott <hi@alecbcs.com>
2025-02-21 11:25:50 -08:00
ByteHamster
b304a2d854 Fix installing rust@nightly (#49098)
Installing `rust@nightly` fails because the package file declares a conflict of rust versions older than `:1.64` with `gcc>=13`. However, because `nightly` is alphanumerically smaller than any actual version number, `nightly` is incorrectly detected to have a conflict with `gcc>=13` as well. Marking `nightly` as an infinity version instead solves this.
2025-02-21 09:53:46 -08:00
Ryan Krattiger
1fa1864b37 Reproducer should deduce artifact root from concrete environment (#45281)
* Reproducer should decude artifact root from concrete environment

* Add documentation on the layout of the artifacts directory

* Use dag hash in the container name

* Add reproducer options to improve local testing

* --use-local-head allows running reproducer with
  the current Spack HEAD commit rather than computing
  a commit for the reproducer

* Add test to verify commits and recreating reproduction environment

* Add test for non-merge commit case

* ci reproduce-build: Drop overwrite option
in favor of throwing an error if the working dir is non-empty
2025-02-21 10:46:43 -06:00
Harmen Stoppels
0da5bafaf2 Repo.packages_with_tags: do not construct a set of all packages (#49141) 2025-02-21 16:23:42 +01:00
Massimiliano Culpo
f4614a4931 Extract some package changes from compiler as deps (#49138) 2025-02-21 12:52:34 +01:00
Harmen Stoppels
b8ec69112f Extracted changes from 45189 (#49137)
Co-Authored-By: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-02-21 10:58:00 +01:00
Massimiliano Culpo
a3645fd372 Make BaseConfiguration pickleable (#47545)
Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-02-21 09:54:22 +01:00
dependabot[bot]
9bcd86071f build(deps): bump sphinx from 8.1.3 to 8.2.0 in /lib/spack/docs (#49118)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 8.1.3 to 8.2.0.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES.rst)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v8.1.3...v8.2.0)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-20 16:42:00 -08:00
Robert Maaskant
b126335800 go: add v1.24.0 (#49104)
* go-bootstrap: add v1.22.12

* go: add v1.24.0

* Reformat package, don't deprecate versions without an active CVE

---------

Co-authored-by: Alec Scott <scott112@llnl.gov>
2025-02-20 16:07:52 -08:00
Derek Ryan Strong
d32b6099b3 sw4: fix build options (#48774)
* Fix sw4 build options

* Update constraint to hdf5@1.14

* Change edit to setup_build_environment

* Use append_flags

* Fix style
2025-02-20 15:02:52 -07:00
Harmen Stoppels
3e8cb852b0 spec.py: use json.dumps directly to avoid hash breakage (#48884) 2025-02-20 17:39:07 +01:00
Richard Berger
c8d7aa1772 lammps: fix pace link dep 2025-02-20 17:37:19 +01:00
Buldram
ec836d740f py-tensorflow: patch for v2.15 build errors (#49001)
* py-tensorflow: patch for v2.15 build errors with new compilers

* py-tensorflow: patch for v2.15 build errors with new compilers

* py-tensorflow: fix clang build and add clang version constraints

* py-tensorflow: use compiler wrapper

* py-tensorflow: relax clang conflict
2025-02-20 13:13:04 +01:00
Teague Sterling
cacdaaf3a9 bcftools: add v1.21, v1.20 (#49070)
Signed-off-by: Teague Sterling <teaguesterling@gmail.com>
2025-02-20 01:58:21 -07:00
Dave Keeshan
165e6b1d5e xnedit: new package (#41255) 2025-02-20 08:03:11 +01:00
Paul
70f5300cf2 Add new package for Jacamar CI (#48424) 2025-02-19 22:18:15 -06:00
Buldram
81e08167e2 nim: fix Musl build with new compilers (#48487)
* nim: fix build with new compilers

* narrow condition for disabling warnings

* move flags into offending module

disables warnings also for compiling projects other than the Nim compiler when necessary

* specify different versions pthread modules

* instead patch SysThread type

* adapt patch for old Nim versions

* Specify hypothetical `:@0.19.6` for patch version constraint
2025-02-19 22:16:12 -06:00
Alex Richert
e9d8c5767b crtm-fix: 3.1.1.2 (#48755)
* crtm-fix: 3.1.1.2

* correct checksum

* exclude test files

* Update package.py
2025-02-19 22:13:08 -06:00
Teague Sterling
4cefa973cd htslib: add v1.21 (#49056)
* Adding variants based of configure flags and an option to compile with PIC

* Adding GCS to htslib

* Revisions from review

Signed-off-by: Teague Sterling <teaguesterling@gmail.com>

* Updating descriptions, fixing flags, fixing version and variant conditions

Signed-off-by: Teague Sterling <teaguesterling@gmail.com>

* htslib: add v1.21

Signed-off-by: Teague Sterling <teaguesterling@gmail.com>

---------

Signed-off-by: Teague Sterling <teaguesterling@gmail.com>
2025-02-19 21:43:10 -06:00
Pruvost Florent
a2bd221ee4 chameleon: update to 1.3.0 (#49112) 2025-02-19 20:03:23 -07:00
Dom Heinzeller
adbb41c7df Bug fixes for fckit (disable finalization of DDTs) and ectrans (disable use of Fortran contiguous keyword) (#49111)
* In var/spack/repos/builtin/packages/ectrans/package.py, always set cmake argument ECTRANS_HAVE_CONTIGUOUS_ISSUE to turn off problematic use of Fortran 'contiguous' keyword
* In var/spack/repos/builtin/packages/ectrans/package.py, always set cmake argument ENABLE_FINAL=OFF to turn off problematic finalization of derived data types
* Update links to issues in fckit and ectrans
* Fix wrong cmake argument for ECTRANS_HAVE_CONTIGUOUS_ISSUE in var/spack/repos/builtin/packages/ectrans/package.py
2025-02-19 20:03:05 -07:00
Joseph Wang
2554c7bd21 py-onnxruntime: add v1.18.0 -> v1.19.2 (#46329)
* py-onnxruntime: add new versions

* py-onnxruntime: add constraints

* py-onnxruntime: fix typo

* py-onnxruntime: fix style

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-19 12:02:27 -08:00
Garth N. Wells
e274e855f1 py-nanobind: add v2.5.0 (#48953)
Also removes inactive maintainer.
2025-02-19 11:47:25 -08:00
Matthew L. Curry
e76ebf2cf7 xz: Work around ASM declaration issue with NVHPC (#49006)
This commit works around an issue described below that xz encounters
during compilation with nvhpc.

https://forums.developer.nvidia.com/t/problem-in-inline-assembly-when-using-multiple-asm-declarations/210952
2025-02-19 11:38:29 -08:00
Pranav Sivaraman
11ba5ebbcd jsoncons: new package (#49105) 2025-02-19 11:13:08 -08:00
Adam J. Stewart
53262b968b py-scikit-image: add v0.25.2 (#49101) 2025-02-19 11:12:07 -08:00
etiennemlb
39620085d4 Add new packages: PDI (and dependencies/plugins) (#48710)
* Add new packages: PDI
* Fix style and  typos
* License and pdi python version/shebang issue
* Version update
* 1.8.0 cutoff and dependency simplifications
* Remove unused guard
2025-02-19 09:56:03 -08:00
Krishna Chilleri
78c985fce4 hpc-beeflow: New package (#49036)
* hpc-beeflow: New package

* Update var/spack/repos/builtin/packages/hpc-beeflow/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* Update var/spack/repos/builtin/packages/hpc-beeflow/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* add new version of py-fastapi

* Update var/spack/repos/builtin/packages/hpc-beeflow/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-19 11:18:01 -06:00
Wouter Deconinck
f9e4d3898a cargo: avoid need to use super().build_args with std_build_args (#49071)
* cargo: avoid need to use super().build_args with std_build_args

* cargo: fix style

* jujutsu: avoid need for super().build_args
2025-02-19 09:01:56 -08:00
Lehman Garrison
75c3d0a053 py-yt: add 4.4.0 and dependencies (#47571)
* py-ewah-bool-utils: add new package

* py-extension-helpers: add 1.2.0

* py-regions: add new package

* py-erfa: add 2.0.1.5

* py-yt: add 4.4.0

* py-yt: respect build_jobs
2025-02-19 08:14:35 -07:00
Stephen Nicholas Swatman
6afe002c94 vecmem: fix SYCL compiler specification (#49108)
This commit adds an additional requirement to the vecmem package,
requiring the OneAPI compiler iff the `sycl` variant is turned on. This
allows us to correctly set the non-standard `SYCLCXX` environment
variable.
2025-02-19 08:54:47 -06:00
Alexandre DENIS
f76e01707a mpi-sync-clocks: new package (#47834)
* mpi_ysnc_clocks: new package

* mpi_sync_clocks: move package to the right location

* mpi_sync_clocks: add copyright header

* mpi-sync-clocks: rename package mpi_sync_clocks -> mpi-sync-clocks to comply with naming convention

* mpi-sync-clocks: update copyright

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* mpi-sync-clocks: streamline autogen

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-19 08:32:04 -06:00
Alexandre DENIS
738ca8e2c2 mpibenchmark: new package (#47835)
* mpibenchmark: new package

* mpibenchmark: add copyright header

* mpibenchmark: move the package to the right location

* mpibenchmark: explicitely disable CUDA & ROCm

* mpibenchmark: update copyright

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* mpibenchmark: streamline management of --enable/--disable

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* mpibenchmark: streamline autogen

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* mpibenchmark: fix coding style

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-19 08:31:15 -06:00
Seth R. Johnson
817df233fb g4vg/vecgeom: add version1.0.2 and patch cuda build failures (#49110)
* vecgeom: remove old patches and add patch for CUDA 11

* g4vg: add 1.0.2
2025-02-19 06:29:01 -07:00
Adam J. Stewart
5ea4d04450 py-scipy: add v1.15.2 (#49074) 2025-02-19 13:08:20 +01:00
Taillefumier Mathieu
49bf5a349e cp2k: fine graining control of the GPU modules (#48925)
Co-authored-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>
Co-authored-by: Mikael Simberg <mikael.simberg@iki.fi>
Co-authored-by: Rocco Meli <r.meli@bluemail.ch>
2025-02-19 09:29:31 +01:00
Robert Maaskant
2427b9649d ca-certificates-mozilla: add 2024-12-31 and deprecate older (#49096) 2025-02-19 00:34:18 -07:00
Robert Maaskant
0cec2c9fc6 glab: v1.52.0 and v1.53.0 (#49094) 2025-02-19 00:34:05 -07:00
Harmen Stoppels
c97be2a9d7 checksum.py tests: extract add_versions_to_pkg fixture (#49100) 2025-02-19 07:33:50 +00:00
Joe Schoonover
3fbdfc464b fluidnumerics-self: new package (#48636)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
Co-authored-by: fluidnumerics-joe <fluidnumerics-joe@users.noreply.github.com>
2025-02-19 00:23:38 -07:00
Buldram
c4449cb201 chez-scheme: new package (#49067)
* chez-scheme: new package

* Add separate zuo package, correct dep flags, disable threads and libffi by default

* zuo: add +big, parallelize build
2025-02-18 16:05:37 -06:00
Christian Heusel
1601193e12 likwid: Fix the perms script (#48666)
* likwid: Fix the perms script

The script loops over the path (which includes the prefix), but
additionally adds the prefix up front which results in duplicate paths
and a double "/" in the command like in the following one:

    chown root:root /opt/csg/spack/opt/spack/linux-debian12-zen2/gcc-12.2.0/likwid-5.4.1-xfc6quebnf2kosydl3ospaeoskxnxwhn//opt/csg/spack/opt/spack/linux-debian12-zen2/gcc-12.2.0/likwid-5.4.1-xfc6quebnf2kosydl3ospaeoskxnxwhn/sbin/likwid-accessD

Additionally the path is currently not quoted which can potentially
result in word splitting for weird paths.

Signed-off-by: Christian Heusel <christian@heusel.eu>

* likwid: Make the perm scripts' name unique

Also move it into the proper binary folder as per the Filesystem
Hierarchy Standard.

Signed-off-by: Christian Heusel <christian@heusel.eu>

---------

Signed-off-by: Christian Heusel <christian@heusel.eu>
2025-02-18 13:18:03 -07:00
Alex Richert
9c5b3ccb4e wgrib2: add cmake builder (#48447)
* wgrib2: add cmake builder

* wgrib2 add maintainer

* [@spackbot] updating style on behalf of AlexanderRichert-NOAA

* style fixes; add tar.gz for old vers

* license update

* wgrib2: don't restrict openjpeg variant by version

* Update var/spack/repos/builtin/packages/wgrib2/package.py

Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>

* [@spackbot] updating style on behalf of AlexanderRichert-NOAA

* Update package.py

* Update package.py

* Update var/spack/repos/builtin/packages/wgrib2/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

---------

Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-18 13:12:42 -07:00
Robert Maaskant
68517389a0 rclone: add v1.68.2 v1.69.0 v1.69.1 (#49083) 2025-02-18 10:42:53 -08:00
Carson Woods
df5ad63331 py-loguru: add v0.7.0 -> v0.7.3 (#48268)
* Added new 4 new versions of py-loguru

* Added new build dependency

* Removed py-setuptools on versions beyond 0.7.2

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* Fixed erroneous dependency range on py-aiocontextvars

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-18 10:34:13 -07:00
Dave Keeshan
e79dc4422e libgpiod: new package (#47724)
* Initial checkin of compile file for the package libgpiod, this covers versions, 1.6.3 through 2.2

* Update var/spack/repos/builtin/packages/libgpiod/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* Update var/spack/repos/builtin/packages/libgpiod/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* Update how version to url is manage in the x.y.0 cases based on fix by @wdconinc

* Remove redundant url at the top since it is now inside url_for_version function

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-18 11:13:51 -06:00
Gregor Olenik
f0e5568a54 neofoam: new package (#47214)
* add neofoam package.py

* add Henning as second maintainer

* format file

* fixup! SPDX License entry

* Apply suggestions from code review

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* Update var/spack/repos/builtin/packages/neofoam/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-18 11:13:43 -06:00
Laurent Chardon
1a1f0aa07b xios: update to v2.6 (#48680)
* xios: update to v2.6

- xios: update to v2.6
- xios: patch remap earcut.hpp for missing include file
- xios: address C++11 requirement
- xios: instruct to use external boost and blitz libraries

* xios: bump revision to 2714

- Bump revision to changeset 2714
- Deprecate older versions that I can't manage to compile
- Confirm clang workaround is still needed
2025-02-18 08:04:06 -07:00
chaoos
c4ea924977 quda: new package (#48939)
* add quda package

* [@spackbot] updating style on behalf of chaoos

* adjusted header comment

* add quda package

* [@spackbot] updating style on behalf of chaoos

* adjusted header comment

* addressing reviewers comments

* formatting, adjusted build types, added tags hep and lattice

* [@spackbot] updating style on behalf of chaoos

* adjusted preferred version

* [@spackbot] updating style on behalf of chaoos
2025-02-18 07:59:01 -07:00
Wouter Deconinck
57df23a51f libx*: add new versions of X packages (#49060) 2025-02-18 15:46:50 +01:00
Harmen Stoppels
97d66b637f Fix tests modifying package.py files (#49093) 2025-02-18 13:28:07 +01:00
Harmen Stoppels
92e1807672 petsc: fix can provide vs provides issue (#49077) 2025-02-18 13:07:42 +01:00
Harmen Stoppels
e4a8d45d86 views: resolve symlinked dir - dir conflict when same file (#49039)
A directory and a symlink to it under the same relative path in a
different prefix

```
/prefix1/dir/
/prefix1/dir/file
/prefix2/dir -> /prefix1/dir/
```

are not a blocker to create a view. The view structure simply looks like
this:

```
/view/dir/
/view/dir/file
```

This should be the case independently of the order in which we visit
prefixes, so we could in principle create views order independently.
2025-02-18 06:53:17 +01:00
Wouter Deconinck
d6669845ed fjcontrib: add v1.055, v1.056, and v1.100 with patch (#49048) 2025-02-18 06:38:51 +01:00
Wouter Deconinck
60efada6a2 catch2: add v3.8.0 (#49052) 2025-02-18 06:37:23 +01:00
Wouter Deconinck
a093a65a25 armadillo: add v14.2.3 (#49051) 2025-02-18 06:33:09 +01:00
Wouter Deconinck
1524aceb9a gocryptfs: add v2.5.1 (#49063) 2025-02-18 06:32:25 +01:00
Wouter Deconinck
9d0766be48 hep: static_analysis: true (#49069) 2025-02-18 06:27:54 +01:00
Wouter Deconinck
7e89b3521a openloops: add v2.1.3, v2.1.4 (#49064) 2025-02-18 06:25:51 +01:00
Harmen Stoppels
2e372c53ab spec.py: remove Spec.virtual_dependencies (#49079) 2025-02-18 06:17:55 +01:00
Alec Scott
8639779002 pass: add master, improve styling (#49081) 2025-02-18 06:13:34 +01:00
Wouter Deconinck
a0e09139fc bioconductor-*: rm in favor of r-* copies (#49089) 2025-02-18 06:06:26 +01:00
Wouter Deconinck
b02ac87c55 apptainer/singularity/singularityCE: variant suid default False (#49088) 2025-02-18 05:26:00 +01:00
dependabot[bot]
a9da160160 build(deps): bump flake8 from 7.1.1 to 7.1.2 in /lib/spack/docs (#49087)
Bumps [flake8](https://github.com/pycqa/flake8) from 7.1.1 to 7.1.2.
- [Commits](https://github.com/pycqa/flake8/compare/7.1.1...7.1.2)

---
updated-dependencies:
- dependency-name: flake8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 20:08:05 -07:00
Alec Scott
f1678f4c7b bfs: add v4.0.5 (#49049)
* bfs: add v4.0.5, liburing: v2.4, v2.9

* Re-enable bfs on developer tools pipelines
2025-02-17 19:05:35 -06:00
dependabot[bot]
dae3b69f2c build(deps): bump flake8 in /.github/workflows/requirements/style (#49086)
Bumps [flake8](https://github.com/pycqa/flake8) from 7.1.1 to 7.1.2.
- [Commits](https://github.com/pycqa/flake8/compare/7.1.1...7.1.2)

---
updated-dependencies:
- dependency-name: flake8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 18:13:42 -06:00
Brian Vanderwende
cec7e6c4b5 GCC 14 needs C-standards workaround flags (#48019) 2025-02-17 16:33:16 -07:00
dmagdavector
5931236f55 py-nbconvert: add v7.14.2 to 7.16 (#47944) 2025-02-17 15:43:21 -07:00
Miranda Mundt
e695185770 py-pyomo: bump to 6.8.2; add new subdep package py-linear-tree (#48164)
* damaris: add v1.12.0, update maintainers (#48674)

Co-authored-by: Etienne Ndamlabin <jean-etienne.ndamlabin-mboula@inria.fr>

* Bump up the version for rocm-6.3.1 release (#48440)

This PR updates the versions for the rocm recipes for rocm-6.3.1 release.

* py-flash-attn: add missing triton dependency (#48645)

* hep stack: additional event generator packages (#48565)

* hep stack: additional event generator packages

* hep: adidtional packages

* hep: collier doesn't have +pic +shared

* py-awkward-cpp: fix scikit-build-core range of applicability

* hep: disable agile

* hep: disable garfieldpp and genie

* py-wxpython: depends_on pkgconfig even if using external wxwidgets

* hep: disable professor

* papi: fix error finding gmake during post-install testing (#48592)

* JAX: add v0.4.32+ (#46346)

* JAX: add v0.4.34

* Disable search for clang

* Update CUDA flags

* Add py-jax 0.4.33, comment out until py-jaxlib 0.4.33 is also released

* Fix GCC build

* Try TF_NVCC_CLANG

* py-jax: add v0.4.34

* jax no longer has separate tags for jaxlib

* Install compiled wheel

* Join path before glob

* Wheel is in spack stage, not tmp path

* Add 0.4.35

* Add newer versions

* Build system has been refactored yet again

* Drop clang

* Fix build with source tarball, rocm support

* Support GCC

* Remove clang-specific compiler flags

* enable_cuda flag was removed

* Fix logic

* py-jax: add v0.4.38

* Add patch to fix GCC support

* Patch no longer needed

* Skip patching, directly pass flags

* New flags

* Remove unused import

* Patch changed

* Use older version of patch

* Newer patch

* Add CUDA symlink

* Symlink more directories

* Recursive symlink

* Import function

* Recursive search

* Undo cuda changes

* Add v0.5.0

* I quit

* py-geemap: add new package (#48602)

* easi: add v1.5.1; relax yaml-cpp and lua requirements (#48675)

* thepeg: extend the rivet@:3 dependency up to version 2.3 (#48691)

Co-authored-by: jmcarcell <jmcarcell@users.noreply.github.com>

* py-ipyrad: adding version 0.9.102 (#48686)

Signed-off-by: Shane Nehring <snehring@iastate.edu>

* autodock-vina: adding version 1.2.6 (#48684)

Signed-off-by: Shane Nehring <snehring@iastate.edu>

* toybox: add v0.8.12 (#48657)

* Changes for NVIDIA HPC SDK 25.1 (#48696)

* update hypre version and add new memalign for petsc (#47831)

* petsc+rocm: add dependency on hipblas-common (#48644)

* spec.py: fix ArchSpec.intersects (#48741)

fixes a bug where `x86_64:` and `ppc64le:` intersected, and x86_64: and :haswell did not.

* ucx: adding 1.18.0 (#48742)

* Adding UCX 1.18.0
* Verified and correct hash.

* MAGMA: add v2.9.0 (#48750)

* Deprecate frontend/backend os/target (#47756)

* package api: drop wildcard re-export (#48760)

* package api: drop wildcard re-export

To ensure package repos are forward/backward compatibility with Spack,
we should explicitly export all symbols we want to expose in the public
package API, and drop `from spack.something import *` because
removal/addition to the public API will go unnoticed.

Also `llnl.util.filesystem` has some methods that shouldn't be exposed
in the package API, so better to enumerate a subset explicitly.

* remove flatten_dependencies / install_dependency_symlinks

* py-cmake: remove. remove deprecated cmake versions (#48763)

* Remove pipelines and images based on ppc64le (#48767)

* petsc: only conflict with kokkos@4.5: if it is enabled (#48698)

* hpctoolkit: Add `+docs` variant and manpages (#48566)

* py-mdit-py-plugins: Add new versions 0.3.5, 0.4.2
  Signed-off-by: Jonathon Anderson <anderson.jonathonm@gmail.com>
* py-myst-parser: Add new versions 0.19.0 to 4.0.0
  Signed-off-by: Jonathon Anderson <anderson.jonathonm@gmail.com>
* hpctoolkit: Add +docs variant and manpages
   This commit unconditionally enables manpages for the HPCToolkit tools.
   The new `+docs` variant enables additional documentation, specifically
   the user's manual. Both require new build-time dependencies.
  Signed-off-by: Jonathon Anderson <anderson.jonathonm@gmail.com>

---------

Signed-off-by: Jonathon Anderson <anderson.jonathonm@gmail.com>

* fmt: simplify +pic (#48766)

Co-authored-by: Harmen Stoppels <harmenstoppels@gmail.com>

* Docs/bugfix: correct return for Adding flags to configure (#48434)

* binutils: conflict on configuration with build issues (#42949)

* Create SALT package.py (#48758)

* Create SALT package.py

Added a package for the SALT Source AnaLysis Toolkit
@zbeekman

* [@spackbot] updating style on behalf of wspear

* Update package.py

Line wrap

---------

Co-authored-by: wspear <wspear@users.noreply.github.com>

* smee-client: add v2.0.4 (#48384)

* CMake: add v3.31.5, v3.30.7 (#48759)

* builtin: remove redundant imports (#48765)

* builtin: remove redundant llnl.util.filesystem import
* remove redundant import spack.version
* unsorted fixes
* more spack.version

* abinit: pass flag correctly (#48788)

* Add py-zarr 3, which includes a new required package py-donfig, and a bug fix to the patch range with numcodecs (#48786)

* libxc: add CMake builder (#48772)

* libsmeagol

* libxc cmake

* cmake support

* revert changes

* make spackbot happy

* fix

* Update package.py

* hipblaslt: update cmake dependency (#48637)

* hipblaslt: update cmake dependency

1 error found in build log:
  >> 3    CMake Error at CMakeLists.txt:24 (cmake_minimum_required):
     4      CMake 3.25.2 or higher is required.  You are running version 3.22.1
     5
     6
     7    -- Configuring incomplete, errors occurred!

See build log for details:
  /scratch/svcpetsc/spack-rocm/spack-stage/spack-stage-hipblaslt-6.3.0-pabb7t4rheqkz74lfzbsnqi6vnpiqwlq/spack-build-out.txt

* Update var/spack/repos/builtin/packages/hipblaslt/package.py

Co-authored-by: afzpatel <122491982+afzpatel@users.noreply.github.com>

---------

Co-authored-by: afzpatel <122491982+afzpatel@users.noreply.github.com>

* Move from python2 compliant IOError and EnvironmentError to python3-only  OSError (#48764)

* IOError -> OSError

* also do EnvironmentError

* py-sphinx: mark Python compatibility (#48796)

* spack.package: wrap llnl.util.tty (#48793)

avoid import of llnl.util.tty in packages

* spack.package: re-export EnvironmentModifications / Prefix (#48792)

* Remove unused values (#48795)

Signed-off-by: Todd Gamblin <tgamblin@llnl.gov>
Co-authored-by: Todd Gamblin <tgamblin@llnl.gov>

* petsc, py-petsc4py: add v3.22.3 (#48785)

* libsmeagol (#48776)

* libsmeagol

* add support for intel and add conflicts

* cp2k

* Bug Fix: Better incremental check for CMake (#48775)

* Bug Fix: Better incremental check for CMake

* Fix syntax error

* Ensure match of config artifact with generator

* add cdo@2.5.0 (#48801)

* Added salt variant to tau (#48782)

* Added salt variant to tau

* Update package.py

* [@spackbot] updating style on behalf of wspear

---------

Co-authored-by: wspear <wspear@users.noreply.github.com>

* Remove patch on main (#48798)

Patch got merged: https://github.com/natefoo/slurm-drmaa/pull/62

* kokkos-nvcc-wrapper: add version 4.5.00 and 4.5.01 (#48802)

* env create: create copies of relative include files in envs created from manifest (#48689)

Currently, environments created from manifest files with relative includes result in broken
references to config files.

This PR modifies `spack env create` to create local copies in the new environment of any local
config files from relative paths in the environment manifest passed as an init file.

This PR does not change the behavior if the include is an absolute path or if the include is from
a relative path outside the environment directory, but it does warn about missing relative includes if
they are inside the environment directory.

Includes regression test and short blurb in docs.

* py-sphinx-rtd-theme: add v2.0.0, v3.0.0 (#48756)

* Add versions 2 and 3 of py-sphinx-rtd-theme.
   Allow for versions of py-sphinx greater than 6.
   Fix the Python version for older versions that depend on distutils.
   Get the py-docutils dependency from the py-sphinx recipe.
* Depend purely on the py-docutils dependency in py-sphinx.
* More refined dependency versioning.
* Fixed versioning for py-sphinx and py-docutils.

* CP2K: add 2025.1 version and DFTD4 support (#48489)

* cp2k: add dftd4 variant

* better conflict and make support

* typo

* Update var/spack/repos/builtin/packages/cp2k/package.py

* Update var/spack/repos/builtin/packages/cp2k/package.py

* oci/opener.py: respect system proxy settings (#48783)

* vtk-m: CMAKE_CXX_COMPILER is not a BOOL (#48813)

* gcc: remove --with-ld=ld-classic (#48826)

* nanotron: add new package (#48582)

* nanotron: add new package

Also, update some dependencies and add missing ones.

* Add variant +examples needed to execute example scripts

* fix: add missing branch attribute

* Remove master version

* fix: use Github hash

* embree: fix tests by building tutorial's embree_viewer for tests (#48392)

* import-check: improve how problematic imports are displayed (#48825)

The import-check action now presents problematic import statements
introduced by the PR better.

The idea is roughly:

* Let (V₁, E₁) be the graph of modules as vertices and import statements
  as edges before the change
* Let (V₂, E₂) be the graph after the code change, which is typically a small
  perturbation of (V₁, E₁).
* X₁ = FAS(V₁, E₁) is the feedback arc set before (a minimal set of edges to
  delete to make it acyclic)
* X₂ = FAS(V₂, E₂ ∖ X₁) is the feedback arc set after deletion of the minimal
  set of edges that made the old graph acyclic.
* X₃ = FAS(V₂, E₂) is the feedback arc set after

Previously I displayed X₁ and X₃ and users had to diff themselves.

Now, I'm showing X₂, which is a small set, typically directly related to
code changes.

However, it can be that a small code change adding say 2 problematic imports
creates a completely different solution X₃ that only requires deletion of just 1
different import. In that case the user is informed that they can potentially do
less work.

So for PR #48784 the output is now:

> The overall number of problematic import statements increased by 1 from 31 to 32.
> This is likely a direct consequence of the following import statements:
> 
> ```
> spack/config imports: spack.spec, spack.util.path, spack.util.remote_file_cache
> ```
> 
> However, instead of removing 3 import statements, it is sufficient to remove only 1
> import statement from the following list:
> 
> ```
> spack/concretize imports: spack.bootstrap, spack.solver.asp
> spack/environment imports: spack.bootstrap, spack.environment
> spack/fetch_strategy imports: spack.version.git_ref_lookup
> spack/install_test imports: spack.build_environment, spack.package_base
> spack/modules imports: spack.modules
> spack/platforms imports: spack.config
> spack/relocate imports: spack.bootstrap
> spack/repo imports: spack.package_base, spack.patch, spack.tag
> spack/spec imports: spack.binary_distribution, spack.compiler, spack.compilers, spack.concretize, spack.environment, spack.hash_types, spack.provider_index, spack.repo, spack.spec_parser, spack.store, spack.traverse, spack.variant, spack.version.git_ref_lookup
> spack/subprocess_context imports: spack.environment
> spack/util/gpg imports: spack.bootstrap
> spack/util/package_hash imports: spack.package_base
> spack/util/path imports: spack.config, spack.environment
> spack/util/remote_file_cache imports: spack.util.web
> ```

from which the user can figure out that
`spack/util/remote_file_cache imports: spack.util.web` is the "bottleneck" now.

* spack_yaml: use unambiguous variable name (#48832)

* style: fix `not in` and `is not` (#48831)

These are some changes that `ruff check --fix` would make that the current
`spack style` also agrees with.  Make the changes now so that the `ruff`
change is less disruptive.

Signed-off-by: Todd Gamblin <tgamblin@llnl.gov>

* Set version to v1.0.0.dev0 (#48791)

* import-check: enable color output (#48842)

* berkeleygw: add -o flag to tar extraction (#48816)

when extracting as root user, avoid that tar attempts to change file ownership

* llvm: deprecate old patch releases (#48762)

* cuda: add v12.8 (#48708)

* sirius: patch pugixml (#48841)

* ziatest: add new package (#48809)

* gitlab: remove isc stacks (#48811)

* gcc: deprecate old patch releases (#48761)

* CP2K: use libxc@7 for master/next release (#48808)

* packge_base.py: remove _patches_by_hash (#48768)

* cdash: avoid build_opener (#48846)

* g4vg: new package (#48844)

* g4vg: new package

* [@spackbot] updating style on behalf of sethrj

* r-dmrcate: add v2.16.0, v3.0.0, v3.2.0 (#48158)

* r-dmrcate: add new versions
* r-dmrcate: require `r@4.3.0` for v2.99.0+
* r-dmrcate: update dependencies

* py-tensorflow: add 2.18.0-rocm-enhanced (#48711)

* py-tensorflow: add 2.18.0-rocm-enhanced

* fix style

* fix style

* fix style

* review changes

* review changes

* remove hipblaslt dependency

* remove ci changes and force ROCm 6.3.1 for newest TF

* remove rocm 6.3.1 dependency

* simplify configure fix

* rocm-examples and rocjpeg: new packages (#47695)

* new package: rocm-examples
* add new package rocjpeg and update rocm-examples for 6.3.0
* fix licenses
* add versions 6.3.1
* change homepage and git
* add f-string

* Tesseract v5.5.0 (#48866)

* leptonica: adding v1.85.0
  Signed-off-by: Shane Nehring <snehring@iastate.edu>
* tesseract: adding v5.5.0
  Signed-off-by: Shane Nehring <snehring@iastate.edu>

---------

Signed-off-by: Shane Nehring <snehring@iastate.edu>

* py-geojson: Add new package  (#48847)

* Add new package py-geojson
* fix when

* isa-l: add v2.31.1 (#48859)

* Add new package func (#48849)

* icu4c: add v75.1, v76.1 (#48858)

* Add new package py-metis (#48848)

* cppgsl: add v4.1.0 (#48864)

* libdrm: add v2.4.124 (#48860)

* amrex: add v25.02 (#48853)

* sherpa: support cxxstd=20 when=@3: (#48829)

* sherpa: support cxxstd=20 when=@3:

* hep: sherpa cxxstd=20

* netlib-scalapack: Update version (#48667)

* Update scalapack version

Signed-off-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>

* use url_for_version

Signed-off-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>

* use spec.satisfies instead of version()

---------

Signed-off-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>
Co-authored-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>

* fcgi: add v2.4.3, v2.4.4 (#48856)

* update pyproject.toml for `ruff format` (#48823)

Add ruff configuration to `pyproject.toml`.

This allows `ruff format` in the Spack repository to format all the files we care about, 
with our line length of 99, the exceptions we already put in place, and excluding things
we don't auto-format, like vendored dependencies.

Right now it'll reformat 175 or so files, but only slightly, in places where `ruff` differs from
`black`. For the most part I like the ruff format decisions better than `black`, but none of
the changes seem too severe.

This does not change `spack style` -- I figure that can come later but this at least will
let people start playing with `ruff`.

---------

Signed-off-by: Todd Gamblin <tgamblin@llnl.gov>

* dd4hep: add v1.31 (#48850)

* libsm: add v1.2.5 (#48862)

* Apply workaround for oneAPI compiler for upcxx problem with a template argument list (#48843)

* Fix upcxx problem with  a template argument list is expected after a name prefixed by the template keyword

* Revert "Fix upcxx problem with  a template argument list is expected after a name prefixed by the template keyword"

This reverts commit faf9b8ce85.

* Apply workaround for oneAPI compiler

* style problem resolved

* use spec.satisfies syntax

---------

Co-authored-by: eugeneswalker <eugenesunsetwalker@gmail.com>

* Remove ISC stacks environment files (#48851)

Follow-up to #48811

* Remove variable from cmake.py (#48824)

* Remove variable from cmake.py

#48775 left a dangling variable that was not caught in CI but by the eyes of @haampie. Restructure variable to local method.

* [@spackbot] updating style on behalf of psakievich

* Update cmake.py

* Update lib/spack/spack/build_systems/cmake.py

* Update lib/spack/spack/build_systems/cmake.py

---------

Co-authored-by: psakievich <psakievich@users.noreply.github.com>

* sirius: add v7.6.2 (#48797)

Co-authored-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>
Co-authored-by: Rocco Meli <r.meli@bluemail.ch>

* gha: standalone import-check (#48873)

* ci: add codecov token secret to coverage upload job (#48880)

Codecov needs to see the token secret when uploading, so we have to
add this line to the workflow YAML:

```yaml
  with:
    token: ${{ secrets.CODECOV_TOKEN }}
```

Signed-off-by: Todd Gamblin <tgamblin@llnl.gov>

* ci: bump import-check (#48883)

* pfind: new package (#48685)

* py-elevation: new package (#48836)

* spec.py: fix hash change due to None vs {} (#48854)

* Fix hash change due to None vs {}

* Enforce null for empty list of external_modules

* nnn: new package (#46174)

Co-authored-by: Bernhard Kaindl <bernhardkaindl7@gmail.com>

* Fix esmf usage, add new version (#48835)

* bash: add autotools dependencies (#48874)

* Scotch: add v7.0.6, add testing option (#48781)

* code-server: update to v4.96.4 (#48828)

* acts: add v39.0.0 (#48839)

This commit adds version 39.0.0 of the ACTS package which, as far as I
can tell, doesn't require any dependency updates.

* spec.py: ensure spec.extra_attributes is {} if is null in json (#48896)

* harfbuzz: add v10.2.0 (#48857)

* libice: add v1.1.2 (#48861)

* relocate.py: don't warn about symlinks (#48904)

`relocate_links` warns when the target is absolute and not matched by
any prefix from the prefix to prefix map.

This can lead to false positives, cause the prefix to prefix map does
not contain trivial/identity entries whenever a package is installed to
its original location.

Since relocate_links is the odd one out there (we don't warn about
similar issues with rpaths, etc), just remove the warning.

* hip-tests: new package (#47273)

* hip-tests: add new package
* remove hip-tests from hip recipe
* remove old versions
* fix style
* add missing import
* bump hip-tests to 6.3.1
* fix style

* flecsi: new version 2.3.1 (#48867)

* flecsi: add new version 2.3.1, remove develop
* flecsi: remove kokkos and openmp variants moving forward
* flecsi: propagate cuda and rocm settings from kokkos
* Update var/spack/repos/builtin/packages/flecsi/package.py
   Co-authored-by: Davis Herring <herring@lanl.gov>
* flecsi: remove redundant depends_on lines
* flecsi: correct legion dependency
* flecsi: deprecate v2.0.0 and v2.1.0
* flecsi: force +openmp if ^kokkos+openmp

---------

Co-authored-by: Davis Herring <herring@lanl.gov>

* Update py-arch, py-statsmodels (add 0.14.1), py-patsy (add 0.5.4) to be able to use py-cython@3 (#48769)

* Add py-patsy@0.5.4
* Correct py-numpy dependency in py-arch
* Add py-statsmodels@0.14.1 and update dependencies
* Add climbfuji as maintainer for py-patsy
* Add climbfuji as maintainer for py-statsmodels
* Update var/spack/repos/builtin/packages/py-statsmodels/package.py

* enzyme: add v0.0.172 (#48881)

* spec.py: ensure == is false if true modulo precomputed dag hash (#48889)

* llvm: fix @15 %apple-clang@16 (#48887)

* spiner: add v1.6.3 (#48871)

* spiner: update package logic

* singularity-eos: remove spiner cuda_arch propagation

* spiner: add version 1.6.3

* sherpa: +hepmc3root only when +root (#48827)

* sherpa: +hepmc3root only when +root

* sherpa: fix style

* salt: add v0.3.0 (#48877)

* salt: Add v0.3.0 of SALT

This version contains important bug fixes for building and parsing
projects containing Fortran

* salt: Be more explicit about dependency types

 - llvm+clang+flang is needed at build, link and runtime for the
   correct operation of SALT
 - Testing with llvm@master ( llvm > 19.x ) shows that SALT is
   currently incompatible with the latest llvm API so an updated salt
   will be required when LLVM 20 is released

* openturbine: add new package (#48683)

* PyTorch: add v2.6.0 (#48794)

* mummer4: patching to allow building with %gcc@13: (#38292)

Co-authored-by: LMS Bioinformatics <bioinformatics@lms.mrc.ac.uk>
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>

* fms: add 2025.01, 2024.03 (#48812)

* py-shapely: add v2.0.7 (#48810)

* spectre: add v2025.01.30 (#48803)

Co-authored-by: sxs-bot <sxs-bot@users.noreply.github.com>

* py-numba: Add version 0.61  (#48837)

* amdfftw: fix broken build, adjust flags for performance tuning (#48754)

With CFLAGS, the code path in the amdfftw build system will bypass the logic around AMD_ARCH.

---------

Co-authored-by: vijay kallesh <Vijay-teekinavar.Kallesh@amd.com>

* justbuild: add v1.4.3 (#48898)

* nvpl-blas, nvpl-lapack: add v0.4.0.1, v0.3.0 (#48901)

* hep stack: build also with cuda and rocm where possible (#48528)

* lcio: add v2.22.4 (#48895)

* Add a message for CMake incremental build (#48905)

* Add a message for CMake incremental build

Requested message to explain CMake phase is getting skipped.

* [@spackbot] updating style on behalf of psakievich

* Update import

---------

Co-authored-by: psakievich <psakievich@users.noreply.github.com>

* dcap: depends_on libxcrypt (#48903)

* Add new version of r-curl (#48912)

* pika: Add 0.32.0 (#48897)

* icu4c: no cxxstd flag option on Windows (#48510)

* ICU4C: Don't reference a spec variant on a platform on which it's not defined

* icu4c: no cxx flag on Windows

* dla-future-fortran: add v0.3.0 (#48900)

* simgrid: add v3.36 (#48909)

* dyninst: cleanup package (#47637)

* Use more idiomatic construct, shorten recipe
* Remove deprecated versions, and associated patches
* Remove v10.0.0

* Windows: Update default config for stage location (#48511)

Current location is within the Spack prefix, which causes builds to
pollute VCS with stage artifacts and generally inflates the Spack
install prefix.

This PR moves it to the user cache location now that we can
consistently support paths with spaces on Windows.

* py-maturin: add v1.8.2 and refined dependencies (#48915)

* clingo-bootstrap: fix +optimized build (#48931)

* fix regression `apple-clang` vs `%apple-clang`
* use f-strings
* remove --verbose flag from LDFLAGS

* Fix regression due to dyninst update (#48935)

* trexio: fix issues with autotools build system (#48923)

* package_base.py: remove use_cray_compiler_names (#48932)

* Apply workarounds for oneAPI compiler for ascent problem with build (#48918)

* Apply workarounds for oneAPI compiler for ascent problem with build

* Use the way with use patch through the PR address

* stylecheck - missing comma

* libgcrypt: fix enforced -O0 (#48940)

Signed-off-by: Shane Nehring <snehring@iastate.edu>
Co-authored-by: Shane Nehring <snehring@iastate.edu>

* serialbox: add version 2.6.2 (#48937)

* nwchem: add master (#48919)

* Add possibility to build nwchem from master branch

* add oneapi@2025: patch for @7.2.3

---------

Co-authored-by: eugeneswalker <eugenesunsetwalker@gmail.com>

* Python: add new versions (#48950)

* Python: add new versions

* black

* reframe: add v4.6.4 -> v4.7.2 (#48242)

* go: add v1.23.6 (#48955)

* qmcpack: add v4.0.0 (#48921)

* py-einops: add v0.8.1 (#48954)

* flux-sched: add v0.42.1 (#48952)

Co-authored-by: github-actions <github-actions@users.noreply.github.com>

* Quantum ESPRESSO: add v7.4.1 (#48949)

* duckdb: add v1.2.0 (#48902)

Signed-off-by: Teague Sterling <teaguesterling@gmail.com>

* mapl: add v2.53.1, v2.54.1 (#48944)

* log.py: remove setenv calls (#48933)

* nim: add v2.2.2 (#48929)

* Update GFE packages (#48899)

* OpenMPI: add version 4.1.8 (#48922)

Signed-off-by: Howard Pritchard <howardp@lanl.gov>

* extrae: tighten dependencies on boost for +dyninst (#48938)

* py-iterative-stats: add 0.1.1 (#48959)

* import-check: bump (#48968)

* ports-of-call: add v1.6.0, v1.7.0, v1.7.1 (#48870)

* acts dependencies: new versions as of 2025/02/10 (#48969)

This commit adds detray v0.88.0 and GeoModel v6.9.0.

* cbtf-krell: Update Boost dependency (#47133)

* Update Boost
* Add gotcha
* Add patch for build errors
* Allow building with latest Dyninst
* Fix patch url

* lua-sol2: Apply workaround for oneAPI compiler for problem with build (#48920)

* Bump up the version for rocm-6.3.2 release (#48787)

* Bump up the version for rocm-6.3.2 release

* rocm-openmp-extras update and style correction

* Updating mivisionx, omniperf, rccl & rocprofiler-systems

* Updating hipsparselt & rocm-opencl

* rocprofiler-systems on gcc-13 and rvs commit instead of patch

* Updated rocjpeg & rocm-examples for 6.3.2

* ROCPROFSYS_BUILD_DYNINST & DYNINST_BUILD_TBB are required only with gcc-13

---------

Co-authored-by: afzpatel <122491982+afzpatel@users.noreply.github.com>

* spack compiler find: detect `flang-new` and `flang` in newer LLVM versions (#48914)

* rivet: patch missing header in 3.1.10 (#48977)

* concretizer: reduce search space with static analysis (#48729)

Currently, when we setup the ASP problem for `clingo`, we don't take into account the configuration. This results in setting up ASP problems that are larger than necessary, with possibly redundant information, and higher concretization times. 

This PR tries to improve things by adding an opt-in feature that computes the _possible dependencies_ of a solve taking also into account the current configuration, and avoids adding possible dependencies that we are certain can't be in the final solution.

The feature can be activated with:
```yaml
concretizer:
  static_analysis: true
```

Examples of simple rules to discard dependencies are:
- Dependencies that are not buildable, and for which no binary is present (e.g. `cray-mpich` etc. on non Cray systems)
- Dependencies that are not for the current platform (e.g. `msmpi` on non Windows platforms)
- Conditional dependencies that cannot be activated, because of some user requirement (e.g. `cuda` etc. if the user requires `~cuda` in configuration)
- Virtual providers that cannot be used, because of a requirement on a virtual

The speed-up these rules seem to give depends on the use case at hand, but if the configuration is updated properly, they are noticeable. 

Since in cases where there is no rule to exclude packages upfront, reuse is active, and this option is activated, it's possible to see some minor slow down, the feature has been added as opt-in, so it's turned off by default.

* spack.util.elf: catch seek errors (#48972)

* hep: rivet: require hepmc=3 (#48976)

* Fix performance issue on macOS (#48997)

archspec.cpu.host() is not memoized, so compute
it as less as possible.

---------

Co-authored-by: alalazo <alalazo@users.noreply.github.com>

* style.py: fix false negative in redundant import statements (#48980)

* PyTorch: build flash attention by default, except in CI (#48521)

* PyTorch: build flash attention by default, except in CI

* Variant is boolean, only available when +cuda/+rocm

* desc -> _desc

* kokkos et al. : don't monkeypatch spec in callbacks (#48916)

Currently, a few packages using kokkos rely on
kokkos itself monkeypatching its own spec to
provide some attribute.

In this commit we change this attribute to be
defined on the package, and never be monkeypatched.

* gmake: add empty libs property, remove link deptypes from dependents (#48995)

* package_hash.py: move metadata_attrs inline out of package_base (#48981)

* gmake: fix def libs/headers (#49009)

* Spec.package_class -> spack.repo.PATH.get_pkg_class (#48985)

* libfabric: use the class variable to get the list of fabrics (#49007)

Suggested by: alalazo <alalazo@users.noreply.github.com>

Signed-off-by: Justin Cook <jscook@lbl.gov>

* py-transformers: add new versions (#49000)

* py-transformers: add new versions

* py-tokenizers: add new versions

* Apply suggestions from code review

* lcio: Add latest 2.22.5 tag (#48991)

* concretize.lp: don't warn about deprecation when external (#49008)

* Spec.is_virtual -> spack.repo.PATH.is_virtual (#48986)

* g4vg: add 'develop' branch (#49003)

* g4vg: add develop version

* celeritas: add develop version

* Fix style

* REVERTME: move celeritas changes to another branch

* Get full repo

* remove unneeded variable

* Remove spack.repo.PATH.is_virtual call from SpecBuildInterface.(#48984)

This PR is effectively a breaking change extracted from #45189, which removes 
support for spec["mpi"] if spec itself is openmpi / mpich that could provide mpi; 
from the Spec instance we don't have any parent it provides it to, 
hence it's a KeyError.

* Spec.validate_detection -> spack.detection.path.validate_detection (#48987)

* hep: add missing language dependencies (#48963)

* highfive: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989283

* lhapdf: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989283

* vc: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989140

* davix: add dependency on C, C++

https://gitlab.spack.io/spack/spack/-/jobs/14989131

* pandorasdk: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989130

* veccore: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989118

* pythia6: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989116

* jwt-cpp: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989115

* collier: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989115

* hepmc: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989112

* clhep: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989075

* fastjet: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14981340

* gosam-contrib: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14978873

* thepeg: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14997553

* cepgen: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14997552

* podio: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14997552

* pandoramonitoring: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14997552

* lcio: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14997513

* geant4: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14997202

* evtgen: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14996817

* apfel: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14996779

* collier: add dependency on C, C++

https://gitlab.spack.io/spack/spack/-/jobs/14996770

* vecgeom: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/15003840

* dd4hep: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/15003839

* opendatadetector: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/15007666

* acts: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/15007827

* hepmc: remove dependency on fortran

Co-authored-by: Seth R. Johnson <johnsonsr@ornl.gov>

* thepeg: remove fortran dep

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* acts: add a conditional build dependency

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* opendatadetector: add comment to explain C dep

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

---------

Co-authored-by: Seth R. Johnson <johnsonsr@ornl.gov>
Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* apptainer: get_full_repo for branch main (#49002)

* unifyfs: Apply workaround for oneAPI compiler for problem with build (#48962)

* solver: add type-hints to OutputConfiguration (#48979)

* Ci: ensure file path comparsion uses posix paths (#47033)

Git always produces posix paths, ensure we're always comparsing apples to apples by normalizing paths compared to git output to posix.

* postgresql: add v17.2 (#47811)

* postgresql: add version 17.2

* postgresql: install flex, bison and perl when building versions 17 and up

* postgresql: do not install perl by default when building versions 17 and up

* cray-mpich: adding partial GTL support (#45830)

cray-mpich now has a rocm variant. You can use gtl_lib in the
flag_handler like so:

```python
    def flag_handler(self, name, flags):
        wrapper_flags = []
        environment_flags = []
        build_system_flags = []

        if self.spec.satisfies("+rocm"):
            if self.spec.satisfies("^cray-mpich"):
                gtl_lib = self.spec["cray-mpich"].package.gtl_lib
                build_system_flags.extend(gtl_lib.get(name) or [])
            # hipcc is not wrapped, we need to pass the flags via the
            # build system.
            build_system_flags.extend(flags)

        return (wrapper_flags, environment_flags, build_system_flags)
```

---------

Co-authored-by: Richard Berger <rberger@lanl.gov>
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
Co-authored-by: Richard Berger <richard.berger@outlook.com>

* lammps: use the Cray GTL (#46090)

* lammps: add 20241119 and 20250204 releases (#48978)

* plog: add new package (#48975)

* binutils: add debuginfod variant + update deps (#49011)

* h5hut: Remove H5_USE_110_API for newer versions (#48885)

* h5hut: Remove H5_USE_110_API for newer versions

* h5hut: style reformat and add maintainer

* h5hut: correct version syntax for <v2.x.x

* h5hut: Bump default version to 2.0.0rc7 and remove older rc candidates

* Update var/spack/repos/builtin/packages/h5hut/package.py

Co-authored-by: Mikael Simberg <mikael.simberg@iki.fi>

---------

Co-authored-by: Alberto Invernizzi <9337627+albestro@users.noreply.github.com>
Co-authored-by: Mikael Simberg <mikael.simberg@iki.fi>

* spack debug create-db-tarball: remove after test failures (#49025)

* bubblewrap: add versions up to v0.11.0 (#49023)

* gftl: add v1.15.2 (#48992)

* py-torchgeo: pyvista dep has been removed (#48990)

* py-memray: add v1.15.0 (#48989)

* yosys: add v0.50 (#48983)

* laszip: Add version 3.4.4. (#48982)

* py-numpy: add v2.2.3 (#49029)

* pandora{pfa,sdk,monitoring}: add new versions and allow setting the C++ standard (#48300)

* pandoramonitoring: add v3.6.0; pandorapfa: add v4.11.2

Remove variables that are not being used in pandorasdk. Use the C++ standard
from ROOT when possible and pass -Wno-error to override the -Werror that will
typically fail with a new standard. Add a cxxstd variant for pandorasdk

* Fix style

* Update var/spack/repos/builtin/packages/pandorasdk/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* Fix style

---------

Co-authored-by: jmcarcell <jmcarcell@users.noreply.github.com>
Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* easi@1.5.2 (#49013)

* Put in maintainers for Kokkos Tools Spack package  (#49018)

* Kokkos Tools package.py: fix maintainers
* Kokkos Tools package.py: remove white space between first and second maintainer in comma-separated list
* [@spackbot] updating style on behalf of vlkale
* Correct maintainers syntax
   Co-authored-by: Richard Berger <richard.berger@outlook.com>

---------

Co-authored-by: vlkale <vlkale@users.noreply.github.com>
Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
Co-authored-by: Richard Berger <richard.berger@outlook.com>

* zlib package: Ensure correct lib search on Windows (#48512)

* Name of zlib's library differs on Windows; also account for name
  differing when building +shared
* `zlib`'s `.libs` implementation was searching for the runtime
  libraries (the .dlls) and should be searching for link-time libs

* Update openfast, amr-wind, and nalu-wind packages (#48994)

* acts: conflicts ^geant4@11.3: when @:35 (#49028)

* yq: add versions 4.44.5 and 4.44.6 and 4.45.1 (#49027)

* openblas: .libs() uses self.libraries attribute (#48942)

Currently this is hardcoded to the same value as listed in the class
definition. If one ever overrides this attribute, such as:

```
packages:
  openblas:
    package_attributes:
      libraries = [ 'libopenblaso64', ]
```

this patch will make sure that override also in the
`spec['openblas'].libs()` call. (Which happens in `hypre`, likely
others).

( see
https://spack.readthedocs.io/en/latest/packages_yaml.html#assigning-package-attributes
)

Thanks to becker33 for debugging help in Slack

* RepoSplit/tests: update repo tests relying on builtin package repo to only use mock repos (#48926)

* RepoSplit/tests: update repo tests relying on builtin

* test_repo_last_mtime: skip on windows due to mtime issues in CI

* MesonPackage: depends_on pkgconfig (#46955)

meson's `dependency` function often uses pkg-config to locate a dependency, and may even fall back to cmake. The former case is very common, and since packagers often forget to add the tiny pkgconfig package as a build dep, we do it for them.

* Spec.__getitem__: restrict to direct deps + transitive runtime deps (#49016)

With this change spec["pkg"] searches only direct dependencies and transitive link/run
dependencies, ordered by depth. This avoids situations where we pick up unwanted 
deps of build/test deps. 

To reach those, you need to do spec["build_dep"]["pkg"] explicitly.

Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>

* views: normalize paths on case insensitive file systems (#47370)

On macOS, prefix_a/file and prefix_b/FILE map to the same file view/file or view/FILE.

This commit ensures that we test whether a view is created on a case insensitive filesystem and handle projection conflicts accordingly.

* Allow tuning max_dupes for build dependencies (#48948)

Up to now, Spack was allowing all build-tools that
may appear in the DAG to have 2 max_dupes.

This is not needed in practice for most of them,
and adding them out of caution just increases
grounding and concretization time.

This PR makes the value of max_dupes configurable
per package, and sets only a few known packages to
2 max_dupes by default.

In case user needs different values, they can
tune the configuration for their use case.

* vtk: fix 9.4.1 concretization (#48946)

* seacas: conflict 2024-06-27 with windows

* vtk: fix 9.4.1 seacas dependency

* cairo: add new version and update build system (#48822)

* update cairo for new meson build system

* update patch range. remove old conflict

* style

* update pango to reflect the changes in cairo

* refine depends

* style

* add lzo depends

* add +shared

* non self-referential variant requireme

* style

* Move +shared variant back to just autotools as meson automatically handles it

* clarify patch when=

* update based on reviews. switch from conflicts to requires to enforce variant synchronization

* refine conflicts and requires

* better group build deps together

* comment for meson build lower version bound

* clarifying comments

* clarify version ranges, enforce build_system with version ranges

* style

* cairo:  no need to require for build_systems

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* fzf: add v0.60.0, improve styling (#49059)

* fd: improve documentation and styling to help newer maintainers (#49058)

* direnv: add master, fix up package for better documentation (#49053)

* GDAL: add v3.10.2 (#49042)

* pbwt: new package (#49055)

* pbwt: add v2.1, v2.0

Signed-off-by: Teague Sterling <teaguesterling@gmail.com>

* [@spackbot] updating style on behalf of teaguesterling

* Update package.py

---------

Signed-off-by: Teague Sterling <teaguesterling@gmail.com>

* py-xarray-regrid: Add new package (#48834)

* Add py-xarray-regrid and required dep flox

* remove boiler plate

* Add missing py310 dep

* py-flox, py-xarray-regrid: add type=("build", "run") to python dependency

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* build(deps): bump isort in /.github/workflows/requirements/style (#48746)

Bumps [isort](https://github.com/pycqa/isort) from 5.13.2 to 6.0.0.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.13.2...6.0.0)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump black from 24.10.0 to 25.1.0 in /lib/spack/docs (#48780)

Bumps [black](https://github.com/psf/black) from 24.10.0 to 25.1.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.10.0...25.1.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* surfer: new package (#48432)

* Add waveform viewer, surfer for RTL simulations

* Ran black over the code following style check failure

* build(deps): bump black in /.github/workflows/requirements/style (#48779)

Bumps [black](https://github.com/psf/black) from 24.10.0 to 25.1.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.10.0...25.1.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* new package: jujutsu (#48231)

* lis: add v2.0.28 -> v2.1.7 (#48308)

* Added LIS 2.1.7

* Added LIS versions from 2.0.28 to 2.1.7

* apply black v25.1.0 (#49076)

* build(deps): bump isort from 5.13.2 to 6.0.0 in /lib/spack/docs (#48747)

Bumps [isort](https://github.com/pycqa/isort) from 5.13.2 to 6.0.0.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.13.2...6.0.0)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Spec.__contains__: restrict to direct build and transitive runtime deps (#49072)

Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>

* mochi-margo/mochi-thallium: new versions (#49037)

* mochi-margo/mochi-thallium: new versions

* mochi-thallium: fixing style

* mochi-thallium: fixing required dependency on mochi-margo versions

* Add new recipe aotriton for rocm. (#49038)

* add new reciple aotriton for rocm. used for py-torch

* update the git info

* fix style error

* fix style error

* fix style error

* address review comments

* fix style error

* update maintainers (#48295)

* acts dependencies: new versions as of 2025/02/17 (#49073)

This commit adds detray v0.88.1, covfie v0.12.0 and v0.12.1, as well as
ACTS v37.1.0.

* magma: remove cuda_arch constraint on 2.9.0+ (#49019)

* plsm: new package (#48875)

* Adding plsm package

* [@spackbot] updating style on behalf of PhilipFackler

* Removing redundant text

* Add description

* Add blank line

* Add cuda_arch and update int64 handling

* gnutls: add v3.8.9 (#49062)

* gnutls: add v3.8.9

* gnutls: address super small nitpick

* gnutls: fix git url

* qemacs: add v6.4.1, fix +doc (#48722)

* py-fastjsonschema: add 2.17 to 2.21.1; note python dependencies (#47926)

* py-fastjsonschema: add 2.17 to 2.21.1; note python dependencies

* py-importlib-resources: add v5.13 to 6.4

* Revert "py-importlib-resources: add v5.13 to 6.4"

This reverts commit 1df208874c799b99dcfc43f13ae85f9324c59b52.

---------

Signed-off-by: Shane Nehring <snehring@iastate.edu>
Signed-off-by: Jonathon Anderson <anderson.jonathonm@gmail.com>
Signed-off-by: Todd Gamblin <tgamblin@llnl.gov>
Signed-off-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>
Signed-off-by: Teague Sterling <teaguesterling@gmail.com>
Signed-off-by: Howard Pritchard <howardp@lanl.gov>
Signed-off-by: Justin Cook <jscook@lbl.gov>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Etienne Ndamlabin <88906611+endamlabin@users.noreply.github.com>
Co-authored-by: Etienne Ndamlabin <jean-etienne.ndamlabin-mboula@inria.fr>
Co-authored-by: Sreenivasa Murthy Kolam <sreenivasamurthy.kolam@amd.com>
Co-authored-by: Thomas Bouvier <contact@thomas-bouvier.io>
Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
Co-authored-by: G-Ragghianti <33492707+G-Ragghianti@users.noreply.github.com>
Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
Co-authored-by: David Schneller <12698011+davschneller@users.noreply.github.com>
Co-authored-by: Juan Miguel Carceller <22276694+jmcarcell@users.noreply.github.com>
Co-authored-by: jmcarcell <jmcarcell@users.noreply.github.com>
Co-authored-by: snehring <7978778+snehring@users.noreply.github.com>
Co-authored-by: Buldram <buldram@proton.me>
Co-authored-by: jmuddnv <143751186+jmuddnv@users.noreply.github.com>
Co-authored-by: Thomas-Ulrich <ulrich@geophysik.uni-muenchen.de>
Co-authored-by: Satish Balay <balay@mcs.anl.gov>
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
Co-authored-by: Filippo Spiga <spiga.filippo@gmail.com>
Co-authored-by: Harmen Stoppels <me@harmenstoppels.nl>
Co-authored-by: Richard Berger <rberger@lanl.gov>
Co-authored-by: Jonathon Anderson <17242663+blue42u@users.noreply.github.com>
Co-authored-by: Harmen Stoppels <harmenstoppels@gmail.com>
Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
Co-authored-by: Eric Berquist <727571+berquist@users.noreply.github.com>
Co-authored-by: wspear <wspear@cs.uoregon.edu>
Co-authored-by: wspear <wspear@users.noreply.github.com>
Co-authored-by: Alec Scott <hi@alecbcs.com>
Co-authored-by: John W. Parent <45471568+johnwparent@users.noreply.github.com>
Co-authored-by: Todd Gamblin <tgamblin@llnl.gov>
Co-authored-by: Chris Marsh <chrismarsh.c2@gmail.com>
Co-authored-by: Rocco Meli <r.meli@bluemail.ch>
Co-authored-by: afzpatel <122491982+afzpatel@users.noreply.github.com>
Co-authored-by: psakievich <psakiev@sandia.gov>
Co-authored-by: Brian Spilner <Try2Code@users.noreply.github.com>
Co-authored-by: Dominic Hofer <6570912+dominichofer@users.noreply.github.com>
Co-authored-by: Greg Becker <becker33@llnl.gov>
Co-authored-by: danielsjensen1 <dsjense@sandia.gov>
Co-authored-by: Till Ehrengruber <till.ehrengruber@cscs.ch>
Co-authored-by: Henri Menke <henri@henrimenke.de>
Co-authored-by: pauleonix <paul.grosse-bley@ziti.uni-heidelberg.de>
Co-authored-by: Mosè Giordano <765740+giordano@users.noreply.github.com>
Co-authored-by: Zack Galbreath <zack.galbreath@kitware.com>
Co-authored-by: Seth R. Johnson <johnsonsr@ornl.gov>
Co-authored-by: Weiqun Zhang <WeiqunZhang@lbl.gov>
Co-authored-by: Taillefumier Mathieu <29380261+mtaillefumier@users.noreply.github.com>
Co-authored-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>
Co-authored-by: Piotr Sacharuk <107190444+PiotrSacharuk@users.noreply.github.com>
Co-authored-by: eugeneswalker <eugenesunsetwalker@gmail.com>
Co-authored-by: psakievich <psakievich@users.noreply.github.com>
Co-authored-by: rfbgo <109985755+rfbgo@users.noreply.github.com>
Co-authored-by: Felix Thaler <thaler@cscs.ch>
Co-authored-by: Bernhard Kaindl <bernhardkaindl7@gmail.com>
Co-authored-by: japlews <22622327+japlews@users.noreply.github.com>
Co-authored-by: George Young <A-N-Other@users.noreply.github.com>
Co-authored-by: Stephen Nicholas Swatman <stephen@v25.nl>
Co-authored-by: Davis Herring <herring@lanl.gov>
Co-authored-by: Dom Heinzeller <dom.heinzeller@icloud.com>
Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja>
Co-authored-by: Izaak "Zaak" Beekman <contact@izaakbeekman.com>
Co-authored-by: ddement <ddement@gatech.edu>
Co-authored-by: LMS Bioinformatics <bioinformatics@lms.mrc.ac.uk>
Co-authored-by: Matt Thompson <matthew.thompson@nasa.gov>
Co-authored-by: SXS Bot <31972027+sxs-bot@users.noreply.github.com>
Co-authored-by: sxs-bot <sxs-bot@users.noreply.github.com>
Co-authored-by: AMD Toolchain Support <73240730+amd-toolchain-support@users.noreply.github.com>
Co-authored-by: vijay kallesh <Vijay-teekinavar.Kallesh@amd.com>
Co-authored-by: Alberto Sartori <alberto.sartori@huawei.com>
Co-authored-by: Alberto Invernizzi <9337627+albestro@users.noreply.github.com>
Co-authored-by: Thomas Madlener <thomas.madlener@desy.de>
Co-authored-by: Mikael Simberg <mikael.simberg@iki.fi>
Co-authored-by: Vinícius <viniciusvgp@gmail.com>
Co-authored-by: Teague Sterling <teaguesterling@users.noreply.github.com>
Co-authored-by: Shane Nehring <snehring@iastate.edu>
Co-authored-by: Sergey Kosukhin <sergey.kosukhin@mpimet.mpg.de>
Co-authored-by: Robert Mijakovic <robert.mijakovic@gmail.com>
Co-authored-by: Paul <bryantpj@ornl.gov>
Co-authored-by: Paul R. C. Kent <kentpr@ornl.gov>
Co-authored-by: Vanessasaurus <814322+vsoch@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@users.noreply.github.com>
Co-authored-by: Howard Pritchard <howardp@lanl.gov>
Co-authored-by: jgraciahlrs <gracia@hlrs.de>
Co-authored-by: Fernando Ayats <ayatsfer@gmail.com>
Co-authored-by: Tim Haines <thaines.astro@gmail.com>
Co-authored-by: renjithravindrankannath <94420380+renjithravindrankannath@users.noreply.github.com>
Co-authored-by: Peter Scheibel <scheibel1@llnl.gov>
Co-authored-by: alalazo <alalazo@users.noreply.github.com>
Co-authored-by: Tara Drwenski <tdrwenski@users.noreply.github.com>
Co-authored-by: Justin Cook <jscook@lbl.gov>
Co-authored-by: jean-francois-sa <jleblancrichard@simplyanalytics.com>
Co-authored-by: etiennemlb <eti.malaboeuf@gmail.com>
Co-authored-by: Richard Berger <richard.berger@outlook.com>
Co-authored-by: Dmitri Smirnov <dmixsmi@gmail.com>
Co-authored-by: John Biddiscombe <biddisco@cscs.ch>
Co-authored-by: Dave Keeshan <96727608+davekeeshan@users.noreply.github.com>
Co-authored-by: Rémi Lacroix <remi.lacroix@idris.fr>
Co-authored-by: Vivek Kale <11766050+vlkale@users.noreply.github.com>
Co-authored-by: vlkale <vlkale@users.noreply.github.com>
Co-authored-by: Marc T. Henry de Frahan <marc.henrydefrahan@nrel.gov>
Co-authored-by: Robert Maaskant <RobertMaaskant@users.noreply.github.com>
Co-authored-by: Matthew Lesko <matthew.w.lesko@nasa.gov>
Co-authored-by: Paul Gessinger <hello@paulgessinger.com>
Co-authored-by: Vicente Bolea <vicente.bolea@kitware.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pranav Sivaraman <pranavsivaraman@gmail.com>
Co-authored-by: Filippo Barbari <filippo.barbari@gmail.com>
Co-authored-by: Matthieu Dorier <mdorier@anl.gov>
Co-authored-by: Nai-Yuan Chiang <sorakid507@gmail.com>
Co-authored-by: Cameron Rutherford <rcamruzz@amazon.com>
Co-authored-by: Philip Fackler <49726797+PhilipFackler@users.noreply.github.com>
Co-authored-by: dmagdavector <david.magda@vectorinstitute.ai>
2025-02-17 15:17:31 -07:00
dmagdavector
5356469ba5 py-fastjsonschema: add 2.17 to 2.21.1; note python dependencies (#47926)
* py-fastjsonschema: add 2.17 to 2.21.1; note python dependencies

* py-importlib-resources: add v5.13 to 6.4

* Revert "py-importlib-resources: add v5.13 to 6.4"

This reverts commit 1df208874c799b99dcfc43f13ae85f9324c59b52.
2025-02-17 13:17:31 -07:00
Buldram
605c3de633 qemacs: add v6.4.1, fix +doc (#48722) 2025-02-17 12:39:43 -06:00
Wouter Deconinck
45c4446b90 gnutls: add v3.8.9 (#49062)
* gnutls: add v3.8.9

* gnutls: address super small nitpick

* gnutls: fix git url
2025-02-17 09:44:00 -08:00
Philip Fackler
4ba6407cb8 plsm: new package (#48875)
* Adding plsm package

* [@spackbot] updating style on behalf of PhilipFackler

* Removing redundant text

* Add description

* Add blank line

* Add cuda_arch and update int64 handling
2025-02-17 12:20:29 -05:00
Cameron Rutherford
c221635c79 magma: remove cuda_arch constraint on 2.9.0+ (#49019) 2025-02-17 17:49:49 +01:00
Stephen Nicholas Swatman
46ff553ec2 acts dependencies: new versions as of 2025/02/17 (#49073)
This commit adds detray v0.88.1, covfie v0.12.0 and v0.12.1, as well as
ACTS v37.1.0.
2025-02-17 08:58:09 -06:00
Nai-Yuan Chiang
fcc85adc7f update maintainers (#48295) 2025-02-17 08:21:52 -06:00
Sreenivasa Murthy Kolam
da1ac0fdd4 Add new recipe aotriton for rocm. (#49038)
* add new reciple aotriton for rocm. used for py-torch

* update the git info

* fix style error

* fix style error

* fix style error

* address review comments

* fix style error
2025-02-17 08:20:36 -06:00
Matthieu Dorier
0accf26472 mochi-margo/mochi-thallium: new versions (#49037)
* mochi-margo/mochi-thallium: new versions

* mochi-thallium: fixing style

* mochi-thallium: fixing required dependency on mochi-margo versions
2025-02-17 08:18:22 -06:00
Harmen Stoppels
545750873e Spec.__contains__: restrict to direct build and transitive runtime deps (#49072)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-02-17 13:57:16 +01:00
dependabot[bot]
7d4523a9fc build(deps): bump isort from 5.13.2 to 6.0.0 in /lib/spack/docs (#48747)
Bumps [isort](https://github.com/pycqa/isort) from 5.13.2 to 6.0.0.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.13.2...6.0.0)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 12:05:41 +01:00
Harmen Stoppels
754a64d1fe apply black v25.1.0 (#49076) 2025-02-17 11:42:12 +01:00
Filippo Barbari
b11578ed7c lis: add v2.0.28 -> v2.1.7 (#48308)
* Added LIS 2.1.7

* Added LIS versions from 2.0.28 to 2.1.7
2025-02-16 19:07:39 -07:00
Pranav Sivaraman
c80dcd8f84 new package: jujutsu (#48231) 2025-02-16 19:41:23 -06:00
dependabot[bot]
aaaf4477c9 build(deps): bump black in /.github/workflows/requirements/style (#48779)
Bumps [black](https://github.com/psf/black) from 24.10.0 to 25.1.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.10.0...25.1.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-16 17:42:46 -07:00
Dave Keeshan
27f123efad surfer: new package (#48432)
* Add waveform viewer, surfer for RTL simulations

* Ran black over the code following style check failure
2025-02-16 17:54:18 -06:00
dependabot[bot]
2b52639032 build(deps): bump black from 24.10.0 to 25.1.0 in /lib/spack/docs (#48780)
Bumps [black](https://github.com/psf/black) from 24.10.0 to 25.1.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.10.0...25.1.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-16 16:37:36 -07:00
dependabot[bot]
a472adf2cb build(deps): bump isort in /.github/workflows/requirements/style (#48746)
Bumps [isort](https://github.com/pycqa/isort) from 5.13.2 to 6.0.0.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.13.2...6.0.0)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-16 16:27:35 -07:00
Chris Marsh
79972d7b57 py-xarray-regrid: Add new package (#48834)
* Add py-xarray-regrid and required dep flox

* remove boiler plate

* Add missing py310 dep

* py-flox, py-xarray-regrid: add type=("build", "run") to python dependency

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-16 12:22:39 -07:00
Teague Sterling
0ffb61e215 pbwt: new package (#49055)
* pbwt: add v2.1, v2.0

Signed-off-by: Teague Sterling <teaguesterling@gmail.com>

* [@spackbot] updating style on behalf of teaguesterling

* Update package.py

---------

Signed-off-by: Teague Sterling <teaguesterling@gmail.com>
2025-02-16 12:08:50 -06:00
Adam J. Stewart
cdd261b63f GDAL: add v3.10.2 (#49042) 2025-02-16 11:48:30 -06:00
Alec Scott
900574ddb3 direnv: add master, fix up package for better documentation (#49053) 2025-02-16 11:35:47 -06:00
Alec Scott
6bc4af11f4 fd: improve documentation and styling to help newer maintainers (#49058) 2025-02-16 11:16:00 -06:00
Alec Scott
6d35a75c4f fzf: add v0.60.0, improve styling (#49059) 2025-02-16 11:13:53 -06:00
Chris Marsh
7e65c57861 cairo: add new version and update build system (#48822)
* update cairo for new meson build system

* update patch range. remove old conflict

* style

* update pango to reflect the changes in cairo

* refine depends

* style

* add lzo depends

* add +shared

* non self-referential variant requireme

* style

* Move +shared variant back to just autotools as meson automatically handles it

* clarify patch when=

* update based on reviews. switch from conflicts to requires to enforce variant synchronization

* refine conflicts and requires

* better group build deps together

* comment for meson build lower version bound

* clarifying comments

* clarify version ranges, enforce build_system with version ranges

* style

* cairo:  no need to require for build_systems

---------

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-15 18:37:43 -07:00
Vicente Bolea
9213bf5919 vtk: fix 9.4.1 concretization (#48946)
* seacas: conflict 2024-06-27 with windows

* vtk: fix 9.4.1 seacas dependency
2025-02-14 16:14:04 -06:00
Massimiliano Culpo
ccd205bfeb Allow tuning max_dupes for build dependencies (#48948)
Up to now, Spack was allowing all build-tools that
may appear in the DAG to have 2 max_dupes.

This is not needed in practice for most of them,
and adding them out of caution just increases
grounding and concretization time.

This PR makes the value of max_dupes configurable
per package, and sets only a few known packages to
2 max_dupes by default.

In case user needs different values, they can
tune the configuration for their use case.
2025-02-14 14:25:12 +01:00
Paul Gessinger
114bd5744f views: normalize paths on case insensitive file systems (#47370)
On macOS, prefix_a/file and prefix_b/FILE map to the same file view/file or view/FILE.

This commit ensures that we test whether a view is created on a case insensitive filesystem and handle projection conflicts accordingly.
2025-02-14 09:35:40 +01:00
Harmen Stoppels
8ef5f1027a Spec.__getitem__: restrict to direct deps + transitive runtime deps (#49016)
With this change spec["pkg"] searches only direct dependencies and transitive link/run
dependencies, ordered by depth. This avoids situations where we pick up unwanted 
deps of build/test deps. 

To reach those, you need to do spec["build_dep"]["pkg"] explicitly.

Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-02-14 08:45:50 +01:00
Wouter Deconinck
36bc53ee07 MesonPackage: depends_on pkgconfig (#46955)
meson's `dependency` function often uses pkg-config to locate a dependency, and may even fall back to cmake. The former case is very common, and since packagers often forget to add the tiny pkgconfig package as a build dep, we do it for them.
2025-02-14 08:36:16 +01:00
Tamara Dahlgren
236b8fc009 RepoSplit/tests: update repo tests relying on builtin package repo to only use mock repos (#48926)
* RepoSplit/tests: update repo tests relying on builtin

* test_repo_last_mtime: skip on windows due to mtime issues in CI
2025-02-13 21:49:50 -08:00
Matthew Lesko
1a42bf043f openblas: .libs() uses self.libraries attribute (#48942)
Currently this is hardcoded to the same value as listed in the class
definition. If one ever overrides this attribute, such as:

```
packages:
  openblas:
    package_attributes:
      libraries = [ 'libopenblaso64', ]
```

this patch will make sure that override also in the
`spec['openblas'].libs()` call. (Which happens in `hypre`, likely
others).

( see
https://spack.readthedocs.io/en/latest/packages_yaml.html#assigning-package-attributes
)

Thanks to becker33 for debugging help in Slack
2025-02-13 21:44:12 -08:00
Robert Maaskant
87cc3280b6 yq: add versions 4.44.5 and 4.44.6 and 4.45.1 (#49027) 2025-02-13 19:48:42 -07:00
Wouter Deconinck
7dc75d5f8c acts: conflicts ^geant4@11.3: when @:35 (#49028) 2025-02-13 19:33:33 -07:00
Marc T. Henry de Frahan
a1bff46435 Update openfast, amr-wind, and nalu-wind packages (#48994) 2025-02-13 19:28:11 -07:00
John W. Parent
12e0eb6178 zlib package: Ensure correct lib search on Windows (#48512)
* Name of zlib's library differs on Windows; also account for name
  differing when building +shared
* `zlib`'s `.libs` implementation was searching for the runtime
  libraries (the .dlls) and should be searching for link-time libs
2025-02-13 17:15:03 -07:00
Vivek Kale
0eb55a0b8f Put in maintainers for Kokkos Tools Spack package (#49018)
* Kokkos Tools package.py: fix maintainers
* Kokkos Tools package.py: remove white space between first and second maintainer in comma-separated list
* [@spackbot] updating style on behalf of vlkale
* Correct maintainers syntax
   Co-authored-by: Richard Berger <richard.berger@outlook.com>

---------

Co-authored-by: vlkale <vlkale@users.noreply.github.com>
Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
Co-authored-by: Richard Berger <richard.berger@outlook.com>
2025-02-13 16:35:22 -07:00
Thomas-Ulrich
6925a53937 easi@1.5.2 (#49013) 2025-02-13 16:29:03 -07:00
Juan Miguel Carceller
e34f04df5e pandora{pfa,sdk,monitoring}: add new versions and allow setting the C++ standard (#48300)
* pandoramonitoring: add v3.6.0; pandorapfa: add v4.11.2

Remove variables that are not being used in pandorasdk. Use the C++ standard
from ROOT when possible and pass -Wno-error to override the -Werror that will
typically fail with a new standard. Add a cxxstd variant for pandorasdk

* Fix style

* Update var/spack/repos/builtin/packages/pandorasdk/package.py

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* Fix style

---------

Co-authored-by: jmcarcell <jmcarcell@users.noreply.github.com>
Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-13 16:09:40 -07:00
Adam J. Stewart
3fe13f0891 py-numpy: add v2.2.3 (#49029) 2025-02-13 15:37:08 -07:00
Rémi Lacroix
c8d244b621 laszip: Add version 3.4.4. (#48982) 2025-02-13 12:47:30 -08:00
Dave Keeshan
bc3132f2a9 yosys: add v0.50 (#48983) 2025-02-13 12:46:21 -08:00
Adam J. Stewart
b79d0bfc80 py-memray: add v1.15.0 (#48989) 2025-02-13 12:45:03 -08:00
Adam J. Stewart
f678e8af4d py-torchgeo: pyvista dep has been removed (#48990) 2025-02-13 12:43:25 -08:00
Matt Thompson
9985ecf6a7 gftl: add v1.15.2 (#48992) 2025-02-13 12:40:24 -08:00
Buldram
5e981797f5 bubblewrap: add versions up to v0.11.0 (#49023) 2025-02-13 06:20:29 -07:00
Harmen Stoppels
a7b542dd37 spack debug create-db-tarball: remove after test failures (#49025) 2025-02-13 13:10:28 +01:00
John Biddiscombe
4dc1a900e2 h5hut: Remove H5_USE_110_API for newer versions (#48885)
* h5hut: Remove H5_USE_110_API for newer versions

* h5hut: style reformat and add maintainer

* h5hut: correct version syntax for <v2.x.x

* h5hut: Bump default version to 2.0.0rc7 and remove older rc candidates

* Update var/spack/repos/builtin/packages/h5hut/package.py

Co-authored-by: Mikael Simberg <mikael.simberg@iki.fi>

---------

Co-authored-by: Alberto Invernizzi <9337627+albestro@users.noreply.github.com>
Co-authored-by: Mikael Simberg <mikael.simberg@iki.fi>
2025-02-13 11:01:14 +01:00
Harmen Stoppels
8697371d82 binutils: add debuginfod variant + update deps (#49011) 2025-02-13 08:00:06 +01:00
Dmitri Smirnov
61899fcfc1 plog: add new package (#48975) 2025-02-13 07:54:00 +01:00
Richard Berger
9697c1934c lammps: add 20241119 and 20250204 releases (#48978) 2025-02-12 15:57:36 -08:00
etiennemlb
a011b49e1e lammps: use the Cray GTL (#46090) 2025-02-12 15:07:51 -07:00
etiennemlb
ae50757f3c cray-mpich: adding partial GTL support (#45830)
cray-mpich now has a rocm variant. You can use gtl_lib in the
flag_handler like so:

```python
    def flag_handler(self, name, flags):
        wrapper_flags = []
        environment_flags = []
        build_system_flags = []

        if self.spec.satisfies("+rocm"):
            if self.spec.satisfies("^cray-mpich"):
                gtl_lib = self.spec["cray-mpich"].package.gtl_lib
                build_system_flags.extend(gtl_lib.get(name) or [])
            # hipcc is not wrapped, we need to pass the flags via the
            # build system.
            build_system_flags.extend(flags)

        return (wrapper_flags, environment_flags, build_system_flags)
```

---------

Co-authored-by: Richard Berger <rberger@lanl.gov>
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
Co-authored-by: Richard Berger <richard.berger@outlook.com>
2025-02-12 12:01:40 -08:00
jean-francois-sa
6f1dce95f9 postgresql: add v17.2 (#47811)
* postgresql: add version 17.2

* postgresql: install flex, bison and perl when building versions 17 and up

* postgresql: do not install perl by default when building versions 17 and up
2025-02-12 13:28:55 -06:00
John W. Parent
fd59d3e589 Ci: ensure file path comparsion uses posix paths (#47033)
Git always produces posix paths, ensure we're always comparsing apples to apples by normalizing paths compared to git output to posix.
2025-02-12 12:14:16 -07:00
Massimiliano Culpo
0172208c52 solver: add type-hints to OutputConfiguration (#48979) 2025-02-12 20:12:12 +01:00
Piotr Sacharuk
02c2516e88 unifyfs: Apply workaround for oneAPI compiler for problem with build (#48962) 2025-02-12 10:25:34 -08:00
Wouter Deconinck
a8e37ccbbb apptainer: get_full_repo for branch main (#49002) 2025-02-12 09:06:59 -08:00
Massimiliano Culpo
f0f463c8dc hep: add missing language dependencies (#48963)
* highfive: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989283

* lhapdf: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989283

* vc: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989140

* davix: add dependency on C, C++

https://gitlab.spack.io/spack/spack/-/jobs/14989131

* pandorasdk: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989130

* veccore: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989118

* pythia6: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989116

* jwt-cpp: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989115

* collier: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989115

* hepmc: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989112

* clhep: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14989075

* fastjet: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14981340

* gosam-contrib: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14978873

* thepeg: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14997553

* cepgen: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14997552

* podio: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14997552

* pandoramonitoring: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14997552

* lcio: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14997513

* geant4: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14997202

* evtgen: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14996817

* apfel: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/14996779

* collier: add dependency on C, C++

https://gitlab.spack.io/spack/spack/-/jobs/14996770

* vecgeom: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/15003840

* dd4hep: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/15003839

* opendatadetector: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/15007666

* acts: add dependency on C

https://gitlab.spack.io/spack/spack/-/jobs/15007827

* hepmc: remove dependency on fortran

Co-authored-by: Seth R. Johnson <johnsonsr@ornl.gov>

* thepeg: remove fortran dep

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* acts: add a conditional build dependency

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

* opendatadetector: add comment to explain C dep

Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>

---------

Co-authored-by: Seth R. Johnson <johnsonsr@ornl.gov>
Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2025-02-12 10:51:23 -06:00
Harmen Stoppels
a137da1cd5 Spec.validate_detection -> spack.detection.path.validate_detection (#48987) 2025-02-12 09:30:14 -07:00
Harmen Stoppels
03e972314f Remove spack.repo.PATH.is_virtual call from SpecBuildInterface.(#48984)
This PR is effectively a breaking change extracted from #45189, which removes 
support for spec["mpi"] if spec itself is openmpi / mpich that could provide mpi; 
from the Spec instance we don't have any parent it provides it to, 
hence it's a KeyError.
2025-02-12 17:17:45 +01:00
Seth R. Johnson
9a7a3d2743 g4vg: add 'develop' branch (#49003)
* g4vg: add develop version

* celeritas: add develop version

* Fix style

* REVERTME: move celeritas changes to another branch

* Get full repo

* remove unneeded variable
2025-02-12 09:04:42 -07:00
Harmen Stoppels
76f00a3659 Spec.is_virtual -> spack.repo.PATH.is_virtual (#48986) 2025-02-12 16:57:27 +01:00
Harmen Stoppels
cd98781fb4 concretize.lp: don't warn about deprecation when external (#49008) 2025-02-12 16:27:37 +01:00
Thomas Madlener
dd16f451fc lcio: Add latest 2.22.5 tag (#48991) 2025-02-12 08:26:12 -07:00
Buldram
4f6cd5abde py-transformers: add new versions (#49000)
* py-transformers: add new versions

* py-tokenizers: add new versions

* Apply suggestions from code review
2025-02-12 07:58:32 -07:00
Justin Cook
d7f05e08be libfabric: use the class variable to get the list of fabrics (#49007)
Suggested by: alalazo <alalazo@users.noreply.github.com>

Signed-off-by: Justin Cook <jscook@lbl.gov>
2025-02-12 14:07:06 +01:00
Harmen Stoppels
9747978c7f Spec.package_class -> spack.repo.PATH.get_pkg_class (#48985) 2025-02-12 11:52:04 +01:00
Harmen Stoppels
f043455ccc gmake: fix def libs/headers (#49009) 2025-02-12 11:07:55 +01:00
Harmen Stoppels
fb9d6427e6 package_hash.py: move metadata_attrs inline out of package_base (#48981) 2025-02-12 10:38:35 +01:00
Tara Drwenski
76e83e10c1 gmake: add empty libs property, remove link deptypes from dependents (#48995) 2025-02-12 10:16:30 +01:00
Massimiliano Culpo
af89bdf632 kokkos et al. : don't monkeypatch spec in callbacks (#48916)
Currently, a few packages using kokkos rely on
kokkos itself monkeypatching its own spec to
provide some attribute.

In this commit we change this attribute to be
defined on the package, and never be monkeypatched.
2025-02-12 07:27:49 +01:00
Adam J. Stewart
46f5b192ef PyTorch: build flash attention by default, except in CI (#48521)
* PyTorch: build flash attention by default, except in CI

* Variant is boolean, only available when +cuda/+rocm

* desc -> _desc
2025-02-11 13:20:10 -08:00
Harmen Stoppels
18cd922aab style.py: fix false negative in redundant import statements (#48980) 2025-02-11 19:30:50 +01:00
Massimiliano Culpo
5518ad9611 Fix performance issue on macOS (#48997)
archspec.cpu.host() is not memoized, so compute
it as less as possible.

---------

Co-authored-by: alalazo <alalazo@users.noreply.github.com>
2025-02-11 18:54:32 +01:00
Wouter Deconinck
57a1807443 hep: rivet: require hepmc=3 (#48976) 2025-02-11 01:33:45 -07:00
Harmen Stoppels
3909308d5c spack.util.elf: catch seek errors (#48972) 2025-02-11 08:52:52 +01:00
Massimiliano Culpo
54210270c8 concretizer: reduce search space with static analysis (#48729)
Currently, when we setup the ASP problem for `clingo`, we don't take into account the configuration. This results in setting up ASP problems that are larger than necessary, with possibly redundant information, and higher concretization times. 

This PR tries to improve things by adding an opt-in feature that computes the _possible dependencies_ of a solve taking also into account the current configuration, and avoids adding possible dependencies that we are certain can't be in the final solution.

The feature can be activated with:
```yaml
concretizer:
  static_analysis: true
```

Examples of simple rules to discard dependencies are:
- Dependencies that are not buildable, and for which no binary is present (e.g. `cray-mpich` etc. on non Cray systems)
- Dependencies that are not for the current platform (e.g. `msmpi` on non Windows platforms)
- Conditional dependencies that cannot be activated, because of some user requirement (e.g. `cuda` etc. if the user requires `~cuda` in configuration)
- Virtual providers that cannot be used, because of a requirement on a virtual

The speed-up these rules seem to give depends on the use case at hand, but if the configuration is updated properly, they are noticeable. 

Since in cases where there is no rule to exclude packages upfront, reuse is active, and this option is activated, it's possible to see some minor slow down, the feature has been added as opt-in, so it's turned off by default.
2025-02-11 08:44:20 +01:00
Wouter Deconinck
1a71bb046e rivet: patch missing header in 3.1.10 (#48977) 2025-02-11 07:40:37 +01:00
Peter Scheibel
dbd6857d32 spack compiler find: detect flang-new and flang in newer LLVM versions (#48914) 2025-02-11 07:34:28 +01:00
renjithravindrankannath
025bc24996 Bump up the version for rocm-6.3.2 release (#48787)
* Bump up the version for rocm-6.3.2 release

* rocm-openmp-extras update and style correction

* Updating mivisionx, omniperf, rccl & rocprofiler-systems

* Updating hipsparselt & rocm-opencl

* rocprofiler-systems on gcc-13 and rvs commit instead of patch

* Updated rocjpeg & rocm-examples for 6.3.2

* ROCPROFSYS_BUILD_DYNINST & DYNINST_BUILD_TBB are required only with gcc-13

---------

Co-authored-by: afzpatel <122491982+afzpatel@users.noreply.github.com>
2025-02-10 21:03:23 -08:00
Piotr Sacharuk
01e16b58a3 lua-sol2: Apply workaround for oneAPI compiler for problem with build (#48920) 2025-02-10 21:51:57 -07:00
Tim Haines
f71e202f24 cbtf-krell: Update Boost dependency (#47133)
* Update Boost
* Add gotcha
* Add patch for build errors
* Allow building with latest Dyninst
* Fix patch url
2025-02-10 13:05:05 -08:00
Stephen Nicholas Swatman
f7edd10c17 acts dependencies: new versions as of 2025/02/10 (#48969)
This commit adds detray v0.88.0 and GeoModel v6.9.0.
2025-02-10 13:27:54 -07:00
Richard Berger
153c0805dd ports-of-call: add v1.6.0, v1.7.0, v1.7.1 (#48870) 2025-02-10 11:55:59 -08:00
Harmen Stoppels
5d8517ef69 import-check: bump (#48968) 2025-02-10 20:48:59 +01:00
Fernando Ayats
f23cae6a86 py-iterative-stats: add 0.1.1 (#48959) 2025-02-10 07:42:20 -08:00
jgraciahlrs
e6e67f8e0a extrae: tighten dependencies on boost for +dyninst (#48938) 2025-02-10 10:43:31 +01:00
Howard Pritchard
e6bef4ca9b OpenMPI: add version 4.1.8 (#48922)
Signed-off-by: Howard Pritchard <howardp@lanl.gov>
2025-02-10 10:00:14 +01:00
Matt Thompson
e3e0bef0de Update GFE packages (#48899) 2025-02-10 09:59:15 +01:00
Buldram
42486d93ec nim: add v2.2.2 (#48929) 2025-02-10 09:58:15 +01:00
Harmen Stoppels
6d608a9664 log.py: remove setenv calls (#48933) 2025-02-10 09:53:36 +01:00
Matt Thompson
04313afc63 mapl: add v2.53.1, v2.54.1 (#48944) 2025-02-10 09:42:35 +01:00
Teague Sterling
f839d2ba56 duckdb: add v1.2.0 (#48902)
Signed-off-by: Teague Sterling <teaguesterling@gmail.com>
2025-02-10 09:37:46 +01:00
Paul R. C. Kent
2b1a8b1913 Quantum ESPRESSO: add v7.4.1 (#48949) 2025-02-10 09:20:21 +01:00
Vanessasaurus
8907003648 flux-sched: add v0.42.1 (#48952)
Co-authored-by: github-actions <github-actions@users.noreply.github.com>
2025-02-10 09:17:56 +01:00
Adam J. Stewart
8afdba4bf7 py-einops: add v0.8.1 (#48954) 2025-02-10 09:13:54 +01:00
Paul R. C. Kent
57cabbfb10 qmcpack: add v4.0.0 (#48921) 2025-02-10 09:02:38 +01:00
Paul
c71efb9040 go: add v1.23.6 (#48955) 2025-02-10 08:37:34 +01:00
Robert Mijakovic
c5dd2d43d2 reframe: add v4.6.4 -> v4.7.2 (#48242) 2025-02-10 08:25:12 +01:00
Adam J. Stewart
34338ef757 Python: add new versions (#48950)
* Python: add new versions

* black
2025-02-09 17:20:19 +01:00
Piotr Sacharuk
c0bdc37226 nwchem: add master (#48919)
* Add possibility to build nwchem from master branch

* add oneapi@2025: patch for @7.2.3

---------

Co-authored-by: eugeneswalker <eugenesunsetwalker@gmail.com>
2025-02-07 10:56:04 -08:00
Sergey Kosukhin
8bad9fb804 serialbox: add version 2.6.2 (#48937) 2025-02-07 10:30:31 -08:00
Harmen Stoppels
2df7cc0087 libgcrypt: fix enforced -O0 (#48940)
Signed-off-by: Shane Nehring <snehring@iastate.edu>
Co-authored-by: Shane Nehring <snehring@iastate.edu>
2025-02-07 19:08:51 +01:00
Piotr Sacharuk
40d40ccc52 Apply workarounds for oneAPI compiler for ascent problem with build (#48918)
* Apply workarounds for oneAPI compiler for ascent problem with build

* Use the way with use patch through the PR address

* stylecheck - missing comma
2025-02-07 06:20:19 -07:00
Harmen Stoppels
afe7d6c39e package_base.py: remove use_cray_compiler_names (#48932) 2025-02-07 12:47:17 +01:00
Rocco Meli
113733d9fb trexio: fix issues with autotools build system (#48923) 2025-02-07 03:42:46 -07:00
Massimiliano Culpo
a8e2da5bb8 Fix regression due to dyninst update (#48935) 2025-02-07 10:46:42 +01:00
Harmen Stoppels
97750189b6 clingo-bootstrap: fix +optimized build (#48931)
* fix regression `apple-clang` vs `%apple-clang`
* use f-strings
* remove --verbose flag from LDFLAGS
2025-02-07 09:46:05 +01:00
Teague Sterling
bcd40835a0 py-maturin: add v1.8.2 and refined dependencies (#48915) 2025-02-07 01:23:33 -07:00
John W. Parent
2c3f2c5733 Windows: Update default config for stage location (#48511)
Current location is within the Spack prefix, which causes builds to
pollute VCS with stage artifacts and generally inflates the Spack
install prefix.

This PR moves it to the user cache location now that we can
consistently support paths with spaces on Windows.
2025-02-06 23:25:11 -08:00
Massimiliano Culpo
302d74394b dyninst: cleanup package (#47637)
* Use more idiomatic construct, shorten recipe
* Remove deprecated versions, and associated patches
* Remove v10.0.0
2025-02-07 08:20:05 +01:00
Vinícius
cf94dc7823 simgrid: add v3.36 (#48909) 2025-02-06 21:03:00 -07:00
Rocco Meli
4411ee3382 dla-future-fortran: add v0.3.0 (#48900) 2025-02-06 18:56:10 -07:00
John W. Parent
f790ce0f72 icu4c: no cxxstd flag option on Windows (#48510)
* ICU4C: Don't reference a spec variant on a platform on which it's not defined

* icu4c: no cxx flag on Windows
2025-02-06 18:55:57 -07:00
Mikael Simberg
64d53037db pika: Add 0.32.0 (#48897) 2025-02-06 18:49:55 -07:00
Chris Marsh
4aef50739b Add new version of r-curl (#48912) 2025-02-06 18:38:09 -07:00
Wouter Deconinck
a6e966f6f2 dcap: depends_on libxcrypt (#48903) 2025-02-06 18:37:51 -07:00
psakievich
1f428c4188 Add a message for CMake incremental build (#48905)
* Add a message for CMake incremental build

Requested message to explain CMake phase is getting skipped.

* [@spackbot] updating style on behalf of psakievich

* Update import

---------

Co-authored-by: psakievich <psakievich@users.noreply.github.com>
2025-02-07 01:32:06 +00:00
Thomas Madlener
731e48b1bd lcio: add v2.22.4 (#48895) 2025-02-06 18:20:34 -07:00
Wouter Deconinck
74ff9ad821 hep stack: build also with cuda and rocm where possible (#48528) 2025-02-06 17:09:15 -07:00
Alberto Invernizzi
16a4eff689 nvpl-blas, nvpl-lapack: add v0.4.0.1, v0.3.0 (#48901) 2025-02-06 15:27:28 -07:00
Alberto Sartori
d0b0d8db50 justbuild: add v1.4.3 (#48898) 2025-02-06 15:21:16 -07:00
AMD Toolchain Support
54f591cce5 amdfftw: fix broken build, adjust flags for performance tuning (#48754)
With CFLAGS, the code path in the amdfftw build system will bypass the logic around AMD_ARCH.

---------

Co-authored-by: vijay kallesh <Vijay-teekinavar.Kallesh@amd.com>
2025-02-06 15:14:44 -07:00
Chris Marsh
8677bb4d43 py-numba: Add version 0.61 (#48837) 2025-02-06 07:54:53 -08:00
SXS Bot
b66b80a96a spectre: add v2025.01.30 (#48803)
Co-authored-by: sxs-bot <sxs-bot@users.noreply.github.com>
2025-02-06 13:49:46 +01:00
Adam J. Stewart
10e21f399c py-shapely: add v2.0.7 (#48810) 2025-02-06 13:45:08 +01:00
Matt Thompson
56892f6140 fms: add 2025.01, 2024.03 (#48812) 2025-02-06 13:44:46 +01:00
George Young
7eddc4b1f8 mummer4: patching to allow building with %gcc@13: (#38292)
Co-authored-by: LMS Bioinformatics <bioinformatics@lms.mrc.ac.uk>
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2025-02-06 13:37:42 +01:00
Adam J. Stewart
3c7392bbcc PyTorch: add v2.6.0 (#48794) 2025-02-06 13:32:53 +01:00
ddement
bb0517f4d9 openturbine: add new package (#48683) 2025-02-06 13:32:14 +01:00
Izaak "Zaak" Beekman
c8994ee50f salt: add v0.3.0 (#48877)
* salt: Add v0.3.0 of SALT

This version contains important bug fixes for building and parsing
projects containing Fortran

* salt: Be more explicit about dependency types

 - llvm+clang+flang is needed at build, link and runtime for the
   correct operation of SALT
 - Testing with llvm@master ( llvm > 19.x ) shows that SALT is
   currently incompatible with the latest llvm API so an updated salt
   will be required when LLVM 20 is released
2025-02-06 13:02:08 +01:00
Wouter Deconinck
4b2f5638f2 sherpa: +hepmc3root only when +root (#48827)
* sherpa: +hepmc3root only when +root

* sherpa: fix style
2025-02-06 12:33:27 +01:00
Richard Berger
31312a379f spiner: add v1.6.3 (#48871)
* spiner: update package logic

* singularity-eos: remove spiner cuda_arch propagation

* spiner: add version 1.6.3
2025-02-06 11:47:44 +01:00
Harmen Stoppels
b0d5f272b0 llvm: fix @15 %apple-clang@16 (#48887) 2025-02-06 10:52:36 +01:00
Harmen Stoppels
1c93fef160 spec.py: ensure == is false if true modulo precomputed dag hash (#48889) 2025-02-06 09:55:27 +01:00
Axel Huebl
8bb5f4faf4 enzyme: add v0.0.172 (#48881) 2025-02-06 09:40:14 +01:00
Dom Heinzeller
f76ab5f72f Update py-arch, py-statsmodels (add 0.14.1), py-patsy (add 0.5.4) to be able to use py-cython@3 (#48769)
* Add py-patsy@0.5.4
* Correct py-numpy dependency in py-arch
* Add py-statsmodels@0.14.1 and update dependencies
* Add climbfuji as maintainer for py-patsy
* Add climbfuji as maintainer for py-statsmodels
* Update var/spack/repos/builtin/packages/py-statsmodels/package.py
2025-02-05 16:23:33 -08:00
Richard Berger
49c831edc3 flecsi: new version 2.3.1 (#48867)
* flecsi: add new version 2.3.1, remove develop
* flecsi: remove kokkos and openmp variants moving forward
* flecsi: propagate cuda and rocm settings from kokkos
* Update var/spack/repos/builtin/packages/flecsi/package.py
   Co-authored-by: Davis Herring <herring@lanl.gov>
* flecsi: remove redundant depends_on lines
* flecsi: correct legion dependency
* flecsi: deprecate v2.0.0 and v2.1.0
* flecsi: force +openmp if ^kokkos+openmp

---------

Co-authored-by: Davis Herring <herring@lanl.gov>
2025-02-05 16:18:58 -08:00
afzpatel
c943c8c1d2 hip-tests: new package (#47273)
* hip-tests: add new package
* remove hip-tests from hip recipe
* remove old versions
* fix style
* add missing import
* bump hip-tests to 6.3.1
* fix style
2025-02-05 15:35:04 -08:00
Harmen Stoppels
e0e6f29584 relocate.py: don't warn about symlinks (#48904)
`relocate_links` warns when the target is absolute and not matched by
any prefix from the prefix to prefix map.

This can lead to false positives, cause the prefix to prefix map does
not contain trivial/identity entries whenever a package is installed to
its original location.

Since relocate_links is the odd one out there (we don't warn about
similar issues with rpaths, etc), just remove the warning.
2025-02-05 12:33:44 -07:00
Wouter Deconinck
72bc3bb803 libice: add v1.1.2 (#48861) 2025-02-05 10:35:34 -08:00
Wouter Deconinck
dba8fe2b96 harfbuzz: add v10.2.0 (#48857) 2025-02-05 10:35:18 -08:00
Harmen Stoppels
4487598d60 spec.py: ensure spec.extra_attributes is {} if is null in json (#48896) 2025-02-05 17:55:53 +01:00
Stephen Nicholas Swatman
495537cf56 acts: add v39.0.0 (#48839)
This commit adds version 39.0.0 of the ACTS package which, as far as I
can tell, doesn't require any dependency updates.
2025-02-05 09:39:21 -06:00
George Young
22c3b4099f code-server: update to v4.96.4 (#48828) 2025-02-05 04:38:11 -07:00
japlews
13978d11a0 Scotch: add v7.0.6, add testing option (#48781) 2025-02-05 12:04:00 +01:00
Alec Scott
a22114b20b bash: add autotools dependencies (#48874) 2025-02-05 11:26:43 +01:00
Chris Marsh
c10624390f Fix esmf usage, add new version (#48835) 2025-02-05 11:24:48 +01:00
Felix Thaler
fb3d9de80b nnn: new package (#46174)
Co-authored-by: Bernhard Kaindl <bernhardkaindl7@gmail.com>
2025-02-05 11:23:28 +01:00
Harmen Stoppels
fbb688af07 spec.py: fix hash change due to None vs {} (#48854)
* Fix hash change due to None vs {}

* Enforce null for empty list of external_modules
2025-02-05 09:48:00 +01:00
Chris Marsh
d34b709425 py-elevation: new package (#48836) 2025-02-05 09:46:49 +01:00
rfbgo
cb0b188cf6 pfind: new package (#48685) 2025-02-05 09:31:10 +01:00
Harmen Stoppels
9a2b0aca66 ci: bump import-check (#48883) 2025-02-05 09:17:01 +01:00
Todd Gamblin
89a8ab3233 ci: add codecov token secret to coverage upload job (#48880)
Codecov needs to see the token secret when uploading, so we have to
add this line to the workflow YAML:

```yaml
  with:
    token: ${{ secrets.CODECOV_TOKEN }}
```

Signed-off-by: Todd Gamblin <tgamblin@llnl.gov>
2025-02-05 01:18:02 +00:00
Harmen Stoppels
5d87166c07 gha: standalone import-check (#48873) 2025-02-04 22:18:30 +01:00
Taillefumier Mathieu
15c989b3fe sirius: add v7.6.2 (#48797)
Co-authored-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>
Co-authored-by: Rocco Meli <r.meli@bluemail.ch>
2025-02-04 13:08:02 -07:00
psakievich
b7f556e4b4 Remove variable from cmake.py (#48824)
* Remove variable from cmake.py

#48775 left a dangling variable that was not caught in CI but by the eyes of @haampie. Restructure variable to local method.

* [@spackbot] updating style on behalf of psakievich

* Update cmake.py

* Update lib/spack/spack/build_systems/cmake.py

* Update lib/spack/spack/build_systems/cmake.py

---------

Co-authored-by: psakievich <psakievich@users.noreply.github.com>
2025-02-04 15:20:15 +01:00
Zack Galbreath
36f32ceda3 Remove ISC stacks environment files (#48851)
Follow-up to #48811
2025-02-04 10:31:40 +01:00
Piotr Sacharuk
01d77ed915 Apply workaround for oneAPI compiler for upcxx problem with a template argument list (#48843)
* Fix upcxx problem with  a template argument list is expected after a name prefixed by the template keyword

* Revert "Fix upcxx problem with  a template argument list is expected after a name prefixed by the template keyword"

This reverts commit faf9b8ce85.

* Apply workaround for oneAPI compiler

* style problem resolved

* use spec.satisfies syntax

---------

Co-authored-by: eugeneswalker <eugenesunsetwalker@gmail.com>
2025-02-04 09:26:44 +01:00
Wouter Deconinck
0049f8332d libsm: add v1.2.5 (#48862) 2025-02-03 23:03:10 -07:00
Wouter Deconinck
39c10c3116 dd4hep: add v1.31 (#48850) 2025-02-03 22:48:17 -07:00
Todd Gamblin
71d1901831 update pyproject.toml for ruff format (#48823)
Add ruff configuration to `pyproject.toml`.

This allows `ruff format` in the Spack repository to format all the files we care about, 
with our line length of 99, the exceptions we already put in place, and excluding things
we don't auto-format, like vendored dependencies.

Right now it'll reformat 175 or so files, but only slightly, in places where `ruff` differs from
`black`. For the most part I like the ruff format decisions better than `black`, but none of
the changes seem too severe.

This does not change `spack style` -- I figure that can come later but this at least will
let people start playing with `ruff`.

---------

Signed-off-by: Todd Gamblin <tgamblin@llnl.gov>
2025-02-03 20:56:05 -08:00
Wouter Deconinck
41e0863b86 fcgi: add v2.4.3, v2.4.4 (#48856) 2025-02-03 21:32:07 -07:00
Taillefumier Mathieu
a75d83f65c netlib-scalapack: Update version (#48667)
* Update scalapack version

Signed-off-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>

* use url_for_version

Signed-off-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>

* use spec.satisfies instead of version()

---------

Signed-off-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>
Co-authored-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>
2025-02-03 21:31:40 -07:00
Wouter Deconinck
f2f13964fb sherpa: support cxxstd=20 when=@3: (#48829)
* sherpa: support cxxstd=20 when=@3:

* hep: sherpa cxxstd=20
2025-02-03 22:24:35 -06:00
Weiqun Zhang
9b032018d6 amrex: add v25.02 (#48853) 2025-02-03 21:23:08 -07:00
Wouter Deconinck
7d470c05be libdrm: add v2.4.124 (#48860) 2025-02-03 21:03:18 -07:00
Wouter Deconinck
664fe9e9e6 cppgsl: add v4.1.0 (#48864) 2025-02-03 20:53:01 -07:00
Chris Marsh
2745a519e2 Add new package py-metis (#48848) 2025-02-03 20:43:12 -07:00
Wouter Deconinck
4348ee1c75 icu4c: add v75.1, v76.1 (#48858) 2025-02-03 20:42:48 -07:00
Chris Marsh
8e39fb1e54 Add new package func (#48849) 2025-02-03 20:38:12 -07:00
Wouter Deconinck
09458312a3 isa-l: add v2.31.1 (#48859) 2025-02-03 20:37:51 -07:00
Chris Marsh
5fd0693df4 py-geojson: Add new package (#48847)
* Add new package py-geojson
* fix when
2025-02-03 20:37:35 -07:00
snehring
f58684429d Tesseract v5.5.0 (#48866)
* leptonica: adding v1.85.0
  Signed-off-by: Shane Nehring <snehring@iastate.edu>
* tesseract: adding v5.5.0
  Signed-off-by: Shane Nehring <snehring@iastate.edu>

---------

Signed-off-by: Shane Nehring <snehring@iastate.edu>
2025-02-03 16:07:54 -08:00
afzpatel
409611a479 rocm-examples and rocjpeg: new packages (#47695)
* new package: rocm-examples
* add new package rocjpeg and update rocm-examples for 6.3.0
* fix licenses
* add versions 6.3.1
* change homepage and git
* add f-string
2025-02-03 13:11:42 -08:00
afzpatel
dd98cfb839 py-tensorflow: add 2.18.0-rocm-enhanced (#48711)
* py-tensorflow: add 2.18.0-rocm-enhanced

* fix style

* fix style

* fix style

* review changes

* review changes

* remove hipblaslt dependency

* remove ci changes and force ROCm 6.3.1 for newest TF

* remove rocm 6.3.1 dependency

* simplify configure fix
2025-02-03 13:38:25 -07:00
Mosè Giordano
5c91667dab r-dmrcate: add v2.16.0, v3.0.0, v3.2.0 (#48158)
* r-dmrcate: add new versions
* r-dmrcate: require `r@4.3.0` for v2.99.0+
* r-dmrcate: update dependencies
2025-02-03 12:17:47 -08:00
Seth R. Johnson
9efd6f3f11 g4vg: new package (#48844)
* g4vg: new package

* [@spackbot] updating style on behalf of sethrj
2025-02-03 11:01:10 -07:00
Harmen Stoppels
a8f5289801 cdash: avoid build_opener (#48846) 2025-02-03 18:41:40 +01:00
Harmen Stoppels
ac635aa777 packge_base.py: remove _patches_by_hash (#48768) 2025-02-03 16:17:42 +01:00
Rocco Meli
45dcddf9c3 CP2K: use libxc@7 for master/next release (#48808) 2025-02-03 15:59:44 +01:00
Harmen Stoppels
f1660722e7 gcc: deprecate old patch releases (#48761) 2025-02-03 15:27:14 +01:00
Zack Galbreath
04b44d841c gitlab: remove isc stacks (#48811) 2025-02-03 15:26:59 +01:00
Mosè Giordano
7f30502297 ziatest: add new package (#48809) 2025-02-03 14:41:38 +01:00
Rocco Meli
61b1586c51 sirius: patch pugixml (#48841) 2025-02-03 06:33:00 -07:00
pauleonix
8579efcadf cuda: add v12.8 (#48708) 2025-02-03 13:49:30 +01:00
Harmen Stoppels
1c3e2b5425 llvm: deprecate old patch releases (#48762) 2025-02-03 11:17:53 +01:00
Henri Menke
011ef0aaaf berkeleygw: add -o flag to tar extraction (#48816)
when extracting as root user, avoid that tar attempts to change file ownership
2025-02-03 11:08:56 +01:00
Harmen Stoppels
9642f3f49a import-check: enable color output (#48842) 2025-02-03 11:02:21 +01:00
Harmen Stoppels
a6c9b55fad Set version to v1.0.0.dev0 (#48791) 2025-02-03 01:42:32 -08:00
Todd Gamblin
608ed967e1 style: fix not in and is not (#48831)
These are some changes that `ruff check --fix` would make that the current
`spack style` also agrees with.  Make the changes now so that the `ruff`
change is less disruptive.

Signed-off-by: Todd Gamblin <tgamblin@llnl.gov>
2025-02-03 00:49:38 -08:00
Todd Gamblin
742eaa32b7 spack_yaml: use unambiguous variable name (#48832) 2025-02-03 09:07:39 +01:00
707 changed files with 13224 additions and 8071 deletions

View File

@@ -81,6 +81,10 @@ jobs:
with:
with_coverage: ${{ needs.changes.outputs.core }}
import-check:
needs: [ changes ]
uses: ./.github/workflows/import-check.yaml
all-prechecks:
needs: [ prechecks ]
if: ${{ always() }}

View File

@@ -33,3 +33,4 @@ jobs:
with:
verbose: true
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}

49
.github/workflows/import-check.yaml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: import-check
on:
workflow_call:
jobs:
# Check we don't make the situation with circular imports worse
import-check:
runs-on: ubuntu-latest
steps:
- uses: julia-actions/setup-julia@v2
with:
version: '1.10'
- uses: julia-actions/cache@v2
# PR: use the base of the PR as the old commit
- name: Checkout PR base commit
if: github.event_name == 'pull_request'
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
ref: ${{ github.event.pull_request.base.sha }}
path: old
# not a PR: use the previous commit as the old commit
- name: Checkout previous commit
if: github.event_name != 'pull_request'
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
fetch-depth: 2
path: old
- name: Checkout previous commit
if: github.event_name != 'pull_request'
run: git -C old reset --hard HEAD^
- name: Checkout new commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
path: new
- name: Install circular import checker
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
repository: haampie/circular-import-fighter
ref: 4cdb0bf15f04ab6b49041d5ef1bfd9644cce7f33
path: circular-import-fighter
- name: Install dependencies
working-directory: circular-import-fighter
run: make -j dependencies
- name: Circular import check
working-directory: circular-import-fighter
run: make -j compare "SPACK_ROOT=../old ../new"

View File

@@ -1,7 +1,7 @@
black==24.10.0
black==25.1.0
clingo==5.7.1
flake8==7.1.1
isort==5.13.2
mypy==1.11.2
types-six==1.17.0.20241205
flake8==7.1.2
isort==6.0.1
mypy==1.15.0
types-six==1.17.0.20250304
vermin==1.6.0

View File

@@ -86,49 +86,6 @@ jobs:
spack -d bootstrap now --dev
spack -d style -t black
spack unit-test -V
# Check we don't make the situation with circular imports worse
import-check:
runs-on: ubuntu-latest
steps:
- uses: julia-actions/setup-julia@v2
with:
version: '1.10'
- uses: julia-actions/cache@v2
# PR: use the base of the PR as the old commit
- name: Checkout PR base commit
if: github.event_name == 'pull_request'
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
ref: ${{ github.event.pull_request.base.sha }}
path: old
# not a PR: use the previous commit as the old commit
- name: Checkout previous commit
if: github.event_name != 'pull_request'
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
fetch-depth: 2
path: old
- name: Checkout previous commit
if: github.event_name != 'pull_request'
run: git -C old reset --hard HEAD^
- name: Checkout new commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
path: new
- name: Install circular import checker
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
repository: haampie/circular-import-fighter
ref: 9a2c728c97f594dec0210e7f85cb7167eaf29176
path: circular-import-fighter
- name: Install dependencies
working-directory: circular-import-fighter
run: make -j dependencies
- name: Circular import check
working-directory: circular-import-fighter
run: make -j compare "SPACK_ROOT=../old ../new"
# Further style checks from pylint
pylint:

1
.gitignore vendored
View File

@@ -201,7 +201,6 @@ tramp
# Org-mode
.org-id-locations
*_archive
# flymake-mode
*_flymake.*

View File

@@ -43,6 +43,28 @@ concretizer:
# (e.g. py-setuptools, cmake etc.)
# "full" (experimental): allows separation of the entire build-tool stack (e.g. the entire "cmake" subDAG)
strategy: minimal
# Maximum number of duplicates in a DAG, when using a strategy that allows duplicates. "default" is the
# number used if there isn't a more specific alternative
max_dupes:
default: 1
# Virtuals
c: 2
cxx: 2
fortran: 1
# Regular packages
cmake: 2
gmake: 2
python: 2
python-venv: 2
py-cython: 2
py-flit-core: 2
py-pip: 2
py-setuptools: 2
py-wheel: 2
xcb-proto: 2
# Compilers
gcc: 2
llvm: 2
# Option to specify compatibility between operating systems for reuse of compilers and packages
# Specified as a key: [list] where the key is the os that is being targeted, and the list contains the OS's
# it can reuse. Note this is a directional compatibility so mutual compatibility between two OS's
@@ -63,3 +85,7 @@ concretizer:
# Setting this to false yields unreproducible results, so we advise to use that value only
# for debugging purposes (e.g. check which constraints can help Spack concretize faster).
error_on_timeout: true
# Static analysis may reduce the concretization time by generating smaller ASP problems, in
# cases where there are requirements that prevent part of the search space to be explored.
static_analysis: false

View File

@@ -1,5 +1,5 @@
config:
locks: false
build_stage::
- '$spack/.staging'
- '$user_cache_path/stage'
stage_name: '{name}-{version}-{hash:7}'

View File

@@ -1761,19 +1761,24 @@ Verifying installations
The ``spack verify`` command can be used to verify the validity of
Spack-installed packages any time after installation.
^^^^^^^^^^^^^^^^^^^^^^^^^
``spack verify manifest``
^^^^^^^^^^^^^^^^^^^^^^^^^
At installation time, Spack creates a manifest of every file in the
installation prefix. For links, Spack tracks the mode, ownership, and
destination. For directories, Spack tracks the mode, and
ownership. For files, Spack tracks the mode, ownership, modification
time, hash, and size. The Spack verify command will check, for every
file in each package, whether any of those attributes have changed. It
will also check for newly added files or deleted files from the
installation prefix. Spack can either check all installed packages
time, hash, and size. The ``spack verify manifest`` command will check,
for every file in each package, whether any of those attributes have
changed. It will also check for newly added files or deleted files from
the installation prefix. Spack can either check all installed packages
using the `-a,--all` or accept specs listed on the command line to
verify.
The ``spack verify`` command can also verify for individual files that
they haven't been altered since installation time. If the given file
The ``spack verify manifest`` command can also verify for individual files
that they haven't been altered since installation time. If the given file
is not in a Spack installation prefix, Spack will report that it is
not owned by any package. To check individual files instead of specs,
use the ``-f,--files`` option.
@@ -1788,6 +1793,22 @@ check only local packages (as opposed to those used transparently from
``upstream`` spack instances) and the ``-j,--json`` option to output
machine-readable json data for any errors.
^^^^^^^^^^^^^^^^^^^^^^^^^^
``spack verify libraries``
^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``spack verify libraries`` command can be used to verify that packages
do not have accidental system dependencies. This command scans the install
prefixes of packages for executables and shared libraries, and resolves
their needed libraries in their RPATHs. When needed libraries cannot be
located, an error is reported. This typically indicates that a package
was linked against a system library, instead of a library provided by
a Spack package.
This verification can also be enabled as a post-install hook by setting
``config:shared_linking:missing_library_policy`` to ``error`` or ``warn``
in :ref:`config.yaml <config-yaml>`.
-----------------------
Filesystem requirements
-----------------------

View File

@@ -223,6 +223,10 @@ def setup(sphinx):
("py:class", "spack.compiler.CompilerCache"),
# TypeVar that is not handled correctly
("py:class", "llnl.util.lang.T"),
("py:class", "llnl.util.lang.KT"),
("py:class", "llnl.util.lang.VT"),
("py:obj", "llnl.util.lang.KT"),
("py:obj", "llnl.util.lang.VT"),
]
# The reST default role (used for this markup: `text`) to use for all documents.

View File

@@ -125,6 +125,8 @@ are stored in ``$spack/var/spack/cache``. These are stored indefinitely
by default. Can be purged with :ref:`spack clean --downloads
<cmd-spack-clean>`.
.. _Misc Cache:
--------------------
``misc_cache``
--------------------
@@ -334,3 +336,52 @@ create a new alias called ``inst`` that will always call ``install -v``:
aliases:
inst: install -v
-------------------------------
``concretization_cache:enable``
-------------------------------
When set to ``true``, Spack will utilize a cache of solver outputs from
successful concretization runs. When enabled, Spack will check the concretization
cache prior to running the solver. If a previous request to solve a given
problem is present in the cache, Spack will load the concrete specs and other
solver data from the cache rather than running the solver. Specs not previously
concretized will be added to the cache on a successful solve. The cache additionally
holds solver statistics, so commands like ``spack solve`` will still return information
about the run that produced a given solver result.
This cache is a subcache of the :ref:`Misc Cache` and as such will be cleaned when the Misc
Cache is cleaned.
When ``false`` or ommitted, all concretization requests will be performed from scatch
----------------------------
``concretization_cache:url``
----------------------------
Path to the location where Spack will root the concretization cache. Currently this only supports
paths on the local filesystem.
Default location is under the :ref:`Misc Cache` at: ``$misc_cache/concretization``
------------------------------------
``concretization_cache:entry_limit``
------------------------------------
Sets a limit on the number of concretization results that Spack will cache. The limit is evaluated
after each concretization run; if Spack has stored more results than the limit allows, the
oldest concretization results are pruned until 10% of the limit has been removed.
Setting this value to 0 disables the automatic pruning. It is expected users will be
responsible for maintaining this cache.
-----------------------------------
``concretization_cache:size_limit``
-----------------------------------
Sets a limit on the size of the concretization cache in bytes. The limit is evaluated
after each concretization run; if Spack has stored more results than the limit allows, the
oldest concretization results are pruned until 10% of the limit has been removed.
Setting this value to 0 disables the automatic pruning. It is expected users will be
responsible for maintaining this cache.

View File

@@ -14,6 +14,7 @@ case you want to skip directly to specific docs:
* :ref:`compilers.yaml <compiler-config>`
* :ref:`concretizer.yaml <concretizer-options>`
* :ref:`config.yaml <config-yaml>`
* :ref:`include.yaml <include-yaml>`
* :ref:`mirrors.yaml <mirrors>`
* :ref:`modules.yaml <modules>`
* :ref:`packages.yaml <packages-config>`

View File

@@ -670,24 +670,45 @@ This configuration sets the default compiler for all packages to
Included configurations
^^^^^^^^^^^^^^^^^^^^^^^
Spack environments allow an ``include`` heading in their yaml
schema. This heading pulls in external configuration files and applies
them to the environment.
Spack environments allow an ``include`` heading in their yaml schema.
This heading pulls in external configuration files and applies them to
the environment.
.. code-block:: yaml
spack:
include:
- relative/path/to/config.yaml
- environment/relative/path/to/config.yaml
- https://github.com/path/to/raw/config/compilers.yaml
- /absolute/path/to/packages.yaml
- path: /path/to/$os/$target/environment
optional: true
- path: /path/to/os-specific/config-dir
when: os == "ventura"
Included configuration files are required *unless* they are explicitly optional
or the entry's condition evaluates to ``false``. Optional includes are specified
with the ``optional`` clause and conditional with the ``when`` clause. (See
:ref:`include-yaml` for more information on optional and conditional entries.)
Files are listed using paths to individual files or directories containing them.
Path entries may be absolute or relative to the environment or specified as
URLs. URLs to individual files need link to the **raw** form of the file's
contents (e.g., `GitHub
<https://docs.github.com/en/repositories/working-with-files/using-files/viewing-and-understanding-files#viewing-or-copying-the-raw-file-content>`_
or `GitLab
<https://docs.gitlab.com/ee/api/repository_files.html#get-raw-file-from-repository>`_).
Only the ``file``, ``ftp``, ``http`` and ``https`` protocols (or schemes) are
supported. Spack-specific, environment and user path variables can be used.
(See :ref:`config-file-variables` for more information.)
.. warning::
Recursive includes are not currently processed in a breadth-first manner
so the value of a configuration option that is altered by multiple included
files may not be what you expect. This will be addressed in a future
update.
Environments can include files or URLs. File paths can be relative or
absolute. URLs include the path to the text for individual files or
can be the path to a directory containing configuration files.
Spack supports ``file``, ``http``, ``https`` and ``ftp`` protocols (or
schemes). Spack-specific, environment and user path variables may be
used in these paths. See :ref:`config-file-variables` for more information.
^^^^^^^^^^^^^^^^^^^^^^^^
Configuration precedence

View File

@@ -0,0 +1,51 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT)
.. _include-yaml:
===============================
Include Settings (include.yaml)
===============================
Spack allows you to include configuration files through ``include.yaml``.
Using the ``include:`` heading results in pulling in external configuration
information to be used by any Spack command.
Included configuration files are required *unless* they are explicitly optional
or the entry's condition evaluates to ``false``. Optional includes are specified
with the ``optional`` clause and conditional with the ``when`` clause. For
example,
.. code-block:: yaml
include:
- /path/to/a/required/config.yaml
- path: /path/to/$os/$target/config
optional: true
- path: /path/to/os-specific/config-dir
when: os == "ventura"
shows all three. The first entry, ``/path/to/a/required/config.yaml``,
indicates that included ``config.yaml`` file is required (so must exist).
Use of ``optional: true`` for ``/path/to/$os/$target/config`` means
the path is only included if it exists. The condition ``os == "ventura"``
in the ``when`` clause for ``/path/to/os-specific/config-dir`` means the
path is only included when the operating system (``os``) is ``ventura``.
The same conditions and variables in `Spec List References
<https://spack.readthedocs.io/en/latest/environments.html#spec-list-references>`_
can be used for conditional activation in the ``when`` clauses.
Included files can be specified by path or by their parent directory.
Paths may be absolute, relative (to the configuration file including the path),
or specified as URLs. Only the ``file``, ``ftp``, ``http`` and ``https`` protocols (or
schemes) are supported. Spack-specific, environment and user path variables
can be used. (See :ref:`config-file-variables` for more information.)
.. warning::
Recursive includes are not currently processed in a breadth-first manner
so the value of a configuration option that is altered by multiple included
files may not be what you expect. This will be addressed in a future
update.

View File

@@ -71,6 +71,7 @@ or refer to the full manual below.
configuration
config_yaml
include_yaml
packages_yaml
build_settings
environments

View File

@@ -820,6 +820,69 @@ presence of a ``SPACK_CDASH_AUTH_TOKEN`` environment variable during the
build group on CDash called "Release Testing" (that group will be created if
it didn't already exist).
.. _ci_artifacts:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CI Artifacts Directory Layout
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When running the CI build using the command ``spack ci rebuild`` a number of directories are created for
storing data generated during the CI job. The default root directory for artifacts is ``job_scratch_root``.
This can be overridden by passing the argument ``--artifacts-root`` to the ``spack ci generate`` command
or by setting the ``SPACK_ARTIFACTS_ROOT`` environment variable in the build job scripts.
The top level directories under the artifact root are ``concrete_environment``, ``logs``, ``reproduction``,
``tests``, and ``user_data``. Spack does not restrict what is written to any of these directories nor does
it require user specified files be written to any specific directory.
------------------------
``concrete_environment``
------------------------
The directory ``concrete_environment`` is used to communicate the ci generate processed ``spack.yaml`` and
the concrete ``spack.lock`` for the CI environment.
--------
``logs``
--------
The directory ``logs`` contains the spack build log, ``spack-build-out.txt``, and the spack build environment
modification file, ``spack-build-mod-env.txt``. Additionally all files specified by the packages ``Builder``
property ``archive_files`` are also copied here (ie. ``CMakeCache.txt`` in ``CMakeBuilder``).
----------------
``reproduction``
----------------
The directory ``reproduction`` is used to store the files needed by the ``spack reproduce-build`` command.
This includes ``repro.json``, copies of all of the files in ``concrete_environment``, the concrete spec
JSON file for the current spec being built, and all of the files written in the artifacts root directory.
The ``repro.json`` file is not versioned and is only designed to work with the version of spack CI was run with.
An example of what a ``repro.json`` may look like is here.
.. code:: json
{
"job_name": "adios2@2.9.2 /feaevuj %gcc@11.4.0 arch=linux-ubuntu20.04-x86_64_v3 E4S ROCm External",
"job_spec_json": "adios2.json",
"ci_project_dir": "/builds/spack/spack"
}
---------
``tests``
---------
The directory ``tests`` is used to store output from running ``spack test <job spec>``. This may or may not have
data in it depending on the package that was built and the availability of tests.
-------------
``user_data``
-------------
The directory ``user_data`` is used to store everything else that shouldn't be copied to the ``reproduction`` direcotory.
Users may use this to store additional logs or metrics or other types of files generated by the build job.
-------------------------------------
Using a custom spack in your pipeline
-------------------------------------

View File

@@ -1,13 +1,13 @@
sphinx==8.1.3
sphinx==8.2.3
sphinxcontrib-programoutput==0.18
sphinx_design==0.6.1
sphinx-rtd-theme==3.0.2
python-levenshtein==0.26.1
python-levenshtein==0.27.1
docutils==0.21.2
pygments==2.19.1
urllib3==2.3.0
pytest==8.3.4
isort==5.13.2
black==24.10.0
flake8==7.1.1
pytest==8.3.5
isort==6.0.1
black==25.1.0
flake8==7.1.2
mypy==1.11.1

View File

@@ -7,6 +7,7 @@
import fnmatch
import glob
import hashlib
import io
import itertools
import numbers
import os
@@ -20,6 +21,7 @@
from contextlib import contextmanager
from itertools import accumulate
from typing import (
IO,
Callable,
Deque,
Dict,
@@ -2454,26 +2456,69 @@ class WindowsSimulatedRPath:
and vis versa.
"""
def __init__(self, package, link_install_prefix=True):
def __init__(
self,
package,
base_modification_prefix: Optional[Union[str, pathlib.Path]] = None,
link_install_prefix: bool = True,
):
"""
Args:
package (spack.package_base.PackageBase): Package requiring links
base_modification_prefix (str|pathlib.Path): Path representation indicating
the root directory in which to establish the simulated rpath, ie where the
symlinks that comprise the "rpath" behavior will be installed.
Note: This is a mutually exclusive option with `link_install_prefix` using
both is an error.
Default: None
link_install_prefix (bool): Link against package's own install or stage root.
Packages that run their own executables during build and require rpaths to
the build directory during build time require this option. Default: install
the build directory during build time require this option.
Default: install
root
Note: This is a mutually exclusive option with `base_modification_prefix`, using
both is an error.
"""
self.pkg = package
self._addl_rpaths = set()
self._addl_rpaths: set[str] = set()
if link_install_prefix and base_modification_prefix:
raise RuntimeError(
"Invalid combination of arguments given to WindowsSimulated RPath.\n"
"Select either `link_install_prefix` to create an install prefix rpath"
" or specify a `base_modification_prefix` for any other link type. "
"Specifying both arguments is invalid."
)
if not (link_install_prefix or base_modification_prefix):
raise RuntimeError(
"Insufficient arguments given to WindowsSimulatedRpath.\n"
"WindowsSimulatedRPath requires one of link_install_prefix"
" or base_modification_prefix to be specified."
" Neither was provided."
)
self.link_install_prefix = link_install_prefix
self._additional_library_dependents = set()
if base_modification_prefix:
self.base_modification_prefix = pathlib.Path(base_modification_prefix)
else:
self.base_modification_prefix = pathlib.Path(self.pkg.prefix)
self._additional_library_dependents: set[pathlib.Path] = set()
if not self.link_install_prefix:
tty.debug(f"Generating rpath for non install context: {base_modification_prefix}")
@property
def library_dependents(self):
"""
Set of directories where package binaries/libraries are located.
"""
return set([pathlib.Path(self.pkg.prefix.bin)]) | self._additional_library_dependents
base_pths = set()
if self.link_install_prefix:
base_pths.add(pathlib.Path(self.pkg.prefix.bin))
base_pths |= self._additional_library_dependents
return base_pths
def add_library_dependent(self, *dest):
"""
@@ -2489,6 +2534,12 @@ def add_library_dependent(self, *dest):
new_pth = pathlib.Path(pth).parent
else:
new_pth = pathlib.Path(pth)
path_is_in_prefix = new_pth.is_relative_to(self.base_modification_prefix)
if not path_is_in_prefix:
raise RuntimeError(
f"Attempting to generate rpath symlink out of rpath context:\
{str(self.base_modification_prefix)}"
)
self._additional_library_dependents.add(new_pth)
@property
@@ -2577,6 +2628,33 @@ def establish_link(self):
self._link(library, lib_dir)
def make_package_test_rpath(pkg, test_dir: Union[str, pathlib.Path]):
"""Establishes a temp Windows simulated rpath for the pkg in the testing directory
so an executable can test the libraries/executables with proper access
to dependent dlls
Note: this is a no-op on all other platforms besides Windows
Args:
pkg (spack.package_base.PackageBase): the package for which the rpath should be computed
test_dir: the testing directory in which we should construct an rpath
"""
# link_install_prefix as false ensures we're not linking into the install prefix
mini_rpath = WindowsSimulatedRPath(pkg, link_install_prefix=False)
# add the testing directory as a location to install rpath symlinks
mini_rpath.add_library_dependent(test_dir)
# check for whether build_directory is available, if not
# assume the stage root is the build dir
build_dir_attr = getattr(pkg, "build_directory", None)
build_directory = build_dir_attr if build_dir_attr else pkg.stage.path
# add the build dir & build dir bin
mini_rpath.add_rpath(os.path.join(build_directory, "bin"))
mini_rpath.add_rpath(os.path.join(build_directory))
# construct rpath
mini_rpath.establish_link()
@system_path_filter
@memoized
def can_access_dir(path):
@@ -2805,6 +2883,20 @@ def keep_modification_time(*filenames):
os.utime(f, (os.path.getatime(f), mtime))
@contextmanager
def temporary_file_position(stream):
orig_pos = stream.tell()
yield
stream.seek(orig_pos)
@contextmanager
def current_file_position(stream: IO[str], loc: int, relative_to=io.SEEK_CUR):
with temporary_file_position(stream):
stream.seek(loc, relative_to)
yield
@contextmanager
def temporary_dir(
suffix: Optional[str] = None, prefix: Optional[str] = None, dir: Optional[str] = None

View File

@@ -11,10 +11,11 @@
import re
import sys
import traceback
import types
import typing
import warnings
from datetime import datetime, timedelta
from typing import Callable, Dict, Iterable, List, Tuple, TypeVar
from typing import Callable, Dict, Iterable, List, Mapping, Optional, Tuple, TypeVar
# Ignore emacs backups when listing modules
ignore_modules = r"^\.#|~$"
@@ -707,14 +708,24 @@ def __init__(self, wrapped_object):
class Singleton:
"""Simple wrapper for lazily initialized singleton objects."""
"""Wrapper for lazily initialized singleton objects."""
def __init__(self, factory):
def __init__(self, factory: Callable[[], object]):
"""Create a new singleton to be inited with the factory function.
Most factories will simply create the object to be initialized and
return it.
In some cases, e.g. when bootstrapping some global state, the singleton
may need to be initialized incrementally. If the factory returns a generator
instead of a regular object, the singleton will assign each result yielded by
the generator to the singleton instance. This allows methods called by
the factory in later stages to refer back to the singleton.
Args:
factory (function): function taking no arguments that
creates the singleton instance.
factory (function): function taking no arguments that creates the
singleton instance.
"""
self.factory = factory
self._instance = None
@@ -722,7 +733,16 @@ def __init__(self, factory):
@property
def instance(self):
if self._instance is None:
self._instance = self.factory()
instance = self.factory()
if isinstance(instance, types.GeneratorType):
# if it's a generator, assign every value
for value in instance:
self._instance = value
else:
# if not, just assign the result like a normal singleton
self._instance = instance
return self._instance
def __getattr__(self, name):
@@ -1080,3 +1100,88 @@ def __set__(self, instance, value):
def factory(self, instance, owner):
raise NotImplementedError("must be implemented by derived classes")
KT = TypeVar("KT")
VT = TypeVar("VT")
class PriorityOrderedMapping(Mapping[KT, VT]):
"""Mapping that iterates over key according to an integer priority. If the priority is
the same for two keys, insertion order is what matters.
The priority is set when the key/value pair is added. If not set, the highest current priority
is used.
"""
_data: Dict[KT, VT]
_priorities: List[Tuple[int, KT]]
def __init__(self) -> None:
self._data = {}
# Tuple of (priority, key)
self._priorities = []
def __getitem__(self, key: KT) -> VT:
return self._data[key]
def __len__(self) -> int:
return len(self._data)
def __iter__(self):
yield from (key for _, key in self._priorities)
def __reversed__(self):
yield from (key for _, key in reversed(self._priorities))
def reversed_keys(self):
"""Iterates over keys from the highest priority, to the lowest."""
return reversed(self)
def reversed_values(self):
"""Iterates over values from the highest priority, to the lowest."""
yield from (self._data[key] for _, key in reversed(self._priorities))
def _highest_priority(self) -> int:
if not self._priorities:
return 0
result, _ = self._priorities[-1]
return result
def add(self, key: KT, *, value: VT, priority: Optional[int] = None) -> None:
"""Adds a key/value pair to the mapping, with a specific priority.
If the priority is None, then it is assumed to be the highest priority value currently
in the container.
Raises:
ValueError: when the same priority is already in the mapping
"""
if priority is None:
priority = self._highest_priority()
if key in self._data:
self.remove(key)
self._priorities.append((priority, key))
# We rely on sort being stable
self._priorities.sort(key=lambda x: x[0])
self._data[key] = value
assert len(self._data) == len(self._priorities)
def remove(self, key: KT) -> VT:
"""Removes a key from the mapping.
Returns:
The value associated with the key being removed
Raises:
KeyError: if the key is not in the mapping
"""
if key not in self._data:
raise KeyError(f"cannot find {key}")
popped_item = self._data.pop(key)
self._priorities = [(p, k) for p, k in self._priorities if k != key]
assert len(self._data) == len(self._priorities)
return popped_item

View File

@@ -41,6 +41,16 @@ def __init__(self, dst, src_a=None, src_b=None):
self.src_a = src_a
self.src_b = src_b
def __repr__(self) -> str:
return f"MergeConflict(dst={self.dst!r}, src_a={self.src_a!r}, src_b={self.src_b!r})"
def _samefile(a: str, b: str):
try:
return os.path.samefile(a, b)
except OSError:
return False
class SourceMergeVisitor(BaseDirectoryVisitor):
"""
@@ -50,9 +60,14 @@ class SourceMergeVisitor(BaseDirectoryVisitor):
- A list of merge conflicts in dst/
"""
def __init__(self, ignore: Optional[Callable[[str], bool]] = None):
def __init__(
self, ignore: Optional[Callable[[str], bool]] = None, normalize_paths: bool = False
):
self.ignore = ignore if ignore is not None else lambda f: False
# On case-insensitive filesystems, normalize paths to detect duplications
self.normalize_paths = normalize_paths
# When mapping <src root> to <dst root>/<projection>, we need to prepend the <projection>
# bit to the relative path in the destination dir.
self.projection: str = ""
@@ -71,10 +86,88 @@ def __init__(self, ignore: Optional[Callable[[str], bool]] = None):
# and can run mkdir in order.
self.directories: Dict[str, Tuple[str, str]] = {}
# If the visitor is configured to normalize paths, keep a map of
# normalized path to: original path, root directory + relative path
self._directories_normalized: Dict[str, Tuple[str, str, str]] = {}
# Files to link. Maps dst_rel to (src_root, src_rel). This is an ordered dict, where files
# are guaranteed to be grouped by src_root in the order they were visited.
self.files: Dict[str, Tuple[str, str]] = {}
# If the visitor is configured to normalize paths, keep a map of
# normalized path to: original path, root directory + relative path
self._files_normalized: Dict[str, Tuple[str, str, str]] = {}
def _in_directories(self, proj_rel_path: str) -> bool:
"""
Check if a path is already in the directory list
"""
if self.normalize_paths:
return proj_rel_path.lower() in self._directories_normalized
else:
return proj_rel_path in self.directories
def _directory(self, proj_rel_path: str) -> Tuple[str, str, str]:
"""
Get the directory that is mapped to a path
"""
if self.normalize_paths:
return self._directories_normalized[proj_rel_path.lower()]
else:
return (proj_rel_path, *self.directories[proj_rel_path])
def _del_directory(self, proj_rel_path: str):
"""
Remove a directory from the list of directories
"""
del self.directories[proj_rel_path]
if self.normalize_paths:
del self._directories_normalized[proj_rel_path.lower()]
def _add_directory(self, proj_rel_path: str, root: str, rel_path: str):
"""
Add a directory to the list of directories.
Also stores the normalized version for later lookups
"""
self.directories[proj_rel_path] = (root, rel_path)
if self.normalize_paths:
self._directories_normalized[proj_rel_path.lower()] = (proj_rel_path, root, rel_path)
def _in_files(self, proj_rel_path: str) -> bool:
"""
Check if a path is already in the files list
"""
if self.normalize_paths:
return proj_rel_path.lower() in self._files_normalized
else:
return proj_rel_path in self.files
def _file(self, proj_rel_path: str) -> Tuple[str, str, str]:
"""
Get the file that is mapped to a path
"""
if self.normalize_paths:
return self._files_normalized[proj_rel_path.lower()]
else:
return (proj_rel_path, *self.files[proj_rel_path])
def _del_file(self, proj_rel_path: str):
"""
Remove a file from the list of files
"""
del self.files[proj_rel_path]
if self.normalize_paths:
del self._files_normalized[proj_rel_path.lower()]
def _add_file(self, proj_rel_path: str, root: str, rel_path: str):
"""
Add a file to the list of files
Also stores the normalized version for later lookups
"""
self.files[proj_rel_path] = (root, rel_path)
if self.normalize_paths:
self._files_normalized[proj_rel_path.lower()] = (proj_rel_path, root, rel_path)
def before_visit_dir(self, root: str, rel_path: str, depth: int) -> bool:
"""
Register a directory if dst / rel_path is not blocked by a file or ignored.
@@ -84,23 +177,28 @@ def before_visit_dir(self, root: str, rel_path: str, depth: int) -> bool:
if self.ignore(rel_path):
# Don't recurse when dir is ignored.
return False
elif proj_rel_path in self.files:
# Can't create a dir where a file is.
src_a_root, src_a_relpath = self.files[proj_rel_path]
self.fatal_conflicts.append(
MergeConflict(
dst=proj_rel_path,
src_a=os.path.join(src_a_root, src_a_relpath),
src_b=os.path.join(root, rel_path),
elif self._in_files(proj_rel_path):
# A file-dir conflict is fatal except if they're the same file (symlinked dir).
src_a = os.path.join(*self._file(proj_rel_path))
src_b = os.path.join(root, rel_path)
if not _samefile(src_a, src_b):
self.fatal_conflicts.append(
MergeConflict(dst=proj_rel_path, src_a=src_a, src_b=src_b)
)
)
return False
elif proj_rel_path in self.directories:
return False
# Remove the link in favor of the dir.
existing_proj_rel_path, _, _ = self._file(proj_rel_path)
self._del_file(existing_proj_rel_path)
self._add_directory(proj_rel_path, root, rel_path)
return True
elif self._in_directories(proj_rel_path):
# No new directory, carry on.
return True
else:
# Register new directory.
self.directories[proj_rel_path] = (root, rel_path)
self._add_directory(proj_rel_path, root, rel_path)
return True
def before_visit_symlinked_dir(self, root: str, rel_path: str, depth: int) -> bool:
@@ -132,7 +230,7 @@ def before_visit_symlinked_dir(self, root: str, rel_path: str, depth: int) -> bo
if handle_as_dir:
return self.before_visit_dir(root, rel_path, depth)
self.visit_file(root, rel_path, depth)
self.visit_file(root, rel_path, depth, symlink=True)
return False
def visit_file(self, root: str, rel_path: str, depth: int, *, symlink: bool = False) -> None:
@@ -140,30 +238,23 @@ def visit_file(self, root: str, rel_path: str, depth: int, *, symlink: bool = Fa
if self.ignore(rel_path):
pass
elif proj_rel_path in self.directories:
# Can't create a file where a dir is; fatal error
self.fatal_conflicts.append(
MergeConflict(
dst=proj_rel_path,
src_a=os.path.join(*self.directories[proj_rel_path]),
src_b=os.path.join(root, rel_path),
elif self._in_directories(proj_rel_path):
# Can't create a file where a dir is, unless they are the same file (symlinked dir),
# in which case we simply drop the symlink in favor of the actual dir.
src_a = os.path.join(*self._directory(proj_rel_path))
src_b = os.path.join(root, rel_path)
if not symlink or not _samefile(src_a, src_b):
self.fatal_conflicts.append(
MergeConflict(dst=proj_rel_path, src_a=src_a, src_b=src_b)
)
)
elif proj_rel_path in self.files:
elif self._in_files(proj_rel_path):
# When two files project to the same path, they conflict iff they are distinct.
# If they are the same (i.e. one links to the other), register regular files rather
# than symlinks. The reason is that in copy-type views, we need a copy of the actual
# file, not the symlink.
src_a = os.path.join(*self.files[proj_rel_path])
src_a = os.path.join(*self._file(proj_rel_path))
src_b = os.path.join(root, rel_path)
try:
samefile = os.path.samefile(src_a, src_b)
except OSError:
samefile = False
if not samefile:
if not _samefile(src_a, src_b):
# Distinct files produce a conflict.
self.file_conflicts.append(
MergeConflict(dst=proj_rel_path, src_a=src_a, src_b=src_b)
@@ -173,12 +264,12 @@ def visit_file(self, root: str, rel_path: str, depth: int, *, symlink: bool = Fa
if not symlink:
# Remove the link in favor of the actual file. The del is necessary to maintain the
# order of the files dict, which is grouped by root.
del self.files[proj_rel_path]
self.files[proj_rel_path] = (root, rel_path)
existing_proj_rel_path, _, _ = self._file(proj_rel_path)
self._del_file(existing_proj_rel_path)
self._add_file(proj_rel_path, root, rel_path)
else:
# Otherwise register this file to be linked.
self.files[proj_rel_path] = (root, rel_path)
self._add_file(proj_rel_path, root, rel_path)
def visit_symlinked_file(self, root: str, rel_path: str, depth: int) -> None:
# Treat symlinked files as ordinary files (without "dereferencing")
@@ -197,11 +288,11 @@ def set_projection(self, projection: str) -> None:
path = ""
for part in self.projection.split(os.sep):
path = os.path.join(path, part)
if path not in self.files:
self.directories[path] = ("<projection>", path)
if not self._in_files(path):
self._add_directory(path, "<projection>", path)
else:
# Can't create a dir where a file is.
src_a_root, src_a_relpath = self.files[path]
_, src_a_root, src_a_relpath = self._file(path)
self.fatal_conflicts.append(
MergeConflict(
dst=path,
@@ -227,8 +318,8 @@ def __init__(self, source_merge_visitor: SourceMergeVisitor):
def before_visit_dir(self, root: str, rel_path: str, depth: int) -> bool:
# If destination dir is a file in a src dir, add a conflict,
# and don't traverse deeper
if rel_path in self.src.files:
src_a_root, src_a_relpath = self.src.files[rel_path]
if self.src._in_files(rel_path):
_, src_a_root, src_a_relpath = self.src._file(rel_path)
self.src.fatal_conflicts.append(
MergeConflict(
rel_path, os.path.join(src_a_root, src_a_relpath), os.path.join(root, rel_path)
@@ -238,8 +329,9 @@ def before_visit_dir(self, root: str, rel_path: str, depth: int) -> bool:
# If destination dir was also a src dir, remove the mkdir
# action, and traverse deeper.
if rel_path in self.src.directories:
del self.src.directories[rel_path]
if self.src._in_directories(rel_path):
existing_proj_rel_path, _, _ = self.src._directory(rel_path)
self.src._del_directory(existing_proj_rel_path)
return True
# If the destination dir does not appear in the src dir,
@@ -252,38 +344,24 @@ def before_visit_symlinked_dir(self, root: str, rel_path: str, depth: int) -> bo
be seen as files; we should not accidentally merge
source dir with a symlinked dest dir.
"""
# Always conflict
if rel_path in self.src.directories:
src_a_root, src_a_relpath = self.src.directories[rel_path]
self.src.fatal_conflicts.append(
MergeConflict(
rel_path, os.path.join(src_a_root, src_a_relpath), os.path.join(root, rel_path)
)
)
if rel_path in self.src.files:
src_a_root, src_a_relpath = self.src.files[rel_path]
self.src.fatal_conflicts.append(
MergeConflict(
rel_path, os.path.join(src_a_root, src_a_relpath), os.path.join(root, rel_path)
)
)
self.visit_file(root, rel_path, depth)
# Never descend into symlinked target dirs.
return False
def visit_file(self, root: str, rel_path: str, depth: int) -> None:
# Can't merge a file if target already exists
if rel_path in self.src.directories:
src_a_root, src_a_relpath = self.src.directories[rel_path]
if self.src._in_directories(rel_path):
_, src_a_root, src_a_relpath = self.src._directory(rel_path)
self.src.fatal_conflicts.append(
MergeConflict(
rel_path, os.path.join(src_a_root, src_a_relpath), os.path.join(root, rel_path)
)
)
elif rel_path in self.src.files:
src_a_root, src_a_relpath = self.src.files[rel_path]
elif self.src._in_files(rel_path):
_, src_a_root, src_a_relpath = self.src._file(rel_path)
self.src.fatal_conflicts.append(
MergeConflict(
rel_path, os.path.join(src_a_root, src_a_relpath), os.path.join(root, rel_path)

View File

@@ -269,7 +269,7 @@ def __init__(
@staticmethod
def _poll_interval_generator(
_wait_times: Optional[Tuple[float, float, float]] = None
_wait_times: Optional[Tuple[float, float, float]] = None,
) -> Generator[float, None, None]:
"""This implements a backoff scheme for polling a contended resource
by suggesting a succession of wait times between polls.

View File

@@ -2,8 +2,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""Utility classes for logging the output of blocks of code.
"""
"""Utility classes for logging the output of blocks of code."""
import atexit
import ctypes
import errno
@@ -344,26 +343,6 @@ def close(self):
self.file.close()
@contextmanager
def replace_environment(env):
"""Replace the current environment (`os.environ`) with `env`.
If `env` is empty (or None), this unsets all current environment
variables.
"""
env = env or {}
old_env = os.environ.copy()
try:
os.environ.clear()
for name, val in env.items():
os.environ[name] = val
yield
finally:
os.environ.clear()
for name, val in old_env.items():
os.environ[name] = val
def log_output(*args, **kwargs):
"""Context manager that logs its output to a file.
@@ -447,7 +426,6 @@ def __init__(
self.echo = echo
self.debug = debug
self.buffer = buffer
self.env = env # the environment to use for _writer_daemon
self.filter_fn = filter_fn
self._active = False # used to prevent re-entry
@@ -519,21 +497,20 @@ def __enter__(self):
# just don't forward input if this fails
pass
with replace_environment(self.env):
self.process = multiprocessing.Process(
target=_writer_daemon,
args=(
input_fd,
read_fd,
self.write_fd,
self.echo,
self.log_file,
child_pipe,
self.filter_fn,
),
)
self.process.daemon = True # must set before start()
self.process.start()
self.process = multiprocessing.Process(
target=_writer_daemon,
args=(
input_fd,
read_fd,
self.write_fd,
self.echo,
self.log_file,
child_pipe,
self.filter_fn,
),
)
self.process.daemon = True # must set before start()
self.process.start()
finally:
if input_fd:
@@ -729,10 +706,7 @@ class winlog:
Does not support the use of 'v' toggling as nixlog does.
"""
def __init__(
self, file_like=None, echo=False, debug=0, buffer=False, env=None, filter_fn=None
):
self.env = env
def __init__(self, file_like=None, echo=False, debug=0, buffer=False, filter_fn=None):
self.debug = debug
self.echo = echo
self.logfile = file_like
@@ -789,11 +763,10 @@ def background_reader(reader, echo_writer, _kill):
reader.close()
self._active = True
with replace_environment(self.env):
self._thread = Thread(
target=background_reader, args=(self.reader, self.echo_writer, self._kill)
)
self._thread.start()
self._thread = Thread(
target=background_reader, args=(self.reader, self.echo_writer, self._kill)
)
self._thread.start()
return self
def __exit__(self, exc_type, exc_val, exc_tb):

View File

@@ -10,9 +10,21 @@
import spack.util.git
#: PEP440 canonical <major>.<minor>.<micro>.<devN> string
__version__ = "0.24.0.dev0"
__version__ = "1.0.0.dev0"
spack_version = __version__
#: The current Package API version implemented by this version of Spack. The Package API defines
#: the Python interface for packages as well as the layout of package repositories. The minor
#: version is incremented when the package API is extended in a backwards-compatible way. The major
#: version is incremented upon breaking changes. This version is changed independently from the
#: Spack version.
package_api_version = (1, 0)
#: The minimum Package API version that this version of Spack is compatible with. This should
#: always be a tuple of the form ``(major, 0)``, since compatibility with vX.Y implies
#: compatibility with vX.0.
min_package_api_version = (1, 0)
def __try_int(v):
try:
@@ -79,4 +91,6 @@ def get_short_version() -> str:
"get_version",
"get_spack_commit",
"get_short_version",
"package_api_version",
"min_package_api_version",
]

View File

@@ -1010,7 +1010,7 @@ def _issues_in_depends_on_directive(pkgs, error_cls):
for dep_name, dep in deps_by_name.items():
def check_virtual_with_variants(spec, msg):
if not spec.virtual or not spec.variants:
if not spack.repo.PATH.is_virtual(spec.name) or not spec.variants:
return
error = error_cls(
f"{pkg_name}: {msg}",

View File

@@ -923,7 +923,7 @@ class FileTypes:
UNKNOWN = 2
NOT_ISO8859_1_TEXT = re.compile(b"[\x00\x7F-\x9F]")
NOT_ISO8859_1_TEXT = re.compile(b"[\x00\x7f-\x9f]")
def file_type(f: IO[bytes]) -> int:
@@ -2529,10 +2529,10 @@ def install_root_node(
allow_missing: when true, allows installing a node with missing dependencies
"""
# Early termination
if spec.external or spec.virtual:
warnings.warn("Skipping external or virtual package {0}".format(spec.format()))
if spec.external or not spec.concrete:
warnings.warn("Skipping external or abstract spec {0}".format(spec.format()))
return
elif spec.concrete and spec.installed and not force:
elif spec.installed and not force:
warnings.warn("Package for spec {0} already installed.".format(spec.format()))
return

View File

@@ -292,7 +292,12 @@ def try_import(self, module: str, abstract_spec_str: str) -> bool:
# Install the spec that should make the module importable
with spack.config.override(self.mirror_scope):
PackageInstaller([concrete_spec.package], fail_fast=True).install()
PackageInstaller(
[concrete_spec.package],
fail_fast=True,
package_use_cache=False,
dependencies_use_cache=False,
).install()
if _try_import_from_store(module, query_spec=concrete_spec, query_info=info):
self.last_search = info
@@ -362,6 +367,7 @@ def ensure_module_importable_or_raise(module: str, abstract_spec: Optional[str]
for current_config in bootstrapping_sources():
if not source_is_enabled(current_config):
continue
with exception_handler.forward(current_config["name"], Exception):
if create_bootstrapper(current_config).try_import(module, abstract_spec):
return

View File

@@ -12,6 +12,7 @@
import spack.phase_callbacks
import spack.spec
import spack.util.prefix
from spack.directives import depends_on
from .cmake import CMakeBuilder, CMakePackage
@@ -371,6 +372,10 @@ class CachedCMakePackage(CMakePackage):
CMakeBuilder = CachedCMakeBuilder
# These dependencies are assumed in the builder
depends_on("c", type="build")
depends_on("cxx", type="build")
def flag_handler(self, name, flags):
if name in ("cflags", "cxxflags", "cppflags", "fflags"):
return None, None, None # handled in the cmake cache

View File

@@ -70,10 +70,16 @@ def build_directory(self):
"""Return the directory containing the main Cargo.toml."""
return self.pkg.stage.source_path
@property
def std_build_args(self):
"""Standard arguments for ``cargo build`` provided as a property for
convenience of package writers."""
return ["-j", str(self.pkg.module.make_jobs)]
@property
def build_args(self):
"""Arguments for ``cargo build``."""
return ["-j", str(self.pkg.module.make_jobs)]
return []
@property
def check_args(self):
@@ -88,7 +94,9 @@ def build(
) -> None:
"""Runs ``cargo install`` in the source directory"""
with fs.working_dir(self.build_directory):
pkg.module.cargo("install", "--root", "out", "--path", ".", *self.build_args)
pkg.module.cargo(
"install", "--root", "out", "--path", ".", *self.std_build_args, *self.build_args
)
def install(
self, pkg: CargoPackage, spec: spack.spec.Spec, prefix: spack.util.prefix.Prefix

View File

@@ -11,6 +11,7 @@
from typing import Any, List, Optional, Tuple
import llnl.util.filesystem as fs
from llnl.util import tty
from llnl.util.lang import stable_partition
import spack.builder
@@ -458,19 +459,23 @@ def cmake(
) -> None:
"""Runs ``cmake`` in the build directory"""
# skip cmake phase if it is an incremental develop build
# These are the files that will re-run CMake that are generated from a successful
# configure step
primary_generator = _extract_primary_generator(self.generator)
if primary_generator == "Unix Makefiles":
configure_artifact = "Makefile"
elif primary_generator == "Ninja":
configure_artifact = "ninja.build"
if spec.is_develop:
# skip cmake phase if it is an incremental develop build
if spec.is_develop and os.path.isfile(
os.path.join(self.build_directory, configure_artifact)
):
return
# Determine the files that will re-run CMake that are generated from a successful
# configure step based on state
primary_generator = _extract_primary_generator(self.generator)
configure_artifact = "Makefile"
if primary_generator == "Ninja":
configure_artifact = "ninja.build"
if os.path.isfile(os.path.join(self.build_directory, configure_artifact)):
tty.msg(
"Incremental build criteria satisfied."
"Skipping CMake configure step. To force configuration run"
f" `spack clean {pkg.name}`"
)
return
options = self.std_cmake_args
options += self.cmake_args()

View File

@@ -15,7 +15,7 @@ class CudaPackage(PackageBase):
"""Auxiliary class which contains CUDA variant, dependencies and conflicts
and is meant to unify and facilitate its usage.
Maintainers: ax3l, Rombur, davidbeckingsale
Maintainers: ax3l, Rombur, davidbeckingsale, pauleonix
"""
# https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#gpu-feature-list
@@ -47,6 +47,12 @@ class CudaPackage(PackageBase):
"89",
"90",
"90a",
"100",
"100a",
"101",
"101a",
"120",
"120a",
)
# FIXME: keep cuda and cuda_arch separate to make usage easier until
@@ -99,39 +105,56 @@ def compute_capabilities(arch_list: Iterable[str]) -> List[str]:
# CUDA version vs Architecture
# https://en.wikipedia.org/wiki/CUDA#GPUs_supported
# https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#deprecated-features
# Tesla support:
depends_on("cuda@:6.0", when="cuda_arch=10")
depends_on("cuda@:6.5", when="cuda_arch=11")
depends_on("cuda@2.1:6.5", when="cuda_arch=12")
depends_on("cuda@2.1:6.5", when="cuda_arch=13")
# Fermi support:
depends_on("cuda@3.0:8.0", when="cuda_arch=20")
depends_on("cuda@3.2:8.0", when="cuda_arch=21")
# Kepler support:
depends_on("cuda@5.0:10.2", when="cuda_arch=30")
depends_on("cuda@5.0:10.2", when="cuda_arch=32")
depends_on("cuda@5.0:11.8", when="cuda_arch=35")
depends_on("cuda@6.5:11.8", when="cuda_arch=37")
# Maxwell support:
depends_on("cuda@6.0:", when="cuda_arch=50")
depends_on("cuda@6.5:", when="cuda_arch=52")
depends_on("cuda@6.5:", when="cuda_arch=53")
# Pascal support:
depends_on("cuda@8.0:", when="cuda_arch=60")
depends_on("cuda@8.0:", when="cuda_arch=61")
depends_on("cuda@8.0:", when="cuda_arch=62")
# Volta support:
depends_on("cuda@9.0:", when="cuda_arch=70")
# Turing support:
depends_on("cuda@9.0:", when="cuda_arch=72")
depends_on("cuda@10.0:", when="cuda_arch=75")
# Ampere support:
depends_on("cuda@11.0:", when="cuda_arch=80")
depends_on("cuda@11.1:", when="cuda_arch=86")
depends_on("cuda@11.4:", when="cuda_arch=87")
# Ada support:
depends_on("cuda@11.8:", when="cuda_arch=89")
# Hopper support:
depends_on("cuda@12.0:", when="cuda_arch=90")
depends_on("cuda@12.0:", when="cuda_arch=90a")
# Blackwell support:
depends_on("cuda@12.8:", when="cuda_arch=100")
depends_on("cuda@12.8:", when="cuda_arch=100a")
depends_on("cuda@12.8:", when="cuda_arch=101")
depends_on("cuda@12.8:", when="cuda_arch=101a")
depends_on("cuda@12.8:", when="cuda_arch=120")
depends_on("cuda@12.8:", when="cuda_arch=120a")
# From the NVIDIA install guide we know of conflicts for particular
# platforms (linux, darwin), architectures (x86, powerpc) and compilers
# (gcc, clang). We don't restrict %gcc and %clang conflicts to
@@ -163,6 +186,7 @@ def compute_capabilities(arch_list: Iterable[str]) -> List[str]:
conflicts("%gcc@12:", when="+cuda ^cuda@:11.8")
conflicts("%gcc@13:", when="+cuda ^cuda@:12.3")
conflicts("%gcc@14:", when="+cuda ^cuda@:12.6")
conflicts("%gcc@15:", when="+cuda ^cuda@:12.8")
conflicts("%clang@12:", when="+cuda ^cuda@:11.4.0")
conflicts("%clang@13:", when="+cuda ^cuda@:11.5")
conflicts("%clang@14:", when="+cuda ^cuda@:11.7")
@@ -171,6 +195,7 @@ def compute_capabilities(arch_list: Iterable[str]) -> List[str]:
conflicts("%clang@17:", when="+cuda ^cuda@:12.3")
conflicts("%clang@18:", when="+cuda ^cuda@:12.5")
conflicts("%clang@19:", when="+cuda ^cuda@:12.6")
conflicts("%clang@20:", when="+cuda ^cuda@:12.8")
# https://gist.github.com/ax3l/9489132#gistcomment-3860114
conflicts("%gcc@10", when="+cuda ^cuda@:11.4.0")

View File

@@ -48,6 +48,9 @@ class MesonPackage(spack.package_base.PackageBase):
variant("strip", default=False, description="Strip targets on install")
depends_on("meson", type="build")
depends_on("ninja", type="build")
# Meson uses pkg-config for dependency detection, and this dependency is
# often overlooked by packages that use meson as a build system.
depends_on("pkgconfig", type="build")
# Python detection in meson requires distutils to be importable, but distutils no longer
# exists in Python 3.12. In Spack, we can't use setuptools as distutils replacement,
# because the distutils-precedence.pth startup file that setuptools ships with is not run

View File

@@ -142,7 +142,7 @@ def setup_run_environment(self, env):
$ source {prefix}/{component}/{version}/env/vars.sh
"""
# Only if environment modifications are desired (default is +envmods)
if "~envmods" not in self.spec:
if "+envmods" in self.spec:
env.extend(
EnvironmentModifications.from_sourcing_file(
self.component_prefix.env.join("vars.sh"), *self.env_script_args

View File

@@ -14,8 +14,9 @@
import zipfile
from collections import namedtuple
from typing import Callable, Dict, List, Set
from urllib.request import HTTPHandler, Request, build_opener
from urllib.request import Request
import llnl.path
import llnl.util.filesystem as fs
import llnl.util.tty as tty
from llnl.util.tty.color import cescape, colorize
@@ -62,6 +63,8 @@
PushResult = namedtuple("PushResult", "success url")
urlopen = web_util.urlopen # alias for mocking in tests
def get_change_revisions():
"""If this is a git repo get the revisions to use when checking
@@ -81,6 +84,9 @@ def get_stack_changed(env_path, rev1="HEAD^", rev2="HEAD"):
whether or not the stack was changed. Returns True if the environment
manifest changed between the provided revisions (or additionally if the
`.gitlab-ci.yml` file itself changed). Returns False otherwise."""
# git returns posix paths always, normalize input to be comptaible
# with that
env_path = llnl.path.convert_to_posix_path(env_path)
git = spack.util.git.git()
if git:
with fs.working_dir(spack.paths.prefix):
@@ -610,7 +616,7 @@ def copy_test_logs_to_artifacts(test_stage, job_test_dir):
copy_files_to_artifacts(os.path.join(test_stage, "*", "*.txt"), job_test_dir)
def download_and_extract_artifacts(url, work_dir):
def download_and_extract_artifacts(url, work_dir) -> str:
"""Look for gitlab artifacts.zip at the given url, and attempt to download
and extract the contents into the given work_dir
@@ -618,6 +624,10 @@ def download_and_extract_artifacts(url, work_dir):
url (str): Complete url to artifacts.zip file
work_dir (str): Path to destination where artifacts should be extracted
Output:
Artifacts root path relative to the archive root
"""
tty.msg(f"Fetching artifacts from: {url}")
@@ -627,31 +637,33 @@ def download_and_extract_artifacts(url, work_dir):
if token:
headers["PRIVATE-TOKEN"] = token
opener = build_opener(HTTPHandler)
request = Request(url, headers=headers)
request.get_method = lambda: "GET"
response = opener.open(request, timeout=SPACK_CDASH_TIMEOUT)
response_code = response.getcode()
if response_code != 200:
msg = f"Error response code ({response_code}) in reproduce_ci_job"
raise SpackError(msg)
request = Request(url, headers=headers, method="GET")
artifacts_zip_path = os.path.join(work_dir, "artifacts.zip")
os.makedirs(work_dir, exist_ok=True)
if not os.path.exists(work_dir):
os.makedirs(work_dir)
try:
response = urlopen(request, timeout=SPACK_CDASH_TIMEOUT)
with open(artifacts_zip_path, "wb") as out_file:
shutil.copyfileobj(response, out_file)
with open(artifacts_zip_path, "wb") as out_file:
shutil.copyfileobj(response, out_file)
with zipfile.ZipFile(artifacts_zip_path) as zip_file:
zip_file.extractall(work_dir)
# Get the artifact root
artifact_root = ""
for f in zip_file.filelist:
if "spack.lock" in f.filename:
artifact_root = os.path.dirname(os.path.dirname(f.filename))
break
except OSError as e:
raise SpackError(f"Error fetching artifacts: {e}")
finally:
try:
os.remove(artifacts_zip_path)
except FileNotFoundError:
# If the file doesn't exist we are already raising
pass
zip_file = zipfile.ZipFile(artifacts_zip_path)
zip_file.extractall(work_dir)
zip_file.close()
os.remove(artifacts_zip_path)
return artifact_root
def get_spack_info():
@@ -765,7 +777,7 @@ def setup_spack_repro_version(repro_dir, checkout_commit, merge_commit=None):
return True
def reproduce_ci_job(url, work_dir, autostart, gpg_url, runtime):
def reproduce_ci_job(url, work_dir, autostart, gpg_url, runtime, use_local_head):
"""Given a url to gitlab artifacts.zip from a failed 'spack ci rebuild' job,
attempt to setup an environment in which the failure can be reproduced
locally. This entails the following:
@@ -779,8 +791,11 @@ def reproduce_ci_job(url, work_dir, autostart, gpg_url, runtime):
commands to run to reproduce the build once inside the container.
"""
work_dir = os.path.realpath(work_dir)
if os.path.exists(work_dir) and os.listdir(work_dir):
raise SpackError(f"Cannot run reproducer in non-emptry working dir:\n {work_dir}")
platform_script_ext = "ps1" if IS_WINDOWS else "sh"
download_and_extract_artifacts(url, work_dir)
artifact_root = download_and_extract_artifacts(url, work_dir)
gpg_path = None
if gpg_url:
@@ -842,6 +857,9 @@ def reproduce_ci_job(url, work_dir, autostart, gpg_url, runtime):
with open(repro_file, encoding="utf-8") as fd:
repro_details = json.load(fd)
spec_file = fs.find(work_dir, repro_details["job_spec_json"])[0]
reproducer_spec = spack.spec.Spec.from_specfile(spec_file)
repro_dir = os.path.dirname(repro_file)
rel_repro_dir = repro_dir.replace(work_dir, "").lstrip(os.path.sep)
@@ -902,17 +920,20 @@ def reproduce_ci_job(url, work_dir, autostart, gpg_url, runtime):
commit_regex = re.compile(r"commit\s+([^\s]+)")
merge_commit_regex = re.compile(r"Merge\s+([^\s]+)\s+into\s+([^\s]+)")
# Try the more specific merge commit regex first
m = merge_commit_regex.search(spack_info)
if m:
# This was a merge commit and we captured the parents
commit_1 = m.group(1)
commit_2 = m.group(2)
if use_local_head:
commit_1 = "HEAD"
else:
# Not a merge commit, just get the commit sha
m = commit_regex.search(spack_info)
# Try the more specific merge commit regex first
m = merge_commit_regex.search(spack_info)
if m:
# This was a merge commit and we captured the parents
commit_1 = m.group(1)
commit_2 = m.group(2)
else:
# Not a merge commit, just get the commit sha
m = commit_regex.search(spack_info)
if m:
commit_1 = m.group(1)
setup_result = False
if commit_1:
@@ -987,6 +1008,8 @@ def reproduce_ci_job(url, work_dir, autostart, gpg_url, runtime):
"entrypoint", entrypoint_script, work_dir, run=False, exit_on_failure=False
)
# Attempt to create a unique name for the reproducer container
container_suffix = "_" + reproducer_spec.dag_hash() if reproducer_spec else ""
docker_command = [
runtime,
"run",
@@ -994,14 +1017,14 @@ def reproduce_ci_job(url, work_dir, autostart, gpg_url, runtime):
"-t",
"--rm",
"--name",
"spack_reproducer",
f"spack_reproducer{container_suffix}",
"-v",
":".join([work_dir, mounted_workdir, "Z"]),
"-v",
":".join(
[
os.path.join(work_dir, "jobs_scratch_dir"),
os.path.join(mount_as_dir, "jobs_scratch_dir"),
os.path.join(work_dir, artifact_root),
os.path.join(mount_as_dir, artifact_root),
"Z",
]
),

View File

@@ -4,7 +4,7 @@
import re
import sys
from typing import Dict, Optional
from typing import Dict, Optional, Tuple
import llnl.string
import llnl.util.lang
@@ -181,7 +181,11 @@ def checksum(parser, args):
print()
if args.add_to_package:
add_versions_to_package(pkg, version_lines, args.batch)
path = spack.repo.PATH.filename_for_package_name(pkg.name)
num_versions_added = add_versions_to_pkg(path, version_lines)
tty.msg(f"Added {num_versions_added} new versions to {pkg.name} in {path}")
if not args.batch and sys.stdin.isatty():
editor(path)
def print_checksum_status(pkg: PackageBase, version_hashes: dict):
@@ -227,20 +231,9 @@ def print_checksum_status(pkg: PackageBase, version_hashes: dict):
tty.die("Invalid checksums found.")
def add_versions_to_package(pkg: PackageBase, version_lines: str, is_batch: bool):
"""
Add checksumed versions to a package's instructions and open a user's
editor so they may double check the work of the function.
Args:
pkg (spack.package_base.PackageBase): A package class for a given package in Spack.
version_lines (str): A string of rendered version lines.
"""
# Get filename and path for package
filename = spack.repo.PATH.filename_for_package_name(pkg.name)
def _update_version_statements(package_src: str, version_lines: str) -> Tuple[int, str]:
"""Returns a tuple of number of versions added and the package's modified contents."""
num_versions_added = 0
version_statement_re = re.compile(r"([\t ]+version\([^\)]*\))")
version_re = re.compile(r'[\t ]+version\(\s*"([^"]+)"[^\)]*\)')
@@ -252,33 +245,34 @@ def add_versions_to_package(pkg: PackageBase, version_lines: str, is_batch: bool
if match:
new_versions.append((Version(match.group(1)), ver_line))
with open(filename, "r+", encoding="utf-8") as f:
contents = f.read()
split_contents = version_statement_re.split(contents)
split_contents = version_statement_re.split(package_src)
for i, subsection in enumerate(split_contents):
# If there are no more versions to add we should exit
if len(new_versions) <= 0:
break
for i, subsection in enumerate(split_contents):
# If there are no more versions to add we should exit
if len(new_versions) <= 0:
break
# Check if the section contains a version
contents_version = version_re.match(subsection)
if contents_version is not None:
parsed_version = Version(contents_version.group(1))
# Check if the section contains a version
contents_version = version_re.match(subsection)
if contents_version is not None:
parsed_version = Version(contents_version.group(1))
if parsed_version < new_versions[0][0]:
split_contents[i:i] = [new_versions.pop(0)[1], " # FIXME", "\n"]
num_versions_added += 1
if parsed_version < new_versions[0][0]:
split_contents[i:i] = [new_versions.pop(0)[1], " # FIXME", "\n"]
num_versions_added += 1
elif parsed_version == new_versions[0][0]:
new_versions.pop(0)
elif parsed_version == new_versions[0][0]:
new_versions.pop(0)
# Seek back to the start of the file so we can rewrite the file contents.
f.seek(0)
f.writelines("".join(split_contents))
return num_versions_added, "".join(split_contents)
tty.msg(f"Added {num_versions_added} new versions to {pkg.name}")
tty.msg(f"Open {filename} to review the additions.")
if sys.stdout.isatty() and not is_batch:
editor(filename)
def add_versions_to_pkg(path: str, version_lines: str) -> int:
"""Add new versions to a package.py file. Returns the number of versions added."""
with open(path, "r", encoding="utf-8") as f:
package_src = f.read()
num_versions_added, package_src = _update_version_statements(package_src, version_lines)
if num_versions_added > 0:
with open(path, "w", encoding="utf-8") as f:
f.write(package_src)
return num_versions_added

View File

@@ -176,6 +176,11 @@ def setup_parser(subparser):
reproduce.add_argument(
"-s", "--autostart", help="Run docker reproducer automatically", action="store_true"
)
reproduce.add_argument(
"--use-local-head",
help="Use the HEAD of the local Spack instead of reproducing a commit",
action="store_true",
)
gpg_group = reproduce.add_mutually_exclusive_group(required=False)
gpg_group.add_argument(
"--gpg-file", help="Path to public GPG key for validating binary cache installs"
@@ -608,7 +613,12 @@ def ci_reproduce(args):
gpg_key_url = None
return spack_ci.reproduce_ci_job(
args.job_url, args.working_dir, args.autostart, gpg_key_url, args.runtime
args.job_url,
args.working_dir,
args.autostart,
gpg_key_url,
args.runtime,
args.use_local_head,
)

View File

@@ -528,7 +528,6 @@ def __call__(self, parser, namespace, values, option_string):
# the const from the constructor or a value from the CLI.
# Note that this is only called if the argument is actually
# specified on the command line.
spack.config.CONFIG.ensure_scope_ordering()
spack.config.set(self.config_path, self.const, scope="command_line")

View File

@@ -350,9 +350,12 @@ def _config_change(config_path, match_spec_str=None):
if spack.config.get(key_path, scope=scope):
ideal_scope_to_modify = scope
break
# If we find our key in a specific scope, that's the one we want
# to modify. Otherwise we use the default write scope.
write_scope = ideal_scope_to_modify or spack.config.default_modify_scope()
update_path = f"{key_path}:[{str(spec)}]"
spack.config.add(update_path, scope=ideal_scope_to_modify)
spack.config.add(update_path, scope=write_scope)
else:
raise ValueError("'config change' can currently only change 'require' sections")

View File

@@ -2,23 +2,11 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import platform
import re
import sys
from datetime import datetime
from glob import glob
import llnl.util.tty as tty
from llnl.util.filesystem import working_dir
import spack
import spack.paths
import spack.platforms
import spack.spec
import spack.store
import spack.util.git
from spack.util.executable import which
description = "debugging commands for troubleshooting Spack"
section = "developer"
@@ -27,63 +15,9 @@
def setup_parser(subparser):
sp = subparser.add_subparsers(metavar="SUBCOMMAND", dest="debug_command")
sp.add_parser("create-db-tarball", help="create a tarball of Spack's installation metadata")
sp.add_parser("report", help="print information useful for bug reports")
def _debug_tarball_suffix():
now = datetime.now()
suffix = now.strftime("%Y-%m-%d-%H%M%S")
git = spack.util.git.git()
if not git:
return "nobranch-nogit-%s" % suffix
with working_dir(spack.paths.prefix):
if not os.path.isdir(".git"):
return "nobranch.nogit.%s" % suffix
# Get symbolic branch name and strip any special chars (mainly '/')
symbolic = git("rev-parse", "--abbrev-ref", "--short", "HEAD", output=str).strip()
symbolic = re.sub(r"[^\w.-]", "-", symbolic)
# Get the commit hash too.
commit = git("rev-parse", "--short", "HEAD", output=str).strip()
if symbolic == commit:
return "nobranch.%s.%s" % (commit, suffix)
else:
return "%s.%s.%s" % (symbolic, commit, suffix)
def create_db_tarball(args):
tar = which("tar")
tarball_name = "spack-db.%s.tar.gz" % _debug_tarball_suffix()
tarball_path = os.path.abspath(tarball_name)
base = os.path.basename(str(spack.store.STORE.root))
transform_args = []
# Currently --transform and -s are not supported by Windows native tar
if "GNU" in tar("--version", output=str):
transform_args = ["--transform", "s/^%s/%s/" % (base, tarball_name)]
elif sys.platform != "win32":
transform_args = ["-s", "/^%s/%s/" % (base, tarball_name)]
wd = os.path.dirname(str(spack.store.STORE.root))
with working_dir(wd):
files = [spack.store.STORE.db._index_path]
files += glob("%s/*/*/*/.spack/spec.json" % base)
files += glob("%s/*/*/*/.spack/spec.yaml" % base)
files = [os.path.relpath(f) for f in files]
args = ["-czf", tarball_path]
args += transform_args
args += files
tar(*args)
tty.msg("Created %s" % tarball_name)
def report(args):
host_platform = spack.platforms.host()
host_os = host_platform.default_operating_system()
@@ -95,5 +29,5 @@ def report(args):
def debug(parser, args):
action = {"create-db-tarball": create_db_tarball, "report": report}
action[args.debug_command](args)
if args.debug_command == "report":
report(args)

View File

@@ -9,9 +9,9 @@
import spack.cmd
import spack.environment as ev
import spack.package_base
import spack.store
from spack.cmd.common import arguments
from spack.solver.input_analysis import create_graph_analyzer
description = "show dependencies of a package"
section = "basic"
@@ -68,15 +68,17 @@ def dependencies(parser, args):
else:
spec = specs[0]
dependencies = spack.package_base.possible_dependencies(
dependencies, virtuals, _ = create_graph_analyzer().possible_dependencies(
spec,
transitive=args.transitive,
expand_virtuals=args.expand_virtuals,
depflag=args.deptype,
allowed_deps=args.deptype,
)
if not args.expand_virtuals:
dependencies.update(virtuals)
if spec.name in dependencies:
del dependencies[spec.name]
dependencies.remove(spec.name)
if dependencies:
colify(sorted(dependencies))

View File

@@ -125,7 +125,7 @@ def develop(parser, args):
version = spec.versions.concrete_range_as_version
if not version:
# look up the maximum version so infintiy versions are preferred for develop
version = max(spec.package_class.versions.keys())
version = max(spack.repo.PATH.get_pkg_class(spec.fullname).versions.keys())
tty.msg(f"Defaulting to highest version: {spec.name}@{version}")
spec.versions = spack.version.VersionList([version])

View File

@@ -545,7 +545,7 @@ def _not_license_excluded(self, x):
package does not explicitly forbid redistributing source."""
if self.private:
return True
elif x.package_class.redistribute_source(x):
elif spack.repo.PATH.get_pkg_class(x.fullname).redistribute_source(x):
return True
else:
tty.debug(

View File

@@ -41,7 +41,11 @@ def providers(parser, args):
specs = spack.cmd.parse_specs(args.virtual_package)
# Check prerequisites
non_virtual = [str(s) for s in specs if not s.virtual or s.name not in valid_virtuals]
non_virtual = [
str(s)
for s in specs
if not spack.repo.PATH.is_virtual(s.name) or s.name not in valid_virtuals
]
if non_virtual:
msg = "non-virtual specs cannot be part of the query "
msg += "[{0}]\n".format(", ".join(non_virtual))

View File

@@ -6,7 +6,7 @@
import os
import re
import sys
from itertools import zip_longest
from itertools import islice, zip_longest
from typing import Dict, List, Optional
import llnl.util.tty as tty
@@ -423,7 +423,8 @@ def _run_import_check(
continue
for m in is_abs_import.finditer(contents):
if contents.count(m.group(1)) == 1:
# Find at most two occurences: the first is the import itself, the second is its usage.
if len(list(islice(re.finditer(rf"{re.escape(m.group(1))}(?!\w)", contents), 2))) == 1:
to_remove.append(m.group(0))
exit_code = 1
print(f"{pretty_path}: redundant import: {m.group(1)}", file=out)
@@ -438,7 +439,7 @@ def _run_import_check(
module = _module_part(root, m.group(0))
if not module or module in to_add:
continue
if re.search(rf"import {re.escape(module)}\b(?!\.)", contents):
if re.search(rf"import {re.escape(module)}(?!\w|\.)", contents):
continue
to_add.add(module)
exit_code = 1

View File

@@ -252,7 +252,9 @@ def has_test_and_tags(pkg_class):
hashes = env.all_hashes() if env else None
specs = spack.store.STORE.db.query(hashes=hashes)
specs = list(filter(lambda s: has_test_and_tags(s.package_class), specs))
specs = list(
filter(lambda s: has_test_and_tags(spack.repo.PATH.get_pkg_class(s.fullname)), specs)
)
spack.cmd.display_specs(specs, long=True)

View File

@@ -216,7 +216,7 @@ def unit_test(parser, args, unknown_args):
# Ensure clingo is available before switching to the
# mock configuration used by unit tests
with spack.bootstrap.ensure_bootstrap_configuration():
spack.bootstrap.ensure_core_dependencies()
spack.bootstrap.ensure_clingo_importable_or_raise()
if pytest is None:
spack.bootstrap.ensure_environment_dependencies()
import pytest

View File

@@ -2,35 +2,48 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import argparse
import io
from typing import List, Optional
import llnl.util.tty as tty
from llnl.string import plural
from llnl.util.filesystem import visit_directory_tree
import spack.cmd
import spack.environment as ev
import spack.spec
import spack.store
import spack.verify
import spack.verify_libraries
from spack.cmd.common import arguments
description = "check that all spack packages are on disk as installed"
description = "verify spack installations on disk"
section = "admin"
level = "long"
MANIFEST_SUBPARSER: Optional[argparse.ArgumentParser] = None
def setup_parser(subparser):
setup_parser.parser = subparser
subparser.add_argument(
def setup_parser(subparser: argparse.ArgumentParser):
global MANIFEST_SUBPARSER
sp = subparser.add_subparsers(metavar="SUBCOMMAND", dest="verify_command")
MANIFEST_SUBPARSER = sp.add_parser(
"manifest", help=verify_manifest.__doc__, description=verify_manifest.__doc__
)
MANIFEST_SUBPARSER.add_argument(
"-l", "--local", action="store_true", help="verify only locally installed packages"
)
subparser.add_argument(
MANIFEST_SUBPARSER.add_argument(
"-j", "--json", action="store_true", help="ouptut json-formatted errors"
)
subparser.add_argument("-a", "--all", action="store_true", help="verify all packages")
subparser.add_argument(
MANIFEST_SUBPARSER.add_argument("-a", "--all", action="store_true", help="verify all packages")
MANIFEST_SUBPARSER.add_argument(
"specs_or_files", nargs=argparse.REMAINDER, help="specs or files to verify"
)
type = subparser.add_mutually_exclusive_group()
type.add_argument(
manifest_sp_type = MANIFEST_SUBPARSER.add_mutually_exclusive_group()
manifest_sp_type.add_argument(
"-s",
"--specs",
action="store_const",
@@ -39,7 +52,7 @@ def setup_parser(subparser):
default="specs",
help="treat entries as specs (default)",
)
type.add_argument(
manifest_sp_type.add_argument(
"-f",
"--files",
action="store_const",
@@ -49,14 +62,67 @@ def setup_parser(subparser):
help="treat entries as absolute filenames\n\ncannot be used with '-a'",
)
libraries_subparser = sp.add_parser(
"libraries", help=verify_libraries.__doc__, description=verify_libraries.__doc__
)
arguments.add_common_arguments(libraries_subparser, ["constraint"])
def verify(parser, args):
cmd = args.verify_command
if cmd == "libraries":
return verify_libraries(args)
elif cmd == "manifest":
return verify_manifest(args)
parser.error("invalid verify subcommand")
def verify_libraries(args):
"""verify that shared libraries of install packages can be located in rpaths (Linux only)"""
specs_from_db = [s for s in args.specs(installed=True) if not s.external]
tty.info(f"Checking {len(specs_from_db)} packages for shared library resolution")
errors = 0
for spec in specs_from_db:
try:
pkg = spec.package
except Exception:
tty.warn(f"Skipping {spec.cformat('{name}{@version}{/hash}')} due to missing package")
error_msg = _verify_libraries(spec, pkg.unresolved_libraries)
if error_msg is not None:
errors += 1
tty.error(error_msg)
if errors:
tty.error(f"Cannot resolve shared libraries in {plural(errors, 'package')}")
return 1
def _verify_libraries(spec: spack.spec.Spec, unresolved_libraries: List[str]) -> Optional[str]:
"""Go over the prefix of the installed spec and verify its shared libraries can be resolved."""
visitor = spack.verify_libraries.ResolveSharedElfLibDepsVisitor(
[*spack.verify_libraries.ALLOW_UNRESOLVED, *unresolved_libraries]
)
visit_directory_tree(spec.prefix, visitor)
if not visitor.problems:
return None
output = io.StringIO()
visitor.write(output, indent=4, brief=True)
message = output.getvalue().rstrip()
return f"{spec.cformat('{name}{@version}{/hash}')}: {spec.prefix}:\n{message}"
def verify_manifest(args):
"""verify that install directories have not been modified since installation"""
local = args.local
if args.type == "files":
if args.all:
setup_parser.parser.print_help()
return 1
MANIFEST_SUBPARSER.error("cannot use --all with --files")
for file in args.specs_or_files:
results = spack.verify.check_file_manifest(file)
@@ -87,8 +153,7 @@ def verify(parser, args):
env = ev.active_environment()
specs = list(map(lambda x: spack.cmd.disambiguate_spec(x, env, local=local), spec_args))
else:
setup_parser.parser.print_help()
return 1
MANIFEST_SUBPARSER.error("use --all or specify specs to verify")
for spec in specs:
tty.debug("Verifying package %s")

View File

@@ -220,7 +220,7 @@ def concretize_one(spec: Union[str, Spec], tests: TestsType = False) -> Spec:
opt, i, answer = min(result.answers)
name = spec.name
# TODO: Consolidate this code with similar code in solve.py
if spec.virtual:
if spack.repo.PATH.is_virtual(spec.name):
providers = [s.name for s in answer.values() if s.package.provides(name)]
name = providers[0]

View File

@@ -32,9 +32,10 @@
import copy
import functools
import os
import os.path
import re
import sys
from typing import Any, Callable, Dict, Generator, List, Optional, Tuple, Union
from typing import Any, Callable, Dict, Generator, List, NamedTuple, Optional, Tuple, Union
import jsonschema
@@ -42,7 +43,6 @@
import spack.error
import spack.paths
import spack.platforms
import spack.schema
import spack.schema.bootstrap
import spack.schema.cdash
@@ -54,24 +54,27 @@
import spack.schema.develop
import spack.schema.env
import spack.schema.env_vars
import spack.schema.include
import spack.schema.merged
import spack.schema.mirrors
import spack.schema.modules
import spack.schema.packages
import spack.schema.repos
import spack.schema.upstreams
import spack.schema.view
# Hacked yaml for configuration files preserves line numbers.
import spack.util.remote_file_cache as rfc_util
import spack.util.spack_yaml as syaml
import spack.util.web as web_util
from spack.util.cpus import cpus_available
from .enums import ConfigScopePriority
#: Dict from section names -> schema for that section
SECTION_SCHEMAS: Dict[str, Any] = {
"compilers": spack.schema.compilers.schema,
"concretizer": spack.schema.concretizer.schema,
"definitions": spack.schema.definitions.schema,
"env_vars": spack.schema.env_vars.schema,
"include": spack.schema.include.schema,
"view": spack.schema.view.schema,
"develop": spack.schema.develop.schema,
"mirrors": spack.schema.mirrors.schema,
@@ -119,6 +122,17 @@
#: Type used for raw YAML configuration
YamlConfigDict = Dict[str, Any]
#: prefix for name of included configuration scopes
INCLUDE_SCOPE_PREFIX = "include"
#: safeguard for recursive includes -- maximum include depth
MAX_RECURSIVE_INCLUDES = 100
def _include_cache_location():
"""Location to cache included configuration files."""
return os.path.join(spack.paths.user_cache_path, "includes")
class ConfigScope:
def __init__(self, name: str) -> None:
@@ -126,6 +140,9 @@ def __init__(self, name: str) -> None:
self.writable = False
self.sections = syaml.syaml_dict()
#: names of any included scopes
self.included_scopes: List[str] = []
def get_section_filename(self, section: str) -> str:
raise NotImplementedError
@@ -408,26 +425,18 @@ def _method(self, *args, **kwargs):
return _method
class Configuration:
"""A full Spack configuration, from a hierarchy of config files.
ScopeWithOptionalPriority = Union[ConfigScope, Tuple[int, ConfigScope]]
ScopeWithPriority = Tuple[int, ConfigScope]
This class makes it easy to add a new scope on top of an existing one.
"""
class Configuration:
"""A hierarchical configuration, merging a number of scopes at different priorities."""
# convert to typing.OrderedDict when we drop 3.6, or OrderedDict when we reach 3.9
scopes: Dict[str, ConfigScope]
scopes: lang.PriorityOrderedMapping[str, ConfigScope]
def __init__(self, *scopes: ConfigScope) -> None:
"""Initialize a configuration with an initial list of scopes.
Args:
scopes: list of scopes to add to this
Configuration, ordered from lowest to highest precedence
"""
self.scopes = collections.OrderedDict()
for scope in scopes:
self.push_scope(scope)
def __init__(self) -> None:
self.scopes = lang.PriorityOrderedMapping()
self.format_updates: Dict[str, List[ConfigScope]] = collections.defaultdict(list)
def ensure_unwrapped(self) -> "Configuration":
@@ -435,36 +444,64 @@ def ensure_unwrapped(self) -> "Configuration":
return self
def highest(self) -> ConfigScope:
"""Scope with highest precedence"""
return next(reversed(self.scopes.values())) # type: ignore
"""Scope with the highest precedence"""
return next(self.scopes.reversed_values()) # type: ignore
@_config_mutator
def ensure_scope_ordering(self):
"""Ensure that scope order matches documented precedent"""
# FIXME: We also need to consider that custom configurations and other orderings
# may not be preserved correctly
if "command_line" in self.scopes:
# TODO (when dropping python 3.6): self.scopes.move_to_end
self.scopes["command_line"] = self.remove_scope("command_line")
def push_scope(
self, scope: ConfigScope, priority: Optional[int] = None, _depth: int = 0
) -> None:
"""Adds a scope to the Configuration, at a given priority.
@_config_mutator
def push_scope(self, scope: ConfigScope) -> None:
"""Add a higher precedence scope to the Configuration."""
tty.debug(f"[CONFIGURATION: PUSH SCOPE]: {str(scope)}", level=2)
self.scopes[scope.name] = scope
If a priority is not given, it is assumed to be the current highest priority.
@_config_mutator
def pop_scope(self) -> ConfigScope:
"""Remove the highest precedence scope and return it."""
name, scope = self.scopes.popitem(last=True) # type: ignore[call-arg]
tty.debug(f"[CONFIGURATION: POP SCOPE]: {str(scope)}", level=2)
return scope
Args:
scope: scope to be added
priority: priority of the scope
"""
tty.debug(f"[CONFIGURATION: PUSH SCOPE]: {str(scope)}, priority={priority}", level=2)
# TODO: As a follow on to #48784, change this to create a graph of the
# TODO: includes AND ensure properly sorted such that the order included
# TODO: at the highest level is reflected in the value of an option that
# TODO: is set in multiple included files.
# before pushing the scope itself, push any included scopes recursively, at same priority
includes = scope.get_section("include")
if includes:
include_paths = [included_path(data) for data in includes["include"]]
for path in reversed(include_paths):
included_scope = include_path_scope(path)
if not included_scope:
continue
if _depth + 1 > MAX_RECURSIVE_INCLUDES: # make sure we're not recursing endlessly
mark = path.path._start_mark if syaml.marked(path.path) else "" # type: ignore
raise RecursiveIncludeError(
f"Maximum include recursion exceeded in {path.path}", str(mark)
)
# record this inclusion so that remove_scope() can use it
scope.included_scopes.append(included_scope.name)
self.push_scope(included_scope, priority=priority, _depth=_depth + 1)
self.scopes.add(scope.name, value=scope, priority=priority)
@_config_mutator
def remove_scope(self, scope_name: str) -> Optional[ConfigScope]:
"""Remove scope by name; has no effect when ``scope_name`` does not exist"""
scope = self.scopes.pop(scope_name, None)
tty.debug(f"[CONFIGURATION: POP SCOPE]: {str(scope)}", level=2)
"""Removes a scope by name, and returns it. If the scope does not exist, returns None."""
try:
scope = self.scopes.remove(scope_name)
tty.debug(f"[CONFIGURATION: REMOVE SCOPE]: {str(scope)}", level=2)
except KeyError as e:
tty.debug(f"[CONFIGURATION: REMOVE SCOPE]: {e}", level=2)
return None
# transitively remove included scopes
for inc in scope.included_scopes:
assert inc in self.scopes, f"Included scope '{inc}' was never added to configuration!"
self.remove_scope(inc)
scope.included_scopes.clear() # clean up includes for bookkeeping
return scope
@property
@@ -473,15 +510,13 @@ def writable_scopes(self) -> Generator[ConfigScope, None, None]:
return (s for s in self.scopes.values() if s.writable)
def highest_precedence_scope(self) -> ConfigScope:
"""Writable scope with highest precedence."""
return next(s for s in reversed(self.scopes.values()) if s.writable) # type: ignore
"""Writable scope with the highest precedence."""
return next(s for s in self.scopes.reversed_values() if s.writable)
def highest_precedence_non_platform_scope(self) -> ConfigScope:
"""Writable non-platform scope with highest precedence"""
"""Writable non-platform scope with the highest precedence"""
return next(
s
for s in reversed(self.scopes.values()) # type: ignore
if s.writable and not s.is_platform_dependent
s for s in self.scopes.reversed_values() if s.writable and not s.is_platform_dependent
)
def matching_scopes(self, reg_expr) -> List[ConfigScope]:
@@ -748,7 +783,7 @@ def override(
"""
if isinstance(path_or_scope, ConfigScope):
overrides = path_or_scope
CONFIG.push_scope(path_or_scope)
CONFIG.push_scope(path_or_scope, priority=None)
else:
base_name = _OVERRIDES_BASE_NAME
# Ensure the new override gets a unique scope name
@@ -762,7 +797,7 @@ def override(
break
overrides = InternalConfigScope(scope_name)
CONFIG.push_scope(overrides)
CONFIG.push_scope(overrides, priority=None)
CONFIG.set(path_or_scope, value, scope=scope_name)
try:
@@ -772,13 +807,86 @@ def override(
assert scope is overrides
def _add_platform_scope(cfg: Configuration, name: str, path: str, writable: bool = True) -> None:
def _add_platform_scope(
cfg: Configuration, name: str, path: str, priority: ConfigScopePriority, writable: bool = True
) -> None:
"""Add a platform-specific subdirectory for the current platform."""
import spack.platforms # circular dependency
platform = spack.platforms.host().name
scope = DirectoryConfigScope(
f"{name}/{platform}", os.path.join(path, platform), writable=writable
)
cfg.push_scope(scope)
cfg.push_scope(scope, priority=priority)
#: Class for the relevance of an optional path conditioned on a limited
#: python code that evaluates to a boolean and or explicit specification
#: as optional.
class IncludePath(NamedTuple):
path: str
when: str
sha256: str
optional: bool
def included_path(entry: Union[str, dict]) -> IncludePath:
"""Convert the included path entry into an IncludePath.
Args:
entry: include configuration entry
Returns: converted entry, where an empty ``when`` means the path is
not conditionally included
"""
if isinstance(entry, str):
return IncludePath(path=entry, sha256="", when="", optional=False)
path = entry["path"]
sha256 = entry.get("sha256", "")
when = entry.get("when", "")
optional = entry.get("optional", False)
return IncludePath(path=path, sha256=sha256, when=when, optional=optional)
def include_path_scope(include: IncludePath) -> Optional[ConfigScope]:
"""Instantiate an appropriate configuration scope for the given path.
Args:
include: optional include path
Returns: configuration scope
Raises:
ValueError: included path has an unsupported URL scheme, is required
but does not exist; configuration stage directory argument is missing
ConfigFileError: unable to access remote configuration file(s)
"""
# circular dependencies
import spack.spec
if (not include.when) or spack.spec.eval_conditional(include.when):
config_path = rfc_util.local_path(include.path, include.sha256, _include_cache_location)
if not config_path:
raise ConfigFileError(f"Unable to fetch remote configuration from {include.path}")
if os.path.isdir(config_path):
# directories are treated as regular ConfigScopes
config_name = f"{INCLUDE_SCOPE_PREFIX}:{os.path.basename(config_path)}"
tty.debug(f"Creating DirectoryConfigScope {config_name} for '{config_path}'")
return DirectoryConfigScope(config_name, config_path)
if os.path.exists(config_path):
# files are assumed to be SingleFileScopes
config_name = f"{INCLUDE_SCOPE_PREFIX}:{config_path}"
tty.debug(f"Creating SingleFileScope {config_name} for '{config_path}'")
return SingleFileScope(config_name, config_path, spack.schema.merged.schema)
if not include.optional:
path = f" at ({config_path})" if config_path != include.path else ""
raise ValueError(f"Required path ({include.path}) does not exist{path}")
return None
def config_paths_from_entry_points() -> List[Tuple[str, str]]:
@@ -806,18 +914,17 @@ def config_paths_from_entry_points() -> List[Tuple[str, str]]:
return config_paths
def create() -> Configuration:
def create_incremental() -> Generator[Configuration, None, None]:
"""Singleton Configuration instance.
This constructs one instance associated with this module and returns
it. It is bundled inside a function so that configuration can be
initialized lazily.
"""
cfg = Configuration()
# first do the builtin, hardcoded defaults
builtin = InternalConfigScope("_builtin", CONFIG_DEFAULTS)
cfg.push_scope(builtin)
cfg = create_from(
(ConfigScopePriority.BUILTIN, InternalConfigScope("_builtin", CONFIG_DEFAULTS))
)
# Builtin paths to configuration files in Spack
configuration_paths = [
@@ -847,16 +954,29 @@ def create() -> Configuration:
# add each scope and its platform-specific directory
for name, path in configuration_paths:
cfg.push_scope(DirectoryConfigScope(name, path))
cfg.push_scope(DirectoryConfigScope(name, path), priority=ConfigScopePriority.CONFIG_FILES)
# Each scope can have per-platform overrides in subdirectories
_add_platform_scope(cfg, name, path, priority=ConfigScopePriority.CONFIG_FILES)
# Each scope can have per-platfom overrides in subdirectories
_add_platform_scope(cfg, name, path)
# yield the config incrementally so that each config level's init code can get
# data from the one below. This can be tricky, but it enables us to have a
# single unified config system.
#
# TODO: think about whether we want to restrict what types of config can be used
# at each level. e.g., we may want to just more forcibly disallow remote
# config (which uses ssl and other config options) for some of the scopes,
# to make the bootstrap issues more explicit, even if allowing config scope
# init to reference lower scopes is more flexible.
yield cfg
return cfg
def create() -> Configuration:
"""Create a configuration using create_incremental(), return the last yielded result."""
return list(create_incremental())[-1]
#: This is the singleton configuration instance for Spack.
CONFIG: Configuration = lang.Singleton(create) # type: ignore
CONFIG: Configuration = lang.Singleton(create_incremental) # type: ignore
def add_from_file(filename: str, scope: Optional[str] = None) -> None:
@@ -952,10 +1072,11 @@ def set(path: str, value: Any, scope: Optional[str] = None) -> None:
Accepts the path syntax described in ``get()``.
"""
return CONFIG.set(path, value, scope)
result = CONFIG.set(path, value, scope)
return result
def scopes() -> Dict[str, ConfigScope]:
def scopes() -> lang.PriorityOrderedMapping[str, ConfigScope]:
"""Convenience function to get list of configuration scopes."""
return CONFIG.scopes
@@ -1409,7 +1530,7 @@ def ensure_latest_format_fn(section: str) -> Callable[[YamlConfigDict], bool]:
@contextlib.contextmanager
def use_configuration(
*scopes_or_paths: Union[ConfigScope, str]
*scopes_or_paths: Union[ScopeWithOptionalPriority, str]
) -> Generator[Configuration, None, None]:
"""Use the configuration scopes passed as arguments within the context manager.
@@ -1424,7 +1545,7 @@ def use_configuration(
global CONFIG
# Normalize input and construct a Configuration object
configuration = _config_from(scopes_or_paths)
configuration = create_from(*scopes_or_paths)
CONFIG.clear_caches(), configuration.clear_caches()
saved_config, CONFIG = CONFIG, configuration
@@ -1435,115 +1556,44 @@ def use_configuration(
CONFIG = saved_config
def _normalize_input(entry: Union[ScopeWithOptionalPriority, str]) -> ScopeWithPriority:
if isinstance(entry, tuple):
return entry
default_priority = ConfigScopePriority.CONFIG_FILES
if isinstance(entry, ConfigScope):
return default_priority, entry
# Otherwise we need to construct it
path = os.path.normpath(entry)
assert os.path.isdir(path), f'"{path}" must be a directory'
name = os.path.basename(path)
return default_priority, DirectoryConfigScope(name, path)
@lang.memoized
def _config_from(scopes_or_paths: List[Union[ConfigScope, str]]) -> Configuration:
scopes = []
for scope_or_path in scopes_or_paths:
# If we have a config scope we are already done
if isinstance(scope_or_path, ConfigScope):
scopes.append(scope_or_path)
continue
# Otherwise we need to construct it
path = os.path.normpath(scope_or_path)
assert os.path.isdir(path), f'"{path}" must be a directory'
name = os.path.basename(path)
scopes.append(DirectoryConfigScope(name, path))
configuration = Configuration(*scopes)
return configuration
def raw_github_gitlab_url(url: str) -> str:
"""Transform a github URL to the raw form to avoid undesirable html.
def create_from(*scopes_or_paths: Union[ScopeWithOptionalPriority, str]) -> Configuration:
"""Creates a configuration object from the scopes passed in input.
Args:
url: url to be converted to raw form
*scopes_or_paths: either a tuple of (priority, ConfigScope), or a ConfigScope, or a string
If priority is not given, it is assumed to be ConfigScopePriority.CONFIG_FILES. If a
string is given, a DirectoryConfigScope is created from it.
Returns:
Raw github/gitlab url or the original url
Examples:
>>> builtin_scope = InternalConfigScope("_builtin", {"config": {"build_jobs": 1}})
>>> cl_scope = InternalConfigScope("command_line", {"config": {"build_jobs": 10}})
>>> cfg = create_from(
... (ConfigScopePriority.COMMAND_LINE, cl_scope),
... (ConfigScopePriority.BUILTIN, builtin_scope)
... )
"""
# Note we rely on GitHub to redirect the 'raw' URL returned here to the
# actual URL under https://raw.githubusercontent.com/ with '/blob'
# removed and or, '/blame' if needed.
if "github" in url or "gitlab" in url:
return url.replace("/blob/", "/raw/")
return url
def collect_urls(base_url: str) -> list:
"""Return a list of configuration URLs.
Arguments:
base_url: URL for a configuration (yaml) file or a directory
containing yaml file(s)
Returns:
List of configuration file(s) or empty list if none
"""
if not base_url:
return []
extension = ".yaml"
if base_url.endswith(extension):
return [base_url]
# Collect configuration URLs if the base_url is a "directory".
_, links = web_util.spider(base_url, 0)
return [link for link in links if link.endswith(extension)]
def fetch_remote_configs(url: str, dest_dir: str, skip_existing: bool = True) -> str:
"""Retrieve configuration file(s) at the specified URL.
Arguments:
url: URL for a configuration (yaml) file or a directory containing
yaml file(s)
dest_dir: destination directory
skip_existing: Skip files that already exist in dest_dir if
``True``; otherwise, replace those files
Returns:
Path to the corresponding file if URL is or contains a
single file and it is the only file in the destination directory or
the root (dest_dir) directory if multiple configuration files exist
or are retrieved.
"""
def _fetch_file(url):
raw = raw_github_gitlab_url(url)
tty.debug(f"Reading config from url {raw}")
return web_util.fetch_url_text(raw, dest_dir=dest_dir)
if not url:
raise ConfigFileError("Cannot retrieve configuration without a URL")
# Return the local path to the cached configuration file OR to the
# directory containing the cached configuration files.
config_links = collect_urls(url)
existing_files = os.listdir(dest_dir) if os.path.isdir(dest_dir) else []
paths = []
for config_url in config_links:
basename = os.path.basename(config_url)
if skip_existing and basename in existing_files:
tty.warn(
f"Will not fetch configuration from {config_url} since a "
f"version already exists in {dest_dir}"
)
path = os.path.join(dest_dir, basename)
else:
path = _fetch_file(config_url)
if path:
paths.append(path)
if paths:
return dest_dir if len(paths) > 1 else paths[0]
raise ConfigFileError(f"Cannot retrieve configuration (yaml) from {url}")
scopes_with_priority = [_normalize_input(x) for x in scopes_or_paths]
result = Configuration()
for priority, scope in scopes_with_priority:
result.push_scope(scope, priority=priority)
return result
def get_mark_from_yaml_data(obj):
@@ -1672,3 +1722,7 @@ def get_path(path, data):
# give up and return None if nothing worked
return None
class RecursiveIncludeError(spack.error.SpackError):
"""Too many levels of recursive includes."""

View File

@@ -57,7 +57,7 @@ def validate(configuration_file):
# Set the default value of the concretization strategy to unify and
# warn if the user explicitly set another value
env_dict.setdefault("concretizer", {"unify": True})
if not env_dict["concretizer"]["unify"] is True:
if env_dict["concretizer"]["unify"] is not True:
warnings.warn(
'"concretizer:unify" is not set to "true", which means the '
"generated image may contain different variants of the same "

View File

@@ -41,6 +41,8 @@
Union,
)
import spack.repo
try:
import uuid
@@ -1556,7 +1558,12 @@ def _query(
# If we did fine something, the query spec can't be virtual b/c we matched an actual
# package installation, so skip the virtual check entirely. If we *didn't* find anything,
# check all the deferred specs *if* the query is virtual.
if not results and query_spec is not None and deferred and query_spec.virtual:
if (
not results
and query_spec is not None
and deferred
and spack.repo.PATH.is_virtual(query_spec.name)
):
results = [spec for spec in deferred if spec.satisfies(query_spec)]
return results

View File

@@ -310,7 +310,7 @@ def find_windows_kit_roots() -> List[str]:
@staticmethod
def find_windows_kit_bin_paths(
kit_base: Union[Optional[str], Optional[list]] = None
kit_base: Union[Optional[str], Optional[list]] = None,
) -> List[str]:
"""Returns Windows kit bin directory per version"""
kit_base = WindowsKitExternalPaths.find_windows_kit_roots() if not kit_base else kit_base
@@ -325,7 +325,7 @@ def find_windows_kit_bin_paths(
@staticmethod
def find_windows_kit_lib_paths(
kit_base: Union[Optional[str], Optional[list]] = None
kit_base: Union[Optional[str], Optional[list]] = None,
) -> List[str]:
"""Returns Windows kit lib directory per version"""
kit_base = WindowsKitExternalPaths.find_windows_kit_roots() if not kit_base else kit_base

View File

@@ -243,7 +243,7 @@ def prefix_from_path(self, *, path: str) -> str:
raise NotImplementedError("must be implemented by derived classes")
def detect_specs(
self, *, pkg: Type["spack.package_base.PackageBase"], paths: List[str]
self, *, pkg: Type["spack.package_base.PackageBase"], paths: Iterable[str]
) -> List["spack.spec.Spec"]:
"""Given a list of files matching the search patterns, returns a list of detected specs.
@@ -259,6 +259,8 @@ def detect_specs(
)
return []
from spack.repo import PATH as repo_path
result = []
for candidate_path, items_in_prefix in _group_by_prefix(
llnl.util.lang.dedupe(paths)
@@ -305,7 +307,10 @@ def detect_specs(
resolved_specs[spec] = candidate_path
try:
spec.validate_detection()
# Validate the spec calling a package specific method
pkg_cls = repo_path.get_pkg_class(spec.name)
validate_fn = getattr(pkg_cls, "validate_detected_spec", lambda x, y: None)
validate_fn(spec, spec.extra_attributes)
except Exception as e:
msg = (
f'"{spec}" has been detected on the system but will '

View File

@@ -568,7 +568,7 @@ def patch(
"""
def _execute_patch(
pkg_or_dep: Union[Type[spack.package_base.PackageBase], Dependency]
pkg_or_dep: Union[Type[spack.package_base.PackageBase], Dependency],
) -> None:
pkg = pkg_or_dep.pkg if isinstance(pkg_or_dep, Dependency) else pkg_or_dep

View File

@@ -25,7 +25,7 @@
}
def _check_concrete(spec):
def _check_concrete(spec: "spack.spec.Spec") -> None:
"""If the spec is not concrete, raise a ValueError"""
if not spec.concrete:
raise ValueError("Specs passed to a DirectoryLayout must be concrete!")
@@ -51,7 +51,7 @@ def specs_from_metadata_dirs(root: str) -> List["spack.spec.Spec"]:
spec = _get_spec(prefix)
if spec:
spec.prefix = prefix
spec.set_prefix(prefix)
specs.append(spec)
continue
@@ -84,7 +84,7 @@ class DirectoryLayout:
def __init__(
self,
root,
root: str,
*,
projections: Optional[Dict[str, str]] = None,
hash_length: Optional[int] = None,
@@ -120,17 +120,17 @@ def __init__(
self.manifest_file_name = "install_manifest.json"
@property
def hidden_file_regexes(self):
def hidden_file_regexes(self) -> Tuple[str]:
return ("^{0}$".format(re.escape(self.metadata_dir)),)
def relative_path_for_spec(self, spec):
def relative_path_for_spec(self, spec: "spack.spec.Spec") -> str:
_check_concrete(spec)
projection = spack.projections.get_projection(self.projections, spec)
path = spec.format_path(projection)
return str(Path(path))
def write_spec(self, spec, path):
def write_spec(self, spec: "spack.spec.Spec", path: str) -> None:
"""Write a spec out to a file."""
_check_concrete(spec)
with open(path, "w", encoding="utf-8") as f:
@@ -138,7 +138,7 @@ def write_spec(self, spec, path):
# the full provenance, so it's availabe if we want it later
spec.to_json(f, hash=ht.dag_hash)
def write_host_environment(self, spec):
def write_host_environment(self, spec: "spack.spec.Spec") -> None:
"""The host environment is a json file with os, kernel, and spack
versioning. We use it in the case that an analysis later needs to
easily access this information.
@@ -148,7 +148,7 @@ def write_host_environment(self, spec):
with open(env_file, "w", encoding="utf-8") as fd:
sjson.dump(environ, fd)
def read_spec(self, path):
def read_spec(self, path: str) -> "spack.spec.Spec":
"""Read the contents of a file and parse them as a spec"""
try:
with open(path, encoding="utf-8") as f:
@@ -159,26 +159,28 @@ def read_spec(self, path):
# Too late for conversion; spec_file_path() already called.
spec = spack.spec.Spec.from_yaml(f)
else:
raise SpecReadError(
"Did not recognize spec file extension:" " {0}".format(extension)
)
raise SpecReadError(f"Did not recognize spec file extension: {extension}")
except Exception as e:
if spack.config.get("config:debug"):
raise
raise SpecReadError("Unable to read file: %s" % path, "Cause: " + str(e))
raise SpecReadError(f"Unable to read file: {path}", f"Cause: {e}")
# Specs read from actual installations are always concrete
spec._mark_concrete()
return spec
def spec_file_path(self, spec):
def spec_file_path(self, spec: "spack.spec.Spec") -> str:
"""Gets full path to spec file"""
_check_concrete(spec)
yaml_path = os.path.join(self.metadata_path(spec), self._spec_file_name_yaml)
json_path = os.path.join(self.metadata_path(spec), self.spec_file_name)
return yaml_path if os.path.exists(yaml_path) else json_path
def deprecated_file_path(self, deprecated_spec, deprecator_spec=None):
def deprecated_file_path(
self,
deprecated_spec: "spack.spec.Spec",
deprecator_spec: Optional["spack.spec.Spec"] = None,
) -> str:
"""Gets full path to spec file for deprecated spec
If the deprecator_spec is provided, use that. Otherwise, assume
@@ -212,16 +214,16 @@ def deprecated_file_path(self, deprecated_spec, deprecator_spec=None):
return yaml_path if os.path.exists(yaml_path) else json_path
def metadata_path(self, spec):
def metadata_path(self, spec: "spack.spec.Spec") -> str:
return os.path.join(spec.prefix, self.metadata_dir)
def env_metadata_path(self, spec):
def env_metadata_path(self, spec: "spack.spec.Spec") -> str:
return os.path.join(self.metadata_path(spec), "install_environment.json")
def build_packages_path(self, spec):
def build_packages_path(self, spec: "spack.spec.Spec") -> str:
return os.path.join(self.metadata_path(spec), self.packages_dir)
def create_install_directory(self, spec):
def create_install_directory(self, spec: "spack.spec.Spec") -> None:
_check_concrete(spec)
# Create install directory with properly configured permissions
@@ -239,7 +241,7 @@ def create_install_directory(self, spec):
self.write_spec(spec, self.spec_file_path(spec))
def ensure_installed(self, spec):
def ensure_installed(self, spec: "spack.spec.Spec") -> None:
"""
Throws InconsistentInstallDirectoryError if:
1. spec prefix does not exist
@@ -266,7 +268,7 @@ def ensure_installed(self, spec):
"Spec file in %s does not match hash!" % spec_file_path
)
def path_for_spec(self, spec):
def path_for_spec(self, spec: "spack.spec.Spec") -> str:
"""Return absolute path from the root to a directory for the spec."""
_check_concrete(spec)
@@ -277,23 +279,13 @@ def path_for_spec(self, spec):
assert not path.startswith(self.root)
return os.path.join(self.root, path)
def remove_install_directory(self, spec, deprecated=False):
def remove_install_directory(self, spec: "spack.spec.Spec", deprecated: bool = False) -> None:
"""Removes a prefix and any empty parent directories from the root.
Raised RemoveFailedError if something goes wrong.
"""
path = self.path_for_spec(spec)
assert path.startswith(self.root)
# Windows readonly files cannot be removed by Python
# directly, change permissions before attempting to remove
if sys.platform == "win32":
kwargs = {
"ignore_errors": False,
"onerror": fs.readonly_file_handler(ignore_errors=False),
}
else:
kwargs = {} # the default value for ignore_errors is false
if deprecated:
if os.path.exists(path):
try:
@@ -304,7 +296,16 @@ def remove_install_directory(self, spec, deprecated=False):
raise RemoveFailedError(spec, path, e) from e
elif os.path.exists(path):
try:
shutil.rmtree(path, **kwargs)
if sys.platform == "win32":
# Windows readonly files cannot be removed by Python
# directly, change permissions before attempting to remove
shutil.rmtree(
path,
ignore_errors=False,
onerror=fs.readonly_file_handler(ignore_errors=False),
)
else:
shutil.rmtree(path)
except OSError as e:
raise RemoveFailedError(spec, path, e) from e

View File

@@ -12,3 +12,13 @@ class InstallRecordStatus(enum.Flag):
DEPRECATED = enum.auto()
MISSING = enum.auto()
ANY = INSTALLED | DEPRECATED | MISSING
class ConfigScopePriority(enum.IntEnum):
"""Priorities of the different kind of config scopes used by Spack"""
BUILTIN = 0
CONFIG_FILES = 1
CUSTOM = 2
ENVIRONMENT = 3
COMMAND_LINE = 4

View File

@@ -10,8 +10,6 @@
import re
import shutil
import stat
import urllib.parse
import urllib.request
import warnings
from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Union
@@ -32,7 +30,6 @@
import spack.paths
import spack.repo
import spack.schema.env
import spack.schema.merged
import spack.spec
import spack.spec_list
import spack.store
@@ -43,7 +40,6 @@
import spack.util.path
import spack.util.spack_json as sjson
import spack.util.spack_yaml as syaml
import spack.util.url
from spack import traverse
from spack.installer import PackageInstaller
from spack.schema.env import TOP_LEVEL_KEY
@@ -51,6 +47,8 @@
from spack.spec_list import SpecList
from spack.util.path import substitute_path_variables
from ..enums import ConfigScopePriority
SpecPair = spack.concretize.SpecPair
#: environment variable used to indicate the active environment
@@ -387,6 +385,7 @@ def create_in_dir(
# dev paths in this environment to refer to their original
# locations.
_rewrite_relative_dev_paths_on_relocation(env, init_file_dir)
_rewrite_relative_repos_paths_on_relocation(env, init_file_dir)
return env
@@ -403,8 +402,8 @@ def _rewrite_relative_dev_paths_on_relocation(env, init_file_dir):
dev_path = substitute_path_variables(entry["path"])
expanded_path = spack.util.path.canonicalize_path(dev_path, default_wd=init_file_dir)
# Skip if the expanded path is the same (e.g. when absolute)
if dev_path == expanded_path:
# Skip if the substituted and expanded path is the same (e.g. when absolute)
if entry["path"] == expanded_path:
continue
tty.debug("Expanding develop path for {0} to {1}".format(name, expanded_path))
@@ -419,6 +418,34 @@ def _rewrite_relative_dev_paths_on_relocation(env, init_file_dir):
env._re_read()
def _rewrite_relative_repos_paths_on_relocation(env, init_file_dir):
"""When initializing the environment from a manifest file and we plan
to store the environment in a different directory, we have to rewrite
relative repo paths to absolute ones and expand environment variables."""
with env:
repos_specs = spack.config.get("repos", default={}, scope=env.scope_name)
if not repos_specs:
return
for i, entry in enumerate(repos_specs):
repo_path = substitute_path_variables(entry)
expanded_path = spack.util.path.canonicalize_path(repo_path, default_wd=init_file_dir)
# Skip if the substituted and expanded path is the same (e.g. when absolute)
if entry == expanded_path:
continue
tty.debug("Expanding repo path for {0} to {1}".format(entry, expanded_path))
repos_specs[i] = expanded_path
spack.config.set("repos", repos_specs, scope=env.scope_name)
env.repos_specs = None
# If we changed the environment's spack.yaml scope, that will not be reflected
# in the manifest that we read
env._re_read()
def environment_dir_from_name(name: str, exists_ok: bool = True) -> str:
"""Returns the directory associated with a named environment.
@@ -546,13 +573,6 @@ def _write_yaml(data, str_or_file):
syaml.dump_config(data, str_or_file, default_flow_style=False)
def _eval_conditional(string):
"""Evaluate conditional definitions using restricted variable scope."""
valid_variables = spack.spec.get_host_environment()
valid_variables.update({"re": re, "env": os.environ})
return eval(string, valid_variables)
def _is_dev_spec_and_has_changed(spec):
"""Check if the passed spec is a dev build and whether it has changed since the
last installation"""
@@ -985,7 +1005,7 @@ def _process_definition(self, entry):
"""Process a single spec definition item."""
when_string = entry.get("when")
if when_string is not None:
when = _eval_conditional(when_string)
when = spack.spec.eval_conditional(when_string)
assert len([x for x in entry if x != "when"]) == 1
else:
when = True
@@ -1530,9 +1550,6 @@ def _get_specs_to_concretize(
return new_user_specs, kept_user_specs, specs_to_concretize
def _concretize_together_where_possible(self, tests: bool = False) -> Sequence[SpecPair]:
# Avoid cyclic dependency
import spack.solver.asp
# Exit early if the set of concretized specs is the set of user specs
new_user_specs, _, specs_to_concretize = self._get_specs_to_concretize()
if not new_user_specs:
@@ -2392,6 +2409,8 @@ def invalidate_repository_cache(self):
def __enter__(self):
self._previous_active = _active_environment
if self._previous_active:
deactivate()
activate(self)
return self
@@ -2641,20 +2660,23 @@ def _ensure_env_dir():
# error handling for bad manifests is handled on other code paths
return
# TODO: make this recursive
includes = manifest[TOP_LEVEL_KEY].get("include", [])
for include in includes:
if os.path.isabs(include):
included_path = spack.config.included_path(include)
path = included_path.path
if os.path.isabs(path):
continue
abspath = pathlib.Path(os.path.normpath(environment_dir / include))
abspath = pathlib.Path(os.path.normpath(environment_dir / path))
common_path = pathlib.Path(os.path.commonpath([environment_dir, abspath]))
if common_path != environment_dir:
tty.debug(f"Will not copy relative include from outside environment: {include}")
tty.debug(f"Will not copy relative include file from outside environment: {path}")
continue
orig_abspath = os.path.normpath(envfile.parent / include)
orig_abspath = os.path.normpath(envfile.parent / path)
if not os.path.exists(orig_abspath):
tty.warn(f"Included file does not exist; will not copy: '{include}'")
tty.warn(f"Included file does not exist; will not copy: '{path}'")
continue
fs.touchp(abspath)
@@ -2877,7 +2899,7 @@ def extract_name(_item):
continue
condition_str = item.get("when", "True")
if not _eval_conditional(condition_str):
if not spack.spec.eval_conditional(condition_str):
continue
yield idx, item
@@ -2938,127 +2960,20 @@ def __iter__(self):
def __str__(self):
return str(self.manifest_file)
@property
def included_config_scopes(self) -> List[spack.config.ConfigScope]:
"""List of included configuration scopes from the manifest.
Scopes are listed in the YAML file in order from highest to
lowest precedence, so configuration from earlier scope will take
precedence over later ones.
This routine returns them in the order they should be pushed onto
the internal scope stack (so, in reverse, from lowest to highest).
Returns: Configuration scopes associated with the environment manifest
Raises:
SpackEnvironmentError: if the manifest includes a remote file but
no configuration stage directory has been identified
"""
scopes: List[spack.config.ConfigScope] = []
# load config scopes added via 'include:', in reverse so that
# highest-precedence scopes are last.
includes = self[TOP_LEVEL_KEY].get("include", [])
missing = []
for i, config_path in enumerate(reversed(includes)):
# allow paths to contain spack config/environment variables, etc.
config_path = substitute_path_variables(config_path)
include_url = urllib.parse.urlparse(config_path)
# If scheme is not valid, config_path is not a url
# of a type Spack is generally aware
if spack.util.url.validate_scheme(include_url.scheme):
# Transform file:// URLs to direct includes.
if include_url.scheme == "file":
config_path = urllib.request.url2pathname(include_url.path)
# Any other URL should be fetched.
elif include_url.scheme in ("http", "https", "ftp"):
# Stage any remote configuration file(s)
staged_configs = (
os.listdir(self.config_stage_dir)
if os.path.exists(self.config_stage_dir)
else []
)
remote_path = urllib.request.url2pathname(include_url.path)
basename = os.path.basename(remote_path)
if basename in staged_configs:
# Do NOT re-stage configuration files over existing
# ones with the same name since there is a risk of
# losing changes (e.g., from 'spack config update').
tty.warn(
"Will not re-stage configuration from {0} to avoid "
"losing changes to the already staged file of the "
"same name.".format(remote_path)
)
# Recognize the configuration stage directory
# is flattened to ensure a single copy of each
# configuration file.
config_path = self.config_stage_dir
if basename.endswith(".yaml"):
config_path = os.path.join(config_path, basename)
else:
staged_path = spack.config.fetch_remote_configs(
config_path, str(self.config_stage_dir), skip_existing=True
)
if not staged_path:
raise SpackEnvironmentError(
"Unable to fetch remote configuration {0}".format(config_path)
)
config_path = staged_path
elif include_url.scheme:
raise ValueError(
f"Unsupported URL scheme ({include_url.scheme}) for "
f"environment include: {config_path}"
)
# treat relative paths as relative to the environment
if not os.path.isabs(config_path):
config_path = os.path.join(self.manifest_dir, config_path)
config_path = os.path.normpath(os.path.realpath(config_path))
if os.path.isdir(config_path):
# directories are treated as regular ConfigScopes
config_name = f"env:{self.name}:{os.path.basename(config_path)}"
tty.debug(f"Creating DirectoryConfigScope {config_name} for '{config_path}'")
scopes.append(spack.config.DirectoryConfigScope(config_name, config_path))
elif os.path.exists(config_path):
# files are assumed to be SingleFileScopes
config_name = f"env:{self.name}:{config_path}"
tty.debug(f"Creating SingleFileScope {config_name} for '{config_path}'")
scopes.append(
spack.config.SingleFileScope(
config_name, config_path, spack.schema.merged.schema
)
)
else:
missing.append(config_path)
continue
if missing:
msg = "Detected {0} missing include path(s):".format(len(missing))
msg += "\n {0}".format("\n ".join(missing))
raise spack.config.ConfigFileError(msg)
return scopes
@property
def env_config_scopes(self) -> List[spack.config.ConfigScope]:
"""A list of all configuration scopes for the environment manifest. On the first call this
instantiates all the scopes, on subsequent calls it returns the cached list."""
if self._config_scopes is not None:
return self._config_scopes
scopes: List[spack.config.ConfigScope] = [
*self.included_config_scopes,
spack.config.SingleFileScope(
self.scope_name,
str(self.manifest_file),
spack.schema.env.schema,
yaml_path=[TOP_LEVEL_KEY],
),
)
]
ensure_no_disallowed_env_config_mods(scopes)
self._config_scopes = scopes
@@ -3067,14 +2982,12 @@ def env_config_scopes(self) -> List[spack.config.ConfigScope]:
def prepare_config_scope(self) -> None:
"""Add the manifest's scopes to the global configuration search path."""
for scope in self.env_config_scopes:
spack.config.CONFIG.push_scope(scope)
spack.config.CONFIG.ensure_scope_ordering()
spack.config.CONFIG.push_scope(scope, priority=ConfigScopePriority.ENVIRONMENT)
def deactivate_config_scope(self) -> None:
"""Remove any of the manifest's scopes from the global config path."""
for scope in self.env_config_scopes:
spack.config.CONFIG.remove_scope(scope.name)
spack.config.CONFIG.ensure_scope_ordering()
@contextlib.contextmanager
def use_config(self):

View File

@@ -9,7 +9,8 @@
import shutil
import stat
import sys
from typing import Callable, Dict, Optional
import tempfile
from typing import Callable, Dict, List, Optional
from typing_extensions import Literal
@@ -77,7 +78,7 @@ def view_copy(
# Order of this dict is somewhat irrelevant
prefix_to_projection = {
s.prefix: view.get_projection_for_spec(s)
str(s.prefix): view.get_projection_for_spec(s)
for s in spec.traverse(root=True, order="breadth")
if not s.external
}
@@ -184,7 +185,7 @@ def __init__(
def link(self, src: str, dst: str, spec: Optional[spack.spec.Spec] = None) -> None:
self._link(src, dst, self, spec)
def add_specs(self, *specs, **kwargs):
def add_specs(self, *specs: spack.spec.Spec, **kwargs) -> None:
"""
Add given specs to view.
@@ -199,19 +200,19 @@ def add_specs(self, *specs, **kwargs):
"""
raise NotImplementedError
def add_standalone(self, spec):
def add_standalone(self, spec: spack.spec.Spec) -> bool:
"""
Add (link) a standalone package into this view.
"""
raise NotImplementedError
def check_added(self, spec):
def check_added(self, spec: spack.spec.Spec) -> bool:
"""
Check if the given concrete spec is active in this view.
"""
raise NotImplementedError
def remove_specs(self, *specs, **kwargs):
def remove_specs(self, *specs: spack.spec.Spec, **kwargs) -> None:
"""
Removes given specs from view.
@@ -230,25 +231,25 @@ def remove_specs(self, *specs, **kwargs):
"""
raise NotImplementedError
def remove_standalone(self, spec):
def remove_standalone(self, spec: spack.spec.Spec) -> None:
"""
Remove (unlink) a standalone package from this view.
"""
raise NotImplementedError
def get_projection_for_spec(self, spec):
def get_projection_for_spec(self, spec: spack.spec.Spec) -> str:
"""
Get the projection in this view for a spec.
"""
raise NotImplementedError
def get_all_specs(self):
def get_all_specs(self) -> List[spack.spec.Spec]:
"""
Get all specs currently active in this view.
"""
raise NotImplementedError
def get_spec(self, spec):
def get_spec(self, spec: spack.spec.Spec) -> Optional[spack.spec.Spec]:
"""
Return the actual spec linked in this view (i.e. do not look it up
in the database by name).
@@ -262,7 +263,7 @@ def get_spec(self, spec):
"""
raise NotImplementedError
def print_status(self, *specs, **kwargs):
def print_status(self, *specs: spack.spec.Spec, **kwargs) -> None:
"""
Print a short summary about the given specs, detailing whether..
* ..they are active in the view.
@@ -693,7 +694,7 @@ def _sanity_check_view_projection(self, specs):
raise ConflictingSpecsError(current_spec, conflicting_spec)
seen[metadata_dir] = current_spec
def add_specs(self, *specs: spack.spec.Spec) -> None:
def add_specs(self, *specs, **kwargs) -> None:
"""Link a root-to-leaf topologically ordered list of specs into the view."""
assert all((s.concrete for s in specs))
if len(specs) == 0:
@@ -708,7 +709,10 @@ def add_specs(self, *specs: spack.spec.Spec) -> None:
def skip_list(file):
return os.path.basename(file) == spack.store.STORE.layout.metadata_dir
visitor = SourceMergeVisitor(ignore=skip_list)
# Determine if the root is on a case-insensitive filesystem
normalize_paths = is_folder_on_case_insensitive_filesystem(self._root)
visitor = SourceMergeVisitor(ignore=skip_list, normalize_paths=normalize_paths)
# Gather all the directories to be made and files to be linked
for spec in specs:
@@ -827,7 +831,7 @@ def get_projection_for_spec(self, spec):
#####################
# utility functions #
#####################
def get_spec_from_file(filename):
def get_spec_from_file(filename) -> Optional[spack.spec.Spec]:
try:
with open(filename, "r", encoding="utf-8") as f:
return spack.spec.Spec.from_yaml(f)
@@ -884,3 +888,8 @@ def get_dependencies(specs):
class ConflictingProjectionsError(SpackError):
"""Raised when a view has a projections file and is given one manually."""
def is_folder_on_case_insensitive_filesystem(path: str) -> bool:
with tempfile.NamedTemporaryFile(dir=path, prefix=".sentinel") as sentinel:
return os.path.exists(os.path.join(path, os.path.basename(sentinel.name).upper()))

View File

@@ -42,10 +42,10 @@
import llnl.util.tty.color
import spack.deptypes as dt
import spack.repo
import spack.spec
import spack.tengine
import spack.traverse
from spack.solver.input_analysis import create_graph_analyzer
def find(seq, predicate):
@@ -537,10 +537,11 @@ def edge_entry(self, edge):
def _static_edges(specs, depflag):
for spec in specs:
pkg_cls = spack.repo.PATH.get_pkg_class(spec.name)
possible = pkg_cls.possible_dependencies(expand_virtuals=True, depflag=depflag)
*_, edges = create_graph_analyzer().possible_dependencies(
spec.name, expand_virtuals=True, allowed_deps=depflag
)
for parent_name, dependencies in possible.items():
for parent_name, dependencies in edges.items():
for dependency_name in dependencies:
yield spack.spec.DependencySpec(
spack.spec.Spec(parent_name),

View File

@@ -2,198 +2,14 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import fnmatch
import io
import os
import re
from typing import Dict, List, Union
import llnl.util.tty as tty
from llnl.util.filesystem import BaseDirectoryVisitor, visit_directory_tree
from llnl.util.lang import stable_partition
from llnl.util.filesystem import visit_directory_tree
import spack.config
import spack.error
import spack.util.elf as elf
#: Patterns for names of libraries that are allowed to be unresolved when *just* looking at RPATHs
#: added by Spack. These are libraries outside of Spack's control, and assumed to be located in
#: default search paths of the dynamic linker.
ALLOW_UNRESOLVED = [
# kernel
"linux-vdso.so.*",
"libselinux.so.*",
# musl libc
"ld-musl-*.so.*",
# glibc
"ld-linux*.so.*",
"ld64.so.*",
"libanl.so.*",
"libc.so.*",
"libdl.so.*",
"libm.so.*",
"libmemusage.so.*",
"libmvec.so.*",
"libnsl.so.*",
"libnss_compat.so.*",
"libnss_db.so.*",
"libnss_dns.so.*",
"libnss_files.so.*",
"libnss_hesiod.so.*",
"libpcprofile.so.*",
"libpthread.so.*",
"libresolv.so.*",
"librt.so.*",
"libSegFault.so.*",
"libthread_db.so.*",
"libutil.so.*",
# gcc -- this is required even with gcc-runtime, because e.g. libstdc++ depends on libgcc_s,
# but the binaries we copy from the compiler don't have an $ORIGIN rpath.
"libasan.so.*",
"libatomic.so.*",
"libcc1.so.*",
"libgcc_s.so.*",
"libgfortran.so.*",
"libgomp.so.*",
"libitm.so.*",
"liblsan.so.*",
"libquadmath.so.*",
"libssp.so.*",
"libstdc++.so.*",
"libtsan.so.*",
"libubsan.so.*",
# systemd
"libudev.so.*",
# cuda driver
"libcuda.so.*",
]
def is_compatible(parent: elf.ElfFile, child: elf.ElfFile) -> bool:
return (
child.elf_hdr.e_type == elf.ELF_CONSTANTS.ET_DYN
and parent.is_little_endian == child.is_little_endian
and parent.is_64_bit == child.is_64_bit
and parent.elf_hdr.e_machine == child.elf_hdr.e_machine
)
def candidate_matches(current_elf: elf.ElfFile, candidate_path: bytes) -> bool:
try:
with open(candidate_path, "rb") as g:
return is_compatible(current_elf, elf.parse_elf(g))
except (OSError, elf.ElfParsingError):
return False
class Problem:
def __init__(
self, resolved: Dict[bytes, bytes], unresolved: List[bytes], relative_rpaths: List[bytes]
) -> None:
self.resolved = resolved
self.unresolved = unresolved
self.relative_rpaths = relative_rpaths
class ResolveSharedElfLibDepsVisitor(BaseDirectoryVisitor):
def __init__(self, allow_unresolved_patterns: List[str]) -> None:
self.problems: Dict[str, Problem] = {}
self._allow_unresolved_regex = re.compile(
"|".join(fnmatch.translate(x) for x in allow_unresolved_patterns)
)
def allow_unresolved(self, needed: bytes) -> bool:
try:
name = needed.decode("utf-8")
except UnicodeDecodeError:
return False
return bool(self._allow_unresolved_regex.match(name))
def visit_file(self, root: str, rel_path: str, depth: int) -> None:
# We work with byte strings for paths.
path = os.path.join(root, rel_path).encode("utf-8")
# For $ORIGIN interpolation: should not have trailing dir seperator.
origin = os.path.dirname(path)
# Retrieve the needed libs + rpaths.
try:
with open(path, "rb") as f:
parsed_elf = elf.parse_elf(f, interpreter=False, dynamic_section=True)
except (OSError, elf.ElfParsingError):
# Not dealing with an invalid ELF file.
return
# If there's no needed libs all is good
if not parsed_elf.has_needed:
return
# Get the needed libs and rpaths (notice: byte strings)
# Don't force an encoding cause paths are just a bag of bytes.
needed_libs = parsed_elf.dt_needed_strs
rpaths = parsed_elf.dt_rpath_str.split(b":") if parsed_elf.has_rpath else []
# We only interpolate $ORIGIN, not $LIB and $PLATFORM, they're not really
# supported in general. Also remove empty paths.
rpaths = [x.replace(b"$ORIGIN", origin) for x in rpaths if x]
# Do not allow relative rpaths (they are relative to the current working directory)
rpaths, relative_rpaths = stable_partition(rpaths, os.path.isabs)
# If there's a / in the needed lib, it's opened directly, otherwise it needs
# a search.
direct_libs, search_libs = stable_partition(needed_libs, lambda x: b"/" in x)
# Do not allow relative paths in direct libs (they are relative to the current working
# directory)
direct_libs, unresolved = stable_partition(direct_libs, os.path.isabs)
resolved: Dict[bytes, bytes] = {}
for lib in search_libs:
if self.allow_unresolved(lib):
continue
for rpath in rpaths:
candidate = os.path.join(rpath, lib)
if candidate_matches(parsed_elf, candidate):
resolved[lib] = candidate
break
else:
unresolved.append(lib)
# Check if directly opened libs are compatible
for lib in direct_libs:
if candidate_matches(parsed_elf, lib):
resolved[lib] = lib
else:
unresolved.append(lib)
if unresolved or relative_rpaths:
self.problems[rel_path] = Problem(resolved, unresolved, relative_rpaths)
def visit_symlinked_file(self, root: str, rel_path: str, depth: int) -> None:
pass
def before_visit_dir(self, root: str, rel_path: str, depth: int) -> bool:
# There can be binaries in .spack/test which shouldn't be checked.
if rel_path == ".spack":
return False
return True
def before_visit_symlinked_dir(self, root: str, rel_path: str, depth: int) -> bool:
return False
class CannotLocateSharedLibraries(spack.error.SpackError):
pass
def maybe_decode(byte_str: bytes) -> Union[str, bytes]:
try:
return byte_str.decode("utf-8")
except UnicodeDecodeError:
return byte_str
import spack.verify_libraries
def post_install(spec, explicit):
@@ -204,36 +20,23 @@ def post_install(spec, explicit):
if policy == "ignore" or spec.external or spec.platform not in ("linux", "freebsd"):
return
visitor = ResolveSharedElfLibDepsVisitor(
[*ALLOW_UNRESOLVED, *spec.package.unresolved_libraries]
visitor = spack.verify_libraries.ResolveSharedElfLibDepsVisitor(
[*spack.verify_libraries.ALLOW_UNRESOLVED, *spec.package.unresolved_libraries]
)
visit_directory_tree(spec.prefix, visitor)
# All good?
if not visitor.problems:
return
# For now just list the issues (print it in ldd style, except we don't recurse)
output = io.StringIO()
output.write("not all executables and libraries can resolve their dependencies:\n")
for path, problem in visitor.problems.items():
output.write(path)
output.write("\n")
for needed, full_path in problem.resolved.items():
output.write(" ")
if needed == full_path:
output.write(maybe_decode(needed))
else:
output.write(f"{maybe_decode(needed)} => {maybe_decode(full_path)}")
output.write("\n")
for not_found in problem.unresolved:
output.write(f" {maybe_decode(not_found)} => not found\n")
for relative_rpath in problem.relative_rpaths:
output.write(f" {maybe_decode(relative_rpath)} => relative rpath\n")
output = io.StringIO("not all executables and libraries can resolve their dependencies:\n")
visitor.write(output)
message = output.getvalue().strip()
if policy == "error":
raise CannotLocateSharedLibraries(message)
tty.warn(message)
class CannotLocateSharedLibraries(spack.error.SpackError):
pass

View File

@@ -21,7 +21,6 @@
from llnl.util.lang import nullcontext
from llnl.util.tty.color import colorize
import spack.build_environment
import spack.config
import spack.error
import spack.package_base
@@ -398,7 +397,7 @@ def stand_alone_tests(self, kwargs):
Args:
kwargs (dict): arguments to be used by the test process
"""
import spack.build_environment
import spack.build_environment # avoid circular dependency
spack.build_environment.start_build_process(self.pkg, test_process, kwargs)
@@ -463,6 +462,8 @@ def write_tested_status(self):
@contextlib.contextmanager
def test_part(pkg: Pb, test_name: str, purpose: str, work_dir: str = ".", verbose: bool = False):
import spack.build_environment # avoid circular dependency
wdir = "." if work_dir is None else work_dir
tester = pkg.tester
assert test_name and test_name.startswith(
@@ -566,7 +567,7 @@ def copy_test_files(pkg: Pb, test_spec: spack.spec.Spec):
# copy test data into test stage data dir
try:
pkg_cls = test_spec.package_class
pkg_cls = spack.repo.PATH.get_pkg_class(test_spec.fullname)
except spack.repo.UnknownPackageError:
tty.debug(f"{test_spec.name}: skipping test data copy since no package class found")
return
@@ -623,7 +624,7 @@ def test_functions(
vpkgs = virtuals(pkg)
for vname in vpkgs:
try:
classes.append((Spec(vname)).package_class)
classes.append(spack.repo.PATH.get_pkg_class(vname))
except spack.repo.UnknownPackageError:
tty.debug(f"{vname}: virtual does not appear to have a package file")
@@ -668,7 +669,7 @@ def process_test_parts(pkg: Pb, test_specs: List[spack.spec.Spec], verbose: bool
# grab test functions associated with the spec, which may be virtual
try:
tests = test_functions(spec.package_class)
tests = test_functions(spack.repo.PATH.get_pkg_class(spec.fullname))
except spack.repo.UnknownPackageError:
# Some virtuals don't have a package so we don't want to report
# them as not having tests when that isn't appropriate.

View File

@@ -814,7 +814,7 @@ def get_depflags(self, pkg: "spack.package_base.PackageBase") -> int:
# Include build dependencies if pkg is going to be built from sources, or
# if build deps are explicitly requested.
if include_build_deps or not (
cache_only or pkg.spec.installed and not pkg.spec.dag_hash() in self.overwrite
cache_only or pkg.spec.installed and pkg.spec.dag_hash() not in self.overwrite
):
depflag |= dt.BUILD
if self.run_tests(pkg):
@@ -2436,11 +2436,7 @@ def _real_install(self) -> None:
# DEBUGGING TIP - to debug this section, insert an IPython
# embed here, and run the sections below without log capture
log_contextmanager = log_output(
log_file,
self.echo,
True,
env=self.unmodified_env,
filter_fn=self.filter_fn,
log_file, self.echo, True, filter_fn=self.filter_fn
)
with log_contextmanager as logger:

View File

@@ -47,6 +47,8 @@
import spack.util.environment
import spack.util.lock
from .enums import ConfigScopePriority
#: names of profile statistics
stat_names = pstats.Stats.sort_arg_dict_default
@@ -872,14 +874,19 @@ def add_command_line_scopes(
scopes = ev.environment_path_scopes(name, path)
if scopes is None:
if os.path.isdir(path): # directory with config files
cfg.push_scope(spack.config.DirectoryConfigScope(name, path, writable=False))
spack.config._add_platform_scope(cfg, name, path, writable=False)
cfg.push_scope(
spack.config.DirectoryConfigScope(name, path, writable=False),
priority=ConfigScopePriority.CUSTOM,
)
spack.config._add_platform_scope(
cfg, name, path, priority=ConfigScopePriority.CUSTOM, writable=False
)
continue
else:
raise spack.error.ConfigError(f"Invalid configuration scope: {path}")
for scope in scopes:
cfg.push_scope(scope)
cfg.push_scope(scope, priority=ConfigScopePriority.CUSTOM)
def _main(argv=None):
@@ -952,7 +959,9 @@ def _main(argv=None):
# Push scopes from the command line last
if args.config_scopes:
add_command_line_scopes(spack.config.CONFIG, args.config_scopes)
spack.config.CONFIG.push_scope(spack.config.InternalConfigScope("command_line"))
spack.config.CONFIG.push_scope(
spack.config.InternalConfigScope("command_line"), priority=ConfigScopePriority.COMMAND_LINE
)
setup_main_options(args)
# ------------------------------------------------------------------------
@@ -998,6 +1007,7 @@ def finish_parse_and_run(parser, cmd_name, main_args, env_format_error):
args, unknown = parser.parse_known_args(main_args.command)
# we need to inherit verbose since the install command checks for it
args.verbose = main_args.verbose
args.lines = main_args.lines
# Now that we know what command this is and what its args are, determine
# whether we can continue with a bad environment and raise if not.

View File

@@ -64,7 +64,7 @@ def from_local_path(path: str):
@staticmethod
def from_url(url: str):
"""Create an anonymous mirror by URL. This method validates the URL."""
if not urllib.parse.urlparse(url).scheme in supported_url_schemes:
if urllib.parse.urlparse(url).scheme not in supported_url_schemes:
raise ValueError(
f'"{url}" is not a valid mirror URL. '
f"Scheme must be one of {supported_url_schemes}."

View File

@@ -330,18 +330,17 @@ class BaseConfiguration:
default_projections = {"all": "{name}/{version}-{compiler.name}-{compiler.version}"}
def __init__(self, spec: spack.spec.Spec, module_set_name: str, explicit: bool) -> None:
# Module where type(self) is defined
m = inspect.getmodule(self)
assert m is not None # make mypy happy
self.module = m
# Spec for which we want to generate a module file
self.spec = spec
self.name = module_set_name
self.explicit = explicit
# Dictionary of configuration options that should be applied
# to the spec
# Dictionary of configuration options that should be applied to the spec
self.conf = merge_config_rules(self.module.configuration(self.name), self.spec)
@property
def module(self):
return inspect.getmodule(self)
@property
def projections(self):
"""Projection from specs to module names"""
@@ -775,10 +774,6 @@ def __init__(
) -> None:
self.spec = spec
# This class is meant to be derived. Get the module of the
# actual writer.
self.module = inspect.getmodule(self)
assert self.module is not None # make mypy happy
m = self.module
# Create the triplet of configuration/layout/context
@@ -816,6 +811,10 @@ def __init__(
name = type(self).__name__
raise ModulercHeaderNotDefined(msg.format(name))
@property
def module(self):
return inspect.getmodule(self)
def _get_template(self):
"""Gets the template that will be rendered for this spec."""
# Get templates and put them in the order of importance:

View File

@@ -209,7 +209,7 @@ def provides(self):
# All the other tokens in the hierarchy must be virtual dependencies
for x in self.hierarchy_tokens:
if self.spec.package.provides(x):
provides[x] = self.spec[x]
provides[x] = self.spec
return provides
@property

View File

@@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
# flake8: noqa: F401
# flake8: noqa: F401, E402
"""spack.package defines the public API for Spack packages, by re-exporting useful symbols from
other modules. Packages should import this module, instead of importing from spack.* directly
to ensure forward compatibility with future versions of Spack."""

View File

@@ -22,7 +22,6 @@
import textwrap
import time
import traceback
import typing
from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Tuple, Type, TypeVar, Union
from typing_extensions import Literal
@@ -126,9 +125,10 @@ def windows_establish_runtime_linkage(self):
# Spack should in general not modify things it has not installed
# we can reasonably expect externals to have their link interface properly established
if sys.platform == "win32" and not self.spec.external:
self.win_rpath.add_library_dependent(*self.win_add_library_dependent())
self.win_rpath.add_rpath(*self.win_add_rpath())
self.win_rpath.establish_link()
win_rpath = fsys.WindowsSimulatedRPath(self)
win_rpath.add_library_dependent(*self.win_add_library_dependent())
win_rpath.add_rpath(*self.win_add_rpath())
win_rpath.establish_link()
#: Registers which are the detectable packages, by repo and package name
@@ -697,9 +697,6 @@ class PackageBase(WindowsRPath, PackageViewMixin, metaclass=PackageMeta):
#: Verbosity level, preserved across installs.
_verbose = None
#: index of patches by sha256 sum, built lazily
_patches_by_hash = None
#: Package homepage where users can find more information about the package
homepage: Optional[str] = None
@@ -713,19 +710,6 @@ class PackageBase(WindowsRPath, PackageViewMixin, metaclass=PackageMeta):
#: Do not include @ here in order not to unnecessarily ping the users.
maintainers: List[str] = []
#: List of attributes to be excluded from a package's hash.
metadata_attrs = [
"homepage",
"url",
"urls",
"list_url",
"extendable",
"parallel",
"make_jobs",
"maintainers",
"tags",
]
#: Set to ``True`` to indicate the stand-alone test requires a compiler.
#: It is used to ensure a compiler and build dependencies like 'cmake'
#: are available to build a custom test code.
@@ -759,7 +743,6 @@ def __init__(self, spec):
# Set up timing variables
self._fetch_time = 0.0
self.win_rpath = fsys.WindowsSimulatedRPath(self)
super().__init__()
def __getitem__(self, key: str) -> "PackageBase":
@@ -825,104 +808,6 @@ def get_variant(self, name: str) -> spack.variant.Variant:
except StopIteration:
raise ValueError(f"No variant '{name}' on spec: {self.spec}")
@classmethod
def possible_dependencies(
cls,
transitive: bool = True,
expand_virtuals: bool = True,
depflag: dt.DepFlag = dt.ALL,
visited: Optional[dict] = None,
missing: Optional[dict] = None,
virtuals: Optional[set] = None,
) -> Dict[str, Set[str]]:
"""Return dict of possible dependencies of this package.
Args:
transitive (bool or None): return all transitive dependencies if
True, only direct dependencies if False (default True)..
expand_virtuals (bool or None): expand virtual dependencies into
all possible implementations (default True)
depflag: dependency types to consider
visited (dict or None): dict of names of dependencies visited so
far, mapped to their immediate dependencies' names.
missing (dict or None): dict to populate with packages and their
*missing* dependencies.
virtuals (set): if provided, populate with virtuals seen so far.
Returns:
(dict): dictionary mapping dependency names to *their*
immediate dependencies
Each item in the returned dictionary maps a (potentially
transitive) dependency of this package to its possible
*immediate* dependencies. If ``expand_virtuals`` is ``False``,
virtual package names wil be inserted as keys mapped to empty
sets of dependencies. Virtuals, if not expanded, are treated as
though they have no immediate dependencies.
Missing dependencies by default are ignored, but if a
missing dict is provided, it will be populated with package names
mapped to any dependencies they have that are in no
repositories. This is only populated if transitive is True.
Note: the returned dict *includes* the package itself.
"""
visited = {} if visited is None else visited
missing = {} if missing is None else missing
visited.setdefault(cls.name, set())
for name, conditions in cls.dependencies_by_name(when=True).items():
# check whether this dependency could be of the type asked for
depflag_union = 0
for deplist in conditions.values():
for dep in deplist:
depflag_union |= dep.depflag
if not (depflag & depflag_union):
continue
# expand virtuals if enabled, otherwise just stop at virtuals
if spack.repo.PATH.is_virtual(name):
if virtuals is not None:
virtuals.add(name)
if expand_virtuals:
providers = spack.repo.PATH.providers_for(name)
dep_names = [spec.name for spec in providers]
else:
visited.setdefault(cls.name, set()).add(name)
visited.setdefault(name, set())
continue
else:
dep_names = [name]
# add the dependency names to the visited dict
visited.setdefault(cls.name, set()).update(set(dep_names))
# recursively traverse dependencies
for dep_name in dep_names:
if dep_name in visited:
continue
visited.setdefault(dep_name, set())
# skip the rest if not transitive
if not transitive:
continue
try:
dep_cls = spack.repo.PATH.get_pkg_class(dep_name)
except spack.repo.UnknownPackageError:
# log unknown packages
missing.setdefault(cls.name, set()).add(dep_name)
continue
dep_cls.possible_dependencies(
transitive, expand_virtuals, depflag, visited, missing, virtuals
)
return visited
@classproperty
def package_dir(cls):
"""Directory where the package.py file lives."""
@@ -2287,55 +2172,6 @@ def rpath_args(self):
build_system_flags = PackageBase.build_system_flags
def use_cray_compiler_names():
"""Compiler names for builds that rely on cray compiler names."""
os.environ["CC"] = "cc"
os.environ["CXX"] = "CC"
os.environ["FC"] = "ftn"
os.environ["F77"] = "ftn"
def possible_dependencies(
*pkg_or_spec: Union[str, spack.spec.Spec, typing.Type[PackageBase]],
transitive: bool = True,
expand_virtuals: bool = True,
depflag: dt.DepFlag = dt.ALL,
missing: Optional[dict] = None,
virtuals: Optional[set] = None,
) -> Dict[str, Set[str]]:
"""Get the possible dependencies of a number of packages.
See ``PackageBase.possible_dependencies`` for details.
"""
packages = []
for pos in pkg_or_spec:
if isinstance(pos, PackageMeta) and issubclass(pos, PackageBase):
packages.append(pos)
continue
if not isinstance(pos, spack.spec.Spec):
pos = spack.spec.Spec(pos)
if spack.repo.PATH.is_virtual(pos.name):
packages.extend(p.package_class for p in spack.repo.PATH.providers_for(pos.name))
continue
else:
packages.append(pos.package_class)
visited: Dict[str, Set[str]] = {}
for pkg in packages:
pkg.possible_dependencies(
visited=visited,
transitive=transitive,
expand_virtuals=expand_virtuals,
depflag=depflag,
missing=missing,
virtuals=virtuals,
)
return visited
def deprecated_version(pkg: PackageBase, version: Union[str, StandardVersion]) -> bool:
"""Return True iff the version is deprecated.

View File

@@ -83,6 +83,7 @@ def __init__(
level: int,
working_dir: str,
reverse: bool = False,
ordering_key: Optional[Tuple[str, int]] = None,
) -> None:
"""Initialize a new Patch instance.
@@ -92,6 +93,7 @@ def __init__(
level: patch level
working_dir: relative path *within* the stage to change to
reverse: reverse the patch
ordering_key: key used to ensure patches are applied in a consistent order
"""
# validate level (must be an integer >= 0)
if not isinstance(level, int) or not level >= 0:
@@ -105,6 +107,13 @@ def __init__(
self.working_dir = working_dir
self.reverse = reverse
# The ordering key is passed when executing package.py directives, and is only relevant
# after a solve to build concrete specs with consistently ordered patches. For concrete
# specs read from a file, we add patches in the order of its patches variants and the
# ordering_key is irrelevant. In that case, use a default value so we don't need to branch
# on whether ordering_key is None where it's used, just to make static analysis happy.
self.ordering_key: Tuple[str, int] = ordering_key or ("", 0)
def apply(self, stage: "spack.stage.Stage") -> None:
"""Apply a patch to source in a stage.
@@ -202,9 +211,8 @@ def __init__(
msg += "package %s.%s does not exist." % (pkg.namespace, pkg.name)
raise ValueError(msg)
super().__init__(pkg, abs_path, level, working_dir, reverse)
super().__init__(pkg, abs_path, level, working_dir, reverse, ordering_key)
self.path = abs_path
self.ordering_key = ordering_key
@property
def sha256(self) -> str:
@@ -266,13 +274,11 @@ def __init__(
archive_sha256: sha256 sum of the *archive*, if the patch is compressed
(only required for compressed URL patches)
"""
super().__init__(pkg, url, level, working_dir, reverse)
super().__init__(pkg, url, level, working_dir, reverse, ordering_key)
self.url = url
self._stage: Optional["spack.stage.Stage"] = None
self.ordering_key = ordering_key
if allowed_archive(self.url) and not archive_sha256:
raise spack.error.PatchDirectiveError(
"Compressed patches require 'archive_sha256' "

View File

@@ -108,6 +108,8 @@ def _get_user_cache_path():
#: transient caches for Spack data (virtual cache, patch sha256 lookup, etc.)
default_misc_cache_path = os.path.join(user_cache_path, "cache")
#: concretization cache for Spack concretizations
default_conc_cache_path = os.path.join(default_misc_cache_path, "concretization")
# Below paths pull configuration from the host environment.
#

View File

@@ -236,22 +236,15 @@ def relocate_elf_binaries(binaries: Iterable[str], prefix_to_prefix: Dict[str, s
_set_elf_rpaths_and_interpreter(path, rpaths=rpaths, interpreter=interpreter)
def _warn_if_link_cant_be_relocated(link: str, target: str):
if not os.path.isabs(target):
return
tty.warn(f'Symbolic link at "{link}" to "{target}" cannot be relocated')
def relocate_links(links: Iterable[str], prefix_to_prefix: Dict[str, str]) -> None:
"""Relocate links to a new install prefix."""
regex = re.compile("|".join(re.escape(p) for p in prefix_to_prefix.keys()))
for link in links:
old_target = readlink(link)
if not os.path.isabs(old_target):
continue
match = regex.match(old_target)
# No match.
if match is None:
_warn_if_link_cant_be_relocated(link, old_target)
continue
new_target = prefix_to_prefix[match.group()] + old_target[match.end() :]
@@ -290,21 +283,21 @@ def relocate_text_bin(binaries: Iterable[str], prefix_to_prefix: PrefixToPrefix)
def is_macho_magic(magic: bytes) -> bool:
return (
# In order of popularity: 64-bit mach-o le/be, 32-bit mach-o le/be.
magic.startswith(b"\xCF\xFA\xED\xFE")
or magic.startswith(b"\xFE\xED\xFA\xCF")
or magic.startswith(b"\xCE\xFA\xED\xFE")
or magic.startswith(b"\xFE\xED\xFA\xCE")
magic.startswith(b"\xcf\xfa\xed\xfe")
or magic.startswith(b"\xfe\xed\xfa\xcf")
or magic.startswith(b"\xce\xfa\xed\xfe")
or magic.startswith(b"\xfe\xed\xfa\xce")
# universal binaries: 0xcafebabe be (most common?) or 0xbebafeca le (not sure if exists).
# Here we need to disambiguate mach-o and JVM class files. In mach-o the next 4 bytes are
# the number of binaries; in JVM class files it's the java version number. We assume there
# are less than 10 binaries in a universal binary.
or (magic.startswith(b"\xCA\xFE\xBA\xBE") and int.from_bytes(magic[4:8], "big") < 10)
or (magic.startswith(b"\xBE\xBA\xFE\xCA") and int.from_bytes(magic[4:8], "little") < 10)
or (magic.startswith(b"\xca\xfe\xba\xbe") and int.from_bytes(magic[4:8], "big") < 10)
or (magic.startswith(b"\xbe\xba\xfe\xca") and int.from_bytes(magic[4:8], "little") < 10)
)
def is_elf_magic(magic: bytes) -> bool:
return magic.startswith(b"\x7FELF")
return magic.startswith(b"\x7fELF")
def is_binary(filename: str) -> bool:
@@ -413,8 +406,8 @@ def fixup_macos_rpaths(spec):
entries which makes it harder to adjust with ``install_name_tool
-delete_rpath``.
"""
if spec.external or spec.virtual:
tty.warn("external or virtual package cannot be fixed up: {0!s}".format(spec))
if spec.external or not spec.concrete:
tty.warn("external/abstract spec cannot be fixed up: {0!s}".format(spec))
return False
if "platform=darwin" not in spec:

View File

@@ -32,6 +32,7 @@
import llnl.util.tty as tty
from llnl.util.filesystem import working_dir
import spack
import spack.caches
import spack.config
import spack.error
@@ -49,6 +50,8 @@
#: Package modules are imported as spack.pkg.<repo-namespace>.<pkg-name>
ROOT_PYTHON_NAMESPACE = "spack.pkg"
_API_REGEX = re.compile(r"^v(\d+)\.(\d+)$")
def python_package_for_repo(namespace):
"""Returns the full namespace of a repository, given its relative one
@@ -909,19 +912,52 @@ def __reduce__(self):
return RepoPath.unmarshal, self.marshal()
def _parse_package_api_version(
config: Dict[str, Any],
min_api: Tuple[int, int] = spack.min_package_api_version,
max_api: Tuple[int, int] = spack.package_api_version,
) -> Tuple[int, int]:
api = config.get("api")
if api is None:
package_api = (1, 0)
else:
if not isinstance(api, str):
raise BadRepoError(f"Invalid Package API version '{api}'. Must be of the form vX.Y")
api_match = _API_REGEX.match(api)
if api_match is None:
raise BadRepoError(f"Invalid Package API version '{api}'. Must be of the form vX.Y")
package_api = (int(api_match.group(1)), int(api_match.group(2)))
if min_api <= package_api <= max_api:
return package_api
min_str = ".".join(str(i) for i in min_api)
max_str = ".".join(str(i) for i in max_api)
curr_str = ".".join(str(i) for i in package_api)
raise BadRepoError(
f"Package API v{curr_str} is not supported by this version of Spack ("
f"must be between v{min_str} and v{max_str})"
)
class Repo:
"""Class representing a package repository in the filesystem.
Each package repository must have a top-level configuration file
called `repo.yaml`.
Each package repository must have a top-level configuration file called `repo.yaml`.
Currently, `repo.yaml` must define:
It contains the following keys:
`namespace`:
A Python namespace where the repository's packages should live.
`subdirectory`:
An optional subdirectory name where packages are placed
`api`:
A string of the form vX.Y that indicates the Package API version. The default is "v1.0".
For the repo to be compatible with the current version of Spack, the version must be
greater than or equal to :py:data:`spack.min_package_api_version` and less than or equal to
:py:data:`spack.package_api_version`.
"""
def __init__(
@@ -958,7 +994,7 @@ def check(condition, msg):
f"{os.path.join(root, repo_config_name)} must define a namespace.",
)
self.namespace = config["namespace"]
self.namespace: str = config["namespace"]
check(
re.match(r"[a-zA-Z][a-zA-Z0-9_.]+", self.namespace),
f"Invalid namespace '{self.namespace}' in repo '{self.root}'. "
@@ -971,12 +1007,14 @@ def check(condition, msg):
# Keep name components around for checking prefixes.
self._names = self.full_namespace.split(".")
packages_dir = config.get("subdirectory", packages_dir_name)
packages_dir: str = config.get("subdirectory", packages_dir_name)
self.packages_path = os.path.join(self.root, packages_dir)
check(
os.path.isdir(self.packages_path), f"No directory '{packages_dir}' found in '{root}'"
)
self.package_api = _parse_package_api_version(config)
# Class attribute overrides by package name
self.overrides = overrides or {}
@@ -1026,7 +1064,7 @@ def is_prefix(self, fullname: str) -> bool:
parts = fullname.split(".")
return self._names[: len(parts)] == parts
def _read_config(self) -> Dict[str, str]:
def _read_config(self) -> Dict[str, Any]:
"""Check for a YAML config file in this db's root directory."""
try:
with open(self.config_file, encoding="utf-8") as reponame_file:
@@ -1368,6 +1406,8 @@ def create_repo(root, namespace=None, subdir=packages_dir_name):
config.write(f" namespace: '{namespace}'\n")
if subdir != packages_dir_name:
config.write(f" subdirectory: '{subdir}'\n")
x, y = spack.package_api_version
config.write(f" api: v{x}.{y}\n")
except OSError as e:
# try to clean up.

View File

@@ -1,6 +1,7 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import codecs
import collections
import hashlib
import os
@@ -13,7 +14,7 @@
import xml.sax.saxutils
from typing import Dict, Optional
from urllib.parse import urlencode
from urllib.request import HTTPSHandler, Request, build_opener
from urllib.request import Request
import llnl.util.tty as tty
from llnl.util.filesystem import working_dir
@@ -24,10 +25,10 @@
import spack.spec
import spack.tengine
import spack.util.git
import spack.util.web as web_util
from spack.error import SpackError
from spack.util.crypto import checksum
from spack.util.log_parse import parse_log_events
from spack.util.web import ssl_create_default_context
from .base import Reporter
from .extract import extract_test_parts
@@ -176,7 +177,7 @@ def build_report_for_package(self, report_dir, package, duration):
# something went wrong pre-cdash "configure" phase b/c we have an exception and only
# "update" was encounterd.
# dump the report in the configure line so teams can see what the issue is
if len(phases_encountered) == 1 and package["exception"]:
if len(phases_encountered) == 1 and package.get("exception"):
# TODO this mapping is not ideal since these are pre-configure errors
# we need to determine if a more appropriate cdash phase can be utilized
# for now we will add a message to the log explaining this
@@ -433,7 +434,6 @@ def upload(self, filename):
# Compute md5 checksum for the contents of this file.
md5sum = checksum(hashlib.md5, filename, block_size=8192)
opener = build_opener(HTTPSHandler(context=ssl_create_default_context()))
with open(filename, "rb") as f:
params_dict = {
"build": self.buildname,
@@ -443,26 +443,21 @@ def upload(self, filename):
}
encoded_params = urlencode(params_dict)
url = "{0}&{1}".format(self.cdash_upload_url, encoded_params)
request = Request(url, data=f)
request = Request(url, data=f, method="PUT")
request.add_header("Content-Type", "text/xml")
request.add_header("Content-Length", os.path.getsize(filename))
if self.authtoken:
request.add_header("Authorization", "Bearer {0}".format(self.authtoken))
try:
# By default, urllib2 only support GET and POST.
# CDash expects this file to be uploaded via PUT.
request.get_method = lambda: "PUT"
response = opener.open(request, timeout=SPACK_CDASH_TIMEOUT)
response = web_util.urlopen(request, timeout=SPACK_CDASH_TIMEOUT)
if self.current_package_name not in self.buildIds:
resp_value = response.read()
if isinstance(resp_value, bytes):
resp_value = resp_value.decode("utf-8")
resp_value = codecs.getreader("utf-8")(response).read()
match = self.buildid_regexp.search(resp_value)
if match:
buildid = match.group(1)
self.buildIds[self.current_package_name] = buildid
except Exception as e:
print("Upload to CDash failed: {0}".format(e))
print(f"Upload to CDash failed: {e}")
def finalize_report(self):
if self.buildIds:

View File

@@ -7,8 +7,7 @@
import warnings
import jsonschema
import llnl.util.lang
import jsonschema.validators
from spack.error import SpecSyntaxError
@@ -18,59 +17,59 @@ class DeprecationMessage(typing.NamedTuple):
error: bool
# jsonschema is imported lazily as it is heavy to import
# and increases the start-up time
def _make_validator():
def _validate_spec(validator, is_spec, instance, schema):
"""Check if the attributes on instance are valid specs."""
import spack.spec_parser
def _validate_spec(validator, is_spec, instance, schema):
"""Check if all additional keys are valid specs."""
import spack.spec_parser
if not validator.is_type(instance, "object"):
return
if not validator.is_type(instance, "object"):
return
for spec_str in instance:
try:
spack.spec_parser.parse(spec_str)
except SpecSyntaxError:
yield jsonschema.ValidationError(f"the key '{spec_str}' is not a valid spec")
properties = schema.get("properties") or {}
def _deprecated_properties(validator, deprecated, instance, schema):
if not (validator.is_type(instance, "object") or validator.is_type(instance, "array")):
return
if not deprecated:
return
deprecations = {
name: DeprecationMessage(message=x["message"], error=x["error"])
for x in deprecated
for name in x["names"]
}
# Get a list of the deprecated properties, return if there is none
issues = [entry for entry in instance if entry in deprecations]
if not issues:
return
# Process issues
errors = []
for name in issues:
msg = deprecations[name].message.format(name=name)
if deprecations[name].error:
errors.append(msg)
else:
warnings.warn(msg)
if errors:
yield jsonschema.ValidationError("\n".join(errors))
return jsonschema.validators.extend(
jsonschema.Draft7Validator,
{"validate_spec": _validate_spec, "deprecatedProperties": _deprecated_properties},
)
for spec_str in instance:
if spec_str in properties:
continue
try:
spack.spec_parser.parse(spec_str)
except SpecSyntaxError:
yield jsonschema.ValidationError(f"the key '{spec_str}' is not a valid spec")
Validator = llnl.util.lang.Singleton(_make_validator)
def _deprecated_properties(validator, deprecated, instance, schema):
if not (validator.is_type(instance, "object") or validator.is_type(instance, "array")):
return
if not deprecated:
return
deprecations = {
name: DeprecationMessage(message=x["message"], error=x["error"])
for x in deprecated
for name in x["names"]
}
# Get a list of the deprecated properties, return if there is none
issues = [entry for entry in instance if entry in deprecations]
if not issues:
return
# Process issues
errors = []
for name in issues:
msg = deprecations[name].message.format(name=name)
if deprecations[name].error:
errors.append(msg)
else:
warnings.warn(msg)
if errors:
yield jsonschema.ValidationError("\n".join(errors))
Validator = jsonschema.validators.extend(
jsonschema.Draft7Validator,
{"additionalKeysAreSpecs": _validate_spec, "deprecatedProperties": _deprecated_properties},
)
def _append(string: str) -> bool:

View File

@@ -84,9 +84,14 @@
"duplicates": {
"type": "object",
"properties": {
"strategy": {"type": "string", "enum": ["none", "minimal", "full"]}
"strategy": {"type": "string", "enum": ["none", "minimal", "full"]},
"max_dupes": {
"type": "object",
"additional_properties": {"type": "integer", "minimum": 1},
},
},
},
"static_analysis": {"type": "boolean"},
"timeout": {"type": "integer", "minimum": 0},
"error_on_timeout": {"type": "boolean"},
"os_compatible": {"type": "object", "additionalProperties": {"type": "array"}},

View File

@@ -58,6 +58,15 @@
{"type": "string"}, # deprecated
]
},
"concretization_cache": {
"type": "object",
"properties": {
"enable": {"type": "boolean"},
"url": {"type": "string"},
"entry_limit": {"type": "integer", "minimum": 0},
"size_limit": {"type": "integer", "minimum": 0},
},
},
"install_hash_length": {"type": "integer", "minimum": 1},
"install_path_scheme": {"type": "string"}, # deprecated
"build_stage": {

View File

@@ -3,12 +3,12 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""Schema for Cray descriptive manifest: this describes a set of
installed packages on the system and also specifies dependency
relationships between them (so this provides more information than
external entries in packages configuration).
installed packages on the system and also specifies dependency
relationships between them (so this provides more information than
external entries in packages configuration).
This does not specify a configuration - it is an input format
that is consumed and transformed into Spack DB records.
This does not specify a configuration - it is an input format
that is consumed and transformed into Spack DB records.
"""
from typing import Any, Dict

View File

@@ -29,11 +29,7 @@
# merged configuration scope schemas
spack.schema.merged.properties,
# extra environment schema properties
{
"include": {"type": "array", "default": [], "items": {"type": "string"}},
"specs": spec_list_schema,
"include_concrete": include_concrete,
},
{"specs": spec_list_schema, "include_concrete": include_concrete},
),
}
}

View File

@@ -0,0 +1,41 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""Schema for include.yaml configuration file.
.. literalinclude:: _spack_root/lib/spack/spack/schema/include.py
:lines: 12-
"""
from typing import Any, Dict
#: Properties for inclusion in other schemas
properties: Dict[str, Any] = {
"include": {
"type": "array",
"default": [],
"additionalProperties": False,
"items": {
"anyOf": [
{
"type": "object",
"properties": {
"when": {"type": "string"},
"path": {"type": "string"},
"sha256": {"type": "string"},
"optional": {"type": "boolean"},
},
"required": ["path"],
"additionalProperties": False,
},
{"type": "string"},
]
},
}
}
#: Full schema with metadata
schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Spack include configuration file schema",
"properties": properties,
}

View File

@@ -21,6 +21,7 @@
import spack.schema.definitions
import spack.schema.develop
import spack.schema.env_vars
import spack.schema.include
import spack.schema.mirrors
import spack.schema.modules
import spack.schema.packages
@@ -40,6 +41,7 @@
spack.schema.definitions.properties,
spack.schema.develop.properties,
spack.schema.env_vars.properties,
spack.schema.include.properties,
spack.schema.mirrors.properties,
spack.schema.modules.properties,
spack.schema.packages.properties,
@@ -48,7 +50,6 @@
spack.schema.view.properties,
)
#: Full schema with metadata
schema = {
"$schema": "http://json-schema.org/draft-07/schema#",

View File

@@ -39,7 +39,7 @@
"load": array_of_strings,
"suffixes": {
"type": "object",
"validate_spec": True,
"additionalKeysAreSpecs": True,
"additionalProperties": {"type": "string"}, # key
},
"environment": spack.schema.environment.definition,
@@ -48,40 +48,44 @@
projections_scheme = spack.schema.projections.properties["projections"]
module_type_configuration: Dict = {
common_props = {
"verbose": {"type": "boolean", "default": False},
"hash_length": {"type": "integer", "minimum": 0, "default": 7},
"include": array_of_strings,
"exclude": array_of_strings,
"exclude_implicits": {"type": "boolean", "default": False},
"defaults": array_of_strings,
"hide_implicits": {"type": "boolean", "default": False},
"naming_scheme": {"type": "string"},
"projections": projections_scheme,
"all": module_file_configuration,
}
tcl_configuration = {
"type": "object",
"default": {},
"validate_spec": True,
"properties": {
"verbose": {"type": "boolean", "default": False},
"hash_length": {"type": "integer", "minimum": 0, "default": 7},
"include": array_of_strings,
"exclude": array_of_strings,
"exclude_implicits": {"type": "boolean", "default": False},
"defaults": array_of_strings,
"hide_implicits": {"type": "boolean", "default": False},
"naming_scheme": {"type": "string"},
"projections": projections_scheme,
"all": module_file_configuration,
},
"additionalKeysAreSpecs": True,
"properties": {**common_props},
"additionalProperties": module_file_configuration,
}
tcl_configuration = module_type_configuration.copy()
lmod_configuration = module_type_configuration.copy()
lmod_configuration["properties"].update(
{
lmod_configuration = {
"type": "object",
"default": {},
"additionalKeysAreSpecs": True,
"properties": {
**common_props,
"core_compilers": array_of_strings,
"hierarchy": array_of_strings,
"core_specs": array_of_strings,
"filter_hierarchy_specs": {
"type": "object",
"validate_spec": True,
"additionalKeysAreSpecs": True,
"additionalProperties": array_of_strings,
},
}
)
},
"additionalProperties": module_file_configuration,
}
module_config_properties = {
"use_view": {"anyOf": [{"type": "string"}, {"type": "boolean"}]},

File diff suppressed because it is too large Load Diff

View File

@@ -265,6 +265,7 @@ error(100, "Cannot select a single version for virtual '{0}'", Virtual)
% If we select a deprecated version, mark the package as deprecated
attr("deprecated", node(ID, Package), Version) :-
attr("version", node(ID, Package), Version),
not external(node(ID, Package)),
pkg_fact(Package, deprecated_version(Version)).
error(100, "Package '{0}' needs the deprecated version '{1}', and this is not allowed", Package, Version)
@@ -523,6 +524,16 @@ error(10, "'{0}' is not a valid dependency for any package in the DAG", Package)
:- attr("node", node(ID, Package)),
not needed(node(ID, Package)).
% Extensions depending on each other must all extend the same node (e.g. all Python packages
% depending on each other must depend on the same Python interpreter)
error(100, "{0} and {1} must depend on the same {2}", ExtensionParent, ExtensionChild, ExtendeePackage)
:- depends_on(ExtensionParent, ExtensionChild),
attr("extends", ExtensionParent, ExtendeePackage),
depends_on(ExtensionParent, node(X, ExtendeePackage)),
depends_on(ExtensionChild, node(Y, ExtendeePackage)),
X != Y.
#defined dependency_type/2.
%-----------------------------------------------------------------------------

View File

@@ -1,179 +0,0 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import collections
from typing import List, Set
from llnl.util import lang
import spack.deptypes as dt
import spack.package_base
import spack.repo
import spack.spec
PossibleDependencies = Set[str]
class Counter:
"""Computes the possible packages and the maximum number of duplicates
allowed for each of them.
Args:
specs: abstract specs to concretize
tests: if True, add test dependencies to the list of possible packages
"""
def __init__(self, specs: List["spack.spec.Spec"], tests: bool) -> None:
runtime_pkgs = spack.repo.PATH.packages_with_tags("runtime")
runtime_virtuals = set()
for x in runtime_pkgs:
pkg_class = spack.repo.PATH.get_pkg_class(x)
runtime_virtuals.update(pkg_class.provided_virtual_names())
self.specs = specs + [spack.spec.Spec(x) for x in runtime_pkgs]
self.link_run_types: dt.DepFlag = dt.LINK | dt.RUN | dt.TEST
self.all_types: dt.DepFlag = dt.ALL
if not tests:
self.link_run_types = dt.LINK | dt.RUN
self.all_types = dt.LINK | dt.RUN | dt.BUILD
self._possible_dependencies: PossibleDependencies = set()
self._possible_virtuals: Set[str] = (
set(x.name for x in specs if x.virtual) | runtime_virtuals
)
def possible_dependencies(self) -> PossibleDependencies:
"""Returns the list of possible dependencies"""
self.ensure_cache_values()
return self._possible_dependencies
def possible_virtuals(self) -> Set[str]:
"""Returns the list of possible virtuals"""
self.ensure_cache_values()
return self._possible_virtuals
def ensure_cache_values(self) -> None:
"""Ensure the cache values have been computed"""
if self._possible_dependencies:
return
self._compute_cache_values()
def possible_packages_facts(self, gen: "spack.solver.asp.PyclingoDriver", fn) -> None:
"""Emit facts associated with the possible packages"""
raise NotImplementedError("must be implemented by derived classes")
def _compute_cache_values(self):
raise NotImplementedError("must be implemented by derived classes")
class NoDuplicatesCounter(Counter):
def _compute_cache_values(self):
result = spack.package_base.possible_dependencies(
*self.specs, virtuals=self._possible_virtuals, depflag=self.all_types
)
self._possible_dependencies = set(result)
def possible_packages_facts(self, gen, fn):
gen.h2("Maximum number of nodes (packages)")
for package_name in sorted(self.possible_dependencies()):
gen.fact(fn.max_dupes(package_name, 1))
gen.newline()
gen.h2("Maximum number of nodes (virtual packages)")
for package_name in sorted(self.possible_virtuals()):
gen.fact(fn.max_dupes(package_name, 1))
gen.newline()
gen.h2("Possible package in link-run subDAG")
for name in sorted(self.possible_dependencies()):
gen.fact(fn.possible_in_link_run(name))
gen.newline()
class MinimalDuplicatesCounter(NoDuplicatesCounter):
def __init__(self, specs, tests):
super().__init__(specs, tests)
self._link_run: PossibleDependencies = set()
self._direct_build: PossibleDependencies = set()
self._total_build: PossibleDependencies = set()
self._link_run_virtuals: Set[str] = set()
def _compute_cache_values(self):
self._link_run = set(
spack.package_base.possible_dependencies(
*self.specs, virtuals=self._possible_virtuals, depflag=self.link_run_types
)
)
self._link_run_virtuals.update(self._possible_virtuals)
for x in self._link_run:
build_dependencies = spack.repo.PATH.get_pkg_class(x).dependencies_of_type(dt.BUILD)
virtuals, reals = lang.stable_partition(
build_dependencies, spack.repo.PATH.is_virtual_safe
)
self._possible_virtuals.update(virtuals)
for virtual_dep in virtuals:
providers = spack.repo.PATH.providers_for(virtual_dep)
self._direct_build.update(str(x) for x in providers)
self._direct_build.update(reals)
self._total_build = set(
spack.package_base.possible_dependencies(
*self._direct_build, virtuals=self._possible_virtuals, depflag=self.all_types
)
)
self._possible_dependencies = set(self._link_run) | set(self._total_build)
def possible_packages_facts(self, gen, fn):
build_tools = spack.repo.PATH.packages_with_tags("build-tools")
gen.h2("Packages with at most a single node")
for package_name in sorted(self.possible_dependencies() - build_tools):
gen.fact(fn.max_dupes(package_name, 1))
gen.newline()
gen.h2("Packages with at multiple possible nodes (build-tools)")
for package_name in sorted(self.possible_dependencies() & build_tools):
gen.fact(fn.max_dupes(package_name, 2))
gen.fact(fn.multiple_unification_sets(package_name))
gen.newline()
gen.h2("Maximum number of nodes (virtual packages)")
for package_name in sorted(self.possible_virtuals()):
gen.fact(fn.max_dupes(package_name, 1))
gen.newline()
gen.h2("Possible package in link-run subDAG")
for name in sorted(self._link_run):
gen.fact(fn.possible_in_link_run(name))
gen.newline()
class FullDuplicatesCounter(MinimalDuplicatesCounter):
def possible_packages_facts(self, gen, fn):
build_tools = spack.repo.PATH.packages_with_tags("build-tools")
counter = collections.Counter(
list(self._link_run) + list(self._total_build) + list(self._direct_build)
)
gen.h2("Maximum number of nodes")
for pkg, count in sorted(counter.items(), key=lambda x: (x[1], x[0])):
count = min(count, 2)
gen.fact(fn.max_dupes(pkg, count))
gen.newline()
gen.h2("Build unification sets ")
for name in sorted(self.possible_dependencies() & build_tools):
gen.fact(fn.multiple_unification_sets(name))
gen.newline()
gen.h2("Possible package in link-run subDAG")
for name in sorted(self._link_run):
gen.fact(fn.possible_in_link_run(name))
gen.newline()
counter = collections.Counter(
list(self._link_run_virtuals) + list(self._possible_virtuals)
)
gen.h2("Maximum number of virtual nodes")
for pkg, count in sorted(counter.items(), key=lambda x: (x[1], x[0])):
gen.fact(fn.max_dupes(pkg, count))
gen.newline()

View File

@@ -0,0 +1,539 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""Classes to analyze the input of a solve, and provide information to set up the ASP problem"""
import collections
from typing import Dict, List, NamedTuple, Set, Tuple, Union
import archspec.cpu
from llnl.util import lang, tty
import spack.binary_distribution
import spack.config
import spack.deptypes as dt
import spack.platforms
import spack.repo
import spack.spec
import spack.store
from spack.error import SpackError
RUNTIME_TAG = "runtime"
class PossibleGraph(NamedTuple):
real_pkgs: Set[str]
virtuals: Set[str]
edges: Dict[str, Set[str]]
class PossibleDependencyGraph:
"""Returns information needed to set up an ASP problem"""
def unreachable(self, *, pkg_name: str, when_spec: spack.spec.Spec) -> bool:
"""Returns true if the context can determine that the condition cannot ever
be met on pkg_name.
"""
raise NotImplementedError
def candidate_targets(self) -> List[archspec.cpu.Microarchitecture]:
"""Returns a list of targets that are candidate for concretization"""
raise NotImplementedError
def possible_dependencies(
self,
*specs: Union[spack.spec.Spec, str],
allowed_deps: dt.DepFlag,
transitive: bool = True,
strict_depflag: bool = False,
expand_virtuals: bool = True,
) -> PossibleGraph:
"""Returns the set of possible dependencies, and the set of possible virtuals.
Both sets always include runtime packages, which may be injected by compilers.
Args:
transitive: return transitive dependencies if True, only direct dependencies if False
allowed_deps: dependency types to consider
strict_depflag: if True, only the specific dep type is considered, if False any
deptype that intersects with allowed deptype is considered
expand_virtuals: expand virtual dependencies into all possible implementations
"""
raise NotImplementedError
class NoStaticAnalysis(PossibleDependencyGraph):
"""Implementation that tries to minimize the setup time (i.e. defaults to give fast
answers), rather than trying to reduce the ASP problem size with more complex analysis.
"""
def __init__(self, *, configuration: spack.config.Configuration, repo: spack.repo.RepoPath):
self.configuration = configuration
self.repo = repo
self.runtime_pkgs = set(self.repo.packages_with_tags(RUNTIME_TAG))
self.runtime_virtuals = set()
self._platform_condition = spack.spec.Spec(
f"platform={spack.platforms.host()} target={archspec.cpu.host().family}:"
)
for x in self.runtime_pkgs:
pkg_class = self.repo.get_pkg_class(x)
self.runtime_virtuals.update(pkg_class.provided_virtual_names())
try:
self.libc_pkgs = [x.name for x in self.providers_for("libc")]
except spack.repo.UnknownPackageError:
self.libc_pkgs = []
def is_virtual(self, name: str) -> bool:
return self.repo.is_virtual(name)
@lang.memoized
def is_allowed_on_this_platform(self, *, pkg_name: str) -> bool:
"""Returns true if a package is allowed on the current host"""
pkg_cls = self.repo.get_pkg_class(pkg_name)
for when_spec, conditions in pkg_cls.requirements.items():
if not when_spec.intersects(self._platform_condition):
continue
for requirements, _, _ in conditions:
if not any(x.intersects(self._platform_condition) for x in requirements):
tty.debug(f"[{__name__}] {pkg_name} is not for this platform")
return False
return True
def providers_for(self, virtual_str: str) -> List[spack.spec.Spec]:
"""Returns a list of possible providers for the virtual string in input."""
return self.repo.providers_for(virtual_str)
def can_be_installed(self, *, pkg_name) -> bool:
"""Returns True if a package can be installed, False otherwise."""
return True
def unreachable(self, *, pkg_name: str, when_spec: spack.spec.Spec) -> bool:
"""Returns true if the context can determine that the condition cannot ever
be met on pkg_name.
"""
return False
def candidate_targets(self) -> List[archspec.cpu.Microarchitecture]:
"""Returns a list of targets that are candidate for concretization"""
platform = spack.platforms.host()
default_target = archspec.cpu.TARGETS[platform.default]
# Construct the list of targets which are compatible with the host
candidate_targets = [default_target] + default_target.ancestors
granularity = self.configuration.get("concretizer:targets:granularity")
host_compatible = self.configuration.get("concretizer:targets:host_compatible")
# Add targets which are not compatible with the current host
if not host_compatible:
additional_targets_in_family = sorted(
[
t
for t in archspec.cpu.TARGETS.values()
if (t.family.name == default_target.family.name and t not in candidate_targets)
],
key=lambda x: len(x.ancestors),
reverse=True,
)
candidate_targets += additional_targets_in_family
# Check if we want only generic architecture
if granularity == "generic":
candidate_targets = [t for t in candidate_targets if t.vendor == "generic"]
return candidate_targets
def possible_dependencies(
self,
*specs: Union[spack.spec.Spec, str],
allowed_deps: dt.DepFlag,
transitive: bool = True,
strict_depflag: bool = False,
expand_virtuals: bool = True,
) -> PossibleGraph:
stack = [x for x in self._package_list(specs)]
virtuals: Set[str] = set()
edges: Dict[str, Set[str]] = {}
while stack:
pkg_name = stack.pop()
if pkg_name in edges:
continue
edges[pkg_name] = set()
# Since libc is not buildable, there is no need to extend the
# search space with libc dependencies.
if pkg_name in self.libc_pkgs:
continue
pkg_cls = self.repo.get_pkg_class(pkg_name=pkg_name)
for name, conditions in pkg_cls.dependencies_by_name(when=True).items():
if all(self.unreachable(pkg_name=pkg_name, when_spec=x) for x in conditions):
tty.debug(
f"[{__name__}] Not adding {name} as a dep of {pkg_name}, because "
f"conditions cannot be met"
)
continue
if not self._has_deptypes(
conditions, allowed_deps=allowed_deps, strict=strict_depflag
):
continue
if name in virtuals:
continue
dep_names = set()
if self.is_virtual(name):
virtuals.add(name)
if expand_virtuals:
providers = self.providers_for(name)
dep_names = {spec.name for spec in providers}
else:
dep_names = {name}
edges[pkg_name].update(dep_names)
if not transitive:
continue
for dep_name in dep_names:
if dep_name in edges:
continue
if not self._is_possible(pkg_name=dep_name):
continue
stack.append(dep_name)
real_packages = set(edges)
if not transitive:
# We exit early, so add children from the edges information
for root, children in edges.items():
real_packages.update(x for x in children if self._is_possible(pkg_name=x))
virtuals.update(self.runtime_virtuals)
real_packages = real_packages | self.runtime_pkgs
return PossibleGraph(real_pkgs=real_packages, virtuals=virtuals, edges=edges)
def _package_list(self, specs: Tuple[Union[spack.spec.Spec, str], ...]) -> List[str]:
stack = []
for current_spec in specs:
if isinstance(current_spec, str):
current_spec = spack.spec.Spec(current_spec)
if self.repo.is_virtual(current_spec.name):
stack.extend([p.name for p in self.providers_for(current_spec.name)])
continue
stack.append(current_spec.name)
return sorted(set(stack))
def _has_deptypes(self, dependencies, *, allowed_deps: dt.DepFlag, strict: bool) -> bool:
if strict is True:
return any(
dep.depflag == allowed_deps for deplist in dependencies.values() for dep in deplist
)
return any(
dep.depflag & allowed_deps for deplist in dependencies.values() for dep in deplist
)
def _is_possible(self, *, pkg_name):
try:
return self.is_allowed_on_this_platform(pkg_name=pkg_name) and self.can_be_installed(
pkg_name=pkg_name
)
except spack.repo.UnknownPackageError:
return False
class StaticAnalysis(NoStaticAnalysis):
"""Performs some static analysis of the configuration, store, etc. to provide more precise
answers on whether some packages can be installed, or used as a provider.
It increases the setup time, but might decrease the grounding and solve time considerably,
especially when requirements restrict the possible choices for providers.
"""
def __init__(
self,
*,
configuration: spack.config.Configuration,
repo: spack.repo.RepoPath,
store: spack.store.Store,
binary_index: spack.binary_distribution.BinaryCacheIndex,
):
super().__init__(configuration=configuration, repo=repo)
self.store = store
self.binary_index = binary_index
@lang.memoized
def providers_for(self, virtual_str: str) -> List[spack.spec.Spec]:
candidates = super().providers_for(virtual_str)
result = []
for spec in candidates:
if not self._is_provider_candidate(pkg_name=spec.name, virtual=virtual_str):
continue
result.append(spec)
return result
@lang.memoized
def buildcache_specs(self) -> List[spack.spec.Spec]:
self.binary_index.update()
return self.binary_index.get_all_built_specs()
@lang.memoized
def can_be_installed(self, *, pkg_name) -> bool:
if self.configuration.get(f"packages:{pkg_name}:buildable", True):
return True
if self.configuration.get(f"packages:{pkg_name}:externals", []):
return True
reuse = self.configuration.get("concretizer:reuse")
if reuse is not False and self.store.db.query(pkg_name):
return True
if reuse is not False and any(x.name == pkg_name for x in self.buildcache_specs()):
return True
tty.debug(f"[{__name__}] {pkg_name} cannot be installed")
return False
@lang.memoized
def _is_provider_candidate(self, *, pkg_name: str, virtual: str) -> bool:
if not self.is_allowed_on_this_platform(pkg_name=pkg_name):
return False
if not self.can_be_installed(pkg_name=pkg_name):
return False
virtual_spec = spack.spec.Spec(virtual)
if self.unreachable(pkg_name=virtual_spec.name, when_spec=pkg_name):
tty.debug(f"[{__name__}] {pkg_name} cannot be a provider for {virtual}")
return False
return True
@lang.memoized
def unreachable(self, *, pkg_name: str, when_spec: spack.spec.Spec) -> bool:
"""Returns true if the context can determine that the condition cannot ever
be met on pkg_name.
"""
candidates = self.configuration.get(f"packages:{pkg_name}:require", [])
if not candidates and pkg_name != "all":
return self.unreachable(pkg_name="all", when_spec=when_spec)
if not candidates:
return False
if isinstance(candidates, str):
candidates = [candidates]
union_requirement = spack.spec.Spec()
for c in candidates:
if not isinstance(c, str):
continue
try:
union_requirement.constrain(c)
except SpackError:
# Less optimized, but shouldn't fail
pass
if not union_requirement.intersects(when_spec):
return True
return False
def create_graph_analyzer() -> PossibleDependencyGraph:
static_analysis = spack.config.CONFIG.get("concretizer:static_analysis", False)
if static_analysis:
return StaticAnalysis(
configuration=spack.config.CONFIG,
repo=spack.repo.PATH,
store=spack.store.STORE,
binary_index=spack.binary_distribution.BINARY_INDEX,
)
return NoStaticAnalysis(configuration=spack.config.CONFIG, repo=spack.repo.PATH)
class Counter:
"""Computes the possible packages and the maximum number of duplicates
allowed for each of them.
Args:
specs: abstract specs to concretize
tests: if True, add test dependencies to the list of possible packages
"""
def __init__(
self, specs: List["spack.spec.Spec"], tests: bool, possible_graph: PossibleDependencyGraph
) -> None:
self.possible_graph = possible_graph
self.specs = specs
self.link_run_types: dt.DepFlag = dt.LINK | dt.RUN | dt.TEST
self.all_types: dt.DepFlag = dt.ALL
if not tests:
self.link_run_types = dt.LINK | dt.RUN
self.all_types = dt.LINK | dt.RUN | dt.BUILD
self._possible_dependencies: Set[str] = set()
self._possible_virtuals: Set[str] = {
x.name for x in specs if spack.repo.PATH.is_virtual(x.name)
}
def possible_dependencies(self) -> Set[str]:
"""Returns the list of possible dependencies"""
self.ensure_cache_values()
return self._possible_dependencies
def possible_virtuals(self) -> Set[str]:
"""Returns the list of possible virtuals"""
self.ensure_cache_values()
return self._possible_virtuals
def ensure_cache_values(self) -> None:
"""Ensure the cache values have been computed"""
if self._possible_dependencies:
return
self._compute_cache_values()
def possible_packages_facts(self, gen: "spack.solver.asp.ProblemInstanceBuilder", fn) -> None:
"""Emit facts associated with the possible packages"""
raise NotImplementedError("must be implemented by derived classes")
def _compute_cache_values(self) -> None:
raise NotImplementedError("must be implemented by derived classes")
class NoDuplicatesCounter(Counter):
def _compute_cache_values(self) -> None:
self._possible_dependencies, virtuals, _ = self.possible_graph.possible_dependencies(
*self.specs, allowed_deps=self.all_types
)
self._possible_virtuals.update(virtuals)
def possible_packages_facts(self, gen: "spack.solver.asp.ProblemInstanceBuilder", fn) -> None:
gen.h2("Maximum number of nodes (packages)")
for package_name in sorted(self.possible_dependencies()):
gen.fact(fn.max_dupes(package_name, 1))
gen.newline()
gen.h2("Maximum number of nodes (virtual packages)")
for package_name in sorted(self.possible_virtuals()):
gen.fact(fn.max_dupes(package_name, 1))
gen.newline()
gen.h2("Possible package in link-run subDAG")
for name in sorted(self.possible_dependencies()):
gen.fact(fn.possible_in_link_run(name))
gen.newline()
class MinimalDuplicatesCounter(NoDuplicatesCounter):
def __init__(
self, specs: List["spack.spec.Spec"], tests: bool, possible_graph: PossibleDependencyGraph
) -> None:
super().__init__(specs, tests, possible_graph)
self._link_run: Set[str] = set()
self._direct_build: Set[str] = set()
self._total_build: Set[str] = set()
self._link_run_virtuals: Set[str] = set()
def _compute_cache_values(self) -> None:
self._link_run, virtuals, _ = self.possible_graph.possible_dependencies(
*self.specs, allowed_deps=self.link_run_types
)
self._possible_virtuals.update(virtuals)
self._link_run_virtuals.update(virtuals)
for x in self._link_run:
reals, virtuals, _ = self.possible_graph.possible_dependencies(
x, allowed_deps=dt.BUILD, transitive=False, strict_depflag=True
)
self._possible_virtuals.update(virtuals)
self._direct_build.update(reals)
self._total_build, virtuals, _ = self.possible_graph.possible_dependencies(
*self._direct_build, allowed_deps=self.all_types
)
self._possible_virtuals.update(virtuals)
self._possible_dependencies = set(self._link_run) | set(self._total_build)
def possible_packages_facts(self, gen, fn):
build_tools = spack.repo.PATH.packages_with_tags("build-tools")
gen.h2("Packages with at most a single node")
for package_name in sorted(self.possible_dependencies() - build_tools):
gen.fact(fn.max_dupes(package_name, 1))
gen.newline()
gen.h2("Packages with at multiple possible nodes (build-tools)")
default = spack.config.CONFIG.get("concretizer:duplicates:max_dupes:default", 2)
for package_name in sorted(self.possible_dependencies() & build_tools):
max_dupes = spack.config.CONFIG.get(
f"concretizer:duplicates:max_dupes:{package_name}", default
)
gen.fact(fn.max_dupes(package_name, max_dupes))
if max_dupes > 1:
gen.fact(fn.multiple_unification_sets(package_name))
gen.newline()
gen.h2("Maximum number of nodes (link-run virtuals)")
for package_name in sorted(self._link_run_virtuals):
gen.fact(fn.max_dupes(package_name, 1))
gen.newline()
gen.h2("Maximum number of nodes (other virtuals)")
for package_name in sorted(self.possible_virtuals() - self._link_run_virtuals):
max_dupes = spack.config.CONFIG.get(
f"concretizer:duplicates:max_dupes:{package_name}", default
)
gen.fact(fn.max_dupes(package_name, max_dupes))
gen.newline()
gen.h2("Possible package in link-run subDAG")
for name in sorted(self._link_run):
gen.fact(fn.possible_in_link_run(name))
gen.newline()
class FullDuplicatesCounter(MinimalDuplicatesCounter):
def possible_packages_facts(self, gen, fn):
build_tools = spack.repo.PATH.packages_with_tags("build-tools")
counter = collections.Counter(
list(self._link_run) + list(self._total_build) + list(self._direct_build)
)
gen.h2("Maximum number of nodes")
for pkg, count in sorted(counter.items(), key=lambda x: (x[1], x[0])):
count = min(count, 2)
gen.fact(fn.max_dupes(pkg, count))
gen.newline()
gen.h2("Build unification sets ")
for name in sorted(self.possible_dependencies() & build_tools):
gen.fact(fn.multiple_unification_sets(name))
gen.newline()
gen.h2("Possible package in link-run subDAG")
for name in sorted(self._link_run):
gen.fact(fn.possible_in_link_run(name))
gen.newline()
counter = collections.Counter(
list(self._link_run_virtuals) + list(self._possible_virtuals)
)
gen.h2("Maximum number of virtual nodes")
for pkg, count in sorted(counter.items(), key=lambda x: (x[1], x[0])):
gen.fact(fn.max_dupes(pkg, count))
gen.newline()
def create_counter(
specs: List[spack.spec.Spec], tests: bool, possible_graph: PossibleDependencyGraph
) -> Counter:
strategy = spack.config.CONFIG.get("concretizer:duplicates:strategy", "none")
if strategy == "full":
return FullDuplicatesCounter(specs, tests=tests, possible_graph=possible_graph)
if strategy == "minimal":
return MinimalDuplicatesCounter(specs, tests=tests, possible_graph=possible_graph)
return NoDuplicatesCounter(specs, tests=tests, possible_graph=possible_graph)

View File

@@ -52,6 +52,7 @@
import enum
import io
import itertools
import json
import os
import pathlib
import platform
@@ -98,7 +99,6 @@
import spack.traverse
import spack.util.executable
import spack.util.hash
import spack.util.module_cmd as md
import spack.util.prefix
import spack.util.spack_json as sjson
import spack.util.spack_yaml as syaml
@@ -798,7 +798,7 @@ def update_deptypes(self, depflag: dt.DepFlag) -> bool:
self.depflag = new
return True
def update_virtuals(self, virtuals: Tuple[str, ...]) -> bool:
def update_virtuals(self, virtuals: Iterable[str]) -> bool:
"""Update the list of provided virtuals"""
old = self.virtuals
self.virtuals = tuple(sorted(set(virtuals).union(self.virtuals)))
@@ -1337,14 +1337,20 @@ class SpecBuildInterface(lang.ObjectWrapper):
"command", default_handler=_command_default_handler, _indirect=True
)
def __init__(self, spec: "Spec", name: str, query_parameters: List[str], _parent: "Spec"):
def __init__(
self,
spec: "Spec",
name: str,
query_parameters: List[str],
_parent: "Spec",
is_virtual: bool,
):
super().__init__(spec)
# Adding new attributes goes after super() call since the ObjectWrapper
# resets __dict__ to behave like the passed object
original_spec = getattr(spec, "wrapped_obj", spec)
self.wrapped_obj = original_spec
self.token = original_spec, name, query_parameters, _parent
is_virtual = spack.repo.PATH.is_virtual(name)
self.token = original_spec, name, query_parameters, _parent, is_virtual
self.last_query = QueryState(
name=name, extra_parameters=query_parameters, isvirtual=is_virtual
)
@@ -1527,9 +1533,8 @@ def __init__(self, spec_like=None, *, external_path=None, external_modules=None)
self._external_path = external_path
self.external_modules = Spec._format_module_list(external_modules)
# This attribute is used to store custom information for
# external specs. None signal that it was not set yet.
self.extra_attributes = None
# This attribute is used to store custom information for external specs.
self.extra_attributes: dict = {}
# This attribute holds the original build copy of the spec if it is
# deployed differently than it was built. None signals that the spec
@@ -1906,10 +1911,22 @@ def package_class(self):
"""Internal package call gets only the class object for a package.
Use this to just get package metadata.
"""
warnings.warn(
"`Spec.package_class` is deprecated and will be removed in version 1.0.0. Use "
"`spack.repo.PATH.get_pkg_class(spec.fullname) instead.",
category=spack.error.SpackAPIWarning,
stacklevel=2,
)
return spack.repo.PATH.get_pkg_class(self.fullname)
@property
def virtual(self):
warnings.warn(
"`Spec.virtual` is deprecated and will be removed in version 1.0.0. Use "
"`spack.repo.PATH.is_virtual(spec.name)` instead.",
category=spack.error.SpackAPIWarning,
stacklevel=2,
)
return spack.repo.PATH.is_virtual(self.name)
@property
@@ -2101,20 +2118,20 @@ def cshort_spec(self):
return self.cformat(spec_format)
@property
def prefix(self):
def prefix(self) -> spack.util.prefix.Prefix:
if not self._concrete:
raise spack.error.SpecError("Spec is not concrete: " + str(self))
raise spack.error.SpecError(f"Spec is not concrete: {self}")
if self._prefix is None:
upstream, record = spack.store.STORE.db.query_by_spec_hash(self.dag_hash())
_, record = spack.store.STORE.db.query_by_spec_hash(self.dag_hash())
if record and record.path:
self.prefix = record.path
self.set_prefix(record.path)
else:
self.prefix = spack.store.STORE.layout.path_for_spec(self)
self.set_prefix(spack.store.STORE.layout.path_for_spec(self))
assert self._prefix is not None
return self._prefix
@prefix.setter
def prefix(self, value):
def set_prefix(self, value: str) -> None:
self._prefix = spack.util.prefix.Prefix(llnl.path.convert_to_platform_path(value))
def spec_hash(self, hash):
@@ -2128,7 +2145,9 @@ def spec_hash(self, hash):
if hash.override is not None:
return hash.override(self)
node_dict = self.to_node_dict(hash=hash)
json_text = sjson.dump(node_dict)
json_text = json.dumps(
node_dict, ensure_ascii=True, indent=None, separators=(",", ":"), sort_keys=False
)
# This implements "frankenhashes", preserving the last 7 characters of the
# original hash when splicing so that we can avoid relocation issues
out = spack.util.hash.b32_hash(json_text)
@@ -2351,15 +2370,10 @@ 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"] = {
"path": self.external_path,
"module": self.external_modules,
"extra_attributes": extra_attributes,
"module": self.external_modules or None,
"extra_attributes": syaml.sorted_dict(self.extra_attributes),
}
if not self._concrete:
@@ -2694,7 +2708,7 @@ def name_and_dependency_types(s: str) -> Tuple[str, dt.DepFlag]:
return name, depflag
def spec_and_dependency_types(
s: Union[Spec, Tuple[Spec, str]]
s: Union[Spec, Tuple[Spec, str]],
) -> Tuple[Spec, dt.DepFlag]:
"""Given a non-string key in the literal, extracts the spec
and its dependency types.
@@ -2723,7 +2737,7 @@ def spec_and_dependency_types(
return spec_builder(spec_dict)
@staticmethod
def from_dict(data):
def from_dict(data) -> "Spec":
"""Construct a spec from JSON/YAML.
Args:
@@ -2746,7 +2760,7 @@ def from_dict(data):
return spec
@staticmethod
def from_yaml(stream):
def from_yaml(stream) -> "Spec":
"""Construct a spec from YAML.
Args:
@@ -2756,7 +2770,7 @@ def from_yaml(stream):
return Spec.from_dict(data)
@staticmethod
def from_json(stream):
def from_json(stream) -> "Spec":
"""Construct a spec from JSON.
Args:
@@ -2766,7 +2780,7 @@ def from_json(stream):
data = sjson.load(stream)
return Spec.from_dict(data)
except Exception as e:
raise sjson.SpackJSONError("error parsing JSON spec:", str(e)) from e
raise sjson.SpackJSONError("error parsing JSON spec:", e) from e
@staticmethod
def extract_json_from_clearsig(data):
@@ -2814,24 +2828,6 @@ def from_detection(
s.extra_attributes = extra_attributes
return s
def validate_detection(self):
"""Validate the detection of an external spec.
This method is used as part of Spack's detection protocol, and is
not meant for client code use.
"""
# Assert that _extra_attributes is a Mapping and not None,
# which likely means the spec was created with Spec.from_detection
msg = 'cannot validate "{0}" since it was not created ' "using Spec.from_detection".format(
self
)
assert isinstance(self.extra_attributes, collections.abc.Mapping), msg
# Validate the spec calling a package specific method
pkg_cls = spack.repo.PATH.get_pkg_class(self.name)
validate_fn = getattr(pkg_cls, "validate_detected_spec", lambda x, y: None)
validate_fn(self, self.extra_attributes)
def _patches_assigned(self):
"""Whether patches have been assigned to this spec by the concretizer."""
# FIXME: _patches_in_order_of_appearance is attached after concretization
@@ -2848,94 +2844,6 @@ def _patches_assigned(self):
return True
@staticmethod
def inject_patches_variant(root):
# This dictionary will store object IDs rather than Specs as keys
# since the Spec __hash__ will change as patches are added to them
spec_to_patches = {}
for s in root.traverse():
# After concretizing, assign namespaces to anything left.
# Note that this doesn't count as a "change". The repository
# configuration is constant throughout a spack run, and
# normalize and concretize evaluate Packages using Repo.get(),
# which respects precedence. So, a namespace assignment isn't
# changing how a package name would have been interpreted and
# we can do it as late as possible to allow as much
# compatibility across repositories as possible.
if s.namespace is None:
s.namespace = spack.repo.PATH.repo_for_pkg(s.name).namespace
if s.concrete:
continue
# Add any patches from the package to the spec.
patches = set()
for cond, patch_list in s.package_class.patches.items():
if s.satisfies(cond):
for patch in patch_list:
patches.add(patch)
if patches:
spec_to_patches[id(s)] = patches
# Also record all patches required on dependencies by
# depends_on(..., patch=...)
for dspec in root.traverse_edges(deptype=all, cover="edges", root=False):
if dspec.spec.concrete:
continue
pkg_deps = dspec.parent.package_class.dependencies
patches = []
for cond, deps_by_name in pkg_deps.items():
if not dspec.parent.satisfies(cond):
continue
dependency = deps_by_name.get(dspec.spec.name)
if not dependency:
continue
for pcond, patch_list in dependency.patches.items():
if dspec.spec.satisfies(pcond):
patches.extend(patch_list)
if patches:
all_patches = spec_to_patches.setdefault(id(dspec.spec), set())
for patch in patches:
all_patches.add(patch)
for spec in root.traverse():
if id(spec) not in spec_to_patches:
continue
patches = list(lang.dedupe(spec_to_patches[id(spec)]))
mvar = spec.variants.setdefault("patches", vt.MultiValuedVariant("patches", ()))
mvar.value = tuple(p.sha256 for p in patches)
# FIXME: Monkey patches mvar to store patches order
full_order_keys = list(tuple(p.ordering_key) + (p.sha256,) for p in patches)
ordered_hashes = sorted(full_order_keys)
tty.debug(
"Ordered hashes [{0}]: ".format(spec.name)
+ ", ".join("/".join(str(e) for e in t) for t in ordered_hashes)
)
mvar._patches_in_order_of_appearance = list(t[-1] for t in ordered_hashes)
@staticmethod
def ensure_external_path_if_external(external_spec):
if external_spec.external_modules and not external_spec.external_path:
compiler = spack.compilers.compiler_for_spec(
external_spec.compiler, external_spec.architecture
)
for mod in compiler.modules:
md.load_module(mod)
# Get the path from the module the package can override the default
# (this is mostly needed for Cray)
pkg_cls = spack.repo.PATH.get_pkg_class(external_spec.name)
package = pkg_cls(external_spec)
external_spec.external_path = getattr(
package, "external_prefix", md.path_from_modules(external_spec.external_modules)
)
@staticmethod
def ensure_no_deprecated(root):
"""Raise if a deprecated spec is in the dag.
@@ -3090,7 +2998,7 @@ def validate_or_raise(self):
# FIXME: raise just the first one encountered
for spec in self.traverse():
# raise an UnknownPackageError if the spec's package isn't real.
if (not spec.virtual) and spec.name:
if spec.name and not spack.repo.PATH.is_virtual(spec.name):
spack.repo.PATH.get_pkg_class(spec.fullname)
# validate compiler in addition to the package name.
@@ -3099,7 +3007,7 @@ def validate_or_raise(self):
raise UnsupportedCompilerError(spec.compiler.name)
# Ensure correctness of variants (if the spec is not virtual)
if not spec.virtual:
if not spack.repo.PATH.is_virtual(spec.name):
Spec.ensure_valid_variants(spec)
substitute_abstract_variants(spec)
@@ -3117,7 +3025,7 @@ def ensure_valid_variants(spec):
if spec.concrete:
return
pkg_cls = spec.package_class
pkg_cls = spack.repo.PATH.get_pkg_class(spec.fullname)
pkg_variants = pkg_cls.variant_names()
# reserved names are variants that may be set on any package
# but are not necessarily recorded by the package's class
@@ -3334,7 +3242,9 @@ def intersects(self, other: Union[str, "Spec"], deps: bool = True) -> bool:
# If the names are different, we need to consider virtuals
if self.name != other.name and self.name and other.name:
if self.virtual and other.virtual:
self_virtual = spack.repo.PATH.is_virtual(self.name)
other_virtual = spack.repo.PATH.is_virtual(other.name)
if self_virtual and other_virtual:
# Two virtual specs intersect only if there are providers for both
lhs = spack.repo.PATH.providers_for(str(self))
rhs = spack.repo.PATH.providers_for(str(other))
@@ -3342,8 +3252,8 @@ def intersects(self, other: Union[str, "Spec"], deps: bool = True) -> bool:
return bool(intersection)
# A provider can satisfy a virtual dependency.
elif self.virtual or other.virtual:
virtual_spec, non_virtual_spec = (self, other) if self.virtual else (other, self)
elif self_virtual or other_virtual:
virtual_spec, non_virtual_spec = (self, other) if self_virtual else (other, self)
try:
# Here we might get an abstract spec
pkg_cls = spack.repo.PATH.get_pkg_class(non_virtual_spec.fullname)
@@ -3413,12 +3323,20 @@ def _intersects_dependencies(self, other):
# These two loops handle cases where there is an overly restrictive
# vpkg in one spec for a provider in the other (e.g., mpi@3: is not
# compatible with mpich2)
for spec in self.virtual_dependencies():
if spec.name in other_index and not other_index.providers_for(spec):
for spec in self.traverse():
if (
spack.repo.PATH.is_virtual(spec.name)
and spec.name in other_index
and not other_index.providers_for(spec)
):
return False
for spec in other.virtual_dependencies():
if spec.name in self_index and not self_index.providers_for(spec):
for spec in other.traverse():
if (
spack.repo.PATH.is_virtual(spec.name)
and spec.name in self_index
and not self_index.providers_for(spec)
):
return False
return True
@@ -3448,7 +3366,9 @@ def satisfies(self, other: Union[str, "Spec"], deps: bool = True) -> bool:
# If the names are different, we need to consider virtuals
if self.name != other.name and self.name and other.name:
# A concrete provider can satisfy a virtual dependency.
if not self.virtual and other.virtual:
if not spack.repo.PATH.is_virtual(self.name) and spack.repo.PATH.is_virtual(
other.name
):
try:
# Here we might get an abstract spec
pkg_cls = spack.repo.PATH.get_pkg_class(self.fullname)
@@ -3516,7 +3436,7 @@ def satisfies(self, other: Union[str, "Spec"], deps: bool = True) -> bool:
lhs_edges: Dict[str, Set[DependencySpec]] = collections.defaultdict(set)
for rhs_edge in other.traverse_edges(root=False, cover="edges"):
# If we are checking for ^mpi we need to verify if there is any edge
if rhs_edge.spec.virtual:
if spack.repo.PATH.is_virtual(rhs_edge.spec.name):
rhs_edge.update_virtuals(virtuals=(rhs_edge.spec.name,))
if not rhs_edge.virtuals:
@@ -3560,10 +3480,6 @@ def satisfies(self, other: Union[str, "Spec"], deps: bool = True) -> bool:
for rhs in other.traverse(root=False)
)
def virtual_dependencies(self):
"""Return list of any virtual deps in this spec."""
return [spec for spec in self.traverse() if spec.virtual]
@property # type: ignore[misc] # decorated prop not supported in mypy
def patches(self):
"""Return patch objects for any patch sha256 sums on this Spec.
@@ -3753,30 +3669,23 @@ def __getitem__(self, name: str):
csv = query_parameters.pop().strip()
query_parameters = re.split(r"\s*,\s*", csv)
order = lambda: itertools.chain(
self.traverse_edges(deptype=dt.LINK, order="breadth", cover="edges"),
self.edges_to_dependencies(depflag=dt.BUILD | dt.RUN | dt.TEST),
self.traverse_edges(deptype=dt.ALL, order="breadth", cover="edges"),
# Consider all direct dependencies and transitive runtime dependencies
order = itertools.chain(
self.edges_to_dependencies(depflag=dt.ALL),
self.traverse_edges(deptype=dt.LINK | dt.RUN, order="breadth", cover="edges"),
)
# Consider runtime dependencies and direct build/test deps before transitive dependencies,
# and prefer matches closest to the root.
try:
child: Spec = next(
e.spec
for e in itertools.chain(
(e for e in order() if e.spec.name == name or name in e.virtuals),
# for historical reasons
(e for e in order() if e.spec.concrete and e.spec.package.provides(name)),
)
)
except StopIteration:
raise KeyError(f"No spec with name {name} in {self}")
edge = next((e for e in order if e.spec.name == name or name in e.virtuals))
except StopIteration as e:
raise KeyError(f"No spec with name {name} in {self}") from e
if self._concrete:
return SpecBuildInterface(child, name, query_parameters, _parent=self)
return SpecBuildInterface(
edge.spec, name, query_parameters, _parent=self, is_virtual=name in edge.virtuals
)
return child
return edge.spec
def __contains__(self, spec):
"""True if this spec or some dependency satisfies the spec.
@@ -3792,8 +3701,11 @@ def __contains__(self, spec):
# if anonymous or same name, we only have to look at the root
if not spec.name or spec.name == self.name:
return self.satisfies(spec)
else:
return any(s.satisfies(spec) for s in self.traverse(root=False))
try:
dep = self[spec.name]
except KeyError:
return False
return dep.satisfies(spec)
def eq_dag(self, other, deptypes=True, vs=None, vo=None):
"""True if the full dependency DAGs of specs are equal."""
@@ -3861,6 +3773,13 @@ def _cmp_iter(self):
for item in self._cmp_node():
yield item
# If there is ever a breaking change to hash computation, whether accidental or purposeful,
# two specs can be identical modulo DAG hash, depending on what time they were concretized
# From the perspective of many operation in Spack (database, build cache, etc) a different
# DAG hash means a different spec. Here we ensure that two otherwise identical specs, one
# serialized before the hash change and one after, are considered different.
yield self.dag_hash() if self.concrete else None
# This needs to be in _cmp_iter so that no specs with different process hashes
# are considered the same by `__hash__` or `__eq__`.
#
@@ -4696,17 +4615,6 @@ def constrain(self, other: "VariantMap") -> bool:
return changed
@property
def concrete(self):
"""Returns True if the spec is concrete in terms of variants.
Returns:
bool: True or False
"""
return self.spec._concrete or all(
v in self for v in self.spec.package_class.variant_names()
)
def copy(self) -> "VariantMap":
clone = VariantMap(self.spec)
for name, variant in self.items():
@@ -4764,14 +4672,14 @@ def substitute_abstract_variants(spec: Spec):
elif name in vt.reserved_names:
continue
variant_defs = spec.package_class.variant_definitions(name)
variant_defs = spack.repo.PATH.get_pkg_class(spec.fullname).variant_definitions(name)
valid_defs = []
for when, vdef in variant_defs:
if when.intersects(spec):
valid_defs.append(vdef)
if not valid_defs:
if name not in spec.package_class.variant_names():
if name not in spack.repo.PATH.get_pkg_class(spec.fullname).variant_names():
unknown.append(name)
else:
whens = [str(when) for when, _ in variant_defs]
@@ -4833,31 +4741,51 @@ def merge_abstract_anonymous_specs(*abstract_specs: Spec):
return merged_spec
def reconstruct_virtuals_on_edges(spec):
"""Reconstruct virtuals on edges. Used to read from old DB and reindex.
def reconstruct_virtuals_on_edges(spec: Spec) -> None:
"""Reconstruct virtuals on edges. Used to read from old DB and reindex."""
virtuals_needed: Dict[str, Set[str]] = {}
virtuals_provided: Dict[str, Set[str]] = {}
for edge in spec.traverse_edges(cover="edges", root=False):
parent_key = edge.parent.dag_hash()
if parent_key not in virtuals_needed:
# Construct which virtuals are needed by parent
virtuals_needed[parent_key] = set()
try:
parent_pkg = edge.parent.package
except Exception as e:
warnings.warn(
f"cannot reconstruct virtual dependencies on {edge.parent.name}: {e}"
)
continue
Args:
spec: spec on which we want to reconstruct virtuals
"""
# Collect all possible virtuals
possible_virtuals = set()
for node in spec.traverse():
try:
possible_virtuals.update({x for x in node.package.dependencies if Spec(x).virtual})
except Exception as e:
warnings.warn(f"cannot reconstruct virtual dependencies on package {node.name}: {e}")
virtuals_needed[parent_key].update(
name
for name, when_deps in parent_pkg.dependencies_by_name(when=True).items()
if spack.repo.PATH.is_virtual(name)
and any(edge.parent.satisfies(x) for x in when_deps)
)
if not virtuals_needed[parent_key]:
continue
# Assume all incoming edges to provider are marked with virtuals=
for vspec in possible_virtuals:
try:
provider = spec[vspec]
except KeyError:
# Virtual not in the DAG
child_key = edge.spec.dag_hash()
if child_key not in virtuals_provided:
virtuals_provided[child_key] = set()
try:
child_pkg = edge.spec.package
except Exception as e:
warnings.warn(
f"cannot reconstruct virtual dependencies on {edge.parent.name}: {e}"
)
continue
virtuals_provided[child_key].update(x.name for x in child_pkg.virtuals_provided)
if not virtuals_provided[child_key]:
continue
for edge in provider.edges_from_dependents():
edge.update_virtuals([vspec])
virtuals_to_add = virtuals_needed[parent_key] & virtuals_provided[child_key]
if virtuals_to_add:
edge.update_virtuals(virtuals_to_add)
class SpecfileReaderBase:
@@ -4908,7 +4836,7 @@ def from_node_dict(cls, node):
spec.external_modules = node["external"]["module"]
if spec.external_modules is False:
spec.external_modules = None
spec.extra_attributes = node["external"].get("extra_attributes", {})
spec.extra_attributes = node["external"].get("extra_attributes") or {}
# specs read in are concrete unless marked abstract
if node.get("concrete", True):
@@ -5202,6 +5130,13 @@ def get_host_environment() -> Dict[str, Any]:
}
def eval_conditional(string):
"""Evaluate conditional definitions using restricted variable scope."""
valid_variables = get_host_environment()
valid_variables.update({"re": re, "env": os.environ})
return eval(string, valid_variables)
class SpecParseError(spack.error.SpecError):
"""Wrapper for ParseError for when we're parsing specs."""

View File

@@ -1,7 +1,7 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
""" Test ABI-based splicing of dependencies """
"""Test ABI-based splicing of dependencies"""
from typing import List

View File

@@ -200,7 +200,11 @@ def dummy_prefix(tmpdir):
@pytest.mark.requires_executables(*required_executables)
@pytest.mark.maybeslow
@pytest.mark.usefixtures(
"default_config", "cache_directory", "install_dir_default_layout", "temporary_mirror"
"default_config",
"cache_directory",
"install_dir_default_layout",
"temporary_mirror",
"mutable_mock_env_path",
)
def test_default_rpaths_create_install_default_layout(temporary_mirror_dir):
"""
@@ -272,7 +276,11 @@ def test_default_rpaths_install_nondefault_layout(temporary_mirror_dir):
@pytest.mark.maybeslow
@pytest.mark.nomockstage
@pytest.mark.usefixtures(
"default_config", "cache_directory", "install_dir_default_layout", "temporary_mirror"
"default_config",
"cache_directory",
"install_dir_default_layout",
"temporary_mirror",
"mutable_mock_env_path",
)
def test_relative_rpaths_install_default_layout(temporary_mirror_dir):
"""
@@ -569,7 +577,6 @@ def test_FetchCacheError_only_accepts_lists_of_errors():
def test_FetchCacheError_pretty_printing_multiple():
e = bindist.FetchCacheError([RuntimeError("Oops!"), TypeError("Trouble!")])
str_e = str(e)
print("'" + str_e + "'")
assert "Multiple errors" in str_e
assert "Error 1: RuntimeError: Oops!" in str_e
assert "Error 2: TypeError: Trouble!" in str_e

View File

@@ -388,7 +388,7 @@ def test_wrapper_variables(
root = spack.concretize.concretize_one("dt-diamond")
for s in root.traverse():
s.prefix = "/{0}-prefix/".format(s.name)
s.set_prefix(f"/{s.name}-prefix/")
dep_pkg = root["dt-diamond-left"].package
dep_lib_paths = ["/test/path/to/ex1.so", "/test/path/to/subdir/ex2.so"]
@@ -396,7 +396,7 @@ def test_wrapper_variables(
dep_libs = LibraryList(dep_lib_paths)
dep2_pkg = root["dt-diamond-right"].package
dep2_pkg.spec.prefix = str(installation_dir_with_headers)
dep2_pkg.spec.set_prefix(str(installation_dir_with_headers))
setattr(dep_pkg, "libs", dep_libs)
try:
@@ -542,7 +542,7 @@ def test_build_jobs_sequential_is_sequential():
spack.config.determine_number_of_jobs(
parallel=False,
max_cpus=8,
config=spack.config.Configuration(
config=spack.config.create_from(
spack.config.InternalConfigScope("command_line", {"config": {"build_jobs": 8}}),
spack.config.InternalConfigScope("defaults", {"config": {"build_jobs": 8}}),
),
@@ -556,7 +556,7 @@ def test_build_jobs_command_line_overrides():
spack.config.determine_number_of_jobs(
parallel=True,
max_cpus=1,
config=spack.config.Configuration(
config=spack.config.create_from(
spack.config.InternalConfigScope("command_line", {"config": {"build_jobs": 10}}),
spack.config.InternalConfigScope("defaults", {"config": {"build_jobs": 1}}),
),
@@ -567,7 +567,7 @@ def test_build_jobs_command_line_overrides():
spack.config.determine_number_of_jobs(
parallel=True,
max_cpus=100,
config=spack.config.Configuration(
config=spack.config.create_from(
spack.config.InternalConfigScope("command_line", {"config": {"build_jobs": 10}}),
spack.config.InternalConfigScope("defaults", {"config": {"build_jobs": 100}}),
),
@@ -581,7 +581,7 @@ def test_build_jobs_defaults():
spack.config.determine_number_of_jobs(
parallel=True,
max_cpus=10,
config=spack.config.Configuration(
config=spack.config.create_from(
spack.config.InternalConfigScope("defaults", {"config": {"build_jobs": 1}})
),
)
@@ -591,7 +591,7 @@ def test_build_jobs_defaults():
spack.config.determine_number_of_jobs(
parallel=True,
max_cpus=10,
config=spack.config.Configuration(
config=spack.config.create_from(
spack.config.InternalConfigScope("defaults", {"config": {"build_jobs": 100}})
),
)

View File

@@ -403,8 +403,8 @@ def test_autoreconf_search_path_args_multiple(default_mock_concretization, tmpdi
aclocal_fst = str(tmpdir.mkdir("fst").mkdir("share").mkdir("aclocal"))
aclocal_snd = str(tmpdir.mkdir("snd").mkdir("share").mkdir("aclocal"))
build_dep_one, build_dep_two = spec.dependencies(deptype="build")
build_dep_one.prefix = str(tmpdir.join("fst"))
build_dep_two.prefix = str(tmpdir.join("snd"))
build_dep_one.set_prefix(str(tmpdir.join("fst")))
build_dep_two.set_prefix(str(tmpdir.join("snd")))
assert spack.build_systems.autotools._autoreconf_search_path_args(spec) == [
"-I",
aclocal_fst,
@@ -422,8 +422,8 @@ def test_autoreconf_search_path_args_skip_automake(default_mock_concretization,
aclocal_snd = str(tmpdir.mkdir("snd").mkdir("share").mkdir("aclocal"))
build_dep_one, build_dep_two = spec.dependencies(deptype="build")
build_dep_one.name = "automake"
build_dep_one.prefix = str(tmpdir.join("fst"))
build_dep_two.prefix = str(tmpdir.join("snd"))
build_dep_one.set_prefix(str(tmpdir.join("fst")))
build_dep_two.set_prefix(str(tmpdir.join("snd")))
assert spack.build_systems.autotools._autoreconf_search_path_args(spec) == ["-I", aclocal_snd]
@@ -434,7 +434,7 @@ def test_autoreconf_search_path_args_external_order(default_mock_concretization,
aclocal_snd = str(tmpdir.mkdir("snd").mkdir("share").mkdir("aclocal"))
build_dep_one, build_dep_two = spec.dependencies(deptype="build")
build_dep_one.external_path = str(tmpdir.join("fst"))
build_dep_two.prefix = str(tmpdir.join("snd"))
build_dep_two.set_prefix(str(tmpdir.join("snd")))
assert spack.build_systems.autotools._autoreconf_search_path_args(spec) == [
"-I",
aclocal_snd,
@@ -447,8 +447,8 @@ def test_autoreconf_search_path_skip_nonexisting(default_mock_concretization, tm
"""Skip -I flags for non-existing directories"""
spec = default_mock_concretization("dttop")
build_dep_one, build_dep_two = spec.dependencies(deptype="build")
build_dep_one.prefix = str(tmpdir.join("fst"))
build_dep_two.prefix = str(tmpdir.join("snd"))
build_dep_one.set_prefix(str(tmpdir.join("fst")))
build_dep_two.set_prefix(str(tmpdir.join("snd")))
assert spack.build_systems.autotools._autoreconf_search_path_args(spec) == []

View File

@@ -210,7 +210,6 @@ def check_args_contents(cc, args, must_contain, must_not_contain):
"""
with set_env(SPACK_TEST_COMMAND="dump-args"):
cc_modified_args = cc(*args, output=str).strip().split("\n")
print(cc_modified_args)
for a in must_contain:
assert a in cc_modified_args
for a in must_not_contain:

View File

@@ -1,8 +1,10 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import io
import os
import subprocess
from urllib.error import HTTPError
import pytest
@@ -15,6 +17,7 @@
import spack.paths as spack_paths
import spack.repo as repo
import spack.util.git
from spack.test.conftest import MockHTTPResponse
pytestmark = [pytest.mark.usefixtures("mock_packages")]
@@ -162,38 +165,8 @@ def test_import_signing_key(mock_gnupghome):
ci.import_signing_key(signing_key)
class FakeWebResponder:
def __init__(self, response_code=200, content_to_read=[]):
self._resp_code = response_code
self._content = content_to_read
self._read = [False for c in content_to_read]
def open(self, request, data=None, timeout=object()):
return self
def getcode(self):
return self._resp_code
def read(self, length=None):
if len(self._content) <= 0:
return None
if not self._read[-1]:
return_content = self._content[-1]
if length:
self._read[-1] = True
else:
self._read.pop()
self._content.pop()
return return_content
self._read.pop()
self._content.pop()
return None
def test_download_and_extract_artifacts(tmpdir, monkeypatch, working_env):
os.environ.update({"GITLAB_PRIVATE_TOKEN": "faketoken"})
def test_download_and_extract_artifacts(tmpdir, monkeypatch):
monkeypatch.setenv("GITLAB_PRIVATE_TOKEN", "faketoken")
url = "https://www.nosuchurlexists.itsfake/artifacts.zip"
working_dir = os.path.join(tmpdir.strpath, "repro")
@@ -201,10 +174,13 @@ def test_download_and_extract_artifacts(tmpdir, monkeypatch, working_env):
spack_paths.test_path, "data", "ci", "gitlab", "artifacts.zip"
)
with open(test_artifacts_path, "rb") as fd:
fake_responder = FakeWebResponder(content_to_read=[fd.read()])
def _urlopen_OK(*args, **kwargs):
with open(test_artifacts_path, "rb") as f:
return MockHTTPResponse(
"200", "OK", {"Content-Type": "application/zip"}, io.BytesIO(f.read())
)
monkeypatch.setattr(ci, "build_opener", lambda handler: fake_responder)
monkeypatch.setattr(ci, "urlopen", _urlopen_OK)
ci.download_and_extract_artifacts(url, working_dir)
@@ -214,7 +190,11 @@ def test_download_and_extract_artifacts(tmpdir, monkeypatch, working_env):
found_install = fs.find(working_dir, "install.sh")
assert len(found_install) == 1
fake_responder._resp_code = 400
def _urlopen_500(*args, **kwargs):
raise HTTPError(url, 500, "Internal Server Error", {}, None)
monkeypatch.setattr(ci, "urlopen", _urlopen_500)
with pytest.raises(spack.error.SpackError):
ci.download_and_extract_artifacts(url, working_dir)
@@ -367,7 +347,6 @@ def test_get_spec_filter_list(mutable_mock_env_path, mutable_mock_repo):
for key, val in expectations.items():
affected_specs = ci.get_spec_filter_list(e1, touched, dependent_traverse_depth=key)
affected_pkg_names = set([s.name for s in affected_specs])
print(f"{key}: {affected_pkg_names}")
assert affected_pkg_names == val

View File

@@ -12,7 +12,7 @@
build_env = SpackCommand("build-env")
@pytest.mark.parametrize("pkg", [("zlib",), ("zlib", "--")])
@pytest.mark.parametrize("pkg", [("pkg-c",), ("pkg-c", "--")])
@pytest.mark.usefixtures("config", "mock_packages", "working_env")
def test_it_just_runs(pkg):
build_env(*pkg)
@@ -38,7 +38,7 @@ def test_build_env_requires_a_spec(args):
@pytest.mark.usefixtures("config", "mock_packages", "working_env")
def test_dump(shell_as, shell, tmpdir):
with tmpdir.as_cwd():
build_env("--dump", _out_file, "zlib")
build_env("--dump", _out_file, "pkg-c")
with open(_out_file, encoding="utf-8") as f:
if shell == "pwsh":
assert any(line.startswith("$Env:PATH") for line in f.readlines())
@@ -51,7 +51,7 @@ def test_dump(shell_as, shell, tmpdir):
@pytest.mark.usefixtures("config", "mock_packages", "working_env")
def test_pickle(tmpdir):
with tmpdir.as_cwd():
build_env("--pickle", _out_file, "zlib")
build_env("--pickle", _out_file, "pkg-c")
environment = pickle.load(open(_out_file, "rb"))
assert isinstance(environment, dict)
assert "PATH" in environment

View File

@@ -148,7 +148,7 @@ def test_update_key_index(
s = spack.concretize.concretize_one("libdwarf")
# Install a package
install(s.name)
install("--fake", s.name)
# Put installed package in the buildcache, which, because we're signing
# it, should result in the public key getting pushed to the buildcache
@@ -178,7 +178,7 @@ def test_buildcache_autopush(tmp_path, install_mockery, mock_fetch):
s = spack.concretize.concretize_one("libdwarf")
# Install and generate build cache index
PackageInstaller([s.package], explicit=True).install()
PackageInstaller([s.package], fake=True, explicit=True).install()
metadata_file = spack.binary_distribution.tarball_name(s, ".spec.json")
@@ -214,13 +214,11 @@ def verify_mirror_contents():
if in_env_pkg in p:
found_pkg = True
if not found_pkg:
print("Expected to find {0} in {1}".format(in_env_pkg, dest_mirror_dir))
assert False
assert found_pkg, f"Expected to find {in_env_pkg} in {dest_mirror_dir}"
# Install a package and put it in the buildcache
s = spack.concretize.concretize_one(out_env_pkg)
install(s.name)
install("--fake", s.name)
buildcache("push", "-u", "-f", src_mirror_url, s.name)
env("create", "test")

View File

@@ -3,6 +3,7 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import argparse
import pathlib
import pytest
@@ -22,7 +23,15 @@
@pytest.fixture
def can_fetch_versions(monkeypatch):
def no_add(monkeypatch):
def add_versions_to_pkg(pkg, version_lines, open_in_editor):
raise AssertionError("Should not be called")
monkeypatch.setattr(spack.cmd.checksum, "add_versions_to_pkg", add_versions_to_pkg)
@pytest.fixture
def can_fetch_versions(monkeypatch, no_add):
"""Fake successful version detection."""
def fetch_remote_versions(pkg, concurrency):
@@ -45,7 +54,7 @@ def url_exists(url, curl=None):
@pytest.fixture
def cannot_fetch_versions(monkeypatch):
def cannot_fetch_versions(monkeypatch, no_add):
"""Fake unsuccessful version detection."""
def fetch_remote_versions(pkg, concurrency):
@@ -88,7 +97,6 @@ def test_checksum_args(arguments, expected):
(["--batch", "preferred-test"], "version of preferred-test"),
(["--latest", "preferred-test"], "Found 1 version"),
(["--preferred", "preferred-test"], "Found 1 version"),
(["--add-to-package", "preferred-test"], "Added 0 new versions to"),
(["--verify", "preferred-test"], "Verified 1 of 1"),
(["--verify", "zlib", "1.2.13"], "1.2.13 [-] No previous checksum"),
],
@@ -271,15 +279,12 @@ def test_checksum_interactive_unrecognized_command():
assert interactive_version_filter(v.copy(), input=input) == v
def test_checksum_versions(mock_packages, can_fetch_versions):
def test_checksum_versions(mock_packages, can_fetch_versions, monkeypatch):
pkg_cls = spack.repo.PATH.get_pkg_class("zlib")
versions = [str(v) for v in pkg_cls.versions]
output = spack_checksum("zlib", *versions)
assert "Found 3 versions" in output
assert "version(" in output
output = spack_checksum("--add-to-package", "zlib", *versions)
assert "Found 3 versions" in output
assert "Added 0 new versions to" in output
def test_checksum_missing_version(mock_packages, cannot_fetch_versions):
@@ -287,7 +292,6 @@ def test_checksum_missing_version(mock_packages, cannot_fetch_versions):
assert "Could not find any remote versions" in output
output = spack_checksum("--add-to-package", "preferred-test", "99.99.99", fail_on_error=False)
assert "Could not find any remote versions" in output
assert "Added 1 new versions to" not in output
def test_checksum_deprecated_version(mock_packages, can_fetch_versions):
@@ -297,8 +301,6 @@ def test_checksum_deprecated_version(mock_packages, can_fetch_versions):
"--add-to-package", "deprecated-versions", "1.1.0", fail_on_error=False
)
assert "Version 1.1.0 is deprecated" in output
# TODO alecbcs: broken assertion.
# assert "Added 0 new versions to" not in output
def test_checksum_url(mock_packages, config):
@@ -337,3 +339,52 @@ def test_checksum_manual_download_fails(mock_packages, monkeypatch):
monkeypatch.setattr(spack.package_base.PackageBase, "download_instr", error)
with pytest.raises(ManualDownloadRequiredError, match=error):
spack_checksum(name, *versions)
def test_upate_package_contents(tmp_path: pathlib.Path):
"""Test that the package.py file is updated with the new versions."""
pkg_path = tmp_path / "package.py"
pkg_path.write_text(
"""\
from spack.package import *
class Zlib(Package):
homepage = "http://zlib.net"
url = "http://zlib.net/fossils/zlib-1.2.11.tar.gz"
version("1.2.11", sha256="c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1")
version("1.2.8", sha256="36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d")
version("1.2.3", sha256="1795c7d067a43174113fdf03447532f373e1c6c57c08d61d9e4e9be5e244b05e")
variant("pic", default=True, description="test")
def install(self, spec, prefix):
make("install")
"""
)
version_lines = """\
version("1.2.13", sha256="abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890")
version("1.2.5", sha256="abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890")
version("1.2.3", sha256="1795c7d067a43174113fdf03447532f373e1c6c57c08d61d9e4e9be5e244b05e")
"""
# two new versions are added
assert spack.cmd.checksum.add_versions_to_pkg(str(pkg_path), version_lines) == 2
assert (
pkg_path.read_text()
== """\
from spack.package import *
class Zlib(Package):
homepage = "http://zlib.net"
url = "http://zlib.net/fossils/zlib-1.2.11.tar.gz"
version("1.2.13", sha256="abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890") # FIXME
version("1.2.11", sha256="c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1")
version("1.2.8", sha256="36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d")
version("1.2.5", sha256="abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890") # FIXME
version("1.2.3", sha256="1795c7d067a43174113fdf03447532f373e1c6c57c08d61d9e4e9be5e244b05e")
variant("pic", default=True, description="test")
def install(self, spec, prefix):
make("install")
"""
)

View File

@@ -28,6 +28,7 @@
from spack.ci.generator_registry import generator
from spack.cmd.ci import FAILED_CREATE_BUILDCACHE_CODE
from spack.database import INDEX_JSON_FILE
from spack.error import SpackError
from spack.schema.buildcache_spec import schema as specfile_schema
from spack.schema.database_index import schema as db_idx_schema
from spack.spec import Spec
@@ -170,7 +171,9 @@ def test_ci_generate_with_env(ci_generate_test, tmp_path, mock_binary_index):
url: https://my.fake.cdash
project: Not used
site: Nothing
"""
""",
"--artifacts-root",
str(tmp_path / "my_artifacts_root"),
)
yaml_contents = syaml.load(outputfile.read_text())
@@ -192,7 +195,7 @@ def test_ci_generate_with_env(ci_generate_test, tmp_path, mock_binary_index):
assert "variables" in yaml_contents
assert "SPACK_ARTIFACTS_ROOT" in yaml_contents["variables"]
assert yaml_contents["variables"]["SPACK_ARTIFACTS_ROOT"] == "jobs_scratch_dir"
assert yaml_contents["variables"]["SPACK_ARTIFACTS_ROOT"] == "my_artifacts_root"
def test_ci_generate_with_env_missing_section(ci_generate_test, tmp_path, mock_binary_index):
@@ -1062,7 +1065,7 @@ def test_ci_rebuild_index(
with open(tmp_path / "spec.json", "w", encoding="utf-8") as f:
f.write(concrete_spec.to_json(hash=ht.dag_hash))
install_cmd("--add", "-f", str(tmp_path / "spec.json"))
install_cmd("--fake", "--add", "-f", str(tmp_path / "spec.json"))
buildcache_cmd("push", "-u", "-f", mirror_url, "callpath")
ci_cmd("rebuild-index")
@@ -1322,44 +1325,50 @@ def test_ci_reproduce(
env.concretize()
env.write()
repro_dir.mkdir()
def fake_download_and_extract_artifacts(url, work_dir, merge_commit_test=True):
with working_dir(tmp_path), ev.Environment(".") as env:
if not os.path.exists(repro_dir):
repro_dir.mkdir()
job_spec = env.concrete_roots()[0]
with open(repro_dir / "archivefiles.json", "w", encoding="utf-8") as f:
f.write(job_spec.to_json(hash=ht.dag_hash))
job_spec = env.concrete_roots()[0]
with open(repro_dir / "archivefiles.json", "w", encoding="utf-8") as f:
f.write(job_spec.to_json(hash=ht.dag_hash))
artifacts_root = repro_dir / "jobs_scratch_dir"
pipeline_path = artifacts_root / "pipeline.yml"
artifacts_root = repro_dir / "scratch_dir"
pipeline_path = artifacts_root / "pipeline.yml"
ci_cmd(
"generate",
"--output-file",
str(pipeline_path),
"--artifacts-root",
str(artifacts_root),
)
job_name = gitlab_generator.get_job_name(job_spec)
with open(repro_dir / "repro.json", "w", encoding="utf-8") as f:
f.write(
json.dumps(
{
"job_name": job_name,
"job_spec_json": "archivefiles.json",
"ci_project_dir": str(repro_dir),
}
ci_cmd(
"generate",
"--output-file",
str(pipeline_path),
"--artifacts-root",
str(artifacts_root),
)
)
with open(repro_dir / "install.sh", "w", encoding="utf-8") as f:
f.write("#!/bin/sh\n\n#fake install\nspack install blah\n")
job_name = gitlab_generator.get_job_name(job_spec)
with open(repro_dir / "spack_info.txt", "w", encoding="utf-8") as f:
f.write(f"\nMerge {last_two_git_commits[1]} into {last_two_git_commits[0]}\n\n")
with open(repro_dir / "repro.json", "w", encoding="utf-8") as f:
f.write(
json.dumps(
{
"job_name": job_name,
"job_spec_json": "archivefiles.json",
"ci_project_dir": str(repro_dir),
}
)
)
def fake_download_and_extract_artifacts(url, work_dir):
pass
with open(repro_dir / "install.sh", "w", encoding="utf-8") as f:
f.write("#!/bin/sh\n\n#fake install\nspack install blah\n")
with open(repro_dir / "spack_info.txt", "w", encoding="utf-8") as f:
if merge_commit_test:
f.write(
f"\nMerge {last_two_git_commits[1]} into {last_two_git_commits[0]}\n\n"
)
else:
f.write(f"\ncommit {last_two_git_commits[1]}\n\n")
return "jobs_scratch_dir"
monkeypatch.setattr(ci, "download_and_extract_artifacts", fake_download_and_extract_artifacts)
rep_out = ci_cmd(
@@ -1375,6 +1384,64 @@ def fake_download_and_extract_artifacts(url, work_dir):
# Make sure we tell the user where it is when not in interactive mode
assert f"$ {repro_dir}/start.sh" in rep_out
# Ensure the correct commits are used
assert f"checkout_commit: {last_two_git_commits[0]}" in rep_out
assert f"merge_commit: {last_two_git_commits[1]}" in rep_out
# Test re-running in dirty working dir
with pytest.raises(SpackError, match=f"{repro_dir}"):
rep_out = ci_cmd(
"reproduce-build",
"https://example.com/api/v1/projects/1/jobs/2/artifacts",
"--working-dir",
str(repro_dir),
output=str,
)
# Cleanup between tests
shutil.rmtree(repro_dir)
# Test --use-local-head
rep_out = ci_cmd(
"reproduce-build",
"https://example.com/api/v1/projects/1/jobs/2/artifacts",
"--use-local-head",
"--working-dir",
str(repro_dir),
output=str,
)
# Make sure we are checkout out the HEAD commit without a merge commit
assert "checkout_commit: HEAD" in rep_out
assert "merge_commit: None" in rep_out
# Test the case where the spack_info.txt is not a merge commit
monkeypatch.setattr(
ci,
"download_and_extract_artifacts",
lambda url, wd: fake_download_and_extract_artifacts(url, wd, False),
)
# Cleanup between tests
shutil.rmtree(repro_dir)
rep_out = ci_cmd(
"reproduce-build",
"https://example.com/api/v1/projects/1/jobs/2/artifacts",
"--working-dir",
str(repro_dir),
output=str,
)
# Make sure the script was generated
assert (repro_dir / "start.sh").exists()
# Make sure we tell the user where it is when not in interactive mode
assert f"$ {repro_dir}/start.sh" in rep_out
# Ensure the correct commit is used (different than HEAD)
assert f"checkout_commit: {last_two_git_commits[1]}" in rep_out
assert "merge_commit: None" in rep_out
@pytest.mark.parametrize(
"url_in,url_out",

View File

@@ -5,6 +5,7 @@
import filecmp
import os
import shutil
import textwrap
import pytest
@@ -259,15 +260,25 @@ def test_update_completion_arg(shell, tmpdir, monkeypatch):
def test_updated_completion_scripts(shell, tmpdir):
"""Make sure our shell tab completion scripts remain up-to-date."""
msg = (
width = 72
lines = textwrap.wrap(
"It looks like Spack's command-line interface has been modified. "
"Please update Spack's shell tab completion scripts by running:\n\n"
" spack commands --update-completion\n\n"
"and adding the changed files to your pull request."
"If differences are more than your global 'include:' scopes, please "
"update Spack's shell tab completion scripts by running:",
width,
)
lines.append("\n spack commands --update-completion\n")
lines.extend(
textwrap.wrap(
"and adding the changed files (minus your global 'include:' scopes) "
"to your pull request.",
width,
)
)
msg = "\n".join(lines)
header = os.path.join(spack.paths.share_path, shell, f"spack-completion.{shell}")
script = "spack-completion.{0}".format(shell)
script = f"spack-completion.{shell}"
old_script = os.path.join(spack.paths.share_path, script)
new_script = str(tmpdir.join(script))

View File

@@ -213,7 +213,7 @@ def test_config_add_update_dict(mutable_empty_config):
def test_config_with_c_argument(mutable_empty_config):
# I don't know how to add a spack argument to a Spack Command, so we test this way
config_file = "config:install_root:root:/path/to/config.yaml"
config_file = "config:install_tree:root:/path/to/config.yaml"
parser = spack.main.make_argument_parser()
args = parser.parse_args(["-c", config_file])
assert config_file in args.config_vars
@@ -221,7 +221,7 @@ def test_config_with_c_argument(mutable_empty_config):
# Add the path to the config
config("add", args.config_vars[0], scope="command_line")
output = config("get", "config")
assert "config:\n install_root:\n root: /path/to/config.yaml" in output
assert "config:\n install_tree:\n root: /path/to/config.yaml" in output
def test_config_add_ordered_dict(mutable_empty_config):
@@ -335,7 +335,7 @@ def test_config_add_override_leaf_from_file(mutable_empty_config, tmpdir):
def test_config_add_update_dict_from_file(mutable_empty_config, tmpdir):
config("add", "packages:all:compiler:[gcc]")
config("add", "packages:all:require:['%gcc']")
# contents to add to file
contents = """spack:
@@ -357,7 +357,7 @@ def test_config_add_update_dict_from_file(mutable_empty_config, tmpdir):
expected = """packages:
all:
target: [x86_64]
compiler: [gcc]
require: ['%gcc']
"""
assert expected == output
@@ -606,7 +606,6 @@ def test_config_prefer_upstream(
packages = syaml.load(open(cfg_file, encoding="utf-8"))["packages"]
# Make sure only the non-default variants are set.
assert packages["all"] == {"compiler": ["gcc@=10.2.1"]}
assert packages["boost"] == {"variants": "+debug +graph", "version": ["1.63.0"]}
assert packages["dependency-install"] == {"version": ["2.0"]}
# Ensure that neither variant gets listed for hdf5, since they conflict

View File

@@ -2,52 +2,16 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import platform
import pytest
import spack
import spack.platforms
import spack.spec
from spack.database import INDEX_JSON_FILE
from spack.main import SpackCommand
from spack.util.executable import which
debug = SpackCommand("debug")
@pytest.mark.db
def test_create_db_tarball(tmpdir, database):
with tmpdir.as_cwd():
debug("create-db-tarball")
# get the first non-dotfile to avoid coverage files in the directory
files = os.listdir(os.getcwd())
tarball_name = next(
f for f in files if not f.startswith(".") and not f.startswith("tests")
)
# debug command made an archive
assert os.path.exists(tarball_name)
# print contents of archive
tar = which("tar")
contents = tar("tzf", tarball_name, output=str)
# DB file is included
assert INDEX_JSON_FILE in contents
# specfiles from all installs are included
for spec in database.query():
# externals won't have a specfile
if spec.external:
continue
spec_suffix = "%s/.spack/spec.json" % spec.dag_hash()
assert spec_suffix in contents
def test_report():
out = debug("report")
host_platform = spack.platforms.host()

View File

@@ -24,32 +24,24 @@
mpi_deps = ["fake"]
def test_direct_dependencies(mock_packages):
out = dependencies("mpileaks")
actual = set(re.split(r"\s+", out.strip()))
expected = set(["callpath"] + mpis)
assert expected == actual
def test_transitive_dependencies(mock_packages):
out = dependencies("--transitive", "mpileaks")
actual = set(re.split(r"\s+", out.strip()))
expected = set(["callpath", "dyninst", "libdwarf", "libelf"] + mpis + mpi_deps)
assert expected == actual
def test_transitive_dependencies_with_deptypes(mock_packages):
out = dependencies("--transitive", "--deptype=link,run", "dtbuild1")
deps = set(re.split(r"\s+", out.strip()))
assert set(["dtlink2", "dtrun2"]) == deps
out = dependencies("--transitive", "--deptype=build", "dtbuild1")
deps = set(re.split(r"\s+", out.strip()))
assert set(["dtbuild2", "dtlink2"]) == deps
out = dependencies("--transitive", "--deptype=link", "dtbuild1")
deps = set(re.split(r"\s+", out.strip()))
assert set(["dtlink2"]) == deps
@pytest.mark.parametrize(
"cli_args,expected",
[
(["mpileaks"], set(["callpath"] + mpis)),
(
["--transitive", "mpileaks"],
set(["callpath", "dyninst", "libdwarf", "libelf"] + mpis + mpi_deps),
),
(["--transitive", "--deptype=link,run", "dtbuild1"], {"dtlink2", "dtrun2"}),
(["--transitive", "--deptype=build", "dtbuild1"], {"dtbuild2", "dtlink2"}),
(["--transitive", "--deptype=link", "dtbuild1"], {"dtlink2"}),
],
)
def test_direct_dependencies(cli_args, expected, mock_runtimes):
out = dependencies(*cli_args)
result = set(re.split(r"\s+", out.strip()))
expected.update(mock_runtimes)
assert expected == result
@pytest.mark.db

View File

@@ -15,18 +15,21 @@
deprecate = SpackCommand("deprecate")
find = SpackCommand("find")
# Unit tests should not be affected by the user's managed environments
pytestmark = pytest.mark.usefixtures("mutable_mock_env_path")
def test_deprecate(mock_packages, mock_archive, mock_fetch, install_mockery):
install("libelf@0.8.13")
install("libelf@0.8.10")
install("--fake", "libelf@0.8.13")
install("--fake", "libelf@0.8.10")
all_installed = spack.store.STORE.db.query()
all_installed = spack.store.STORE.db.query("libelf")
assert len(all_installed) == 2
deprecate("-y", "libelf@0.8.10", "libelf@0.8.13")
non_deprecated = spack.store.STORE.db.query()
all_available = spack.store.STORE.db.query(installed=InstallRecordStatus.ANY)
non_deprecated = spack.store.STORE.db.query("libelf")
all_available = spack.store.STORE.db.query("libelf", installed=InstallRecordStatus.ANY)
assert all_available == all_installed
assert non_deprecated == spack.store.STORE.db.query("libelf@0.8.13")
@@ -39,24 +42,24 @@ def test_deprecate_fails_no_such_package(mock_packages, mock_archive, mock_fetch
output = deprecate("-y", "libelf@0.8.10", "libelf@0.8.13", fail_on_error=False)
assert "Spec 'libelf@0.8.10' matches no installed packages" in output
install("libelf@0.8.10")
install("--fake", "libelf@0.8.10")
output = deprecate("-y", "libelf@0.8.10", "libelf@0.8.13", fail_on_error=False)
assert "Spec 'libelf@0.8.13' matches no installed packages" in output
def test_deprecate_install(mock_packages, mock_archive, mock_fetch, install_mockery):
"""Tests that the ```-i`` option allows us to deprecate in favor of a spec
that is not yet installed."""
install("libelf@0.8.10")
to_deprecate = spack.store.STORE.db.query()
def test_deprecate_install(mock_packages, mock_archive, mock_fetch, install_mockery, monkeypatch):
"""Tests that the -i option allows us to deprecate in favor of a spec
that is not yet installed.
"""
install("--fake", "libelf@0.8.10")
to_deprecate = spack.store.STORE.db.query("libelf")
assert len(to_deprecate) == 1
deprecate("-y", "-i", "libelf@0.8.10", "libelf@0.8.13")
non_deprecated = spack.store.STORE.db.query()
deprecated = spack.store.STORE.db.query(installed=InstallRecordStatus.DEPRECATED)
non_deprecated = spack.store.STORE.db.query("libelf")
deprecated = spack.store.STORE.db.query("libelf", installed=InstallRecordStatus.DEPRECATED)
assert deprecated == to_deprecate
assert len(non_deprecated) == 1
assert non_deprecated[0].satisfies("libelf@0.8.13")
@@ -64,8 +67,8 @@ def test_deprecate_install(mock_packages, mock_archive, mock_fetch, install_mock
def test_deprecate_deps(mock_packages, mock_archive, mock_fetch, install_mockery):
"""Test that the deprecate command deprecates all dependencies properly."""
install("libdwarf@20130729 ^libelf@0.8.13")
install("libdwarf@20130207 ^libelf@0.8.10")
install("--fake", "libdwarf@20130729 ^libelf@0.8.13")
install("--fake", "libdwarf@20130207 ^libelf@0.8.10")
new_spec = spack.concretize.concretize_one("libdwarf@20130729^libelf@0.8.13")
old_spec = spack.concretize.concretize_one("libdwarf@20130207^libelf@0.8.10")
@@ -81,14 +84,14 @@ def test_deprecate_deps(mock_packages, mock_archive, mock_fetch, install_mockery
assert all_available == all_installed
assert sorted(all_available) == sorted(deprecated + non_deprecated)
assert sorted(non_deprecated) == sorted(list(new_spec.traverse()))
assert sorted(deprecated) == sorted(list(old_spec.traverse()))
assert sorted(non_deprecated) == sorted(new_spec.traverse())
assert sorted(deprecated) == sorted([old_spec, old_spec["libelf"]])
def test_uninstall_deprecated(mock_packages, mock_archive, mock_fetch, install_mockery):
"""Tests that we can still uninstall deprecated packages."""
install("libelf@0.8.13")
install("libelf@0.8.10")
install("--fake", "libelf@0.8.13")
install("--fake", "libelf@0.8.10")
deprecate("-y", "libelf@0.8.10", "libelf@0.8.13")
@@ -104,9 +107,9 @@ def test_uninstall_deprecated(mock_packages, mock_archive, mock_fetch, install_m
def test_deprecate_already_deprecated(mock_packages, mock_archive, mock_fetch, install_mockery):
"""Tests that we can re-deprecate a spec to change its deprecator."""
install("libelf@0.8.13")
install("libelf@0.8.12")
install("libelf@0.8.10")
install("--fake", "libelf@0.8.13")
install("--fake", "libelf@0.8.12")
install("--fake", "libelf@0.8.10")
deprecated_spec = spack.concretize.concretize_one("libelf@0.8.10")
@@ -117,8 +120,8 @@ def test_deprecate_already_deprecated(mock_packages, mock_archive, mock_fetch, i
deprecate("-y", "libelf@0.8.10", "libelf@0.8.13")
non_deprecated = spack.store.STORE.db.query()
all_available = spack.store.STORE.db.query(installed=InstallRecordStatus.ANY)
non_deprecated = spack.store.STORE.db.query("libelf")
all_available = spack.store.STORE.db.query("libelf", installed=InstallRecordStatus.ANY)
assert len(non_deprecated) == 2
assert len(all_available) == 3
@@ -129,9 +132,9 @@ def test_deprecate_already_deprecated(mock_packages, mock_archive, mock_fetch, i
def test_deprecate_deprecator(mock_packages, mock_archive, mock_fetch, install_mockery):
"""Tests that when a deprecator spec is deprecated, its deprecatee specs
are updated to point to the new deprecator."""
install("libelf@0.8.13")
install("libelf@0.8.12")
install("libelf@0.8.10")
install("--fake", "libelf@0.8.13")
install("--fake", "libelf@0.8.12")
install("--fake", "libelf@0.8.10")
first_deprecated_spec = spack.concretize.concretize_one("libelf@0.8.10")
second_deprecated_spec = spack.concretize.concretize_one("libelf@0.8.12")
@@ -144,8 +147,8 @@ def test_deprecate_deprecator(mock_packages, mock_archive, mock_fetch, install_m
deprecate("-y", "libelf@0.8.12", "libelf@0.8.13")
non_deprecated = spack.store.STORE.db.query()
all_available = spack.store.STORE.db.query(installed=InstallRecordStatus.ANY)
non_deprecated = spack.store.STORE.db.query("libelf")
all_available = spack.store.STORE.db.query("libelf", installed=InstallRecordStatus.ANY)
assert len(non_deprecated) == 1
assert len(all_available) == 3
@@ -158,8 +161,8 @@ def test_deprecate_deprecator(mock_packages, mock_archive, mock_fetch, install_m
def test_concretize_deprecated(mock_packages, mock_archive, mock_fetch, install_mockery):
"""Tests that the concretizer throws an error if we concretize to a
deprecated spec"""
install("libelf@0.8.13")
install("libelf@0.8.10")
install("--fake", "libelf@0.8.13")
install("--fake", "libelf@0.8.10")
deprecate("-y", "libelf@0.8.10", "libelf@0.8.13")

Some files were not shown because too many files have changed in this diff Show More