Compare commits

..

376 Commits

Author SHA1 Message Date
Alex Richert
a6cfeabc10 cairo: add shared and pic variants (#40302) 2023-10-13 14:21:43 -06:00
Martin Aumüller
a3a29006aa wayland: dot is a build dependency (#39854)
* wayland: dot is a build dependency

otherwise this build failure happens:
../spack-src/doc/meson.build:5:6: ERROR: Program 'dot' not found or not executable

* wayland: make building of documentation optional

renders several dependencies optional
2023-10-13 21:57:13 +02:00
Harmen Stoppels
a5cb7a9816 spack checksum: improve interactive filtering (#40403)
* spack checksum: improve interactive filtering

* fix signature of executable

* Fix restart when using editor

* Don't show [x version(s) are new] when no known versions (e.g. in spack create <url>)

* Test ^D in test_checksum_interactive_quit_from_ask_each

* formatting

* colorize / skip header on invalid command

* show original total, not modified total

* use colify for command list

* Warn about possible URL changes

* show possible URL change as comment

* make mypy happy

* drop numbers

* [o]pen editor -> [e]dit
2023-10-13 19:43:22 +00:00
Gabriel Cretin
edf4aa9f52 Fpocket: fix installation (#40499)
* Fpocket: fix edit() positional args + add install()

* Remove comments

* Fix line too long

* Fix line too long

* Remove extension specification in version

Co-authored-by: Alec Scott <alec@bcs.sh>

* Use f-strings

Co-authored-by: Alec Scott <alec@bcs.sh>

* Fix styling

* Use the default MakefilePackage install stage

---------

Co-authored-by: Alec Scott <alec@bcs.sh>
2023-10-13 11:30:20 -07:00
Dom Heinzeller
02c680ec3a texinfo package: fix external detection (#40470)
A complete texinfo install includes both `info` and `makeinfo`. Some
system installations of texinfo may exclude one or the other. This
updates the external finding logic to require both.
2023-10-13 10:39:08 -07:00
David Huber
8248e180ca Add gsi-ncdiag v1.1.2 (#40508) 2023-10-13 08:48:23 -07:00
Harmen Stoppels
c9677b2465 Expand multiple build systems section (#39589)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2023-10-13 14:59:44 +02:00
Massimiliano Culpo
3752fe9e42 Better error message when wrong platform is used (#40492)
fixes #40299
2023-10-13 11:18:55 +02:00
Matthew Chan
8a0de10f60 containerize: update docs to activate env before using container templates (#40493) 2023-10-13 06:59:44 +00:00
Adam J. Stewart
6aa8d76e32 py-cmocean: add v3.0.3 (#40482) 2023-10-12 20:32:48 -06:00
Nils Vu
fb1d0f60d9 catch2: add +pic and +shared options (#40337)
Also add latest version
2023-10-12 20:13:01 -06:00
Martin Aumüller
728eaa515f ospray: new versions 2.11.0 and 2.12.0 (#40394)
* openimagedenoise: checksum 2.0.1
* ospray: new versions 2.11.0 and 2.12.0
  - both depend on embree@4
  - also update dependency versions for rkcommon, openvkl, openimagedenois and ispc
  - expose that dependency on openvkl is optional since @2.11 with variant "volumes"
* ospray: limit embree to @3 for ospray @:2.10
2023-10-12 14:13:15 -07:00
Julius Plehn
7c354095a9 Updates Variorum to 0.7.0 (#40488) 2023-10-12 11:27:06 -06:00
Harmen Stoppels
64ef33767f modules:prefix_inspections: allow empty dict (#40485)
Currently

```
modules:
  prefix_inspections:: {}
```

gives you the builtin defaults instead of no mapping.
2023-10-12 09:28:16 -07:00
Dennis Klein
265432f7b7 libzmq: Revert "libzmq: make location of libsodium explicit (#34553)" (#40477)
and make variants independent of upstream defaults
2023-10-12 09:15:00 -06:00
dependabot[bot]
aa7dfdb5c7 build(deps): bump python-levenshtein in /lib/spack/docs (#40461)
Bumps [python-levenshtein](https://github.com/maxbachmann/python-Levenshtein) from 0.22.0 to 0.23.0.
- [Release notes](https://github.com/maxbachmann/python-Levenshtein/releases)
- [Changelog](https://github.com/maxbachmann/python-Levenshtein/blob/main/HISTORY.md)
- [Commits](https://github.com/maxbachmann/python-Levenshtein/compare/v0.22.0...v0.23.0)

---
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>
2023-10-12 14:38:33 +00:00
Alec Scott
bfe37435a4 go: add v1.21.3 and deprecate previous versions due to CVE-2023-39533 (#40454) 2023-10-12 07:40:04 -06:00
Adam J. Stewart
285a50f862 PyTorch: fix build with Xcode 15 (#40460) 2023-10-12 07:27:03 -06:00
Harmen Stoppels
995e82e72b gettext: Add 0.22.3 and fix keyerror: "shared" (#39423)
After the merge of #37957 (Add static and pic variants), if a gettext install
from a build before that merge is present, building any package using gettext
fails with keyerror: "shared" because the use of self.spec.variants["shared"]
does not check for the presence of the new variant in the old installation
but expects that the new key variants["shared"] exists always.

Fix it with a fallback to the default of True and update gettext to v22.3

Co-authored-by: Bernharad Kaindl <43588962+bernhardkaindl@users.noreply.github.com>
2023-10-12 04:40:38 -06:00
Massimiliano Culpo
3935e047c6 Remove deprecated "extra_instructions" option for containers (#40365) 2023-10-12 12:12:15 +02:00
Harmen Stoppels
0fd2427d9b clingo: fix build with Python 3.12 (#40154) 2023-10-12 12:11:22 +02:00
Alec Scott
30d29d0201 acfl: use f-strings (#40433) 2023-10-12 11:30:22 +02:00
Tim Haines
3e1f2392d4 must: add versions 1.8.0 and 1.9.0 (#40141) 2023-10-11 22:34:22 -07:00
Lydéric Debusschère
6a12a40208 [add] py-cylc-rose: new recipe (#39980)
* [add] py-cylc-rose: new recipe

* py-cylc-rose: update recipe

---------

Co-authored-by: LydDeb <lyderic.debusschere.tgcc@cea.fr>
2023-10-11 22:31:46 -07:00
Leonhard Reichenbach
90e73391c2 opendatadetector: add version v3.0.0 (#39693) 2023-10-11 22:29:00 -07:00
Alec Scott
deec1b7c2e adios2: use f-strings (#40437) 2023-10-11 21:08:00 -06:00
Scott Wittenburg
d9cb1a1070 buildcache: Tell servers not to cache index or hash (#40339) 2023-10-11 18:13:57 -06:00
afzpatel
01747b50df fix ck build for 5.6.1 (#40304)
* initial commit to fix ck build for 5.6.1
* disable mlir for miopen-hip
* use satisfies for checking specs and add nlohmann-json dependency for 5.4 onwards
2023-10-11 14:43:21 -07:00
Alex Richert
df01a11e07 apr-util: Fix spack install apr-util +crypto ^openssl~shared (#40301) 2023-10-11 23:38:28 +02:00
Victor Brunini
7a4b479724 cmake: drop CMAKE_STATIC_LINKER_FLAGS (#40423)
Because those end up being passed to ar which does not understand linker
arguments. This was making ldflags largely unusuable for statically
linked cmake packages.
2023-10-11 23:30:44 +02:00
Harmen Stoppels
89e34d56a1 curl: add v8.4.0, allow r@8.3: to use it (#40442)
* curl: 8.4.0

* fix r curl upperbound range
2023-10-11 21:04:09 +02:00
Miroslav Stoyanov
a5853ee51a update for the tasmanain versions (#40453) 2023-10-11 12:33:31 -06:00
Alec Scott
537ab48167 acts: use f-strings (#40434) 2023-10-11 11:03:30 -07:00
Alec Scott
e43a090877 abduco: use f-string (#40432) 2023-10-11 19:51:26 +02:00
Alec Scott
275a2f35b5 adiak: use f-strings (#40435) 2023-10-11 10:48:39 -07:00
Alec Scott
dae746bb96 abacus: use f-string (#40431) 2023-10-11 19:48:32 +02:00
Alec Scott
3923b81d87 adios: use f-strings (#40436) 2023-10-11 10:47:42 -07:00
Alec Scott
5d582a5e48 7zip: use f-strings (#40430) 2023-10-11 19:46:23 +02:00
Alec Scott
7dbc712fba 3proxy: use f-strings (#40429) 2023-10-11 19:44:57 +02:00
Alec Scott
639ef9e24a adol-c: use f-strings (#40438) 2023-10-11 10:43:31 -07:00
Alex Richert
86d2200523 krb5: Fix spack install krb5 ^openssl~shared (#40306) 2023-10-11 19:37:48 +02:00
Massimiliano Culpo
fe6860e0d7 cmake: add v3.27.7 (#40441) 2023-10-11 10:20:49 -07:00
Manuela Kuhn
8f2e68aeb8 c-blosc2: add 2.10.5 (#40428) 2023-10-11 19:19:58 +02:00
Laura Weber
bc4c887452 tecplot: Add version 2023r1 (#40425) 2023-10-11 10:05:37 -07:00
Alec Scott
b3534b4435 restic: add v0.16.0 (#40439) 2023-10-11 19:04:26 +02:00
Massimiliano Culpo
861bb4d35a Update bootstrap buildcache to support Python 3.12 (#40404)
* Add support for Python 3.12
* Use optimized build of clingo
2023-10-11 19:03:17 +02:00
Harmen Stoppels
65e7ec0509 spider: respect <base> tag (#40443) 2023-10-11 08:49:50 -07:00
Manuela Kuhn
1ab8886695 qt-base: fix-build without opengl (#40421) 2023-10-11 08:56:59 -04:00
dependabot[bot]
26136c337f build(deps): bump mypy from 1.5.1 to 1.6.0 in /.github/workflows/style (#40422)
Bumps [mypy](https://github.com/python/mypy) from 1.5.1 to 1.6.0.
- [Commits](https://github.com/python/mypy/compare/v1.5.1...v1.6.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>
2023-10-11 06:35:51 -06:00
dependabot[bot]
e3b71b32aa build(deps): bump mypy from 1.5.1 to 1.6.0 in /lib/spack/docs (#40424)
Bumps [mypy](https://github.com/python/mypy) from 1.5.1 to 1.6.0.
- [Commits](https://github.com/python/mypy/compare/v1.5.1...v1.6.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>
2023-10-11 12:35:41 +00:00
Alec Scott
6d1711f4c2 Update legacy .format() calls to fstrings in installer.py (#40426) 2023-10-11 12:35:37 +00:00
Massimiliano Culpo
26f291ef25 spack buildcache: fix a typo in a function call (#40446)
fixes #40415
2023-10-11 13:09:21 +02:00
Martin Aumüller
da030617a1 botan: checksum 3.2.0 (#40417) 2023-10-10 21:52:51 -06:00
Martin Aumüller
1ebfcd3b18 openvkl: add 1.3.2 (#40392)
* openvkl: add 1.3.2

works with (and requires) embree@4

* openvkl: simplify formatting with f-string

thank you for the suggestion in the review
2023-10-10 21:24:17 -06:00
Edward Hartnett
d385a57da3 w3emc: add v2.11.0 (#40376)
* added version 2.11.0

* more fixes
2023-10-10 15:11:14 -07:00
eugeneswalker
37df8bfc73 e4s arm stack: duplicate and target neoverse v1 (#40369)
* e4s arm stack: duplicate and target both neoverse n1, v1

* remove neoverse_n1 target until issue #40397 is resolved
2023-10-10 14:32:51 -07:00
Adam J. Stewart
b781a530a1 GCC: fix build with Apple Clang 15 (#40318) 2023-10-10 22:35:15 +02:00
Harmen Stoppels
390b0aa25c More helpful error when patch lookup fails (#40379) 2023-10-10 21:09:04 +02:00
Adam J. Stewart
620835e30c py-jupyter-packaging: remove duplicate packages (#38671)
* py-jupyter-packaging: remove duplicate packages

* Allow py-jupyter-packaging to be duplicated in DAG

* Deprecate version of py-jupyterlab that requires py-jupyter-packaging at run-time
2023-10-10 13:50:22 -05:00
Adam J. Stewart
da10487219 Update PyTorch ecosystem (#40321)
* Update PyTorch ecosystem

* py-pybind11: better documentation of supported compilers

* py-torchdata: add v0.7.0

* Black fixes

* py-torchtext: fix Python reqs

* py-horovod: py-torch 2.1.0 not yet supported
2023-10-10 13:45:32 -05:00
Miroslav Stoyanov
4d51810888 find rocm fix (#40388)
* find rocm fix
* format fix
* style fix
* formatting is broken
2023-10-10 10:42:26 -07:00
Harmen Stoppels
6c7b2e1056 git: optimize build by not setting CFLAGS (#40387) 2023-10-10 11:48:06 +02:00
Carlos Bederián
749e99bf11 python: add 3.11.6 (#40384) 2023-10-10 09:53:04 +02:00
Martin Aumüller
6db8e0a61e embree: checksum 4.3.0 (#40395) 2023-10-09 20:44:10 -06:00
Martin Aumüller
6fe914421a rkcommon: checksum 0.11.0 (#40391) 2023-10-09 20:43:56 -06:00
Andrew W Elble
9275f180bb openmm: new version 8.0.0 (#40396) 2023-10-09 20:33:40 -06:00
Tom Epperly
2541b42fc2 Add a new release sha256 hash (#37680) 2023-10-09 20:28:45 -06:00
Auriane R
fb340f130b Add pika 0.19.1 (#40385) 2023-10-09 20:23:54 -06:00
Dennis Klein
d2ddd99ef6 libzmq: add v4.3.5 (#40383) 2023-10-09 17:30:46 -06:00
kenche-linaro
492a8111b9 linaro-forge: added package file for rebranded product (#39587) 2023-10-09 12:14:14 -07:00
George Young
d846664165 paintor: new package @3.0 (#40359)
* paintor: new package @3.0
* Update var/spack/repos/builtin/packages/paintor/package.py
---------

Co-authored-by: LMS Bioinformatics <bioinformatics@lms.mrc.ac.uk>
Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
2023-10-09 09:54:44 -07:00
Vanessasaurus
31b3e4898b Add: flux-pmix 0.4.0 (#40323)
* Automated deployment to update package flux-pmix 2023-10-05

* Pin exactly to flux-core 0.49.0 when between 0.3 and 0.4

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

Co-authored-by: Mark Grondona <mark.grondona@gmail.com>

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

Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>

---------

Co-authored-by: github-actions <github-actions@users.noreply.github.com>
Co-authored-by: Mark Grondona <mark.grondona@gmail.com>
Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
2023-10-09 09:29:18 -07:00
Harmen Stoppels
82f1267486 unparse: drop python 3.3 remnants (#40331) 2023-10-09 08:22:27 -07:00
Harmen Stoppels
19202b2528 docs: update Spack prerequisites (#40381) 2023-10-09 13:41:36 +00:00
Adam J. Stewart
831cbec71f py-pydevtool: add new package (#40377) 2023-10-09 15:09:59 +02:00
Patrick Broderick
bb2ff802e2 fftx: add v1.1.3 (#40283) 2023-10-09 15:06:59 +02:00
dependabot[bot]
83e9537f57 build(deps): bump python-levenshtein in /lib/spack/docs (#40220)
Bumps [python-levenshtein](https://github.com/maxbachmann/python-Levenshtein) from 0.21.1 to 0.22.0.
- [Release notes](https://github.com/maxbachmann/python-Levenshtein/releases)
- [Changelog](https://github.com/maxbachmann/python-Levenshtein/blob/main/HISTORY.md)
- [Commits](https://github.com/maxbachmann/python-Levenshtein/compare/v0.21.1...v0.22.0)

---
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>
2023-10-09 15:02:14 +02:00
Gavin John
3488e83deb py-s3cmd: Add new versions (#40212)
* Add new versions of py-s3cmd

* Use correct hashes
2023-10-09 07:46:38 -05:00
Jacob King
c116eee921 nimrod-aai: add v23.9. (#40303) 2023-10-09 14:39:40 +02:00
Adam J. Stewart
9cb291b41b py-jsonargparse: add v4.25.0 (#40185) 2023-10-09 14:33:45 +02:00
Thomas Dickerson
c0f1072dc7 racket packages: fix typo after multiple build systems support (#40088) 2023-10-09 14:21:13 +02:00
Jordan Galby
3108036533 elfutils: fix +debuginfod again with new libarchive versions (#40314) 2023-10-09 14:17:58 +02:00
Mike Renfro
215c699307 velvet: improved variants (#40225) 2023-10-09 12:47:54 +02:00
jmuddnv
f609093c6e Adding NVIDIA HPC SDK 23.9 (#40371) 2023-10-09 12:35:59 +02:00
Joe Schoonover
eb4fd98f09 feq-parse: add v2.0.3 (#40230) 2023-10-09 12:31:23 +02:00
Harmen Stoppels
08da9a854a parser: use non-capturing groups (#40373) 2023-10-09 07:18:27 +02:00
Mark (he/his) C. Miller
3a18fe04cc Update CITATION.cff with conf dates (#40375)
Add `start-date` and `end-date` to citation
2023-10-08 18:04:25 -07:00
Harmen Stoppels
512e41a84a py-setuptools: sdist + rpath patch backport (#40205) 2023-10-08 11:47:36 -06:00
Alex Richert
8089aedde1 gettext: Add static and pic options (#37957) 2023-10-08 17:42:21 +02:00
Manuela Kuhn
6b9e103305 py-tables: add 3.9.0 (#40340)
* py-tables: add 3.9.0

* Add conflict with apple-clang
2023-10-08 10:28:13 -05:00
Jen Herting
00396fbe6c [py-tokenizers] added version 0.13.3 (#40360) 2023-10-08 10:27:18 -05:00
Jen Herting
a3be9cb853 [py-tensorboardx] Added version 2.6.2.2 (#39731)
* [py-tensorboardx] Added version 2.6.2.2

* [py-tensorboardx] flake8

* [py-tensorboardx] requires py-setuptools-scm
2023-10-08 10:21:55 -05:00
Jen Herting
81f58229ab py-torch-sparse: add v0.6.17 (#39495)
* [py-torch-sparse] New version 0.6.17

* [py-torch-sparse] added dependency on parallel-hashmap

* [py-torch-sparse]

- spack only supports python@3.7:
- py-pytest-runner only needed with old versions
2023-10-08 10:20:46 -05:00
Jen Herting
2eb16a8ea2 [py-lvis] New package (#39080)
* [py-lvis] New package

* [py-lvis] flake8

* [py-lvis] os agnostic

* [py-lvis] added comment for imported dependency

* [py-lvis] style fix
2023-10-08 10:18:01 -05:00
Manuela Kuhn
9db782f8d9 py-bids-validator: add 1.13.1 (#40356)
* py-bids-validator: add 1.13.1

* Fix style
2023-10-08 10:16:08 -05:00
Lydéric Debusschère
633df54520 [add] py-cylc-flow: new recipe (#39986)
* [add] py-cylc-flow: new recipe

* py-cylc-flow: fix py-protobuf version

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

* py-cylc-flow: fix py-colorama version

Co-authored-by: Manuela Kuhn <36827019+manuelakuhn@users.noreply.github.com>

* py-cylc-flow: Update dependence on py-aiofiles

Co-authored-by: Manuela Kuhn <36827019+manuelakuhn@users.noreply.github.com>

* py-cylc-flow: Update dependence on py-pyzmq

Co-authored-by: Manuela Kuhn <36827019+manuelakuhn@users.noreply.github.com>

* py-cylcflow: remove useless dependence

* py-cylc-flow: fix indent

* py-cylc-flow: fix argument in depends_on; move lines

* py-cylc-flow: fix the type of the dependence py-setuptools

---------

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
Co-authored-by: Manuela Kuhn <36827019+manuelakuhn@users.noreply.github.com>
Co-authored-by: LydDeb <lyderic.debusschere.tgcc@cea.fr>
2023-10-08 10:06:13 -05:00
Mark (he/his) C. Miller
e2a7f2ee9a Update CITATION.cff (#40363)
You will note the `Cite this repository` link is not working.

This commit fixes the underlying file...

* `authors` was not indented
* `authors` required by `preferred-citation`
* `authors` list required at top level (I simply duplicated)
* `"USA"` not correct country code
* `month` requires an integer month number
* Added URL to the actual pdf of the cited paper
* Used `identifiers` for doi and LLNL doc number
* added `abstract` copied from paper

Various fixes were confirmed by `cffconvert` using `docker run -v `pwd`:/app citationcff/cffconvert --validate`
2023-10-07 17:44:31 -07:00
Massimiliano Culpo
28c49930e2 Remove warning for custom module configuration, when no module is enabled (#40358)
The warning was added in v0.20 and was slated for removal in v0.21
2023-10-07 09:21:04 +02:00
Ken Raffenetti
6c1868f8ae yaksa: add version 0.3 (#40368) 2023-10-06 22:28:15 -06:00
Massimiliano Culpo
4f992475f4 Python add v3.11.5 (#40330) 2023-10-06 18:03:00 -06:00
Alex Richert
7a358c9005 Change 'exit' to 'return' in setup-env.sh (#36137)
* Change 'exit' to 'return' in `setup-env.sh` to avoid losing shell in some cases when sourcing twice.
2023-10-06 16:19:19 -07:00
Veselin Dobrev
b5079614b0 MFEM: add new version v4.6 (#40170)
* [mfem] Initial changes for v4.6

* [@spackbot] updating style on behalf of v-dobrev

* [mfem] Set the proper download link for v4.6
2023-10-06 15:31:23 -07:00
Alex Richert
482525d0f9 Update bufr recipe (#40033)
* Update bufr recipe
* Add v12.0.1
* style fixes
* remove test-related functionality for bufr
* Re-add testing

---------

Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
2023-10-06 15:04:51 -07:00
snehring
599220924d wise2: adding new package wise2 (#40341) 2023-10-06 14:24:44 -07:00
Harmen Stoppels
d341be83e5 VersionRange: improve error message for empty range (#40345) 2023-10-06 14:19:49 -07:00
George Young
b027d7d0de metal: new package @2020-05-05 (#40355)
* metal: new package
* style

---------

Co-authored-by: LMS Bioinformatics <bioinformatics@lms.mrc.ac.uk>
2023-10-06 14:14:45 -07:00
Howard Pritchard
0357df0c8b openmpi: add 4.1.6 release (#40361)
related to #40232

Signed-off-by: Howard Pritchard <howardp@lanl.gov>
2023-10-06 13:06:37 -07:00
Edward Hartnett
f70ae6e3c4 g2: updated for 3.4.8 release (#40366)
* updated for 3.4.8 release
2023-10-06 13:02:17 -07:00
Manuela Kuhn
921ed1c21b py-expecttest: new package (#40347) 2023-10-06 14:34:47 -05:00
Manuela Kuhn
c95d43771a py-asttokens: add 2.4.0 (#40349) 2023-10-06 14:33:56 -05:00
Manuela Kuhn
db3d816f8b py-argcomplete: add 3.1.2 (#40348) 2023-10-06 14:32:21 -05:00
Manuela Kuhn
1d6a142608 py-anyio: add 4.0.0 (#40346) 2023-10-06 14:27:53 -05:00
George Young
98271c3712 topaz: new package @0.2.5 (#40352)
* topaz: new package @0.2.5

* switching over to pypi

---------

Co-authored-by: LMS Bioinformatics <bioinformatics@lms.mrc.ac.uk>
2023-10-06 13:00:03 -06:00
Manuela Kuhn
e3f6df884e py-zipp: add 3.17.0 (#40278)
* py-zipp: add 3.17.0

* Re-add python@3.7 dependency
2023-10-06 13:54:25 -05:00
Sam Gillingham
b0f36b2cd9 RIOS: add recent versions (#40243)
* add recent versions of RIOS

* fix depends_on syntax

* fix typo

* fix sha and add parallel variant

* remove self

* try doing in one
2023-10-06 13:52:15 -05:00
Lydéric Debusschère
5524492e25 [add] py-metomi-rose: new recipe, required by py-cylc-rose (#39981)
* [add] py-metomi-rose: new recipe, required by py-cylc-rose

* py-metomi-rose: remove version constraint on python

---------

Co-authored-by: LydDeb <lyderic.debusschere.tgcc@cea.fr>
2023-10-06 13:49:59 -05:00
Sam Gillingham
112f045352 py-tuiview: add recent versions of tuiview (#40244)
* add recent versions of tuiview and remove Qt4 version

* reformat

* fix stray tabs

* add back a deprecated 1.1.7

* tabs

* more tabs

* reformat

* comma
2023-10-06 13:49:06 -05:00
Harmen Stoppels
72ed8711a7 unparse: drop python 2 remnants (#40329) 2023-10-06 09:42:47 -07:00
Harmen Stoppels
55e0c2c900 openssh: 9.5p1 (#40354) 2023-10-06 09:37:42 -07:00
Massimiliano Culpo
e20c05fcdf Make "minimal" the default duplicate strategy (#39621)
* Allow branching out of the "generic build" unification set

For cases like the one in https://github.com/spack/spack/pull/39661
we need to relax rules on unification sets.

The issue is that, right now, nodes in the "generic build" unification
set are unified together with their build dependencies. This was done
out of caution to avoid the risk of circular dependencies, which would
ultimately cause a very slow solve.

For build-tools like Cython, however, the build dependencies is masked
by a long chain of "build, run" dependencies that belong in the
"generic build" unification space.

To allow splitting on cases like this, we relax the rule disallowing
branching out of the "generic build" unification set.

* Fix issue with pure build virtual dependencies

Pure build virtual dependencies were not accounted properly in the
list of possible virtuals. This caused some facts connecting virtuals
to the corresponding providers to not be emitted, and in the end
lead to unsat problems.

* Fixed a few issues in packages

py-gevent: restore dependency on py-cython@3
jsoncpp: fix typo in build dependency
ecp-data-vis-sdk: update spack.yaml and cmake recipe
py-statsmodels: add v0.13.5

* Make dependency on "blt" of type "build"
2023-10-06 10:24:21 +02:00
Harmen Stoppels
36183eac40 python: add 3.12.0 (but keep 3.11 preferred) (#40282) 2023-10-06 09:44:09 +02:00
Alex Richert
7254c76b68 ecFlow update (#40305)
* Support static openssl for ecflow

* Update ecflow/static openssl

* Update ssl settings in ecflow

* add pic variant for ecflow

* style fix

* Update package.py

* Update package.py
2023-10-05 20:04:44 -07:00
eugeneswalker
e0e6ff5a68 Revert "cray rhel: disable due to runner issues (#40324)" (#40335)
This reverts commit bf7f54449b.
2023-10-05 10:32:52 -07:00
snehring
b0d49d4973 pbmpi: adding new version and maintainer (#40319) 2023-10-05 10:13:50 -07:00
Harmen Stoppels
4ce5d14066 unparse: drop python 3.4 remnants (#40333) 2023-10-05 09:52:23 -07:00
Thomas Madlener
9e9653ac58 whizard: Make sure to detect LCIO if requested (#40316) 2023-10-05 08:53:56 -07:00
Auriane R
bec873aec9 Add pika 0.19.0 (#40313) 2023-10-05 09:34:22 +02:00
Harmen Stoppels
bf7f54449b cray rhel: disable due to runner issues (#40324) 2023-10-05 08:45:33 +02:00
Cameron Rutherford
9f0e3c0fed exago: add and logging variant. (#40188) 2023-10-05 06:57:17 +02:00
eugeneswalker
79e7da9420 trilinos: add variant to build tests (#40284)
* trilinos: add variant: testing

* trilinos: rename +testing to +test
2023-10-04 16:32:30 -05:00
Harmen Stoppels
0f43074f3e Improve build isolation in PythonPipBuilder (#40224)
We run pip with `--no-build-isolation` because we don't wanna let pip
install build deps.

As a consequence, when pip runs hooks, it runs hooks of *any* package it
can find in `sys.path`.

For Spack-built Python this includes user site packages -- there
shouldn't be any system site packages. So in this case it suffices to
set the environment variable PYTHONNOUSERSITE=1.

For external Python, more needs to be done, cause there is no env
variable that disables both system and user site packages; setting the
`python -S` flag doesn't work because pip runs subprocesses that don't
inherit this flag (and there is no API to know if -S was passed)

So, for external Python, an empty venv is created before invoking pip in
Spack's build env ensures that pip can no longer see anything but
standard libraries and `PYTHONPATH`.

The downside of this is that pip will generate shebangs that point to
the python executable from the venv. So, for external python an extra
step is necessary where we fix up shebangs post install.
2023-10-04 14:38:50 -05:00
Ken Raffenetti
d297098504 yaksa: Allow unsupported host compiler with CUDA (#40298)
Fixes #40272.
2023-10-04 09:37:58 -07:00
Josh Bowden
284eaf1afe Damaris release v1.9.2 (#40285)
* Update to latest dot versions and improved installation of Damaris python module damaris4py

* fix for visit dependency typo

* whitespace check

* whitespace check

* fix for style issue

* reviewer suggestions for integrating Python added

* suggestion for boost depends statement added
2023-10-04 09:34:43 -06:00
Dom Heinzeller
da637dba84 Add new package awscli-v2 and its missing dependency awscrt (#40288)
* Add new package awscli-v2 and its missing dependency awscrt

* Remove boilerplate comments from awscli-v2 and awscrt packages

* Fix typos in var/spack/repos/builtin/packages/awscli-v2/package.py

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

* Address reviewer comments

* Remove py-pip version dependency from var/spack/repos/builtin/packages/awscli-v2/package.py

---------

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2023-10-04 09:34:23 -06:00
Harmen Stoppels
931fce2c24 py-isort: needs setuptools build dep before v5 (#40234)
* py-isort: needs setuptools build dep before v5

Detected in #40224.

In the past, system setuptools could be picked up when using an external
python, so py-isort@4 would install fine. With the linked PR, pip can
only consider packages that Spack controls from PYTHONPATH, so the issue
of missing py-setuptools showed up.

* py-importlib-metadata: fix lowerbounds on python

* review

* py-isort unconditionally add optional setuptools dep to prevent picking up user package at runtime

* style

* drop optional py-setuptools run dep
2023-10-04 03:31:46 -06:00
Adam J. Stewart
42fbf17c82 py-einops: add v0.7.0 (#40296) 2023-10-04 04:28:49 -05:00
Harmen Stoppels
d9cacf664c petsc: add conflict on rocm 5.6: for now (#40300)
hipsparse@5.6.0 changed hipsparseSpSV_solve() API, but reverted in 5.6.1
2023-10-04 09:59:59 +02:00
Scott Wittenburg
7bf6780de2 ci: pull E4S images from github instead of dockerhub (#40307) 2023-10-04 09:55:06 +02:00
eugeneswalker
91178d40f3 e4s arm: disable bricks due to target=aarch64 not being respected (#40308) 2023-10-04 09:51:14 +02:00
kwryankrattiger
2817cd2936 ADIOS2: v2.8 is not compatible with HDF5 v1.14: (#40258) 2023-10-03 16:45:24 -05:00
Scott Wittenburg
92a6ddcbc3 ci: Change how job names appear in gitlab (#39963) 2023-10-03 15:16:41 -06:00
Sinan
58017f484c fix_qgis_build_with_pysip5 (#39941)
* fix_qgis_build_with_pysip5

* build fails with newer protobuf

* somehow findgdal can figure this out.

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

* fix gdal lib again

* qgis needs QtPositioning provided by qt+location option

* fix FindPyQt5 cmake file

* fix bug

* fix qsci sip issue

* fix bug

* blackify

* improve

* add latest LTR

* add build dep

* revert until bug is fixed

* specify proj version for qgis 3.28

* improve gdal libs search via indicating gdal-config

* make flake happy

* improve deps

* add 3.28.11, improve style

* fix style

* [@spackbot] updating style on behalf of Sinan81

---------

Co-authored-by: Sinan81 <Sinan@world>
Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
Co-authored-by: Sinan81 <Sinan81@users.noreply.github.com>
2023-10-03 14:21:51 -05:00
George Young
86d2e1af97 falco: new package @1.2.1 (#40289)
* falco: new package @1.2.1
* specifying gmake
* Replacing homepage - readthedocs is empty

---------

Co-authored-by: LMS Bioinformatics <bioinformatics@lms.mrc.ac.uk>
2023-10-03 11:26:49 -07:00
Adam J. Stewart
bf23be291b py-tables: add v3.8.0 (#40295) 2023-10-03 11:12:55 -07:00
Lydéric Debusschère
3b32a9918c [add] py-graphene: new recipe, required by py-cylc-flow (#39988) 2023-10-03 11:21:36 -06:00
Jordan Galby
f0260c84b4 Fix binutils regression on +gas~ld fix (#40292) 2023-10-03 17:28:55 +02:00
eugeneswalker
8746c75db0 e4s ci stacks: sync with e4s-23.08 (#40263)
* e4s amd64 gcc ci stack: sync with e4s-23.08

* e4s amd64 oneapi ci stack: sync with e4s-23.08

* e4s ppc64 gcc ci stack: sync with e4s-23.08

* add new ci stack: e4s amd64 gcc w/ external rocm

* add new ci stack: e4s arm gcc ci

* updates

* py-scipy: -fvisibility issue is resolved in 2023.1.0: #39464

* paraview oneapi fails

* comment out pkgs that fail to build on power

* fix arm stack name

* fix cabana +cuda specification

* comment out failing spces

* visit fails build on arm

* comment out slepc arm builds due to make issue

* comment out failing dealii arm builds
2023-10-03 08:12:51 -07:00
Gavin John
e8f230199f py-biom-format: Fix package file issues and bring up to date (#39962)
* Fix python versioning issue for py-biom-format

* Update deps according to feedback

* Remove version requirement for py-cython

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

* Only depend on py-six for versions >=2.1.10

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

* Add py-future as non-dependency for 2.1.15

* There we are. Everything anyone could ever want

* Missed cython version change

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

---------

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2023-10-03 09:55:15 -05:00
GeorgeJuniorGG
1e3c7abc1c Adding dynaconf module (#39762)
* Adding dynaconf module

* Fixing style

* Adding dependency
2023-10-03 06:23:29 -05:00
Manuela Kuhn
12e51da102 py-yarl: add 1.9.2 (#40277) 2023-10-03 06:22:20 -05:00
Tom Payerle
992291c738 py-dipy: Update version to support python@3.10 (#40229)
* py-dipy: Update version to support python@3.10

py-dipy only adds support to python@3.10 in py-dipy@1.5.0

See #40228

* py-dipy: fix formatting issues

* py-dipy: another formatting fix

* py-dipy: Use depends instead of conflicts

* py-dipy: formatting fix

* py-dipy: Updating for @1.7.0

Added new minimum version requirements for
py-cython
py-numpy
py-scipy
py-h5py
as suggested by @manuelakuhn
(py-nibabel min version unchanged for @1.7.0)
2023-10-03 06:10:14 -05:00
Manuela Kuhn
78e63fa257 py-wcwidth: add 0.2.7 (#40256) 2023-10-03 06:04:30 -05:00
Manuela Kuhn
487ea8b263 py-virtualenv: add 20.24.5 (#40255)
* py-virtualenv: add 20.22.0

* py-platformdirs: add 3.5.3

* py-filelock: add 3.12.4

* py-distlib: add 0.3.7
2023-10-03 06:03:35 -05:00
Manuela Kuhn
0d877b4184 py-websocket-client: add 1.6.3 (#40274) 2023-10-03 05:58:53 -05:00
Manuela Kuhn
994544f208 py-werkzeug: add 2.3.7 and 3.0.0 (#40275) 2023-10-03 05:57:27 -05:00
Manuela Kuhn
36bb2a5d09 py-wrapt: add 1.15.0 (#40276) 2023-10-03 05:55:28 -05:00
Stephen Hudson
071c1c38dc py-libEnsemble: add v1.0.0 (#40203)
* py-libEnsemble: add v1.0.0

* Add version ranges for deps

* Add comments to variants

* Put when before type

* Fix line lengths

* Re-format

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

Co-authored-by: Manuela Kuhn <36827019+manuelakuhn@users.noreply.github.com>

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

Co-authored-by: Manuela Kuhn <36827019+manuelakuhn@users.noreply.github.com>

---------

Co-authored-by: Manuela Kuhn <36827019+manuelakuhn@users.noreply.github.com>
2023-10-03 05:48:17 -05:00
Lydéric Debusschère
b480ae2b7d [add] py-graphql-relay: new package (#39807)
* [add] py-graphql-relay: new package

* py-graphql-relay: Update package.py

Remove leftovers from version 3.2.0:
* archive name in pypi
* dependencies

* [fix] py-graphql-relay: remove constraint on python version; add dependence py-rx because of ModuleNotFoundError during spack test

* [fix] py-graphql-relay: remove py-rx dependence; py-graphql-core: add dependencies for version 2.3.2

* py-graphql-core: Update from review; set build backend, py-poetry for version 3: and py-setuptools for version 2

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

---------

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2023-10-03 05:45:06 -05:00
Lydéric Debusschère
7a390f503d [add] py-metomi-isodatetime: new recipe, required by py-cylc-flow (#39990)
* [add] py-metomi-isodatetime: new recipe, required by py-cylc-flow

* py-metomi-isodatetime: use sources from pypi instead of github
2023-10-03 05:42:46 -05:00
dependabot[bot]
b7cb3462d4 build(deps): bump actions/setup-python from 4.7.0 to 4.7.1 (#40287)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.7.0 to 4.7.1.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](61a6322f88...65d7f2d534)

---
updated-dependencies:
- dependency-name: actions/setup-python
  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>
2023-10-03 12:28:02 +02:00
dependabot[bot]
f2230100ac build(deps): bump urllib3 from 2.0.5 to 2.0.6 in /lib/spack/docs (#40286)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.5 to 2.0.6.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/v2.0.5...2.0.6)

---
updated-dependencies:
- dependency-name: urllib3
  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>
2023-10-03 12:27:36 +02:00
Massimiliano Culpo
4b06862a7f Deactivate Cray sles, due to unavailable runner (#40291)
This reverts commit 0274091204.
2023-10-03 11:06:36 +02:00
Harmen Stoppels
06057d6dba Buildcache tarballs with rootfs structure (#39341)
Two changes in this PR:

1. Register absolute paths in tarballs, which makes it easier
   to use them as container image layers, or rootfs in general, outside
   of Spack. Spack supports this already on develop.
2. Assemble the tarfile entries "by hand", which has a few advantages:
   1. Avoid reading `/etc/passwd`, `/etc/groups`, `/etc/nsswitch.conf`
      which `tar.add(dir)` does _for each file it adds_
   2. Reduce the number of stat calls per file added by a factor two,
      compared to `tar.add`, which should help with slow, shared filesystems
      where these calls are expensive
   4. Create normalized `TarInfo` entries from the start, instead of letting
      Python create them and patching them after the fact
   5. Don't recurse into subdirs before processing files, to avoid
      keeping nested directories opened. (this changes the tar entry
      order slightly, it's like sorting by `(not is_dir, name)`.
2023-10-03 09:56:18 +02:00
Sam Reeve
bb03a1768b Add AdditiveFOAM package (#39295)
* Add AdditiveFOAM package
* Add AdditiveFOAM build and install

Co-authored-by: kjrstory <kjrstory@gmail.com>
Co-authored-by: Knapp, Gerry <knappgl@ornl.gov>

---------

Co-authored-by: kjrstory <kjrstory@gmail.com>
Co-authored-by: Knapp, Gerry <knappgl@ornl.gov>
2023-10-02 16:27:13 -07:00
Adam J. Stewart
75ed26258c py-torchgeo: add v0.5.0 (#40267)
* py-torchgeo: add v0.5.0

* Better documentation of dependency quirks
2023-10-02 15:23:49 -05:00
eugeneswalker
1da8477a3c vtk-m@2.0: depend on kokkos@3.7:3.9 per issue #40268 (#40281) 2023-10-02 12:26:55 -07:00
Christoph Weber
4c111554ae Add ipm package (#40069) 2023-10-02 11:46:17 -07:00
renjithravindrankannath
615312fcee Rocm 5.6.0 & 5.6.1 release updates (#39673)
* 5.6.0 updates
* Rocm 5.6.0 updates
* Style and audit corrections for 5.6
* Patching smi path for tests.
* Style correction
* 5.6.1 updates
* Updated hip tests for ci build  failure
   Updated hiprand with the release tag
   Taken care the review comment rocsolver
* Adding rocm-smi path for 5.6
* Adding the patch file
* Setting library directory uniform
* gl depends on mesa but it should not be llvm variant
* Fix for the issue 39520 by setting CMAKE_INSTALL_LIBDIR=lib
* i1 muls can sometimes happen after SCEV. They resulted in
   ISel failures because we were missing the patterns for them.
* 5.6.0 & 5.6.1 updates for migraphx, miopen-hip, mivisionx
* Revert "5.6.0 & 5.6.1 updates for migraphx, miopen-hip, mivisionx"
   This reverts commit f54c9c6c67.
* Revert operator mixup fix
* Splitting compiler-rt-linkage-for-host and operator mixup patch
* Adding missing patch for reverting operator mixup
* 5.6 update for composable-kernel,migraphx,miopen-hip and mivisionx
* Updating rvs, rcd and rccl for 5.6.1. adding comment for llvm patch
2023-10-02 11:36:51 -07:00
Joseph Wang
453625014d fix lhapdf package (#37384)
* fix lhapdf package
* [@spackbot] updating style on behalf of joequant

---------

Co-authored-by: joequant <joequant@users.noreply.github.com>
2023-10-02 11:33:54 -07:00
G-Ragghianti
1b75651af6 Implemented +sycl for slate (#39927)
* Implemented +sycl for slate

* style

* style

* add slate +sycl to ci

* slate +sycl: explicitly specify +mpi

* comment out slate+sycl+mpi in e4s oneapi stack

* removing requirement of intel-oneapi-mpi

* Added slate+sycl to e4s oneapi stack

* Removing obsolete comment

---------

Co-authored-by: eugeneswalker <eugenesunsetwalker@gmail.com>
2023-10-02 07:35:00 -07:00
Thomas Madlener
b3e3604f46 libtirpc: Add latest version and allow for builds on macOS (#40189) 2023-10-02 15:02:33 +02:00
Harmen Stoppels
6c4ce379ca buildcache: ignore errors of newer buildcache version (#40279)
Currently buildcaches are forward incompatible in an annoying way: spack
errors out when trying to use them.

With this change, you just get a warning.
2023-10-02 14:51:48 +02:00
Harmen Stoppels
a9dcba76ce py-importlib-metadata: add patch releases (#40249)
importlib_metadata 4.11.4 fixes some nasty issues with
`metadata.entry_points(...)`, so ensure we have those bugfixes.
2023-10-02 10:09:36 +02:00
Harmen Stoppels
32f21f2a01 Spack python 3.12: PEP 695 unparse support (#40155) 2023-10-02 00:25:52 -07:00
Greg Sjaardema
e60bbd1bfc Cgns fix no fortran config (#40241)
* SEACAS: Update package.py to handle new SEACAS project name

The base project name for the SEACAS project has changed from
"SEACASProj" to "SEACAS" as of @2022-10-14, so the package
needed to be updated to use the new project name when needed.

The refactor also changes several:
    "-DSome_CMAKE_Option:BOOL=ON"
to
   define("Some_CMAKE_Option", True)

* CGNS: If fortran not enabled, do not specify parallel fortran compiler

* Update package formatting as suggested by black

* Accept suggested change
2023-10-02 16:03:47 +09:00
Freifrau von Bleifrei
71c5b948d0 discotec package: add selalib variant (#40222) 2023-10-02 07:14:50 +02:00
Tom Payerle
726d6b9881 zoltan: Fixes for #40198 (#40199)
Fix issue in configure_args which resulted in duplicate "--with-ldflags" arguments (with different values) being passed to configure.  And extended the fix to similar arguments.

Also, repeated some flags to "--with-libs" to "--with-ldflags" as when the flags were only in "--with-libs", they did not seem to be picked up everywhere.  I suspect this is a bug in the configure script, but adding to both locations seems to solve it and should not have any adverse effects.

Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2023-10-02 07:11:36 +02:00
Sinan
aff64c02e8 xv: new package (#40032)
Co-authored-by: Sinan81 <Sinan@world>
2023-10-02 07:06:00 +02:00
Matthew Archer
31ae5cba91 add maintainers to py-nanobind (#40235) 2023-10-02 07:03:49 +02:00
Sam Reeve
0a91d2411a cabana: add v0.6 (#40168) 2023-10-02 06:57:55 +02:00
snehring
5f3af3d5e4 perl-dbd-mysql update to 4.050 (#40245)
* perl-devel-checklib: adding new package perl-devel-checklib

* perl-dbd-mysql: adding new version 4.050 and a new build dep
2023-10-02 06:45:11 +02:00
Satish Balay
37158cb913 petsc,py-petsc4py,slepc,py-slepc4py: add version 3.20.0 (#40260) 2023-10-02 06:28:37 +02:00
Wouter Deconinck
a596e16a37 libxkbcommon: new versions 1.4.1, 1.5.0 (#40273) 2023-10-02 05:54:55 +02:00
Weiqun Zhang
4e69f5121f amrex: add v23.10 (#40270) 2023-10-02 05:53:16 +02:00
Wouter Deconinck
2a0f4393c3 assimp: new version 5.3.1 (#40271) 2023-10-02 05:52:30 +02:00
Wouter Deconinck
c9e1e7d90c acts: impose cxxstd variant on geant4 dependency (#39767) 2023-10-02 05:49:51 +02:00
Juan Miguel Carceller
7170f2252c rivet: remove deprecated versions and clean up recipe (#39861)
Co-authored-by: jmcarcell <jmcarcell@users.noreply.github.com>
Co-authored-by: Wouter Deconinck <wdconinc@gmail.com>
2023-10-02 05:48:35 +02:00
eugeneswalker
b09073e01e py-pandas@0.24.2 %oneapi: add cflag=-Wno-error=implicit-function-declaration (#39470) 2023-10-01 14:42:56 -06:00
eugeneswalker
2d509dc3eb py-scipy: -fvisibility issue is resolved in 2023.1.0: (#39464)
* py-scipy: -fvisibility issue is resolved in 2023.1.0:

* e4s oneapi ci: add py-scipy
2023-10-01 17:29:21 +00:00
Martin Aumüller
8a9d45cc29 embree: fix linux build on aarch64 for 3.13.5 (#39749)
- upstream patch does not apply cleanly to older versions, not required
  for newer ones
- also add conflict for older versions, except for 3.13.3 which works by
  chance
2023-10-01 09:04:37 -07:00
Wouter Deconinck
b25f8643ff geant4, vecgeom: support variant cxxstd=20 (#39785) 2023-10-01 21:33:37 +09:00
Juan Miguel Carceller
9120b6644d qt: change version for opengl dependencies (#39718) 2023-10-01 21:31:11 +09:00
eugeneswalker
68dbd25f5f e4s cray sles ci: expand spec list (#40162)
* e4s cray sles stack: expand spec list

* remove unnecessary packages:trilinos:one_of
2023-09-30 21:32:33 -07:00
Todd Gamblin
9e54134daf docs: Replace package list with packages.spack.io (#40251)
For a long time, the docs have generated a huge, static HTML package list. It has some
disadvantages:

* It's slow to load
* It's slow to build
* It's hard to search

We now have a nice website that can tell us about Spack packages, and it's searchable so
users can easily find the one or two packages out of 7400 that they're looking for. We
should link to this instead of including a static package list page in the docs.

- [x] Replace package list link with link to packages.spack.io
- [x] Remove `package_list.html` generation from `conf.py`.
- [x] Add a new section for "Links" to the docs.
- [x] Remove docstring notes from contribution guide (we haven't generated RST
      for package docstrings for a while)
- [x] Remove referencese to `package-list` from docs.
2023-10-01 05:36:22 +02:00
eugeneswalker
08a9345fcc e4s ci: add packages: drishti, dxt-explorer (#39597)
* e4s ci: add packages: drishti, dxt-explorer

* e4s oneapi ci: comment out dxt-explorer until r%oneapi issue #40257 is resolved
2023-09-30 06:15:58 +09:00
John W. Parent
7d072cc16f Windows: detect all available SDK versions (#39823)
Currently, Windows SDK detection will only pick up SDK versions
related to the current version of Windows Spack is running on.
However, in some circumstances, we want to detect other version
of the SDK, for example, for compiling on Windows 11 for Windows
10 to ensure an API is compatible with Win10.
2023-09-29 20:17:10 +00:00
snehring
d81f457e7a modeltest-ng: adding new version, swapping maintainer (#40217)
Co-authored-by: Bernhard Kaindl <bernhardkaindl7@gmail.com>
2023-09-29 20:19:29 +02:00
Peter Scheibel
3969653f1b Cray manifest: compiler handling fixes (#40061)
* Make use of `prefix` in the Cray manifest schema (prepend it to
  the relative CC etc.) - this was a Spack error.
* Warn people when wrong-looking compilers are found in the manifest
  (i.e. non-existent CC path).
* Bypass compilers that we fail to add (don't allow a single bad
  compiler to terminate the entire read-cray-manifest action).
* Refactor Cray manifest tests: module-level variables have been
  replaced with fixtures, specifically using the `test_platform`
  fixture, which allows the unit tests to run with the new
  concretizer.
* Add unit test to check case where adding a compiler raises an
  exception (check that this doesn't prevent processing the
  rest of the manifest).
2023-09-29 09:47:30 -07:00
Jordan Galby
db37672abf Print error when missing git (#40254)
Like a missing curl.
2023-09-29 15:14:39 +00:00
eugeneswalker
1f75ca96df kokkos-nvcc-wrapper: add v4.1.00 (#40240) 2023-09-29 17:08:42 +02:00
Harmen Stoppels
605835fe42 Don't drop build deps on overwrite install (#40252)
If you `spack install x ^y` where `y` is a pure build dep of `x`, and
then uninstall `y`, and then `spack install --overwrite x ^y`, the build
fails because `y` is not re-installed.

Same can happen when you install a develop spec, run `spack gc`,
modify sources, and install again; develop specs rely on overwrite
install to work correctly.
2023-09-29 16:40:21 +02:00
Abhishek Yenpure
6c2748c37d Adding Catalyst 2.0 smoke test (#40112)
--  Performaing formatting changes
  --  Formatting file to conform with spack style
  --  Adding updates from review
  --  Removing old release candidates from the specification
  --  Adding external conduit support for Catalyst
  --  Adding Catalyst to `CMAKE_PREFIX_PATH` for the test to find
2023-09-29 16:36:24 +02:00
Massimiliano Culpo
210d221357 Test package detection in a systematic way (#18175)
This PR adds a new audit sub-command to check that detection of relevant packages
is performed correctly in a few scenarios mocking real use-cases. The data for each 
package being tested is in a YAML file called detection_test.yaml alongside the 
corresponding package.py file.

This is to allow encoding detection tests for compilers and other widely used tools, 
in preparation for compilers as dependencies.
2023-09-29 10:24:42 +02:00
Mark W. Krentel
c9ef5c8152 hpctoolkit: add version 2023.08.1 (#40248)
Add versions 2020.08.1 and branch 2023.08.stable.  Note: the version
numbers are a little different.  Here, 2023.08.1 means release no. 1
from the release/2023.08 branch.
2023-09-29 00:48:05 -06:00
eugeneswalker
0274091204 Revert "e4s cray sles: suspend ci until machine issues resolved (#40219)" (#40238)
This reverts commit 5165524ca6.
2023-09-29 07:25:50 +02:00
John W. Parent
3f2f0cc146 openblas package: fix lib suffix construction in libs (#40242) 2023-09-28 22:02:37 -06:00
Massimiliano Culpo
a236fce31f Partial removal of circular dependencies between spack and llnl (#40090)
Modifications:
- [x] Move `spack.util.string` to `llnl.string`
- [x] Remove dependency of `llnl` on `spack.error`
- [x] Move path of `spack.util.path` to `llnl.path`
- [x] Move `spack.util.environment.get_host_*` to `spack.spec`
2023-09-28 16:21:52 +00:00
snehring
f77a38a96b mash: fix compilation for aarch64 (#40218) 2023-09-28 10:16:11 -06:00
Harmen Stoppels
6d55066b94 Use st_nlink in hardlink tracking (#39328)
Only add potential hardlinks to a set/dict, instead of each file. This
should be much cheaper, since hardlinks are very rare.
2023-09-28 13:24:56 +00:00
Harmen Stoppels
78132f2d6b glibc: dont link libgcc_eh.a pre 2.17, and backport at_random auxval patch (#40013)
This resolves an interesting circular dependency between gcc and glibc:

1. glibc < 2.17 depends on libgcc.a and libgcc_eh.a
2. libgcc_eh.a is only built when gcc is configured with
   --enable-shared
3. but building shared libraries requires crt*.o and libc.so

Backport AT_RANDOM auxval changes to avoid dealing with wrong inline 
assembly (fallback code fails on ubuntu 23.04)
2023-09-28 13:30:43 +02:00
Brian Vanderwende
fba47e87d7 Support optional vars script arguments (#40064) 2023-09-28 06:52:22 -04:00
Massimiliano Culpo
bf8e8d9f5f cmake: add v3.27.6 (#40037)
Co-authored-by: Harmen Stoppels <me@harmenstoppels.nl>
2023-09-28 11:06:28 +02:00
Sam Gillingham
ebc0e9be19 kealib: add 1.5.1 and 1.5.2 versions (#40202)
* add recent kealib versions
* udpdate depends_on so hl not required for latest version
2023-09-27 19:08:28 -06:00
Vicente Bolea
b6f08f1d4e vtk-m: add VTK-m 2.1.0-rc1 (#39581) 2023-09-27 10:13:18 -06:00
Jared Popelar
d9724597ed Trilinos package: build on Windows (#34622)
Update Trilinos and dependencies to build a limited version of Trilinos
on Windows.

* Support trilinos~mpi~shared on Windows
* superlu: force CMake build on Windows
* boost: update to build on Windows (proper option formatting and
  build tool names)
* pcre, openblas: add CMake-based build (keep prior build system
  as default on platforms other than Windows)
* openblas: add patch when using Intel Fortran compiler (currently
  this is included as part of the hybrid %msvc compiler in Spack)

Co-authored-by: John Parent <john.parent@kitware.com>
2023-09-27 09:58:12 -06:00
kwryankrattiger
c90c946d52 ParaView: Add versio 5.11.2 (#40213) 2023-09-27 10:20:13 -05:00
Martin Aumüller
bb66d15d08 ffmpeg: fix build with XCode 15 (#40187)
As reported in #40159, a shared library build of ffmpeg 6.0 fails with the linker that was added with XCode 15:
ld: building exports trie: duplicate symbol '_av_ac3_parse_header'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Forcing the old linker with -Wl,-ld_classic works around this.
2023-09-27 16:41:32 +02:00
snehring
1cd2d07f0b last: add new version, fix build on aarch64 (#40216)
Co-authored-by: Bernhard Kaindl <bernhardkaindl7@gmail.com>
2023-09-27 16:32:18 +02:00
Garth N. Wells
43cb49d87a py-nanonbind: add new versions (#40161) 2023-09-27 16:28:26 +02:00
eugeneswalker
5165524ca6 e4s cray sles: suspend ci until machine issues resolved (#40219) 2023-09-27 04:51:34 +02:00
Martin Aumüller
38dc3a6896 vtk: @9.2 need seacas@2022-10-14, fix macos (#39896)
Co-authored-by: Bernhard Kaindl <bernhardkaindl7@gmail.com>
2023-09-26 13:48:44 -06:00
John W. Parent
115e448bd3 Paraview package: update freetype find patch for shared libs (#40085)
VTK's (and therefore Paraview's) FindFreetype module required patching to
handle static import libraries from Freetype. However it did not cover
shared libraries. This adds support for importing shared freetype into the VTK build
2023-09-26 10:41:24 -07:00
Harmen Stoppels
5c25437c9f spack --profile: dump to stderr (#40209) 2023-09-26 16:18:47 +02:00
Christoph Weber
0e72ff4a0d ploticus: new package (#39881)
Co-authored-by: Bernhard Kaindl <contact@bernhard.kaindl.dev>
2023-09-26 08:15:12 -05:00
Matt Fraser
90edd18d1f Add NCCL v2.18.5-1 release to recipe (#40201) 2023-09-26 08:05:23 -05:00
Massimiliano Culpo
40dbadb868 crosstool-ng: add v1.26.0 (#40204) 2023-09-26 11:17:39 +02:00
Martin Aumüller
c16546bd4c libressl: fix package & new versions (#39741) 2023-09-26 10:39:29 +02:00
Dom Heinzeller
143e6a4fbb Always apply Python unixcompilers.py rpath fix, not just on cray (#39929)
* Rename var/spack/repos/builtin/packages/python/cray-rpath-3.1.patch as var/spack/repos/builtin/packages/python/rpath-non-gcc.patch and apply unconditionally

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

---------

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2023-09-26 02:38:20 -06:00
Martin Aumüller
13816f19fd opencv: add 4.7.0 and 4.8.0 and fix ffmpeg dependency (#39013) 2023-09-26 10:28:29 +02:00
Martin Aumüller
34ff3b408b seacas: correctly limit fmt dependency (#39756)
versions older than 2022-10-14 do not build with fmt@10, either:
fmt/core.h:1579:3: error: static_assert failed due to requirement 'formattable'
2023-09-26 06:35:38 +02:00
Victor A. P. Magri
aec88ef3e6 hypre: add support for magma (#40121) 2023-09-26 06:27:14 +02:00
snehring
9fda22d942 bcl2fastq2: patch for compiling on aarch64 (#40195) 2023-09-26 06:26:19 +02:00
snehring
550613ee3a gmap-gsnap: add v2023-07-20 and aarch64 support (#40200) 2023-09-26 05:59:31 +02:00
Ethan Williams
5341834ebe Elbencho: add elbencho package (#40193)
* add elbencho package
* pep8 compliant
* add description
* depends on boost
* boost options
* dependencies
* fix ncurses not linking properly missing tinfo
* pep8 fix
* fix style of boost variants
* final style fix - spack style is happy
* correct cufile env variable name

---------

Co-authored-by: Ethan W <mail@ethanwilliams.xyz>
2023-09-25 18:53:28 -06:00
Alberto Invernizzi
fc027e34d1 apex: add new version 2.6.3 + deal with ompt build problem (#40073)
* add new version 2.6.3
* add conflict for openmp when using gcc
2023-09-25 16:00:58 -07:00
Harmen Stoppels
aef58776b4 openssl: new versions (#40194)
apparently there was still a 1.1.1 release
2023-09-25 21:54:05 +02:00
Cameron Smith
4e17a40d09 omegah: new version (#40192) 2023-09-25 13:53:36 -06:00
Matthieu Dorier
d97251a4c6 spdlog: add version 1.12.0 (#40186) 2023-09-25 12:23:02 -07:00
snehring
2a66a67132 subread: removing mtune arg to compiler (#40197) 2023-09-25 12:19:25 -07:00
eugeneswalker
10fd69ec74 new package: gsibec (#40137) 2023-09-25 11:28:04 -06:00
Harmen Stoppels
9889a0cac6 py-numcodecs: drop upperbound, add new version, avoid native compilation (#40183)
* py-numcodecs: drop upperbound, add new version, avoid native compilation

* py-numcodecs: add entrypoints

* Remove another upperbound on python

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

---------

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2023-09-25 07:28:32 -06:00
Harmen Stoppels
65ffd0dd63 jsoncpp: add meson build system, update package, update cmake ~ownlibs (#39639) 2023-09-25 10:13:30 +02:00
Bernhard Kaindl
3d2c779b87 openssh: add version 9.4p1 and fix compile issue with new zlib-1.3 (#40174)
The fix for the compile issue was improved by Bernhard Kaindl.
He also added to fix two classes of other build fails:
- add missing openssl dependency version limit to older openssh versions
- add missing -fcommon for new compilers building old openssh versions

Co-authored-by: snehring <snehring@iastate.edu>
2023-09-25 08:30:10 +02:00
Harmen Stoppels
b57c2a10d4 phist: remove python 3.10 upperbound (#40175) 2023-09-25 08:28:13 +02:00
Diego Alvarez S
849a0a5eeb Add opendjk 11.0.20.1+1, 17.0.8.1+1 (#40035) 2023-09-25 05:09:30 +02:00
Rocco Meli
7e4a6160b9 namd: Add NAMD 3.0b3 and ARM support (#40134) 2023-09-25 05:04:17 +02:00
dependabot[bot]
646e7b4b00 build(deps): bump black in /.github/workflows/style (#40165)
Bumps [black](https://github.com/psf/black) from 23.1.0 to 23.9.1.
- [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/23.1.0...23.9.1)

---
updated-dependencies:
- dependency-name: black
  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>
2023-09-24 17:48:02 +00:00
eugeneswalker
eea86c3981 new package: ecmwf-atlas (#40136) 2023-09-24 10:43:09 -06:00
dependabot[bot]
37c48fc82c build(deps): bump urllib3 from 2.0.4 to 2.0.5 in /lib/spack/docs (#40119)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.4 to 2.0.5.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.0.4...v2.0.5)

---
updated-dependencies:
- dependency-name: urllib3
  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>
2023-09-24 17:35:48 +02:00
George Young
47daba3dc1 blast-plus: add 2.14.1 (#40179)
Co-authored-by: LMS Bioinformatics <bioinformatics@lms.mrc.ac.uk>
2023-09-24 09:33:38 -06:00
Brian Vanderwende
46062d98fd visit: Add NetCDF format support (#40065) 2023-09-24 17:26:34 +02:00
François Trahay
4e37084ed4 EZTrace: add v2.1 (#39748) 2023-09-24 17:12:32 +02:00
Thomas Madlener
e7c229393d garfieldpp: Fix the signature of setup_dependent_build_environment (#40133) 2023-09-24 17:04:41 +02:00
Houjun Tang
87fd9c3e93 sw4: add v3.0 (#40146) 2023-09-24 16:54:32 +02:00
snehring
676f2a3175 hmmer: adding new version 3.4 (#40148) 2023-09-24 16:53:18 +02:00
Adam J. Stewart
5fe7f5329b py-torchvision: minimize dependencies (#40163) 2023-09-24 16:27:09 +02:00
Adam J. Stewart
c6a3dd03ab py-torchmetrics: add v1.2.0 (#40164) 2023-09-24 16:25:34 +02:00
Hartmut Kaiser
ebdd5e28f2 flecsi: bumping HPX requirement to V1.9.1 (#32355) 2023-09-24 16:24:33 +02:00
dependabot[bot]
068abdd105 build(deps): bump mypy from 1.5.0 to 1.5.1 in /.github/workflows/style (#40166)
Bumps [mypy](https://github.com/python/mypy) from 1.5.0 to 1.5.1.
- [Commits](https://github.com/python/mypy/compare/v1.5.0...v1.5.1)

---
updated-dependencies:
- dependency-name: mypy
  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>
2023-09-24 16:21:41 +02:00
dependabot[bot]
9ec372a86c build(deps): bump actions/checkout from 4.0.0 to 4.1.0 (#40172)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](3df4ab11eb...8ade135a41)

---
updated-dependencies:
- dependency-name: actions/checkout
  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>
2023-09-24 16:08:15 +02:00
Alec Scott
5e05f6b7c6 bfs: add v3.0.2 (#40176) 2023-09-24 15:53:15 +02:00
Alec Scott
7988d8c67d glab: add v1.33.0 (#40177) 2023-09-24 15:53:01 +02:00
Alec Scott
658a3f2fdb hugo: add v0.118.2 (#40178) 2023-09-24 15:52:42 +02:00
Rocco Meli
582f0289af Add mda-xdrlib and update pyedr and panedr (#39912)
* ensure umpire~cuda~rocm when ~cuda~rocm

* Add mda-xdrlib and update pyedr and panedr

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

Co-authored-by: Manuela Kuhn <36827019+manuelakuhn@users.noreply.github.com>

* code review

* fix python pin, conflated with py-tomli

---------

Co-authored-by: Manuela Kuhn <36827019+manuelakuhn@users.noreply.github.com>
2023-09-24 02:07:59 -06:00
eugeneswalker
95b737d923 trilinos +shylu: patch to resolve trilinos issue #12048 (#40169)
* trilinos +shylu: patch to resolve trilinos issue #12048

* e4s ci: build xyce ^trilinos+shylu

---------

Co-authored-by: Seth R. Johnson <johnsonsr@ornl.gov>
2023-09-24 16:28:03 +09:00
Adam J. Stewart
d7e9a13f53 protobuf: add v4.24.3 (#40152) 2023-09-23 20:04:10 +02:00
Tom Payerle
25e45f9f07 py-tinyarray: add version 1.2.4, needed for python@3.10 (#40171)
* py-tinyarray: add version 1.2.4, needed for python@3.10

Added @1.2.4
Require @1.2.4 when using python@3.10:

* py-tinyarray: format fix
2023-09-23 08:57:46 -05:00
Cameron Smith
38cc51ec36 pumi: add version 2.2.8 (#40143) 2023-09-22 14:38:46 -07:00
Massimiliano Culpo
5c10c29923 Pin the version of tools used in CI, have dependabot manage their version (#40066) 2023-09-22 10:33:01 -07:00
eugeneswalker
daf95227bf e4s cray rhel stack: expand to full spec list (#40111)
* e4s cray rhel stack: expand to full spec list

* comment out gasnet; require %gcc for unzip

* require openblas@0.3.20 to get around %cce error; follow up with issue report

* comment out failing specs;

* comment out axom and xyce due to errors

* improve clarity of failing specs
2023-09-22 16:04:20 +00:00
Adam J. Stewart
480a5e0848 py-pyzmq: fix order of decorators (#40157) 2023-09-22 17:20:56 +02:00
Satish Balay
783e253f7d llvm: add version 17.0.1 (#40108) 2023-09-22 14:41:23 +02:00
Harmen Stoppels
716196930a Remove distutils dependency in Spack (#40153)
* msvc.py: don't import distutils

Introduced in #27021, makes Spack forward incompatible with Python.

The module was already deprecated at the time of the PR.

* update spack package
2023-09-22 13:04:58 +02:00
Adam J. Stewart
f42402129a py-matplotlib: add v3.7.3 (#39961) 2023-09-22 11:23:57 +02:00
Adam J. Stewart
419878f035 Add support for macOS Sonoma (#40115) 2023-09-22 04:21:26 -05:00
Harmen Stoppels
32927fd1c1 py-pyzmq: force recythonize of older versions (#40151) 2023-09-22 03:18:34 -06:00
Harmen Stoppels
092a5a8d75 py-gpy: re-cythonize & drop python upperbound (#40089)
* py-gpy: drop cython induced python upperbound

* py-gpy: bump scipy

* py-fn-py: python bounds for old version, new version w/o

* py-statsmodels: force recythonization

* py-gpy: clarifying comment about cython build type
2023-09-22 04:18:01 -05:00
Adam J. Stewart
f082b19058 py-pyproj: add v3.6.1 (#40128) 2023-09-22 03:29:37 -05:00
Harmen Stoppels
eb7e26006f py-hpbandster: use build/run deps instead of build (#40102) 2023-09-22 02:18:39 -06:00
Adam J. Stewart
2d3d9640dc py-pandas: add v2.1.1 (#40127) 2023-09-22 10:16:01 +02:00
Adam J. Stewart
f95080393a libzmq: fix build with Apple Clang 15.0.0 (#40116) 2023-09-22 10:14:43 +02:00
Adam J. Stewart
0b8203940a OpenBLAS: add v0.3.24 (#40132)
Co-authored-by: adamjstewart <adamjstewart@users.noreply.github.com>
2023-09-22 08:58:23 +02:00
Adam J. Stewart
3bd7859e7f py-scikit-learn: add v1.3.1 (#40126) 2023-09-22 08:39:38 +02:00
eugeneswalker
599b612edf add met v11.1.0 (#40138) 2023-09-22 08:35:10 +02:00
eugeneswalker
6f9126d738 add metplus v5.1.0 (#40139) 2023-09-22 08:30:38 +02:00
eugeneswalker
59399ab1f8 add scotch v7.0.4 (#40140) 2023-09-22 08:30:22 +02:00
Lydéric Debusschère
b67f619448 py-aiofiles: Add version 0.7.0 required by py-cylc-flow (#39987)
* py-aiofiles: Add version 0.7.0 required by py-cylc-flow

* py-aiofiles: update from review

* depends on py-setuptools before 0.6
* depends on py-poetry-core after 0.7

Co-authored-by: Manuela Kuhn <36827019+manuelakuhn@users.noreply.github.com>

* py-aiofiles: Taking reviewing into account; add a upper version constraint for Python.

* py-aiofiles: update from review, set lower version of python

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

---------

Co-authored-by: Manuela Kuhn <36827019+manuelakuhn@users.noreply.github.com>
Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2023-09-22 00:29:03 -05:00
eugeneswalker
2755706115 Revert "e4s-cray: drop in ci as there are no runners (#40122)" (#40144)
This reverts commit bd8d0324a9.
2023-09-21 22:38:26 -06:00
Thiago Genez
43ed8a12b7 openssh: Fix segfault on x86_64-darwin (#40044)
Import patches from homebrew
2023-09-22 01:41:22 +02:00
Alex Richert
3f5b4a4907 Update grib-util package.py (#40120) 2023-09-21 14:15:06 -07:00
Garth N. Wells
cd16478aba py-fenics-dolfinx: add version upper bound for Python dependency (#40125)
* py-fenics-dolfinx: add upper bound on Python version

* Small fix

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>

---------

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2023-09-21 13:17:45 -06:00
Rocco Meli
aa87c747f9 Add missing platform in Charm++ (#40051)
Add missing `linux` platform in Charm++ when building for `arm8`.
2023-09-21 20:31:17 +02:00
Steven R. Brandt
9210b19398 lorene: add C++ headers to the install (#39909) 2023-09-21 20:27:23 +02:00
George Young
4d156b9e6b relion: add 4.0.1, fix build on Rocky8 (#40074)
Co-authored-by: LMS Bioinformatics <bioinformatics@lms.mrc.ac.uk>
2023-09-21 20:24:03 +02:00
Jonas Thies
56df8b61a2 phist: fix compatibility with python@3.11: (#40082) 2023-09-21 20:21:35 +02:00
Anton Kozhevnikov
170867e38a SIRIUS: remove old versions (#40105) 2023-09-21 20:18:58 +02:00
Wileam Y. Phan
5ca9fd6c82 Fix false detection of llvm-amdgpu as llvm and llvm-doe (#40113) 2023-09-21 20:15:20 +02:00
Robert Underwood
ef165c80b3 py-nanobind add cmake path (#40079)
* py-nanobind add cmake path

* fix style

---------

Co-authored-by: Robert Underwood <runderwood@anl.gov>
2023-09-21 13:15:02 -05:00
Lydéric Debusschère
6859694e8e [add] py-graphql-ws: new recipe, required by py-cylc-uiserver (#39991)
* [add] py-graphql-ws: new recipe, required by py-cylc-uiserver

* py-graphql-ws: remove constraint on version for python
2023-09-21 13:14:11 -05:00
John W. Parent
aeaca77630 Harden compiler detection against errors (#39736)
Fixes #39622

Add a timeout to compiler detection and allow Spack to proceed when
this timeout occurs.

In all cases, the timeout is 120 seconds: it is assumed any compiler
invocation we do for the purposes of verifying it would resolve in
that amount of time.

Also refine executables that are tested as being possible MSVC
instances, and limit where we try to detect MSVC. In more detail:

* Compiler detection should timeout after a certain period of time.
  Because compiler detection executes arbitrary executables on the
  system, we could encounter a program that just hangs, or even a
  compiler that hangs on a license key or similar. A timeout
  prevents this from hanging Spack.
* Prevents things like cl-.* from being detected as potential MSVC
  installs. cl is always just cl in all cases that Spack supports.
  Change the MSVC class to indicate this.
* Prevent compilers unsupported on certain platforms from being
  detected there (i.e. don't look for MSVC on systems other than
  Windows).

The first point alone is sufficient to address #39622, but the
next two reduce the likelihood of timeouts (which is useful since
those slow down the user even if they are survivable).
2023-09-21 10:42:12 -07:00
AMD Toolchain Support
2a9d1d444b aocl-sparse: use .libs instead of hard-coded value for library computation (#39868)
Co-authored-by: matooley <phil.tooley@amd.com>
2023-09-21 18:47:29 +02:00
Massimiliano Culpo
abad16c198 Restore virtuals normalization on edge construction (#40130)
Put back normalization of the "virtuals" input as a sorted tuple. 

Without this we might get edges that differ just for the order of 
virtuals, or that have lists, which are not hashable.

Add unit-tests to prevent regressions.
2023-09-21 17:02:34 +02:00
Massimiliano Culpo
4c0bc39054 Remove Python 3.6 from bootstrap tests on Ubuntu, add 3.11 (#40131) 2023-09-21 15:14:47 +02:00
Harmen Stoppels
501d322264 e4s: drop python 3.8 preference (#40123) 2023-09-21 15:07:21 +02:00
Manuela Kuhn
59fc09e93f py-versioneer: add 0.29 (#40076) 2023-09-21 07:22:20 -05:00
Harmen Stoppels
8bd54e2f8f cython: fix recythonize by default patch (#40096) 2023-09-21 07:09:47 -05:00
Sinan
bd8d121a23 package:pylint fix isort dependency versions (#40094)
Co-authored-by: sbulut <sbulut@3vgeomatics.com>
2023-09-21 06:43:44 -05:00
Lydéric Debusschère
2bd487988f [add] py-ansimarkup: new recipe required by py-cylc-flow (#39989)
* [add] py-ansimarkup: new recipe required by py-cylc-flow

* py-ansimarkup: remove version constraint on python, add version 2.1.0
2023-09-21 06:36:15 -05:00
Manuela Kuhn
452e56f467 py-vcrpy: add 5.1.0 (#40075) 2023-09-21 06:28:25 -05:00
Christian Glusa
62e94b0cb7 py-scikit-sparse: add 0.4.11, 0.4.12 (#40077) 2023-09-21 06:27:04 -05:00
Thomas Dickerson
5d331d4141 Bazel patch specs were too restrictive (#40084)
These patches should always be applied - the existing Bazel code is always wrong, working on some older compilers was a lucky fluke.
2023-09-21 05:27:11 -05:00
Harmen Stoppels
bd8d0324a9 e4s-cray: drop in ci as there are no runners (#40122) 2023-09-21 09:54:06 +00:00
Adam J. Stewart
d79a3ecc28 py-gevent: relax dependency constraints (#40117) 2023-09-21 09:00:28 +02:00
Harmen Stoppels
dac3b45387 gptune: doesnt depend on cython (#40104) 2023-09-20 15:31:45 -07:00
Dom Heinzeller
31fe78e378 ESMF package: fix netcdf static libs and variant combinations (#39738)
Add "snapshot" variant for identifying UFS WM support
2023-09-20 10:28:52 -07:00
Patrick Gartung
e16ca49036 Revert PR 40091 which duplicates PR 38987 (#40107) 2023-09-20 13:03:49 -04:00
Auriane R
a7ee72708a Add support for C++23 in pika and pika-algorithms packages (#40078)
* Add C++23 support for pika

* Add C++23 support for pika-algorithms as well
2023-09-20 09:28:25 -06:00
Auriane R
c4a53cf376 Add 23 and 26 to the cxxstd variant for boost (#40081) 2023-09-20 16:21:06 +02:00
Massimiliano Culpo
e963d02a07 Fix a leftover typo from depflag rework (#40101) 2023-09-20 14:16:53 +00:00
Harmen Stoppels
f89451b4b8 cython: add build-tools tag (#40100) 2023-09-20 15:18:04 +02:00
Raffaele Solcà
9c87506c2c DLA-Future: add v0.2.1 (#40098) 2023-09-20 14:58:23 +02:00
Auriane R
35223543e9 Add 23 to the cxxstd variant of fmt (#40080) 2023-09-20 11:20:41 +02:00
Marc Mengel
e1b22325ea Add details on error messages from requirements (#40092) 2023-09-20 06:16:29 +02:00
Patrick Gartung
2389047072 Fix error in qt5.15 building qtlocation with gcc13 (#40091) 2023-09-19 16:18:34 -06:00
Richard Berger
f49c58708b FleCSI updates (#40087)
* flecsi: update description and flog variant help
* flecsi: use kokkos_cxx when needed
2023-09-19 14:28:13 -06:00
Daryl W. Grunau
d916073397 eospac: expose version 6.5.7 (#40060)
Co-authored-by: Daryl W. Grunau <dwg@lanl.gov>
2023-09-19 11:44:20 -07:00
AMD Toolchain Support
bfa514af98 python version dependency for supporting nwchem-702 build (#40072)
Co-authored-by: viveshar <vivek.sharma2@amd.com>
2023-09-19 11:41:04 -07:00
Harmen Stoppels
c57e2140c2 ci: dont use nightly image tag (#40070) 2023-09-19 17:53:28 +02:00
Tuomas Koskela
9e21d490ea conquest: add new package (#40053) 2023-09-19 09:38:37 -06:00
Massimiliano Culpo
3b4ca0374e Use process pool executors for web-crawling and retrieving archives (#39888)
Fix a race condition when searching urls, and updating a shared
set '_visited'.
2023-09-19 15:32:59 +02:00
Harmen Stoppels
7d33c36a30 ci: drop redundant packages.yaml (#40068) 2023-09-19 11:47:48 +02:00
Massimiliano Culpo
4f14db19c4 ASP-based solver: declare deprecated versions iff config:deprecated:true (#40011)
By default, do not let deprecated versions enter the solve.

Previously you could concretize to something deprecated, only to get errors on install.

With this commit, we get errors on concretization, so the issue is caught earlier.
2023-09-19 09:44:49 +00:00
AMD Toolchain Support
a0dcf9620b Lammps: don't apply AOCC patches to versions containing the backport (#39844)
Co-authored-by: Phil Tooley <phil.tooley@amd.com>
2023-09-19 08:52:15 +02:00
Tim Haines
9a9c3a984b extrae: add versions 4.0.5, 4.0.6 (#40063) 2023-09-19 08:45:59 +02:00
Manuela Kuhn
a3543e2248 py-typing-extensions: add 4.8.0 (#40049) 2023-09-19 01:02:31 -05:00
Adam J. Stewart
4cdbb04b15 py-lightning: add v2.0.8/9 (#40058) 2023-09-18 21:13:24 -06:00
Adam J. Stewart
2594be9459 py-rarfile: add v4.1 (#40054) 2023-09-18 19:58:39 -06:00
Scott Wittenburg
8f07983ab6 adios2: add smoke tests (#39970) 2023-09-18 19:43:46 -06:00
dependabot[bot]
8e34eaaa75 build(deps): bump docker/setup-buildx-action from 2.10.0 to 3.0.0 (#39967)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.10.0 to 3.0.0.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](885d1462b8...f95db51fdd)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  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>
2023-09-19 00:48:30 +00:00
Andrew-Dunning-NNL
7e7d373ab3 mdspan: new package (#40024)
* new package mdspan

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

Co-authored-by: Alec Scott <alec@bcs.sh>

* mdspan- fix style

---------

Co-authored-by: Alec Scott <alec@bcs.sh>
2023-09-18 18:44:17 -06:00
Adam J. Stewart
dbd520f851 Better detection of Python libs/headers (#39308) 2023-09-18 15:46:33 -07:00
afzpatel
4fd7fa5fc1 new package composable kernel (#39222)
* initial commit to add composable kernel package
* change dependencies to type build and add amdgpu_target variant
* fix spacing
* fix styling
* remove rocmmlir from miopen-hip recipe
* enable miopen with ck after 5.5.1
* fix typo
2023-09-18 14:24:45 -07:00
Johann Gaebler
84d2097a8c r-wru: Add R package wru (#39935) 2023-09-18 14:15:56 -07:00
Brian Vanderwende
842f19c6e3 grads: add versions and variants (#40017)
* Add grads versions, variants, and dependency
* Bugfix for hdf4 libs and style fixes
* Switch boolean variant checking syntax
2023-09-18 13:34:46 -07:00
eugeneswalker
577ea0a0a8 pmix: new versions (#40055) 2023-09-18 12:47:36 -07:00
Brian Vanderwende
4d8f9ff3e8 xxdiff: add new package (#40021)
* Add new package xxdiff

* style fixes

* Versioning updates to match best practices

* Full hash and flex, bison as build deps
2023-09-18 12:40:22 -07:00
rfeki
60ce6c7302 Add cuda as a variant to opa-psm2 (#39754)
Signed-off-by: Raafat Feki <rfeki@cornelisnetworks.com>
2023-09-18 12:28:37 -07:00
Manuela Kuhn
d111bde69e py-tqdm: add 4.66.1 (#39952) 2023-09-18 13:04:39 -06:00
eugeneswalker
3045ed0e43 Revert "gitlab ci: temporarily disable darwin aarch64 (#39974)" (#40052)
This reverts commit 2c13361b09.
2023-09-18 12:48:32 -06:00
Freifrau von Bleifrei
2de0e30016 SeLaLib: add new package (#39847) 2023-09-18 13:15:10 -05:00
Manuela Kuhn
15085ef6e5 py-tornado: add 6.3.3 (#39949)
* py-tornado: add 6.3.3

* Fix style
2023-09-18 11:18:36 -06:00
Manuela Kuhn
0c2849da4d py-twine: add 4.0.2 (#40026) 2023-09-18 11:50:51 -05:00
Manuela Kuhn
75eeab1297 py-types-psutil: add 5.9.5.16 (#40027) 2023-09-18 11:49:20 -05:00
Dom Heinzeller
b8e32ff6b3 Fix several build errors for hdf-eos2 (not only but in particular on macOS w/ apple-clang) (#39877)
Fix permissions for configure file in var/spack/repos/builtin/packages/hdf-eos2/package.py, fix dependencies to match what hdf provides, update compiler flags for apple-clang
2023-09-18 18:47:25 +02:00
Manuela Kuhn
e7924148af py-types-typed-ast: add 1.5.8.7 (#40047) 2023-09-18 11:47:00 -05:00
Manuela Kuhn
d454cf4711 py-types-urllib3: add 1.26.25.14 (#40048)
* py-types-urllib3: add 1.26.25.14

* Fix style
2023-09-18 11:44:26 -05:00
George Young
ba81ef50f5 cpat: new package @3.0.4 (#40022)
* cpat: new package @3.0.4

* Update package.py

---------

Co-authored-by: LMS Bioinformatics <bioinformatics@lms.mrc.ac.uk>
2023-09-18 11:37:21 -05:00
Manuela Kuhn
d5dd4b8b5d py-types-python-dateutil: add 2.8.19.14 (#40038) 2023-09-18 11:34:53 -05:00
Manuela Kuhn
0e47548cb6 py-types-requests: add 2.31.0.2 (#40039) 2023-09-18 11:34:01 -05:00
Manuela Kuhn
74974d85f6 py-types-setuptools: add 68.2.0.0 (#40040) 2023-09-18 11:33:01 -05:00
dependabot[bot]
7925bb575e build(deps): bump docker/login-action from 2.2.0 to 3.0.0 (#39966)
Bumps [docker/login-action](https://github.com/docker/login-action) from 2.2.0 to 3.0.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](465a07811f...343f7c4344)

---
updated-dependencies:
- dependency-name: docker/login-action
  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>
2023-09-18 18:23:37 +02:00
dependabot[bot]
976cb02f78 build(deps): bump docker/setup-qemu-action from 2.2.0 to 3.0.0 (#39968)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2.2.0 to 3.0.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](2b82ce82d5...68827325e0)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  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>
2023-09-18 18:22:58 +02:00
dependabot[bot]
f1bdc74789 build(deps): bump docker/build-push-action from 4.2.1 to 5.0.0 (#39969)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4.2.1 to 5.0.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](0a97817b6a...0565240e2d)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  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>
2023-09-18 18:22:41 +02:00
Lydéric Debusschère
920347c21a py-werkzeug: Add version 0.12.2 required by py-graphene-tornado @2.6.1 (#39984) 2023-09-18 11:21:22 -05:00
Ben Cowan
c00ece6cf2 Enabled building GCC 13.1 on darwin/aarch64. (#38667) 2023-09-18 18:20:19 +02:00
Juan Miguel Carceller
7b0157c7e7 python: Don't prefer 3.10 (#40036) 2023-09-18 10:08:49 -06:00
Lydéric Debusschère
1b3a2ba06a [add] py-ldap3: new recipe, required by py-metomi-rose (#39982) 2023-09-18 11:06:23 -05:00
Manuela Kuhn
dc22a80f86 py-traits: add 6.4.2 (#39976) 2023-09-18 10:57:47 -05:00
Manuela Kuhn
27d6a75692 py-trove-classifiers: add 2023.8.7 (#39977) 2023-09-18 10:50:55 -05:00
George Young
70456ce4a7 py-rseqc: add 5.0.1 (#39953)
* py-rseqec: add 5.0.1

* Update package.py

* style ...

---------

Co-authored-by: LMS Bioinformatics <bioinformatics@lms.mrc.ac.uk>
2023-09-18 10:49:58 -05:00
Lydéric Debusschère
078369ec2b [chore] py-aniso8601: Add version 7.0.0 (#39808)
* [chore] py-aniso8601: Add version 3.0.2 required by py-graphene

* py-aniso8601: Add version 7.0.0 and constraints on python version

* py-aniso8601: fix style

* [fix] py-aniso8601: remove version 3.0.2 which depends on removed version of python; set the minimal version of python to 3.7

* py-aniso8601: remove version constraint on python
2023-09-18 10:46:30 -05:00
Diego Alvarez S
da8e022f6b Nextflow: add 22.04.3 (#40034) 2023-09-18 17:39:27 +02:00
George Young
c8a3f1a8ae chexmix: new package (#38441)
Co-authored-by: LMS Bioinformatics <bioinformatics@lms.mrc.ac.uk>
2023-09-18 17:36:44 +02:00
Michael Kuhn
be3f7b5da3 checksum: use FIXME instead of FIX ME when adding versions (#40050)
The former is highlighted by editors, while the latter is not.
2023-09-18 17:31:11 +02:00
Martin Aumüller
68d7ce3bb6 coin3d: apply upstream patches to fix build on Centos 8 (#39839)
fixes undefined references to dlerror, dlopen, dlsym, dlclose and
XDefaultScreenOfDisplay, XScreenNumberOfScreen, XCreatePixmap, XFree, XFreePixmap, XCloseDisplay, XOpenDisplay
2023-09-18 17:16:56 +02:00
Rémi Lacroix
7a490e95b6 Julia: Fix sha256 for some LLVM patches (#40041) 2023-09-18 10:52:00 +02:00
594 changed files with 19161 additions and 5201 deletions

View File

@@ -10,3 +10,8 @@ updates:
directory: "/lib/spack/docs"
schedule:
interval: "daily"
# Requirements to run style checks
- package-ecosystem: "pip"
directory: "/.github/workflows/style"
schedule:
interval: "daily"

View File

@@ -22,8 +22,8 @@ jobs:
matrix:
operating_system: ["ubuntu-latest", "macos-latest"]
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # @v2
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # @v2
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # @v2
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # @v2
with:
python-version: ${{inputs.python_version}}
- name: Install Python packages
@@ -34,6 +34,7 @@ jobs:
run: |
. share/spack/setup-env.sh
coverage run $(which spack) audit packages
coverage run $(which spack) audit externals
coverage combine
coverage xml
- name: Package audits (without coverage)
@@ -41,6 +42,7 @@ jobs:
run: |
. share/spack/setup-env.sh
$(which spack) audit packages
$(which spack) audit externals
- uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # @v2.1.0
if: ${{ inputs.with_coverage == 'true' }}
with:

View File

@@ -24,7 +24,7 @@ jobs:
make patch unzip which xz python3 python3-devel tree \
cmake bison bison-devel libstdc++-static
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
- name: Setup non-root user
@@ -42,8 +42,8 @@ jobs:
shell: runuser -u spack-test -- bash {0}
run: |
source share/spack/setup-env.sh
spack bootstrap disable github-actions-v0.5
spack bootstrap disable github-actions-v0.4
spack bootstrap disable github-actions-v0.3
spack external find cmake bison
spack -d solve zlib
tree ~/.spack/bootstrap/store/
@@ -62,7 +62,7 @@ jobs:
make patch unzip xz-utils python3 python3-dev tree \
cmake bison
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
- name: Setup non-root user
@@ -80,8 +80,8 @@ jobs:
shell: runuser -u spack-test -- bash {0}
run: |
source share/spack/setup-env.sh
spack bootstrap disable github-actions-v0.5
spack bootstrap disable github-actions-v0.4
spack bootstrap disable github-actions-v0.3
spack external find cmake bison
spack -d solve zlib
tree ~/.spack/bootstrap/store/
@@ -99,7 +99,7 @@ jobs:
bzip2 curl file g++ gcc gfortran git gnupg2 gzip \
make patch unzip xz-utils python3 python3-dev tree
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
- name: Setup non-root user
@@ -133,7 +133,7 @@ jobs:
make patch unzip which xz python3 python3-devel tree \
cmake bison
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
- name: Setup repo
@@ -145,8 +145,8 @@ jobs:
- name: Bootstrap clingo
run: |
source share/spack/setup-env.sh
spack bootstrap disable github-actions-v0.5
spack bootstrap disable github-actions-v0.4
spack bootstrap disable github-actions-v0.3
spack external find cmake bison
spack -d solve zlib
tree ~/.spack/bootstrap/store/
@@ -158,13 +158,13 @@ jobs:
run: |
brew install cmake bison@2.7 tree
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
- name: Bootstrap clingo
run: |
source share/spack/setup-env.sh
export PATH=/usr/local/opt/bison@2.7/bin:$PATH
spack bootstrap disable github-actions-v0.5
spack bootstrap disable github-actions-v0.4
spack bootstrap disable github-actions-v0.3
spack external find --not-buildable cmake bison
spack -d solve zlib
tree ~/.spack/bootstrap/store/
@@ -179,11 +179,11 @@ jobs:
run: |
brew install tree
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
- name: Bootstrap clingo
run: |
set -ex
for ver in '3.6' '3.7' '3.8' '3.9' '3.10' ; do
for ver in '3.7' '3.8' '3.9' '3.10' '3.11' ; do
not_found=1
ver_dir="$(find $RUNNER_TOOL_CACHE/Python -wholename "*/${ver}.*/*/bin" | grep . || true)"
echo "Testing $ver_dir"
@@ -204,7 +204,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
- name: Setup repo
@@ -214,7 +214,7 @@ jobs:
- name: Bootstrap clingo
run: |
set -ex
for ver in '3.6' '3.7' '3.8' '3.9' '3.10' ; do
for ver in '3.7' '3.8' '3.9' '3.10' '3.11' ; do
not_found=1
ver_dir="$(find $RUNNER_TOOL_CACHE/Python -wholename "*/${ver}.*/*/bin" | grep . || true)"
echo "Testing $ver_dir"
@@ -247,7 +247,7 @@ jobs:
bzip2 curl file g++ gcc patchelf gfortran git gzip \
make patch unzip xz-utils python3 python3-dev tree
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
- name: Setup non-root user
@@ -265,6 +265,7 @@ jobs:
shell: runuser -u spack-test -- bash {0}
run: |
source share/spack/setup-env.sh
spack bootstrap disable github-actions-v0.4
spack bootstrap disable spack-install
spack -d gpg list
tree ~/.spack/bootstrap/store/
@@ -283,7 +284,7 @@ jobs:
make patch unzip xz-utils python3 python3-dev tree \
gawk
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
- name: Setup non-root user
@@ -302,8 +303,8 @@ jobs:
run: |
source share/spack/setup-env.sh
spack solve zlib
spack bootstrap disable github-actions-v0.5
spack bootstrap disable github-actions-v0.4
spack bootstrap disable github-actions-v0.3
spack -d gpg list
tree ~/.spack/bootstrap/store/
@@ -316,10 +317,11 @@ jobs:
# Remove GnuPG since we want to bootstrap it
sudo rm -rf /usr/local/bin/gpg
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
- name: Bootstrap GnuPG
run: |
source share/spack/setup-env.sh
spack bootstrap disable github-actions-v0.4
spack bootstrap disable spack-install
spack -d gpg list
tree ~/.spack/bootstrap/store/
@@ -333,13 +335,13 @@ jobs:
# Remove GnuPG since we want to bootstrap it
sudo rm -rf /usr/local/bin/gpg
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
- name: Bootstrap GnuPG
run: |
source share/spack/setup-env.sh
spack solve zlib
spack bootstrap disable github-actions-v0.5
spack bootstrap disable github-actions-v0.4
spack bootstrap disable github-actions-v0.3
spack -d gpg list
tree ~/.spack/bootstrap/store/

View File

@@ -56,7 +56,7 @@ jobs:
if: github.repository == 'spack/spack'
steps:
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # @v2
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # @v2
- name: Set Container Tag Normal (Nightly)
run: |
@@ -92,13 +92,13 @@ jobs:
path: dockerfiles
- name: Set up QEMU
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # @v1
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # @v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # @v1
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # @v1
- name: Log in to GitHub Container Registry
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # @v1
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # @v1
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -106,13 +106,13 @@ jobs:
- name: Log in to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # @v1
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # @v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build & Deploy ${{ matrix.dockerfile[0] }}
uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # @v2
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # @v2
with:
context: dockerfiles/${{ matrix.dockerfile[0] }}
platforms: ${{ matrix.dockerfile[1] }}

View File

@@ -35,7 +35,7 @@ jobs:
core: ${{ steps.filter.outputs.core }}
packages: ${{ steps.filter.outputs.packages }}
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # @v2
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # @v2
if: ${{ github.event_name == 'push' }}
with:
fetch-depth: 0

View File

@@ -14,10 +14,10 @@ jobs:
build-paraview-deps:
runs-on: windows-latest
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236
with:
python-version: 3.9
- name: Install Python packages

View File

@@ -0,0 +1,7 @@
black==23.9.1
clingo==5.6.2
flake8==6.1.0
isort==5.12.0
mypy==1.6.0
types-six==1.16.21.9
vermin==1.5.2

View File

@@ -15,7 +15,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
concretizer: ['clingo']
on_develop:
- ${{ github.ref == 'refs/heads/develop' }}
@@ -45,12 +45,16 @@ jobs:
os: ubuntu-latest
concretizer: 'clingo'
on_develop: false
- python-version: '3.11'
os: ubuntu-latest
concretizer: 'clingo'
on_develop: false
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # @v2
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # @v2
with:
fetch-depth: 0
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # @v2
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # @v2
with:
python-version: ${{ matrix.python-version }}
- name: Install System packages
@@ -94,10 +98,10 @@ jobs:
shell:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # @v2
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # @v2
with:
fetch-depth: 0
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # @v2
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # @v2
with:
python-version: '3.11'
- name: Install System packages
@@ -133,7 +137,7 @@ jobs:
dnf install -y \
bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \
make patch tcl unzip which xz
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # @v2
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # @v2
- name: Setup repo and non-root user
run: |
git --version
@@ -152,10 +156,10 @@ jobs:
clingo-cffi:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # @v2
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # @v2
with:
fetch-depth: 0
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # @v2
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # @v2
with:
python-version: '3.11'
- name: Install System packages
@@ -185,12 +189,12 @@ jobs:
runs-on: macos-latest
strategy:
matrix:
python-version: ["3.10"]
python-version: ["3.11"]
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # @v2
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # @v2
with:
fetch-depth: 0
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # @v2
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # @v2
with:
python-version: ${{ matrix.python-version }}
- name: Install Python packages

View File

@@ -18,15 +18,15 @@ jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # @v2
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # @v2
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236
with:
python-version: '3.11'
cache: 'pip'
- name: Install Python Packages
run: |
pip install --upgrade pip
pip install --upgrade vermin
pip install --upgrade pip setuptools
pip install -r .github/workflows/style/requirements.txt
- name: vermin (Spack's Core)
run: vermin --backport importlib --backport argparse --violations --backport typing -t=3.6- -vvv lib/spack/spack/ lib/spack/llnl/ bin/
- name: vermin (Repositories)
@@ -35,16 +35,17 @@ jobs:
style:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # @v2
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # @v2
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236
with:
python-version: '3.11'
cache: 'pip'
- name: Install Python packages
run: |
python3 -m pip install --upgrade pip setuptools types-six black==23.1.0 mypy isort clingo flake8
pip install --upgrade pip setuptools
pip install -r .github/workflows/style/requirements.txt
- name: Setup git configuration
run: |
# Need this for the git tests to succeed.
@@ -68,7 +69,7 @@ jobs:
dnf install -y \
bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \
make patch tcl unzip which xz
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # @v2
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # @v2
- name: Setup repo and non-root user
run: |
git --version

View File

@@ -15,10 +15,10 @@ jobs:
unit-tests:
runs-on: windows-latest
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236
with:
python-version: 3.9
- name: Install Python packages
@@ -39,10 +39,10 @@ jobs:
unit-tests-cmd:
runs-on: windows-latest
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236
with:
python-version: 3.9
- name: Install Python packages
@@ -63,10 +63,10 @@ jobs:
build-abseil:
runs-on: windows-latest
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236
with:
python-version: 3.9
- name: Install Python packages

View File

@@ -27,12 +27,53 @@
# And here's the CITATION.cff format:
#
cff-version: 1.2.0
type: software
message: "If you are referencing Spack in a publication, please cite the paper below."
title: "The Spack Package Manager: Bringing Order to HPC Software Chaos"
abstract: >-
Large HPC centers spend considerable time supporting software for thousands of users, but the complexity of HPC software is quickly outpacing the capabilities of existing software management tools.
Scientific applications require specific versions of compilers, MPI, and other dependency libraries, so using a single, standard software stack is infeasible.
However, managing many configurations is difficult because the configuration space is combinatorial in size.
We introduce Spack, a tool used at Lawrence Livermore National Laboratory to manage this complexity.
Spack provides a novel, re- cursive specification syntax to invoke parametric builds of packages and dependencies.
It allows any number of builds to coexist on the same system, and it ensures that installed packages can find their dependencies, regardless of the environment.
We show through real-world use cases that Spack supports diverse and demanding applications, bringing order to HPC software chaos.
preferred-citation:
title: "The Spack Package Manager: Bringing Order to HPC Software Chaos"
type: conference-paper
doi: "10.1145/2807591.2807623"
url: "https://github.com/spack/spack"
url: "https://tgamblin.github.io/pubs/spack-sc15.pdf"
authors:
- family-names: "Gamblin"
given-names: "Todd"
- family-names: "LeGendre"
given-names: "Matthew"
- family-names: "Collette"
given-names: "Michael R."
- family-names: "Lee"
given-names: "Gregory L."
- family-names: "Moody"
given-names: "Adam"
- family-names: "de Supinski"
given-names: "Bronis R."
- family-names: "Futral"
given-names: "Scott"
conference:
name: "Supercomputing 2015 (SC15)"
city: "Austin"
region: "Texas"
country: "US"
date-start: 2015-11-15
date-end: 2015-11-20
month: 11
year: 2015
identifiers:
- description: "The concept DOI of the work."
type: doi
value: 10.1145/2807591.2807623
- description: "The DOE Document Release Number of the work"
type: other
value: "LLNL-CONF-669890"
authors:
- family-names: "Gamblin"
given-names: "Todd"
- family-names: "LeGendre"
@@ -47,12 +88,3 @@ preferred-citation:
given-names: "Bronis R."
- family-names: "Futral"
given-names: "Scott"
title: "The Spack Package Manager: Bringing Order to HPC Software Chaos"
conference:
name: "Supercomputing 2015 (SC15)"
city: "Austin"
region: "Texas"
country: "USA"
month: November 15-20
year: 2015
notes: LLNL-CONF-669890

View File

@@ -9,15 +9,15 @@ bootstrap:
# may not be able to bootstrap all the software that Spack needs,
# depending on its type.
sources:
- name: 'github-actions-v0.5'
metadata: $spack/share/spack/bootstrap/github-actions-v0.5
- name: 'github-actions-v0.4'
metadata: $spack/share/spack/bootstrap/github-actions-v0.4
- name: 'github-actions-v0.3'
metadata: $spack/share/spack/bootstrap/github-actions-v0.3
- name: 'spack-install'
metadata: $spack/share/spack/bootstrap/spack-install
trusted:
# By default we trust bootstrapping from sources and from binaries
# produced on Github via the workflow
github-actions-v0.5: true
github-actions-v0.4: true
github-actions-v0.3: true
spack-install: true

View File

@@ -41,4 +41,4 @@ concretizer:
# "none": allows a single node for any package in the DAG.
# "minimal": allows the duplication of 'build-tools' nodes only (e.g. py-setuptools, cmake etc.)
# "full" (experimental): allows separation of the entire build-tool stack (e.g. the entire "cmake" subDAG)
strategy: none
strategy: minimal

View File

@@ -1,4 +1,3 @@
package_list.html
command_index.rst
spack*.rst
llnl*.rst

View File

@@ -45,7 +45,8 @@ Listing available packages
To install software with Spack, you need to know what software is
available. You can see a list of available package names at the
:ref:`package-list` webpage, or using the ``spack list`` command.
`packages.spack.io <https://packages.spack.io>`_ website, or
using the ``spack list`` command.
.. _cmd-spack-list:
@@ -60,7 +61,7 @@ can install:
:ellipsis: 10
There are thousands of them, so we've truncated the output above, but you
can find a :ref:`full list here <package-list>`.
can find a `full list here <https://packages.spack.io>`_.
Packages are listed by name in alphabetical order.
A pattern to match with no wildcards, ``*`` or ``?``,
will be treated as though it started and ended with

View File

@@ -3,6 +3,103 @@
SPDX-License-Identifier: (Apache-2.0 OR MIT)
.. _concretizer-options:
==========================================
Concretization Settings (concretizer.yaml)
==========================================
The ``concretizer.yaml`` configuration file allows to customize aspects of the
algorithm used to select the dependencies you install. The default configuration
is the following:
.. literalinclude:: _spack_root/etc/spack/defaults/concretizer.yaml
:language: yaml
--------------------------------
Reuse already installed packages
--------------------------------
The ``reuse`` attribute controls whether Spack will prefer to use installed packages (``true``), or
whether it will do a "fresh" installation and prefer the latest settings from
``package.py`` files and ``packages.yaml`` (``false``).
You can use:
.. code-block:: console
% spack install --reuse <spec>
to enable reuse for a single installation, and you can use:
.. code-block:: console
spack install --fresh <spec>
to do a fresh install if ``reuse`` is enabled by default.
``reuse: true`` is the default.
------------------------------------------
Selection of the target microarchitectures
------------------------------------------
The options under the ``targets`` attribute control which targets are considered during a solve.
Currently the options in this section are only configurable from the ``concretizer.yaml`` file
and there are no corresponding command line arguments to enable them for a single solve.
The ``granularity`` option can take two possible values: ``microarchitectures`` and ``generic``.
If set to:
.. code-block:: yaml
concretizer:
targets:
granularity: microarchitectures
Spack will consider all the microarchitectures known to ``archspec`` to label nodes for
compatibility. If instead the option is set to:
.. code-block:: yaml
concretizer:
targets:
granularity: generic
Spack will consider only generic microarchitectures. For instance, when running on an
Haswell node, Spack will consider ``haswell`` as the best target in the former case and
``x86_64_v3`` as the best target in the latter case.
The ``host_compatible`` option is a Boolean option that determines whether or not the
microarchitectures considered during the solve are constrained to be compatible with the
host Spack is currently running on. For instance, if this option is set to ``true``, a
user cannot concretize for ``target=icelake`` while running on an Haswell node.
---------------
Duplicate nodes
---------------
The ``duplicates`` attribute controls whether the DAG can contain multiple configurations of
the same package. This is mainly relevant for build dependencies, which may have their version
pinned by some nodes, and thus be required at different versions by different nodes in the same
DAG.
The ``strategy`` option controls how the solver deals with duplicates. If the value is ``none``,
then a single configuration per package is allowed in the DAG. This means, for instance, that only
a single ``cmake`` or a single ``py-setuptools`` version is allowed. The result would be a slightly
faster concretization, at the expense of making a few specs unsolvable.
If the value is ``minimal`` Spack will allow packages tagged as ``build-tools`` to have duplicates.
This allows, for instance, to concretize specs whose nodes require different, and incompatible, ranges
of some build tool. For instance, in the figure below the latest `py-shapely` requires a newer `py-setuptools`,
while `py-numpy` still needs an older version:
.. figure:: images/shapely_duplicates.svg
:scale: 70 %
:align: center
Up to Spack v0.20 ``duplicates:strategy:none`` was the default (and only) behavior. From Spack v0.21 the
default behavior is ``duplicates:strategy:minimal``.
.. _build-settings:
================================
@@ -232,76 +329,6 @@ Specific limitations include:
then Spack will not add a new external entry (``spack config blame packages``
can help locate all external entries).
.. _concretizer-options:
----------------------
Concretizer options
----------------------
``packages.yaml`` gives the concretizer preferences for specific packages,
but you can also use ``concretizer.yaml`` to customize aspects of the
algorithm it uses to select the dependencies you install:
.. literalinclude:: _spack_root/etc/spack/defaults/concretizer.yaml
:language: yaml
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Reuse already installed packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``reuse`` attribute controls whether Spack will prefer to use installed packages (``true``), or
whether it will do a "fresh" installation and prefer the latest settings from
``package.py`` files and ``packages.yaml`` (``false``).
You can use:
.. code-block:: console
% spack install --reuse <spec>
to enable reuse for a single installation, and you can use:
.. code-block:: console
spack install --fresh <spec>
to do a fresh install if ``reuse`` is enabled by default.
``reuse: true`` is the default.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Selection of the target microarchitectures
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The options under the ``targets`` attribute control which targets are considered during a solve.
Currently the options in this section are only configurable from the ``concretizer.yaml`` file
and there are no corresponding command line arguments to enable them for a single solve.
The ``granularity`` option can take two possible values: ``microarchitectures`` and ``generic``.
If set to:
.. code-block:: yaml
concretizer:
targets:
granularity: microarchitectures
Spack will consider all the microarchitectures known to ``archspec`` to label nodes for
compatibility. If instead the option is set to:
.. code-block:: yaml
concretizer:
targets:
granularity: generic
Spack will consider only generic microarchitectures. For instance, when running on an
Haswell node, Spack will consider ``haswell`` as the best target in the former case and
``x86_64_v3`` as the best target in the latter case.
The ``host_compatible`` option is a Boolean option that determines whether or not the
microarchitectures considered during the solve are constrained to be compatible with the
host Spack is currently running on. For instance, if this option is set to ``true``, a
user cannot concretize for ``target=icelake`` while running on an Haswell node.
.. _package-requirements:
--------------------

View File

@@ -25,8 +25,8 @@ use Spack to build packages with the tools.
The Spack Python class ``IntelOneapiPackage`` is a base class that is
used by ``IntelOneapiCompilers``, ``IntelOneapiMkl``,
``IntelOneapiTbb`` and other classes to implement the oneAPI
packages. See the :ref:`package-list` for the full list of available
oneAPI packages or use::
packages. Search for ``oneAPI`` at `<packages.spack.io>`_ for the full
list of available oneAPI packages, or use::
spack list -d oneAPI

View File

@@ -48,9 +48,6 @@
os.environ["COLIFY_SIZE"] = "25x120"
os.environ["COLUMNS"] = "120"
# Generate full package list if needed
subprocess.call(["spack", "list", "--format=html", "--update=package_list.html"])
# Generate a command index if an update is needed
subprocess.call(
[

View File

@@ -212,18 +212,12 @@ under the ``container`` attribute of environments:
final:
- libgomp
# Extra instructions
extra_instructions:
final: |
RUN echo 'export PS1="\[$(tput bold)\]\[$(tput setaf 1)\][gromacs]\[$(tput setaf 2)\]\u\[$(tput sgr0)\]:\w $ "' >> ~/.bashrc
# Labels for the image
labels:
app: "gromacs"
mpi: "mpich"
A detailed description of the options available can be found in the
:ref:`container_config_options` section.
A detailed description of the options available can be found in the :ref:`container_config_options` section.
-------------------
Setting Base Images
@@ -525,6 +519,13 @@ the example below:
COPY data /share/myapp/data
{% endblock %}
The Dockerfile is generated by running:
.. code-block:: console
$ spack -e /opt/environment containerize
Note that the environment must be active for spack to read the template.
The recipe that gets generated contains the two extra instruction that we added in our template extension:
.. code-block:: Dockerfile

View File

@@ -310,53 +310,11 @@ Once all of the dependencies are installed, you can try building the documentati
$ make clean
$ make
If you see any warning or error messages, you will have to correct those before
your PR is accepted.
If you are editing the documentation, you should obviously be running the
documentation tests. But even if you are simply adding a new package, your
changes could cause the documentation tests to fail:
.. code-block:: console
package_list.rst:8745: WARNING: Block quote ends without a blank line; unexpected unindent.
At first, this error message will mean nothing to you, since you didn't edit
that file. Until you look at line 8745 of the file in question:
.. code-block:: rst
Description:
NetCDF is a set of software libraries and self-describing, machine-
independent data formats that support the creation, access, and sharing
of array-oriented scientific data.
Our documentation includes :ref:`a list of all Spack packages <package-list>`.
If you add a new package, its docstring is added to this page. The problem in
this case was that the docstring looked like:
.. code-block:: python
class Netcdf(Package):
"""
NetCDF is a set of software libraries and self-describing,
machine-independent data formats that support the creation,
access, and sharing of array-oriented scientific data.
"""
Docstrings cannot start with a newline character, or else Sphinx will complain.
Instead, they should look like:
.. code-block:: python
class Netcdf(Package):
"""NetCDF is a set of software libraries and self-describing,
machine-independent data formats that support the creation,
access, and sharing of array-oriented scientific data."""
Documentation changes can result in much more obfuscated warning messages.
If you don't understand what they mean, feel free to ask when you submit
your PR.
If you see any warning or error messages, you will have to correct those before your PR
is accepted. If you are editing the documentation, you should be running the
documentation tests to make sure there are no errors. Documentation changes can result
in some obfuscated warning messages. If you don't understand what they mean, feel free
to ask when you submit your PR.
--------
Coverage

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -54,9 +54,16 @@ or refer to the full manual below.
features
getting_started
basic_usage
Tutorial: Spack 101 <https://spack-tutorial.readthedocs.io>
replace_conda_homebrew
.. toctree::
:maxdepth: 2
:caption: Links
Tutorial (spack-tutorial.rtfd.io) <https://spack-tutorial.readthedocs.io>
Packages (packages.spack.io) <https://packages.spack.io>
Binaries (binaries.spack.io) <https://cache.spack.io>
.. toctree::
:maxdepth: 2
:caption: Reference
@@ -72,7 +79,6 @@ or refer to the full manual below.
repositories
binary_caches
command_index
package_list
chain
extensions
pipelines

View File

@@ -1,17 +0,0 @@
.. Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT)
.. _package-list:
============
Package List
============
This is a list of things you can install using Spack. It is
automatically generated based on the packages in this Spack
version.
.. raw:: html
:file: package_list.html

View File

@@ -3635,7 +3635,8 @@ regardless of the build system. The arguments for the phase are:
The arguments ``spec`` and ``prefix`` are passed only for convenience, as they always
correspond to ``self.spec`` and ``self.spec.prefix`` respectively.
If the ``package.py`` encodes builders explicitly, the signature for a phase changes slightly:
If the ``package.py`` has build instructions in a separate
:ref:`builder class <multiple_build_systems>`, the signature for a phase changes slightly:
.. code-block:: python
@@ -3645,56 +3646,6 @@ If the ``package.py`` encodes builders explicitly, the signature for a phase cha
In this case the package is passed as the second argument, and ``self`` is the builder instance.
.. _multiple_build_systems:
^^^^^^^^^^^^^^^^^^^^^^
Multiple build systems
^^^^^^^^^^^^^^^^^^^^^^
There are cases where a software actively supports two build systems, or changes build systems
as it evolves, or needs different build systems on different platforms. Spack allows dealing with
these cases natively, if a recipe is written using builders explicitly.
For instance, software that supports two build systems unconditionally should derive from
both ``*Package`` base classes, and declare the possible use of multiple build systems using
a directive:
.. code-block:: python
class ArpackNg(CMakePackage, AutotoolsPackage):
build_system("cmake", "autotools", default="cmake")
In this case the software can be built with both ``autotools`` and ``cmake``. Since the package
supports multiple build systems, it is necessary to declare which one is the default. The ``package.py``
will likely contain some overriding of default builder methods:
.. code-block:: python
class CMakeBuilder(spack.build_systems.cmake.CMakeBuilder):
def cmake_args(self):
pass
class AutotoolsBuilder(spack.build_systems.autotools.AutotoolsBuilder):
def configure_args(self):
pass
In more complex cases it might happen that the build system changes according to certain conditions,
for instance across versions. That can be expressed with conditional variant values:
.. code-block:: python
class ArpackNg(CMakePackage, AutotoolsPackage):
build_system(
conditional("cmake", when="@0.64:"),
conditional("autotools", when="@:0.63"),
default="cmake",
)
In the example the directive impose a change from ``Autotools`` to ``CMake`` going
from ``v0.63`` to ``v0.64``.
^^^^^^^^^^^^^^^^^^
Mixin base classes
^^^^^^^^^^^^^^^^^^
@@ -3741,6 +3692,106 @@ for instance:
In the example above ``Cp2k`` inherits all the conflicts and variants that ``CudaPackage`` defines.
.. _multiple_build_systems:
----------------------
Multiple build systems
----------------------
There are cases where a package actively supports two build systems, or changes build systems
as it evolves, or needs different build systems on different platforms. Spack allows dealing with
these cases by splitting the build instructions into separate builder classes.
For instance, software that supports two build systems unconditionally should derive from
both ``*Package`` base classes, and declare the possible use of multiple build systems using
a directive:
.. code-block:: python
class Example(CMakePackage, AutotoolsPackage):
variant("my_feature", default=True)
build_system("cmake", "autotools", default="cmake")
In this case the software can be built with both ``autotools`` and ``cmake``. Since the package
supports multiple build systems, it is necessary to declare which one is the default.
Additional build instructions are split into separate builder classes:
.. code-block:: python
class CMakeBuilder(spack.build_systems.cmake.CMakeBuilder):
def cmake_args(self):
return [
self.define_from_variant("MY_FEATURE", "my_feature")
]
class AutotoolsBuilder(spack.build_systems.autotools.AutotoolsBuilder):
def configure_args(self):
return self.with_or_without("my-feature", variant="my_feature")
In this example, ``spack install example +feature build_sytem=cmake`` will
pick the ``CMakeBuilder`` and invoke ``cmake -DMY_FEATURE:BOOL=ON``.
Similarly, ``spack install example +feature build_system=autotools`` will pick
the ``AutotoolsBuilder`` and invoke ``./configure --with-my-feature``.
Dependencies are always specified in the package class. When some dependencies
depend on the choice of the build system, it is possible to use when conditions as
usual:
.. code-block:: python
class Example(CMakePackage, AutotoolsPackage):
build_system("cmake", "autotools", default="cmake")
# Runtime dependencies
depends_on("ncurses")
depends_on("libxml2")
# Lowerbounds for cmake only apply when using cmake as the build system
with when("build_system=cmake"):
depends_on("cmake@3.18:", when="@2.0:", type="build")
depends_on("cmake@3:", type="build")
# Specify extra build dependencies used only in the configure script
with when("build_system=autotools"):
depends_on("perl", type="build")
depends_on("pkgconfig", type="build")
Very often projects switch from one build system to another, or add support
for a new build system from a certain version, which means that the choice
of the build system typically depends on a version range. Those situations can
be handled by using conditional values in the ``build_system`` directive:
.. code-block:: python
class Example(CMakePackage, AutotoolsPackage):
build_system(
conditional("cmake", when="@0.64:"),
conditional("autotools", when="@:0.63"),
default="cmake",
)
In the example the directive impose a change from ``Autotools`` to ``CMake`` going
from ``v0.63`` to ``v0.64``.
The ``build_system`` can be used as an ordinary variant, which also means that it can
be used in ``depends_on`` statements. This can be useful when a package *requires* that
its dependency has a CMake config file, meaning that the dependent can only build when the
dependency is built with CMake, and not Autotools. In that case, you can force the choice
of the build system in the dependent:
.. code-block:: python
class Dependent(CMakePackage):
depends_on("example build_system=cmake")
.. _install-environment:
-----------------------
@@ -6196,7 +6247,100 @@ follows:
"foo-package@{0}".format(version_str)
)
.. _package-lifecycle:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Add detection tests to packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To ensure that software is detected correctly for multiple configurations
and on different systems users can write a ``detection_test.yaml`` file and
put it in the package directory alongside the ``package.py`` file.
This YAML file contains enough information for Spack to mock an environment
and try to check if the detection logic yields the results that are expected.
As a general rule, attributes at the top-level of ``detection_test.yaml``
represent search mechanisms and they each map to a list of tests that should confirm
the validity of the package's detection logic.
The detection tests can be run with the following command:
.. code-block:: console
$ spack audit externals
Errors that have been detected are reported to screen.
""""""""""""""""""""""""""
Tests for PATH inspections
""""""""""""""""""""""""""
Detection tests insisting on ``PATH`` inspections are listed under
the ``paths`` attribute:
.. code-block:: yaml
paths:
- layout:
- executables:
- "bin/clang-3.9"
- "bin/clang++-3.9"
script: |
echo "clang version 3.9.1-19ubuntu1 (tags/RELEASE_391/rc2)"
echo "Target: x86_64-pc-linux-gnu"
echo "Thread model: posix"
echo "InstalledDir: /usr/bin"
results:
- spec: 'llvm@3.9.1 +clang~lld~lldb'
Each test is performed by first creating a temporary directory structure as
specified in the corresponding ``layout`` and by then running
package detection and checking that the outcome matches the expected
``results``. The exact details on how to specify both the ``layout`` and the
``results`` are reported in the table below:
.. list-table:: Test based on PATH inspections
:header-rows: 1
* - Option Name
- Description
- Allowed Values
- Required Field
* - ``layout``
- Specifies the filesystem tree used for the test
- List of objects
- Yes
* - ``layout:[0]:executables``
- Relative paths for the mock executables to be created
- List of strings
- Yes
* - ``layout:[0]:script``
- Mock logic for the executable
- Any valid shell script
- Yes
* - ``results``
- List of expected results
- List of objects (empty if no result is expected)
- Yes
* - ``results:[0]:spec``
- A spec that is expected from detection
- Any valid spec
- Yes
"""""""""""""""""""""""""""""""
Reuse tests from other packages
"""""""""""""""""""""""""""""""
When using a custom repository, it is possible to customize a package that already exists in ``builtin``
and reuse its external tests. To do so, just write a ``detection_tests.yaml`` alongside the customized
``package.py`` with an ``includes`` attribute. For instance the ``detection_tests.yaml`` for
``myrepo.llvm`` might look like:
.. code-block:: yaml
includes:
- "builtin.llvm"
This YAML file instructs Spack to run the detection tests defined in ``builtin.llvm`` in addition to
those locally defined in the file.
-----------------------------
Style guidelines for packages

View File

@@ -4,7 +4,7 @@
SPDX-License-Identifier: (Apache-2.0 OR MIT)
=====================================
Using Spack to Replace Homebrew/Conda
Spack for Homebrew/Conda Users
=====================================
Spack is an incredibly powerful package manager, designed for supercomputers
@@ -191,18 +191,18 @@ The ``--fresh`` flag tells Spack to use the latest version of every package
where possible instead of trying to optimize for reuse of existing installed
packages.
The ``--force`` flag in addition tells Spack to overwrite its previous
concretization decisions, allowing you to choose a new version of Python.
If any of the new packages like Bash are already installed, ``spack install``
The ``--force`` flag in addition tells Spack to overwrite its previous
concretization decisions, allowing you to choose a new version of Python.
If any of the new packages like Bash are already installed, ``spack install``
won't re-install them, it will keep the symlinks in place.
-----------------------------------
Updating & Cleaning Up Old Packages
-----------------------------------
If you're looking to mimic the behavior of Homebrew, you may also want to
clean up out-of-date packages from your environment after an upgrade. To
upgrade your entire software stack within an environment and clean up old
If you're looking to mimic the behavior of Homebrew, you may also want to
clean up out-of-date packages from your environment after an upgrade. To
upgrade your entire software stack within an environment and clean up old
package versions, simply run the following commands:
.. code-block:: console
@@ -212,9 +212,9 @@ package versions, simply run the following commands:
$ spack concretize --fresh --force
$ spack install
$ spack gc
Running ``spack mark -i --all`` tells Spack to mark all of the existing
packages within an environment as "implicitly" installed. This tells
Running ``spack mark -i --all`` tells Spack to mark all of the existing
packages within an environment as "implicitly" installed. This tells
spack's garbage collection system that these packages should be cleaned up.
Don't worry however, this will not remove your entire environment.
@@ -223,8 +223,8 @@ a fresh concretization and will re-mark any packages that should remain
installed as "explicitly" installed.
**Note:** if you use multiple spack environments you should re-run ``spack install``
in each of your environments prior to running ``spack gc`` to prevent spack
from uninstalling any shared packages that are no longer required by the
in each of your environments prior to running ``spack gc`` to prevent spack
from uninstalling any shared packages that are no longer required by the
environment you just upgraded.
--------------

View File

@@ -2,12 +2,12 @@ sphinx==7.2.6
sphinxcontrib-programoutput==0.17
sphinx_design==0.5.0
sphinx-rtd-theme==1.3.0
python-levenshtein==0.21.1
python-levenshtein==0.23.0
docutils==0.18.1
pygments==2.16.1
urllib3==2.0.4
urllib3==2.0.6
pytest==7.4.2
isort==5.12.0
black==23.9.1
flake8==6.1.0
mypy==1.5.1
mypy==1.6.0

View File

@@ -1,9 +1,8 @@
Name, Supported Versions, Notes, Requirement Reason
Python, 3.6--3.11, , Interpreter for Spack
Python, 3.6--3.12, , Interpreter for Spack
C/C++ Compilers, , , Building software
make, , , Build software
patch, , , Build software
bash, , , Compiler wrappers
tar, , , Extract/create archives
gzip, , , Compress/Decompress archives
unzip, , , Compress/Decompress archives
1 Name Supported Versions Notes Requirement Reason
2 Python 3.6--3.11 3.6--3.12 Interpreter for Spack
3 C/C++ Compilers Building software
4 make Build software
5 patch Build software
bash Compiler wrappers
6 tar Extract/create archives
7 gzip Compress/Decompress archives
8 unzip Compress/Decompress archives

105
lib/spack/llnl/path.py Normal file
View File

@@ -0,0 +1,105 @@
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""Path primitives that just require Python standard library."""
import functools
import sys
from typing import List, Optional
from urllib.parse import urlparse
class Path:
"""Enum to identify the path-style."""
unix: int = 0
windows: int = 1
platform_path: int = windows if sys.platform == "win32" else unix
def format_os_path(path: str, mode: int = Path.unix) -> str:
"""Formats the input path to use consistent, platform specific separators.
Absolute paths are converted between drive letters and a prepended '/' as per platform
requirement.
Parameters:
path: the path to be normalized, must be a string or expose the replace method.
mode: the path file separator style to normalize the passed path to.
Default is unix style, i.e. '/'
"""
if not path:
return path
if mode == Path.windows:
path = path.replace("/", "\\")
else:
path = path.replace("\\", "/")
return path
def convert_to_posix_path(path: str) -> str:
"""Converts the input path to POSIX style."""
return format_os_path(path, mode=Path.unix)
def convert_to_windows_path(path: str) -> str:
"""Converts the input path to Windows style."""
return format_os_path(path, mode=Path.windows)
def convert_to_platform_path(path: str) -> str:
"""Converts the input path to the current platform's native style."""
return format_os_path(path, mode=Path.platform_path)
def path_to_os_path(*parameters: str) -> List[str]:
"""Takes an arbitrary number of positional parameters, converts each argument of type
string to use a normalized filepath separator, and returns a list of all values.
"""
def _is_url(path_or_url: str) -> bool:
if "\\" in path_or_url:
return False
url_tuple = urlparse(path_or_url)
return bool(url_tuple.scheme) and len(url_tuple.scheme) > 1
result = []
for item in parameters:
if isinstance(item, str) and not _is_url(item):
item = convert_to_platform_path(item)
result.append(item)
return result
def system_path_filter(_func=None, arg_slice: Optional[slice] = None):
"""Filters function arguments to account for platform path separators.
Optional slicing range can be specified to select specific arguments
This decorator takes all (or a slice) of a method's positional arguments
and normalizes usage of filepath separators on a per platform basis.
Note: `**kwargs`, urls, and any type that is not a string are ignored
so in such cases where path normalization is required, that should be
handled by calling path_to_os_path directly as needed.
Parameters:
arg_slice: a slice object specifying the slice of arguments
in the decorated method over which filepath separators are
normalized
"""
def holder_func(func):
@functools.wraps(func)
def path_filter_caller(*args, **kwargs):
args = list(args)
if arg_slice:
args[arg_slice] = path_to_os_path(*args[arg_slice])
else:
args = path_to_os_path(*args)
return func(*args, **kwargs)
return path_filter_caller
if _func:
return holder_func(_func)
return holder_func

67
lib/spack/llnl/string.py Normal file
View File

@@ -0,0 +1,67 @@
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""String manipulation functions that do not have other dependencies than Python
standard library
"""
from typing import List, Optional
def comma_list(sequence: List[str], article: str = "") -> str:
if type(sequence) is not list:
sequence = list(sequence)
if not sequence:
return ""
if len(sequence) == 1:
return sequence[0]
out = ", ".join(str(s) for s in sequence[:-1])
if len(sequence) != 2:
out += "," # oxford comma
out += " "
if article:
out += article + " "
out += str(sequence[-1])
return out
def comma_or(sequence: List[str]) -> str:
"""Return a string with all the elements of the input joined by comma, but the last
one (which is joined by 'or').
"""
return comma_list(sequence, "or")
def comma_and(sequence: List[str]) -> str:
"""Return a string with all the elements of the input joined by comma, but the last
one (which is joined by 'and').
"""
return comma_list(sequence, "and")
def quote(sequence: List[str], q: str = "'") -> List[str]:
"""Quotes each item in the input list with the quote character passed as second argument."""
return [f"{q}{e}{q}" for e in sequence]
def plural(n: int, singular: str, plural: Optional[str] = None, show_n: bool = True) -> str:
"""Pluralize <singular> word by adding an s if n != 1.
Arguments:
n: number of things there are
singular: singular form of word
plural: optional plural form, for when it's not just singular + 's'
show_n: whether to include n in the result string (default True)
Returns:
"1 thing" if n == 1 or "n things" if n != 1
"""
number = f"{n} " if show_n else ""
if n == 1:
return f"{number}{singular}"
elif plural is not None:
return f"{number}{plural}"
else:
return f"{number}{singular}s"

View File

@@ -28,7 +28,8 @@
from llnl.util.symlink import islink, readlink, resolve_link_target_relative_to_the_link, symlink
from spack.util.executable import Executable, which
from spack.util.path import path_to_os_path, system_path_filter
from ..path import path_to_os_path, system_path_filter
if sys.platform != "win32":
import grp
@@ -336,8 +337,7 @@ def groupid_to_group(x):
if string:
regex = re.escape(regex)
filenames = path_to_os_path(*filenames)
for filename in filenames:
for filename in path_to_os_path(*filenames):
msg = 'FILTER FILE: {0} [replacing "{1}"]'
tty.debug(msg.format(filename, regex))

View File

@@ -14,7 +14,7 @@
from llnl.util import lang, tty
import spack.util.string
from ..string import plural
if sys.platform != "win32":
import fcntl
@@ -169,7 +169,7 @@ def _attempts_str(wait_time, nattempts):
if nattempts <= 1:
return ""
attempts = spack.util.string.plural(nattempts, "attempt")
attempts = plural(nattempts, "attempt")
return " after {} and {}".format(lang.pretty_seconds(wait_time), attempts)

View File

@@ -11,8 +11,7 @@
from llnl.util import lang, tty
from spack.error import SpackError
from spack.util.path import system_path_filter
from ..path import system_path_filter
if sys.platform == "win32":
from win32file import CreateHardLink
@@ -338,7 +337,7 @@ def resolve_link_target_relative_to_the_link(link):
return os.path.join(link_dir, target)
class SymlinkError(SpackError):
class SymlinkError(RuntimeError):
"""Exception class for errors raised while creating symlinks,
junctions and hard links
"""

View File

@@ -38,10 +38,13 @@ def _search_duplicate_compilers(error_cls):
import ast
import collections
import collections.abc
import glob
import inspect
import itertools
import pathlib
import pickle
import re
import warnings
from urllib.request import urlopen
import llnl.util.lang
@@ -798,3 +801,76 @@ def _analyze_variants_in_directive(pkg, constraint, directive, error_cls):
errors.append(err)
return errors
#: Sanity checks on package directives
external_detection = AuditClass(
group="externals",
tag="PKG-EXTERNALS",
description="Sanity checks for external software detection",
kwargs=("pkgs",),
)
def packages_with_detection_tests():
"""Return the list of packages with a corresponding detection_test.yaml file."""
import spack.config
import spack.util.path
to_be_tested = []
for current_repo in spack.repo.PATH.repos:
namespace = current_repo.namespace
packages_dir = pathlib.PurePath(current_repo.packages_path)
pattern = packages_dir / "**" / "detection_test.yaml"
pkgs_with_tests = [
f"{namespace}.{str(pathlib.PurePath(x).parent.name)}" for x in glob.glob(str(pattern))
]
to_be_tested.extend(pkgs_with_tests)
return to_be_tested
@external_detection
def _test_detection_by_executable(pkgs, error_cls):
"""Test drive external detection for packages"""
import spack.detection
errors = []
# Filter the packages and retain only the ones with detection tests
pkgs_with_tests = packages_with_detection_tests()
selected_pkgs = []
for current_package in pkgs_with_tests:
_, unqualified_name = spack.repo.partition_package_name(current_package)
# Check for both unqualified name and qualified name
if unqualified_name in pkgs or current_package in pkgs:
selected_pkgs.append(current_package)
selected_pkgs.sort()
if not selected_pkgs:
summary = "No detection test to run"
details = [f' "{p}" has no detection test' for p in pkgs]
warnings.warn("\n".join([summary] + details))
return errors
for pkg_name in selected_pkgs:
for idx, test_runner in enumerate(
spack.detection.detection_tests(pkg_name, spack.repo.PATH)
):
specs = test_runner.execute()
expected_specs = test_runner.expected_specs
not_detected = set(expected_specs) - set(specs)
if not_detected:
summary = pkg_name + ": cannot detect some specs"
details = [f'"{s}" was not detected [test_id={idx}]' for s in sorted(not_detected)]
errors.append(error_cls(summary=summary, details=details))
not_expected = set(specs) - set(expected_specs)
if not_expected:
summary = pkg_name + ": detected unexpected specs"
msg = '"{0}" was detected, but was not expected [test_id={1}]'
details = [msg.format(s, idx) for s in sorted(not_expected)]
errors.append(error_cls(summary=summary, details=details))
return errors

View File

@@ -23,7 +23,7 @@
import warnings
from contextlib import closing, contextmanager
from gzip import GzipFile
from typing import List, NamedTuple, Optional, Union
from typing import Dict, List, NamedTuple, Optional, Tuple, Union
from urllib.error import HTTPError, URLError
import llnl.util.filesystem as fsys
@@ -34,6 +34,7 @@
import spack.cmd
import spack.config as config
import spack.database as spack_db
import spack.error
import spack.hooks
import spack.hooks.sbang
import spack.mirror
@@ -215,11 +216,11 @@ def _associate_built_specs_with_mirror(self, cache_key, mirror_url):
with self._index_file_cache.read_transaction(cache_key):
db._read_from_file(cache_path)
except spack_db.InvalidDatabaseVersionError as e:
msg = (
tty.warn(
f"you need a newer Spack version to read the buildcache index for the "
f"following mirror: '{mirror_url}'. {e.database_version_message}"
)
raise BuildcacheIndexError(msg) from e
return
spec_list = db.query_local(installed=False, in_buildcache=True)
@@ -624,8 +625,7 @@ def buildinfo_file_name(prefix):
"""
Filename of the binary package meta-data file
"""
name = os.path.join(prefix, ".spack/binary_distribution")
return name
return os.path.join(prefix, ".spack/binary_distribution")
def read_buildinfo_file(prefix):
@@ -646,8 +646,7 @@ class BuildManifestVisitor(BaseDirectoryVisitor):
directories."""
def __init__(self):
# Save unique identifiers of files to avoid
# relocating hardlink files for each path.
# Save unique identifiers of hardlinks to avoid relocating them multiple times
self.visited = set()
# Lists of files we will check
@@ -656,6 +655,8 @@ def __init__(self):
def seen_before(self, root, rel_path):
stat_result = os.lstat(os.path.join(root, rel_path))
if stat_result.st_nlink == 1:
return False
identifier = (stat_result.st_dev, stat_result.st_ino)
if identifier in self.visited:
return True
@@ -912,7 +913,7 @@ def _read_specs_and_push_index(file_list, read_method, cache_prefix, db, temp_di
index_json_path,
url_util.join(cache_prefix, "index.json"),
keep_original=False,
extra_args={"ContentType": "application/json"},
extra_args={"ContentType": "application/json", "CacheControl": "no-cache"},
)
# Push the hash
@@ -920,7 +921,7 @@ def _read_specs_and_push_index(file_list, read_method, cache_prefix, db, temp_di
index_hash_path,
url_util.join(cache_prefix, "index.json.hash"),
keep_original=False,
extra_args={"ContentType": "text/plain"},
extra_args={"ContentType": "text/plain", "CacheControl": "no-cache"},
)
@@ -1156,57 +1157,99 @@ def gzip_compressed_tarfile(path):
yield tar
def deterministic_tarinfo(tarinfo: tarfile.TarInfo):
# We only add files, symlinks, hardlinks, and directories
# No character devices, block devices and FIFOs should ever enter a tarball.
if tarinfo.isdev():
return None
# For distribution, it makes no sense to user/group data; since (a) they don't exist
# on other machines, and (b) they lead to surprises as `tar x` run as root will change
# ownership if it can. We want to extract as the current user. By setting owner to root,
# root will extract as root, and non-privileged user will extract as themselves.
tarinfo.uid = 0
tarinfo.gid = 0
tarinfo.uname = ""
tarinfo.gname = ""
# Reset mtime to epoch time, our prefixes are not truly immutable, so files may get
# touched; as long as the content does not change, this ensures we get stable tarballs.
tarinfo.mtime = 0
# Normalize mode
if tarinfo.isfile() or tarinfo.islnk():
# If user can execute, use 0o755; else 0o644
# This is to avoid potentially unsafe world writable & exeutable files that may get
# extracted when Python or tar is run with privileges
tarinfo.mode = 0o644 if tarinfo.mode & 0o100 == 0 else 0o755
else: # symbolic link and directories
tarinfo.mode = 0o755
return tarinfo
def _tarinfo_name(p: str):
return p.lstrip("/")
def tar_add_metadata(tar: tarfile.TarFile, path: str, data: dict):
# Serialize buildinfo for the tarball
bstring = syaml.dump(data, default_flow_style=True).encode("utf-8")
tarinfo = tarfile.TarInfo(name=path)
tarinfo.size = len(bstring)
tar.addfile(deterministic_tarinfo(tarinfo), io.BytesIO(bstring))
def tarfile_of_spec_prefix(tar: tarfile.TarFile, prefix: str) -> None:
"""Create a tarfile of an install prefix of a spec. Skips existing buildinfo file.
Only adds regular files, symlinks and dirs. Skips devices, fifos. Preserves hardlinks.
Normalizes permissions like git. Tar entries are added in depth-first pre-order, with
dir entries partitioned by file | dir, and sorted alphabetically, for reproducibility.
Partitioning ensures only one dir is in memory at a time, and sorting improves compression.
Args:
tar: tarfile object to add files to
prefix: absolute install prefix of spec"""
if not os.path.isabs(prefix) or not os.path.isdir(prefix):
raise ValueError(f"prefix '{prefix}' must be an absolute path to a directory")
hardlink_to_tarinfo_name: Dict[Tuple[int, int], str] = dict()
stat_key = lambda stat: (stat.st_dev, stat.st_ino)
try: # skip buildinfo file if it exists
files_to_skip = [stat_key(os.lstat(buildinfo_file_name(prefix)))]
except OSError:
files_to_skip = []
dir_stack = [prefix]
while dir_stack:
dir = dir_stack.pop()
# Add the dir before its contents
dir_info = tarfile.TarInfo(_tarinfo_name(dir))
dir_info.type = tarfile.DIRTYPE
dir_info.mode = 0o755
tar.addfile(dir_info)
# Sort by name: reproducible & improves compression
with os.scandir(dir) as it:
entries = sorted(it, key=lambda entry: entry.name)
new_dirs = []
for entry in entries:
if entry.is_dir(follow_symlinks=False):
new_dirs.append(entry.path)
continue
file_info = tarfile.TarInfo(_tarinfo_name(entry.path))
s = entry.stat(follow_symlinks=False)
# Skip existing binary distribution files.
id = stat_key(s)
if id in files_to_skip:
continue
# Normalize the mode
file_info.mode = 0o644 if s.st_mode & 0o100 == 0 else 0o755
if entry.is_symlink():
file_info.type = tarfile.SYMTYPE
file_info.linkname = os.readlink(entry.path)
tar.addfile(file_info)
elif entry.is_file(follow_symlinks=False):
# Deduplicate hardlinks
if s.st_nlink > 1:
if id in hardlink_to_tarinfo_name:
file_info.type = tarfile.LNKTYPE
file_info.linkname = hardlink_to_tarinfo_name[id]
tar.addfile(file_info)
continue
hardlink_to_tarinfo_name[id] = file_info.name
# If file not yet seen, copy it.
file_info.type = tarfile.REGTYPE
file_info.size = s.st_size
with open(entry.path, "rb") as f:
tar.addfile(file_info, f)
dir_stack.extend(reversed(new_dirs)) # we pop, so reverse to stay alphabetical
def deterministic_tarinfo_without_buildinfo(tarinfo: tarfile.TarInfo):
"""Skip buildinfo file when creating a tarball, and normalize other tarinfo fields."""
if tarinfo.name.endswith("/.spack/binary_distribution"):
return None
return deterministic_tarinfo(tarinfo)
def _do_create_tarball(tarfile_path: str, binaries_dir: str, pkg_dir: str, buildinfo: dict):
def _do_create_tarball(tarfile_path: str, binaries_dir: str, buildinfo: dict):
with gzip_compressed_tarfile(tarfile_path) as tar:
tar.add(name=binaries_dir, arcname=pkg_dir, filter=deterministic_tarinfo_without_buildinfo)
tar_add_metadata(tar, buildinfo_file_name(pkg_dir), buildinfo)
# Tarball the install prefix
tarfile_of_spec_prefix(tar, binaries_dir)
# Serialize buildinfo for the tarball
bstring = syaml.dump(buildinfo, default_flow_style=True).encode("utf-8")
tarinfo = tarfile.TarInfo(name=_tarinfo_name(buildinfo_file_name(binaries_dir)))
tarinfo.type = tarfile.REGTYPE
tarinfo.size = len(bstring)
tarinfo.mode = 0o644
tar.addfile(tarinfo, io.BytesIO(bstring))
class PushOptions(NamedTuple):
@@ -1278,14 +1321,12 @@ def _build_tarball_in_stage_dir(spec: Spec, out_url: str, stage_dir: str, option
):
raise NoOverwriteException(url_util.format(remote_specfile_path))
pkg_dir = os.path.basename(spec.prefix.rstrip(os.path.sep))
binaries_dir = spec.prefix
# create info for later relocation and create tar
buildinfo = get_buildinfo_dict(spec)
_do_create_tarball(tarfile_path, binaries_dir, pkg_dir, buildinfo)
_do_create_tarball(tarfile_path, binaries_dir, buildinfo)
# get the sha256 checksum of the tarball
checksum = checksum_tarball(tarfile_path)
@@ -1417,7 +1458,7 @@ def try_fetch(url_to_fetch):
try:
stage.fetch()
except web_util.FetchError:
except spack.error.FetchError:
stage.destroy()
return None
@@ -1580,9 +1621,10 @@ def dedupe_hardlinks_if_necessary(root, buildinfo):
for rel_path in buildinfo[key]:
stat_result = os.lstat(os.path.join(root, rel_path))
identifier = (stat_result.st_dev, stat_result.st_ino)
if identifier in visited:
continue
visited.add(identifier)
if stat_result.st_nlink > 1:
if identifier in visited:
continue
visited.add(identifier)
new_list.append(rel_path)
buildinfo[key] = new_list
@@ -2144,7 +2186,7 @@ def get_keys(install=False, trust=False, force=False, mirrors=None):
if not os.path.exists(stage.save_filename):
try:
stage.fetch()
except web_util.FetchError:
except spack.error.FetchError:
continue
tty.debug("Found key {0}".format(fingerprint))
@@ -2296,7 +2338,7 @@ def _download_buildcache_entry(mirror_root, descriptions):
try:
stage.fetch()
break
except web_util.FetchError as e:
except spack.error.FetchError as e:
tty.debug(e)
else:
if fail_if_missing:

View File

@@ -228,7 +228,7 @@ def _install_and_test(
if not abstract_spec.intersects(candidate_spec):
continue
if python_spec is not None and python_spec not in abstract_spec:
if python_spec is not None and not abstract_spec.intersects(f"^{python_spec}"):
continue
for _, pkg_hash, pkg_sha256 in item["binaries"]:

View File

@@ -43,6 +43,7 @@
from typing import List, Tuple
import llnl.util.tty as tty
from llnl.string import plural
from llnl.util.filesystem import join_path
from llnl.util.lang import dedupe
from llnl.util.symlink import symlink
@@ -82,7 +83,6 @@
from spack.util.executable import Executable
from spack.util.log_parse import make_log_context, parse_log_events
from spack.util.module_cmd import load_module, module, path_from_modules
from spack.util.string import plural
#
# This can be set by the user to globally disable parallel builds.

View File

@@ -142,10 +142,10 @@ def flags_to_build_system_args(self, flags):
# We specify for each of them.
if flags["ldflags"]:
ldflags = " ".join(flags["ldflags"])
ld_string = "-DCMAKE_{0}_LINKER_FLAGS={1}"
# cmake has separate linker arguments for types of builds.
for type in ["EXE", "MODULE", "SHARED", "STATIC"]:
self.cmake_flag_args.append(ld_string.format(type, ldflags))
self.cmake_flag_args.append(f"-DCMAKE_EXE_LINKER_FLAGS={ldflags}")
self.cmake_flag_args.append(f"-DCMAKE_MODULE_LINKER_FLAGS={ldflags}")
self.cmake_flag_args.append(f"-DCMAKE_SHARED_LINKER_FLAGS={ldflags}")
# CMake has libs options separated by language. Apply ours to each.
if flags["ldlibs"]:

View File

@@ -10,7 +10,7 @@
import spack.builder
import spack.package_base
from spack.directives import build_system, depends_on, variant
from spack.directives import build_system, conflicts, depends_on, variant
from spack.multimethod import when
from ._checks import BaseBuilder, execute_build_time_tests
@@ -47,6 +47,13 @@ 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")
# 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
# when setuptools is in PYTHONPATH; it has to be in system site-packages. In a future meson
# release, the distutils requirement will be dropped, so this conflict can be relaxed.
# We have patches to make it work with meson 1.1 and above.
conflicts("^python@3.12:", when="^meson@:1.0")
def flags_to_build_system_args(self, flags):
"""Produces a list of all command line arguments to pass the specified

View File

@@ -61,6 +61,11 @@ def component_prefix(self):
"""Path to component <prefix>/<component>/<version>."""
return self.prefix.join(join_path(self.component_dir, self.spec.version))
@property
def env_script_args(self):
"""Additional arguments to pass to vars.sh script."""
return ()
def install(self, spec, prefix):
self.install_component(basename(self.url_for_version(spec.version)))
@@ -124,7 +129,7 @@ def setup_run_environment(self, env):
if "~envmods" not in self.spec:
env.extend(
EnvironmentModifications.from_sourcing_file(
join_path(self.component_prefix, "env", "vars.sh")
join_path(self.component_prefix, "env", "vars.sh"), *self.env_script_args
)
)

View File

@@ -6,6 +6,7 @@
import os
import re
import shutil
import stat
from typing import Optional
import archspec
@@ -25,6 +26,7 @@
from spack.directives import build_system, depends_on, extends, maintainers
from spack.error import NoHeadersError, NoLibrariesError, SpecError
from spack.install_test import test_part
from spack.util.executable import Executable
from spack.version import Version
from ._checks import BaseBuilder, execute_install_time_tests
@@ -319,9 +321,12 @@ def list_url(cls):
def headers(self):
"""Discover header files in platlib."""
# Remove py- prefix in package name
name = self.spec.name[3:]
# Headers may be in either location
include = self.prefix.join(self.spec["python"].package.include)
platlib = self.prefix.join(self.spec["python"].package.platlib)
include = self.prefix.join(self.spec["python"].package.include).join(name)
platlib = self.prefix.join(self.spec["python"].package.platlib).join(name)
headers = fs.find_all_headers(include) + fs.find_all_headers(platlib)
if headers:
@@ -335,18 +340,64 @@ def libs(self):
"""Discover libraries in platlib."""
# Remove py- prefix in package name
library = "lib" + self.spec.name[3:].replace("-", "?")
root = self.prefix.join(self.spec["python"].package.platlib)
name = self.spec.name[3:]
for shared in [True, False]:
libs = fs.find_libraries(library, root, shared=shared, recursive=True)
if libs:
return libs
root = self.prefix.join(self.spec["python"].package.platlib).join(name)
libs = fs.find_all_libraries(root, recursive=True)
if libs:
return libs
msg = "Unable to recursively locate {} libraries in {}"
raise NoLibrariesError(msg.format(self.spec.name, root))
def fixup_shebangs(path: str, old_interpreter: bytes, new_interpreter: bytes):
# Recurse into the install prefix and fixup shebangs
exe = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
dirs = [path]
hardlinks = set()
while dirs:
with os.scandir(dirs.pop()) as entries:
for entry in entries:
if entry.is_dir(follow_symlinks=False):
dirs.append(entry.path)
continue
# Only consider files, not symlinks
if not entry.is_file(follow_symlinks=False):
continue
lstat = entry.stat(follow_symlinks=False)
# Skip over files that are not executable
if not (lstat.st_mode & exe):
continue
# Don't modify hardlinks more than once
if lstat.st_nlink > 1:
key = (lstat.st_ino, lstat.st_dev)
if key in hardlinks:
continue
hardlinks.add(key)
# Finally replace shebangs if any.
with open(entry.path, "rb+") as f:
contents = f.read(2)
if contents != b"#!":
continue
contents += f.read()
if old_interpreter not in contents:
continue
f.seek(0)
f.write(contents.replace(old_interpreter, new_interpreter))
f.truncate()
@spack.builder.builder("python_pip")
class PythonPipBuilder(BaseBuilder):
phases = ("install",)
@@ -443,8 +494,36 @@ def global_options(self, spec, prefix):
"""
return []
@property
def _build_venv_path(self):
"""Return the path to the virtual environment used for building when
python is external."""
return os.path.join(self.spec.package.stage.path, "build_env")
@property
def _build_venv_python(self) -> Executable:
"""Return the Python executable in the build virtual environment when
python is external."""
return Executable(os.path.join(self._build_venv_path, "bin", "python"))
def install(self, pkg, spec, prefix):
"""Install everything from build directory."""
python: Executable = spec["python"].command
# Since we invoke pip with --no-build-isolation, we have to make sure that pip cannot
# execute hooks from user and system site-packages.
if spec["python"].external:
# There are no environment variables to disable the system site-packages, so we use a
# virtual environment instead. The downside of this approach is that pip produces
# incorrect shebangs that refer to the virtual environment, which we have to fix up.
python("-m", "venv", "--without-pip", self._build_venv_path)
pip = self._build_venv_python
else:
# For a Spack managed Python, system site-packages is empty/unused by design, so it
# suffices to disable user site-packages, for which there is an environment variable.
pip = python
pip.add_default_env("PYTHONNOUSERSITE", "1")
pip.add_default_arg("-m")
pip.add_default_arg("pip")
args = PythonPipBuilder.std_args(pkg) + ["--prefix=" + prefix]
@@ -468,8 +547,31 @@ def install(self, pkg, spec, prefix):
else:
args.append(".")
pip = inspect.getmodule(pkg).pip
with fs.working_dir(self.build_directory):
pip(*args)
@spack.builder.run_after("install")
def fixup_shebangs_pointing_to_build(self):
"""When installing a package using an external python, we use a temporary virtual
environment which improves build isolation. The downside is that pip produces shebangs
that point to the temporary virtual environment. This method fixes them up to point to the
underlying Python."""
# No need to fixup shebangs if no build venv was used. (this post install function also
# runs when install was overridden in another package, so check existence of the venv path)
if not os.path.exists(self._build_venv_path):
return
# Use sys.executable, since that's what pip uses.
interpreter = (
lambda python: python("-c", "import sys; print(sys.executable)", output=str)
.strip()
.encode("utf-8")
)
fixup_shebangs(
path=self.spec.prefix,
old_interpreter=interpreter(self._build_venv_python),
new_interpreter=interpreter(self.spec["python"].command),
)
spack.builder.run_after("install")(execute_install_time_tests)

View File

@@ -64,7 +64,7 @@ class RacketBuilder(spack.builder.Builder):
@property
def subdirectory(self):
if self.racket_name:
if self.pkg.racket_name:
return "pkgs/{0}".format(self.pkg.racket_name)
return None

View File

@@ -50,6 +50,9 @@
TEMP_STORAGE_MIRROR_NAME = "ci_temporary_mirror"
SPACK_RESERVED_TAGS = ["public", "protected", "notary"]
SHARED_PR_MIRROR_URL = "s3://spack-binaries-prs/shared_pr_mirror"
JOB_NAME_FORMAT = (
"{name}{@version} {/hash:7} {%compiler.name}{@compiler.version}{arch=architecture}"
)
spack_gpg = spack.main.SpackCommand("gpg")
spack_compiler = spack.main.SpackCommand("compiler")
@@ -69,48 +72,23 @@ def __exit__(self, exc_type, exc_value, exc_traceback):
return False
def get_job_name(spec, osarch, build_group):
"""Given the necessary parts, format the gitlab job name
def get_job_name(spec: spack.spec.Spec, build_group: str = ""):
"""Given a spec and possibly a build group, return the job name. If the
resulting name is longer than 255 characters, it will be truncated.
Arguments:
spec (spack.spec.Spec): Spec job will build
osarch: Architecture TODO: (this is a spack.spec.ArchSpec,
but sphinx doesn't recognize the type and fails).
build_group (str): Name of build group this job belongs to (a CDash
notion)
Returns: The job name
"""
item_idx = 0
format_str = ""
format_args = []
format_str += "{{{0}}}".format(item_idx)
format_args.append(spec.name)
item_idx += 1
format_str += "/{{{0}}}".format(item_idx)
format_args.append(spec.dag_hash(7))
item_idx += 1
format_str += " {{{0}}}".format(item_idx)
format_args.append(spec.version)
item_idx += 1
format_str += " {{{0}}}".format(item_idx)
format_args.append(spec.compiler)
item_idx += 1
format_str += " {{{0}}}".format(item_idx)
format_args.append(osarch)
item_idx += 1
job_name = spec.format(JOB_NAME_FORMAT)
if build_group:
format_str += " {{{0}}}".format(item_idx)
format_args.append(build_group)
item_idx += 1
job_name = "{0} {1}".format(job_name, build_group)
return format_str.format(*format_args)
return job_name[:255]
def _remove_reserved_tags(tags):
@@ -337,7 +315,7 @@ def _spec_matches(spec, match_string):
def _format_job_needs(
dep_jobs, osname, build_group, prune_dag, rebuild_decisions, enable_artifacts_buildcache
dep_jobs, build_group, prune_dag, rebuild_decisions, enable_artifacts_buildcache
):
needs_list = []
for dep_job in dep_jobs:
@@ -347,7 +325,7 @@ def _format_job_needs(
if not prune_dag or rebuild:
needs_list.append(
{
"job": get_job_name(dep_job, dep_job.architecture, build_group),
"job": get_job_name(dep_job, build_group),
"artifacts": enable_artifacts_buildcache,
}
)
@@ -1023,8 +1001,7 @@ def main_script_replacements(cmd):
if "after_script" in job_object:
job_object["after_script"] = _unpack_script(job_object["after_script"])
osname = str(release_spec.architecture)
job_name = get_job_name(release_spec, osname, build_group)
job_name = get_job_name(release_spec, build_group)
job_vars = job_object.setdefault("variables", {})
job_vars["SPACK_JOB_SPEC_DAG_HASH"] = release_spec_dag_hash
@@ -1051,7 +1028,6 @@ def main_script_replacements(cmd):
job_object["needs"].extend(
_format_job_needs(
dep_jobs,
osname,
build_group,
prune_dag,
rebuild_decisions,

View File

@@ -11,6 +11,7 @@
from textwrap import dedent
from typing import List, Match, Tuple
import llnl.string
import llnl.util.tty as tty
from llnl.util.filesystem import join_path
from llnl.util.lang import attr_setdefault, index_by
@@ -29,7 +30,6 @@
import spack.user_environment as uenv
import spack.util.spack_json as sjson
import spack.util.spack_yaml as syaml
import spack.util.string
# cmd has a submodule called "list" so preserve the python list module
python_list = list
@@ -516,7 +516,7 @@ def print_how_many_pkgs(specs, pkg_type=""):
category, e.g. if pkg_type is "installed" then the message
would be "3 installed packages"
"""
tty.msg("%s" % spack.util.string.plural(len(specs), pkg_type + " package"))
tty.msg("%s" % llnl.string.plural(len(specs), pkg_type + " package"))
def spack_is_git_repo():

View File

@@ -3,6 +3,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import llnl.util.tty as tty
import llnl.util.tty.colify
import llnl.util.tty.color as cl
import spack.audit
@@ -20,6 +21,15 @@ def setup_parser(subparser):
# Audit configuration files
sp.add_parser("configs", help="audit configuration files")
# Audit package recipes
external_parser = sp.add_parser("externals", help="check external detection in packages")
external_parser.add_argument(
"--list",
action="store_true",
dest="list_externals",
help="if passed, list which packages have detection tests",
)
# Https and other linting
https_parser = sp.add_parser("packages-https", help="check https in packages")
https_parser.add_argument(
@@ -29,7 +39,7 @@ def setup_parser(subparser):
# Audit package recipes
pkg_parser = sp.add_parser("packages", help="audit package recipes")
for group in [pkg_parser, https_parser]:
for group in [pkg_parser, https_parser, external_parser]:
group.add_argument(
"name",
metavar="PKG",
@@ -62,6 +72,18 @@ def packages_https(parser, args):
_process_reports(reports)
def externals(parser, args):
if args.list_externals:
msg = "@*{The following packages have detection tests:}"
tty.msg(cl.colorize(msg))
llnl.util.tty.colify.colify(spack.audit.packages_with_detection_tests(), indent=2)
return
pkgs = args.name or spack.repo.PATH.all_package_names()
reports = spack.audit.run_group(args.subcommand, pkgs=pkgs)
_process_reports(reports)
def list(parser, args):
for subcommand, check_tags in spack.audit.GROUPS.items():
print(cl.colorize("@*b{" + subcommand + "}:"))
@@ -78,6 +100,7 @@ def list(parser, args):
def audit(parser, args):
subcommands = {
"configs": configs,
"externals": externals,
"packages": packages,
"packages-https": packages_https,
"list": list,

View File

@@ -13,6 +13,7 @@
import llnl.util.tty as tty
import llnl.util.tty.color as clr
from llnl.string import plural
from llnl.util.lang import elide_list
import spack.binary_distribution as bindist
@@ -32,7 +33,6 @@
from spack.cmd import display_specs
from spack.spec import Spec, save_dependency_specfiles
from spack.stage import Stage
from spack.util.string import plural
description = "create, download and install binary packages"
section = "packaging"
@@ -268,7 +268,7 @@ def _matching_specs(specs: List[Spec]) -> List[Spec]:
return [spack.cmd.disambiguate_spec(s, ev.active_environment(), installed=any) for s in specs]
def push_fn(args):
def push_fn(args: argparse.Namespace):
"""create a binary package and push it to a mirror"""
if args.spec_file:
tty.warn(
@@ -414,7 +414,7 @@ def preview_fn(args):
)
def check_fn(args):
def check_fn(args: argparse.Namespace):
"""check specs against remote binary mirror(s) to see if any need to be rebuilt
this command uses the process exit code to indicate its result, specifically, if the
@@ -429,7 +429,7 @@ def check_fn(args):
specs = spack.cmd.parse_specs(args.spec or args.spec_file)
if specs:
specs = _matching_specs(specs, specs)
specs = _matching_specs(specs)
else:
specs = spack.cmd.require_active_env("buildcache check").all_specs()
@@ -527,7 +527,7 @@ def copy_buildcache_file(src_url, dest_url, local_path=None):
temp_stage.create()
temp_stage.fetch()
web_util.push_to_url(local_path, dest_url, keep_original=True)
except web_util.FetchError as e:
except spack.error.FetchError as e:
# Expected, since we have to try all the possible extensions
tty.debug("no such file: {0}".format(src_url))
tty.debug(e)

View File

@@ -7,6 +7,7 @@
import re
import sys
import llnl.string
import llnl.util.lang
from llnl.util import tty
@@ -15,6 +16,7 @@
import spack.spec
import spack.stage
import spack.util.crypto
import spack.util.web as web_util
from spack.cmd.common import arguments
from spack.package_base import PackageBase, deprecated_version, preferred_version
from spack.util.editor import editor
@@ -66,7 +68,7 @@ def setup_parser(subparser):
modes_parser.add_argument(
"--verify", action="store_true", default=False, help="verify known package checksums"
)
arguments.add_common_arguments(subparser, ["package"])
arguments.add_common_arguments(subparser, ["package", "jobs"])
subparser.add_argument(
"versions", nargs=argparse.REMAINDER, help="versions to generate checksums for"
)
@@ -96,7 +98,7 @@ def checksum(parser, args):
# Add latest version if requested
if args.latest:
remote_versions = pkg.fetch_remote_versions()
remote_versions = pkg.fetch_remote_versions(args.jobs)
if len(remote_versions) > 0:
latest_version = sorted(remote_versions.keys(), reverse=True)[0]
versions.append(latest_version)
@@ -119,27 +121,47 @@ def checksum(parser, args):
# if we get here, it's because no valid url was provided by the package
# do expensive fallback to try to recover
if remote_versions is None:
remote_versions = pkg.fetch_remote_versions()
remote_versions = pkg.fetch_remote_versions(args.jobs)
if version in remote_versions:
url_dict[version] = remote_versions[version]
if len(versions) <= 0:
if remote_versions is None:
remote_versions = pkg.fetch_remote_versions()
remote_versions = pkg.fetch_remote_versions(args.jobs)
url_dict = remote_versions
# A spidered URL can differ from the package.py *computed* URL, pointing to different tarballs.
# For example, GitHub release pages sometimes have multiple tarballs with different shasum:
# - releases/download/1.0/<pkg>-1.0.tar.gz (uploaded tarball)
# - archive/refs/tags/1.0.tar.gz (generated tarball)
# We wanna ensure that `spack checksum` and `spack install` ultimately use the same URL, so
# here we check whether the crawled and computed URLs disagree, and if so, prioritize the
# former if that URL exists (just sending a HEAD request that is).
url_changed_for_version = set()
for version, url in url_dict.items():
possible_urls = pkg.all_urls_for_version(version)
if url not in possible_urls:
for possible_url in possible_urls:
if web_util.url_exists(possible_url):
url_dict[version] = possible_url
break
else:
url_changed_for_version.add(version)
if not url_dict:
tty.die(f"Could not find any remote versions for {pkg.name}")
# print an empty line to create a new output section block
print()
elif len(url_dict) > 1 and not args.batch and sys.stdin.isatty():
filtered_url_dict = spack.stage.interactive_version_filter(
url_dict, pkg.versions, url_changes=url_changed_for_version
)
if filtered_url_dict is None:
exit(0)
url_dict = filtered_url_dict
else:
tty.info(f"Found {llnl.string.plural(len(url_dict), 'version')} of {pkg.name}")
version_hashes = spack.stage.get_checksums_for_versions(
url_dict,
pkg.name,
keep_stage=args.keep_stage,
batch=(args.batch or len(versions) > 0 or len(url_dict) == 1),
fetch_options=pkg.fetch_options,
url_dict, pkg.name, keep_stage=args.keep_stage, fetch_options=pkg.fetch_options
)
if args.verify:
@@ -239,7 +261,7 @@ def add_versions_to_package(pkg: PackageBase, version_lines: str):
parsed_version = Version(contents_version.group(1))
if parsed_version < new_versions[0][0]:
split_contents[i:i] = [new_versions.pop(0)[1], " # FIX ME", "\n"]
split_contents[i:i] = [new_versions.pop(0)[1], " # FIXME", "\n"]
num_versions_added += 1
elif parsed_version == new_versions[0][0]:

View File

@@ -5,6 +5,7 @@
import os
import re
import sys
import urllib.parse
import llnl.util.tty as tty
@@ -823,6 +824,11 @@ def get_versions(args, name):
# Find available versions
try:
url_dict = spack.url.find_versions_of_archive(args.url)
if len(url_dict) > 1 and not args.batch and sys.stdin.isatty():
url_dict_filtered = spack.stage.interactive_version_filter(url_dict)
if url_dict_filtered is None:
exit(0)
url_dict = url_dict_filtered
except UndetectableVersionError:
# Use fake versions
tty.warn("Couldn't detect version in: {0}".format(args.url))
@@ -834,11 +840,7 @@ def get_versions(args, name):
url_dict = {version: args.url}
version_hashes = spack.stage.get_checksums_for_versions(
url_dict,
name,
first_stage_function=guesser,
keep_stage=args.keep_stage,
batch=(args.batch or len(url_dict) == 1),
url_dict, name, first_stage_function=guesser, keep_stage=args.keep_stage
)
versions = get_version_lines(version_hashes, url_dict)

View File

@@ -9,6 +9,7 @@
import sys
import tempfile
import llnl.string as string
import llnl.util.filesystem as fs
import llnl.util.tty as tty
from llnl.util.tty.colify import colify
@@ -28,7 +29,6 @@
import spack.schema.env
import spack.spec
import spack.tengine
import spack.util.string as string
from spack.util.environment import EnvironmentModifications
description = "manage virtual environments"

View File

@@ -5,6 +5,7 @@
import argparse
import errno
import os
import re
import sys
from typing import List, Optional
@@ -156,11 +157,20 @@ def packages_to_search_for(
):
result = []
for current_tag in tags:
result.extend(spack.repo.PATH.packages_with_tags(current_tag))
result.extend(spack.repo.PATH.packages_with_tags(current_tag, full=True))
if names:
result = [x for x in result if x in names]
# Match both fully qualified and unqualified
parts = [rf"(^{x}$|[.]{x}$)" for x in names]
select_re = re.compile("|".join(parts))
result = [x for x in result if select_re.search(x)]
if exclude:
result = [x for x in result if x not in exclude]
# Match both fully qualified and unqualified
parts = [rf"(^{x}$|[.]{x}$)" for x in exclude]
select_re = re.compile("|".join(parts))
result = [x for x in result if not select_re.search(x)]
return result

View File

@@ -6,10 +6,11 @@
import posixpath
import sys
from llnl.path import convert_to_posix_path
import spack.paths
import spack.util.executable
from spack.spec import Spec
from spack.util.path import convert_to_posix_path
description = "generate Windows installer"
section = "admin"

View File

@@ -176,17 +176,29 @@ def solve(parser, args):
output = sys.stdout if "asp" in show else None
setup_only = set(show) == {"asp"}
unify = spack.config.get("concretizer:unify")
allow_deprecated = spack.config.get("config:deprecated", False)
if unify != "when_possible":
# set up solver parameters
# Note: reuse and other concretizer prefs are passed as configuration
result = solver.solve(
specs, out=output, timers=args.timers, stats=args.stats, setup_only=setup_only
specs,
out=output,
timers=args.timers,
stats=args.stats,
setup_only=setup_only,
allow_deprecated=allow_deprecated,
)
if not setup_only:
_process_result(result, show, required_format, kwargs)
else:
for idx, result in enumerate(
solver.solve_in_rounds(specs, out=output, timers=args.timers, stats=args.stats)
solver.solve_in_rounds(
specs,
out=output,
timers=args.timers,
stats=args.stats,
allow_deprecated=allow_deprecated,
)
):
if "solutions" in show:
tty.msg("ROUND {0}".format(idx))

View File

@@ -5,6 +5,7 @@
import io
import sys
import llnl.string
import llnl.util.tty as tty
import llnl.util.tty.colify as colify
@@ -24,7 +25,7 @@ def report_tags(category, tags):
if isatty:
num = len(tags)
fmt = "{0} package tag".format(category)
buffer.write("{0}:\n".format(spack.util.string.plural(num, fmt)))
buffer.write("{0}:\n".format(llnl.string.plural(num, fmt)))
if tags:
colify.colify(tags, output=buffer, tty=isatty, indent=4)

View File

@@ -37,10 +37,7 @@ def setup_parser(subparser):
action="store_true",
help="only list remote versions newer than the latest checksummed version",
)
subparser.add_argument(
"-c", "--concurrency", default=32, type=int, help="number of concurrent requests"
)
arguments.add_common_arguments(subparser, ["package"])
arguments.add_common_arguments(subparser, ["package", "jobs"])
def versions(parser, args):
@@ -68,7 +65,7 @@ def versions(parser, args):
if args.safe:
return
fetched_versions = pkg.fetch_remote_versions(args.concurrency)
fetched_versions = pkg.fetch_remote_versions(args.jobs)
if args.new:
if sys.stdout.isatty():

View File

@@ -13,6 +13,7 @@
import tempfile
from typing import List, Optional, Sequence
import llnl.path
import llnl.util.lang
import llnl.util.tty as tty
from llnl.util.filesystem import path_contains_subdirectory, paths_containing_libs
@@ -24,7 +25,6 @@
import spack.util.module_cmd
import spack.version
from spack.util.environment import filter_system_paths
from spack.util.path import system_path_filter
__all__ = ["Compiler"]
@@ -39,10 +39,17 @@ def _get_compiler_version_output(compiler_path, version_arg, ignore_errors=()):
version_arg (str): the argument used to extract version information
"""
compiler = spack.util.executable.Executable(compiler_path)
compiler_invocation_args = {
"output": str,
"error": str,
"ignore_errors": ignore_errors,
"timeout": 120,
"fail_on_error": True,
}
if version_arg:
output = compiler(version_arg, output=str, error=str, ignore_errors=ignore_errors)
output = compiler(version_arg, **compiler_invocation_args)
else:
output = compiler(output=str, error=str, ignore_errors=ignore_errors)
output = compiler(**compiler_invocation_args)
return output
@@ -153,7 +160,7 @@ def _parse_link_paths(string):
return implicit_link_dirs
@system_path_filter
@llnl.path.system_path_filter
def _parse_non_system_link_dirs(string: str) -> List[str]:
"""Parses link paths out of compiler debug output.
@@ -229,6 +236,9 @@ class Compiler:
# by any compiler
_all_compiler_rpath_libraries = ["libc", "libc++", "libstdc++"]
#: Platform matcher for Platform objects supported by compiler
is_supported_on_platform = lambda x: True
# Default flags used by a compiler to set an rpath
@property
def cc_rpath_arg(self):
@@ -594,8 +604,6 @@ def search_regexps(cls, language):
compiler_names = getattr(cls, "{0}_names".format(language))
prefixes = [""] + cls.prefixes
suffixes = [""]
# Windows compilers generally have an extension of some sort
# as do most files on Windows, handle that case here
if sys.platform == "win32":
ext = r"\.(?:exe|bat)"
cls_suf = [suf + ext for suf in cls.suffixes]

View File

@@ -10,7 +10,7 @@
import itertools
import multiprocessing.pool
import os
from typing import Dict
from typing import Dict, List
import archspec.cpu
@@ -298,7 +298,7 @@ def select_new_compilers(compilers, scope=None):
return compilers_not_in_config
def supported_compilers():
def supported_compilers() -> List[str]:
"""Return a set of names of compilers supported by Spack.
See available_compilers() to get a list of all the available
@@ -306,10 +306,41 @@ def supported_compilers():
"""
# Hack to be able to call the compiler `apple-clang` while still
# using a valid python name for the module
return sorted(
name if name != "apple_clang" else "apple-clang"
for name in llnl.util.lang.list_modules(spack.paths.compilers_path)
)
return sorted(all_compiler_names())
def supported_compilers_for_host_platform() -> List[str]:
"""Return a set of compiler class objects supported by Spack
that are also supported by the current host platform
"""
host_plat = spack.platforms.real_host()
return supported_compilers_for_platform(host_plat)
def supported_compilers_for_platform(platform: spack.platforms.Platform) -> List[str]:
"""Return a set of compiler class objects supported by Spack
that are also supported by the provided platform
Args:
platform (str): string representation of platform
for which compiler compatability should be determined
"""
return [
name
for name in supported_compilers()
if class_for_compiler_name(name).is_supported_on_platform(platform)
]
def all_compiler_names() -> List[str]:
def replace_apple_clang(name):
return name if name != "apple_clang" else "apple-clang"
return [replace_apple_clang(name) for name in all_compiler_module_names()]
def all_compiler_module_names() -> List[str]:
return [name for name in llnl.util.lang.list_modules(spack.paths.compilers_path)]
@_auto_compiler_spec
@@ -628,7 +659,7 @@ def arguments_to_detect_version_fn(operating_system, paths):
def _default(search_paths):
command_arguments = []
files_to_be_tested = fs.files_in(*search_paths)
for compiler_name in spack.compilers.supported_compilers():
for compiler_name in spack.compilers.supported_compilers_for_host_platform():
compiler_cls = class_for_compiler_name(compiler_name)
for language in ("cc", "cxx", "f77", "fc"):
@@ -687,9 +718,11 @@ def _default(fn_args):
value = fn_args._replace(id=compiler_id._replace(version=version))
return value, None
error = "Couldn't get version for compiler {0}".format(path)
error = f"Couldn't get version for compiler {path}".format(path)
except spack.util.executable.ProcessError as e:
error = "Couldn't get version for compiler {0}\n".format(path) + str(e)
error = f"Couldn't get version for compiler {path}\n" + str(e)
except spack.util.executable.ProcessTimeoutError as e:
error = f"Couldn't get version for compiler {path}\n" + str(e)
except Exception as e:
# Catching "Exception" here is fine because it just
# means something went wrong running a candidate executable.

View File

@@ -112,6 +112,7 @@ def extract_version_from_output(cls, output):
match = re.search(r"AOCC_(\d+)[._](\d+)[._](\d+)", output)
if match:
return ".".join(match.groups())
return "unknown"
@classmethod
def fc_version(cls, fortran_compiler):

View File

@@ -7,7 +7,6 @@
import re
import subprocess
import sys
from distutils.version import StrictVersion
from typing import Dict, List, Set
import spack.compiler
@@ -115,11 +114,11 @@ def command_str(self):
def get_valid_fortran_pth(comp_ver):
cl_ver = str(comp_ver)
sort_fn = lambda fc_ver: StrictVersion(fc_ver)
sort_fn = lambda fc_ver: Version(fc_ver)
sort_fc_ver = sorted(list(avail_fc_version), key=sort_fn)
for ver in sort_fc_ver:
if ver in fortran_mapping:
if StrictVersion(cl_ver) <= StrictVersion(fortran_mapping[ver]):
if Version(cl_ver) <= Version(fortran_mapping[ver]):
return fc_path[ver]
return None
@@ -154,9 +153,12 @@ class Msvc(Compiler):
#: Regex used to extract version from compiler's output
version_regex = r"([1-9][0-9]*\.[0-9]*\.[0-9]*)"
# The MSVC compiler class overrides this to prevent instances
# of erroneous matching on executable names that cannot be msvc
# compilers
suffixes = []
# Initialize, deferring to base class but then adding the vcvarsallfile
# file based on compiler executable path.
is_supported_on_platform = lambda x: isinstance(x, spack.platforms.Windows)
def __init__(self, *args, **kwargs):
# This positional argument "paths" is later parsed and process by the base class
@@ -167,6 +169,8 @@ def __init__(self, *args, **kwargs):
cspec = args[0]
new_pth = [pth if pth else get_valid_fortran_pth(cspec.version) for pth in paths]
paths[:] = new_pth
# Initialize, deferring to base class but then adding the vcvarsallfile
# file based on compiler executable path.
super().__init__(*args, **kwargs)
# To use the MSVC compilers, VCVARS must be invoked
# VCVARS is located at a fixed location, referencable

View File

@@ -744,8 +744,11 @@ def concretize_specs_together(*abstract_specs, **kwargs):
def _concretize_specs_together_new(*abstract_specs, **kwargs):
import spack.solver.asp
allow_deprecated = spack.config.get("config:deprecated", False)
solver = spack.solver.asp.Solver()
result = solver.solve(abstract_specs, tests=kwargs.get("tests", False))
result = solver.solve(
abstract_specs, tests=kwargs.get("tests", False), allow_deprecated=allow_deprecated
)
result.raise_if_unsat()
return [s.copy() for s in result.specs]

View File

@@ -272,13 +272,6 @@ def _os_pkg_manager(self):
raise spack.error.SpackError(msg)
return os_pkg_manager
@tengine.context_property
def extra_instructions(self):
Extras = namedtuple("Extra", ["build", "final"])
extras = self.container_config.get("extra_instructions", {})
build, final = extras.get("build", None), extras.get("final", None)
return Extras(build=build, final=final)
@tengine.context_property
def labels(self):
return self.container_config.get("labels", {})

View File

@@ -4,6 +4,9 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import json
import os
import traceback
import warnings
import jsonschema
import jsonschema.exceptions
@@ -46,9 +49,29 @@ def translated_compiler_name(manifest_compiler_name):
)
def compiler_from_entry(entry):
def compiler_from_entry(entry: dict, manifest_path: str):
# Note that manifest_path is only passed here to compose a
# useful warning message when paths appear to be missing.
compiler_name = translated_compiler_name(entry["name"])
paths = entry["executables"]
if "prefix" in entry:
prefix = entry["prefix"]
paths = dict(
(lang, os.path.join(prefix, relpath))
for (lang, relpath) in entry["executables"].items()
)
else:
paths = entry["executables"]
# Do a check for missing paths. Note that this isn't possible for
# all compiler entries, since their "paths" might actually be
# exe names like "cc" that depend on modules being loaded. Cray
# manifest entries are always paths though.
missing_paths = []
for path in paths.values():
if not os.path.exists(path):
missing_paths.append(path)
# to instantiate a compiler class we may need a concrete version:
version = "={}".format(entry["version"])
arch = entry["arch"]
@@ -57,8 +80,18 @@ def compiler_from_entry(entry):
compiler_cls = spack.compilers.class_for_compiler_name(compiler_name)
spec = spack.spec.CompilerSpec(compiler_cls.name, version)
paths = [paths.get(x, None) for x in ("cc", "cxx", "f77", "fc")]
return compiler_cls(spec, operating_system, target, paths)
path_list = [paths.get(x, None) for x in ("cc", "cxx", "f77", "fc")]
if missing_paths:
warnings.warn(
"Manifest entry refers to nonexistent paths:\n\t"
+ "\n\t".join(missing_paths)
+ f"\nfor {str(spec)}"
+ f"\nin {manifest_path}"
+ "\nPlease report this issue"
)
return compiler_cls(spec, operating_system, target, path_list)
def spec_from_entry(entry):
@@ -187,12 +220,21 @@ def read(path, apply_updates):
tty.debug("{0}: {1} specs read from manifest".format(path, str(len(specs))))
compilers = list()
if "compilers" in json_data:
compilers.extend(compiler_from_entry(x) for x in json_data["compilers"])
compilers.extend(compiler_from_entry(x, path) for x in json_data["compilers"])
tty.debug("{0}: {1} compilers read from manifest".format(path, str(len(compilers))))
# Filter out the compilers that already appear in the configuration
compilers = spack.compilers.select_new_compilers(compilers)
if apply_updates and compilers:
spack.compilers.add_compilers_to_config(compilers, init_config=False)
for compiler in compilers:
try:
spack.compilers.add_compilers_to_config([compiler], init_config=False)
except Exception:
warnings.warn(
f"Could not add compiler {str(compiler.spec)}: "
f"\n\tfrom manifest: {path}"
"\nPlease reexecute with 'spack -d' and include the stack trace"
)
tty.debug(f"Include this\n{traceback.format_exc()}")
if apply_updates:
for spec in specs.values():
spack.store.STORE.db.add(spec, directory_layout=None)

View File

@@ -4,6 +4,7 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from .common import DetectedPackage, executable_prefix, update_configuration
from .path import by_path, executables_in_path
from .test import detection_tests
__all__ = [
"DetectedPackage",
@@ -11,4 +12,5 @@
"executables_in_path",
"executable_prefix",
"update_configuration",
"detection_tests",
]

View File

@@ -299,36 +299,36 @@ def find_windows_compiler_bundled_packages() -> List[str]:
class WindowsKitExternalPaths:
plat_major_ver = None
if sys.platform == "win32":
plat_major_ver = str(winOs.windows_version()[0])
@staticmethod
def find_windows_kit_roots() -> Optional[str]:
def find_windows_kit_roots() -> List[str]:
"""Return Windows kit root, typically %programfiles%\\Windows Kits\\10|11\\"""
if sys.platform != "win32":
return None
return []
program_files = os.environ["PROGRAMFILES(x86)"]
kit_base = os.path.join(
program_files, "Windows Kits", WindowsKitExternalPaths.plat_major_ver
)
return kit_base
kit_base = os.path.join(program_files, "Windows Kits", "**")
return glob.glob(kit_base)
@staticmethod
def find_windows_kit_bin_paths(kit_base: Optional[str] = None) -> List[str]:
"""Returns Windows kit bin directory per version"""
kit_base = WindowsKitExternalPaths.find_windows_kit_roots() if not kit_base else kit_base
assert kit_base is not None, "unexpected value for kit_base"
kit_bin = os.path.join(kit_base, "bin")
return glob.glob(os.path.join(kit_bin, "[0-9]*", "*\\"))
assert kit_base, "Unexpectedly empty value for Windows kit base path"
kit_paths = []
for kit in kit_base:
kit_bin = os.path.join(kit, "bin")
kit_paths.extend(glob.glob(os.path.join(kit_bin, "[0-9]*", "*\\")))
return kit_paths
@staticmethod
def find_windows_kit_lib_paths(kit_base: Optional[str] = None) -> List[str]:
"""Returns Windows kit lib directory per version"""
kit_base = WindowsKitExternalPaths.find_windows_kit_roots() if not kit_base else kit_base
assert kit_base is not None, "unexpected value for kit_base"
kit_lib = os.path.join(kit_base, "Lib")
return glob.glob(os.path.join(kit_lib, "[0-9]*", "*", "*\\"))
assert kit_base, "Unexpectedly empty value for Windows kit base path"
kit_paths = []
for kit in kit_base:
kit_lib = os.path.join(kit, "Lib")
kit_paths.extend(glob.glob(os.path.join(kit_lib, "[0-9]*", "*", "*\\")))
return kit_paths
@staticmethod
def find_windows_driver_development_kit_paths() -> List[str]:
@@ -347,23 +347,30 @@ def find_windows_kit_reg_installed_roots_paths() -> List[str]:
if not reg:
# couldn't find key, return empty list
return []
return WindowsKitExternalPaths.find_windows_kit_lib_paths(
reg.get_value("KitsRoot%s" % WindowsKitExternalPaths.plat_major_ver).value
)
kit_root_reg = re.compile(r"KitsRoot[0-9]+")
root_paths = []
for kit_root in filter(kit_root_reg.match, reg.get_values().keys()):
root_paths.extend(
WindowsKitExternalPaths.find_windows_kit_lib_paths(reg.get_value(kit_root).value)
)
return root_paths
@staticmethod
def find_windows_kit_reg_sdk_paths() -> List[str]:
reg = spack.util.windows_registry.WindowsRegistryView(
"SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v%s.0"
% WindowsKitExternalPaths.plat_major_ver,
sdk_paths = []
sdk_regex = re.compile(r"v[0-9]+.[0-9]+")
windows_reg = spack.util.windows_registry.WindowsRegistryView(
"SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows",
root_key=spack.util.windows_registry.HKEY.HKEY_LOCAL_MACHINE,
)
if not reg:
# couldn't find key, return empty list
return []
return WindowsKitExternalPaths.find_windows_kit_lib_paths(
reg.get_value("InstallationFolder").value
)
for key in filter(sdk_regex.match, [x.name for x in windows_reg.get_subkeys()]):
reg = windows_reg.get_subkey(key)
sdk_paths.extend(
WindowsKitExternalPaths.find_windows_kit_lib_paths(
reg.get_value("InstallationFolder").value
)
)
return sdk_paths
def find_win32_additional_install_paths() -> List[str]:

View File

@@ -2,7 +2,7 @@
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""Detection of software installed in the system based on paths inspections
"""Detection of software installed in the system, based on paths inspections
and running executables.
"""
import collections
@@ -322,12 +322,14 @@ def by_path(
path_hints: Optional[List[str]] = None,
max_workers: Optional[int] = None,
) -> Dict[str, List[DetectedPackage]]:
"""Return the list of packages that have been detected on the system,
searching by path.
"""Return the list of packages that have been detected on the system, keyed by
unqualified package name.
Args:
packages_to_search: list of package classes to be detected
packages_to_search: list of packages to be detected. Each package can be either unqualified
of fully qualified
path_hints: initial list of paths to be searched
max_workers: maximum number of workers to search for packages in parallel
"""
# TODO: Packages should be able to define both .libraries and .executables in the future
# TODO: determine_spec_details should get all relevant libraries and executables in one call
@@ -355,7 +357,8 @@ def by_path(
try:
detected = future.result(timeout=DETECTION_TIMEOUT)
if detected:
result[pkg_name].extend(detected)
_, unqualified_name = spack.repo.partition_package_name(pkg_name)
result[unqualified_name].extend(detected)
except Exception:
llnl.util.tty.debug(
f"[EXTERNAL DETECTION] Skipping {pkg_name}: timeout reached"

View File

@@ -0,0 +1,187 @@
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""Create and run mock e2e tests for package detection."""
import collections
import contextlib
import pathlib
import tempfile
from typing import Any, Deque, Dict, Generator, List, NamedTuple, Tuple
import jinja2
from llnl.util import filesystem
import spack.repo
import spack.spec
from spack.util import spack_yaml
from .path import by_path
class MockExecutables(NamedTuple):
"""Mock executables to be used in detection tests"""
#: Relative paths for mock executables to be created
executables: List[str]
#: Shell script for the mock executable
script: str
class ExpectedTestResult(NamedTuple):
"""Data structure to model assertions on detection tests"""
#: Spec to be detected
spec: str
class DetectionTest(NamedTuple):
"""Data structure to construct detection tests by PATH inspection.
Packages may have a YAML file containing the description of one or more detection tests
to be performed. Each test creates a few mock executable scripts in a temporary folder,
and checks that detection by PATH gives the expected results.
"""
pkg_name: str
layout: List[MockExecutables]
results: List[ExpectedTestResult]
class Runner:
"""Runs an external detection test"""
def __init__(self, *, test: DetectionTest, repository: spack.repo.RepoPath) -> None:
self.test = test
self.repository = repository
self.tmpdir = tempfile.TemporaryDirectory()
def execute(self) -> List[spack.spec.Spec]:
"""Executes a test and returns the specs that have been detected.
This function sets-up a test in a temporary directory, according to the prescriptions
in the test layout, then performs a detection by executables and returns the specs that
have been detected.
"""
with self._mock_layout() as path_hints:
entries = by_path([self.test.pkg_name], path_hints=path_hints)
_, unqualified_name = spack.repo.partition_package_name(self.test.pkg_name)
specs = set(x.spec for x in entries[unqualified_name])
return list(specs)
@contextlib.contextmanager
def _mock_layout(self) -> Generator[List[str], None, None]:
hints = set()
try:
for entry in self.test.layout:
exes = self._create_executable_scripts(entry)
for mock_executable in exes:
hints.add(str(mock_executable.parent))
yield list(hints)
finally:
self.tmpdir.cleanup()
def _create_executable_scripts(self, mock_executables: MockExecutables) -> List[pathlib.Path]:
relative_paths = mock_executables.executables
script = mock_executables.script
script_template = jinja2.Template("#!/bin/bash\n{{ script }}\n")
result = []
for mock_exe_path in relative_paths:
rel_path = pathlib.Path(mock_exe_path)
abs_path = pathlib.Path(self.tmpdir.name) / rel_path
abs_path.parent.mkdir(parents=True, exist_ok=True)
abs_path.write_text(script_template.render(script=script))
filesystem.set_executable(abs_path)
result.append(abs_path)
return result
@property
def expected_specs(self) -> List[spack.spec.Spec]:
return [spack.spec.Spec(r.spec) for r in self.test.results]
def detection_tests(pkg_name: str, repository: spack.repo.RepoPath) -> List[Runner]:
"""Returns a list of test runners for a given package.
Currently, detection tests are specified in a YAML file, called ``detection_test.yaml``,
alongside the ``package.py`` file.
This function reads that file to create a bunch of ``Runner`` objects.
Args:
pkg_name: name of the package to test
repository: repository where the package lives
"""
result = []
detection_tests_content = read_detection_tests(pkg_name, repository)
tests_by_path = detection_tests_content.get("paths", [])
for single_test_data in tests_by_path:
mock_executables = []
for layout in single_test_data["layout"]:
mock_executables.append(
MockExecutables(executables=layout["executables"], script=layout["script"])
)
expected_results = []
for assertion in single_test_data["results"]:
expected_results.append(ExpectedTestResult(spec=assertion["spec"]))
current_test = DetectionTest(
pkg_name=pkg_name, layout=mock_executables, results=expected_results
)
result.append(Runner(test=current_test, repository=repository))
return result
def read_detection_tests(pkg_name: str, repository: spack.repo.RepoPath) -> Dict[str, Any]:
"""Returns the normalized content of the detection_tests.yaml associated with the package
passed in input.
The content is merged with that of any package that is transitively included using the
"includes" attribute.
Args:
pkg_name: name of the package to test
repository: repository in which to search for packages
"""
content_stack, seen = [], set()
included_packages: Deque[str] = collections.deque()
root_detection_yaml, result = _detection_tests_yaml(pkg_name, repository)
included_packages.extend(result.get("includes", []))
seen |= set(result.get("includes", []))
while included_packages:
current_package = included_packages.popleft()
try:
current_detection_yaml, content = _detection_tests_yaml(current_package, repository)
except FileNotFoundError as e:
msg = (
f"cannot read the detection tests from the '{current_package}' package, "
f"included by {root_detection_yaml}"
)
raise FileNotFoundError(msg + f"\n\n\t{e}\n")
content_stack.append((current_package, content))
included_packages.extend(x for x in content.get("includes", []) if x not in seen)
seen |= set(content.get("includes", []))
result.setdefault("paths", [])
for pkg_name, content in content_stack:
result["paths"].extend(content.get("paths", []))
return result
def _detection_tests_yaml(
pkg_name: str, repository: spack.repo.RepoPath
) -> Tuple[pathlib.Path, Dict[str, Any]]:
pkg_dir = pathlib.Path(repository.filename_for_package_name(pkg_name)).parent
detection_tests_yaml = pkg_dir / "detection_test.yaml"
with open(str(detection_tests_yaml)) as f:
content = spack_yaml.load(f)
return detection_tests_yaml, content

View File

@@ -120,10 +120,8 @@ def write_host_environment(self, spec):
versioning. We use it in the case that an analysis later needs to
easily access this information.
"""
from spack.util.environment import get_host_environment_metadata
env_file = self.env_metadata_path(spec)
environ = get_host_environment_metadata()
environ = spack.spec.get_host_environment_metadata()
with open(env_file, "w") as fd:
sjson.dump(environ, fd)

View File

@@ -404,7 +404,7 @@ def _write_yaml(data, str_or_file):
def _eval_conditional(string):
"""Evaluate conditional definitions using restricted variable scope."""
valid_variables = spack.util.environment.get_host_environment()
valid_variables = spack.spec.get_host_environment()
valid_variables.update({"re": re, "env": os.environ})
return eval(string, valid_variables)
@@ -1396,7 +1396,10 @@ def _concretize_together_where_possible(
result_by_user_spec = {}
solver = spack.solver.asp.Solver()
for result in solver.solve_in_rounds(specs_to_concretize, tests=tests):
allow_deprecated = spack.config.get("config:deprecated", False)
for result in solver.solve_in_rounds(
specs_to_concretize, tests=tests, allow_deprecated=allow_deprecated
):
result_by_user_spec.update(result.specs_by_input)
result = []

View File

@@ -128,3 +128,7 @@ def __init__(self, provided, required, constraint_type):
self.provided = provided
self.required = required
self.constraint_type = constraint_type
class FetchError(SpackError):
"""Superclass for fetch-related errors."""

View File

@@ -35,6 +35,7 @@
import llnl.util
import llnl.util.filesystem as fs
import llnl.util.tty as tty
from llnl.string import comma_and, quote
from llnl.util.filesystem import get_single_file, mkdirp, temp_cwd, temp_rename, working_dir
from llnl.util.symlink import symlink
@@ -49,7 +50,6 @@
import spack.version.git_ref_lookup
from spack.util.compression import decompressor_for
from spack.util.executable import CommandNotFoundError, which
from spack.util.string import comma_and, quote
#: List of all fetch strategies, created by FetchStrategy metaclass.
all_strategies = []
@@ -401,7 +401,7 @@ def _fetch_curl(self, url):
try:
web_util.check_curl_code(curl.returncode)
except web_util.FetchError as err:
except spack.error.FetchError as err:
raise spack.fetch_strategy.FailedDownloadError(url, str(err))
self._check_headers(headers)
@@ -734,7 +734,11 @@ def version_from_git(git_exe):
@property
def git(self):
if not self._git:
self._git = spack.util.git.git()
try:
self._git = spack.util.git.git(required=True)
except CommandNotFoundError as exc:
tty.error(str(exc))
raise
# Disable advice for a quieter fetch
# https://github.com/git/git/blob/master/Documentation/RelNotes/1.7.2.txt
@@ -1290,7 +1294,7 @@ def fetch(self):
parsed_url = urllib.parse.urlparse(self.url)
if parsed_url.scheme != "s3":
raise web_util.FetchError("S3FetchStrategy can only fetch from s3:// urls.")
raise spack.error.FetchError("S3FetchStrategy can only fetch from s3:// urls.")
tty.debug("Fetching {0}".format(self.url))
@@ -1337,7 +1341,7 @@ def fetch(self):
parsed_url = urllib.parse.urlparse(self.url)
if parsed_url.scheme != "gs":
raise web_util.FetchError("GCSFetchStrategy can only fetch from gs:// urls.")
raise spack.error.FetchError("GCSFetchStrategy can only fetch from gs:// urls.")
tty.debug("Fetching {0}".format(self.url))
@@ -1431,7 +1435,7 @@ def from_kwargs(**kwargs):
on attribute names (e.g., ``git``, ``hg``, etc.)
Raises:
spack.util.web.FetchError: If no ``fetch_strategy`` matches the args.
spack.error.FetchError: If no ``fetch_strategy`` matches the args.
"""
for fetcher in all_strategies:
if fetcher.matches(kwargs):
@@ -1538,7 +1542,7 @@ def for_package_version(pkg, version=None):
# if it's a commit, we must use a GitFetchStrategy
if isinstance(version, spack.version.GitVersion):
if not hasattr(pkg, "git"):
raise web_util.FetchError(
raise spack.error.FetchError(
f"Cannot fetch git version for {pkg.name}. Package has no 'git' attribute"
)
# Populate the version with comparisons to other commits
@@ -1688,11 +1692,11 @@ def destroy(self):
shutil.rmtree(self.root, ignore_errors=True)
class NoCacheError(web_util.FetchError):
class NoCacheError(spack.error.FetchError):
"""Raised when there is no cached archive for a package."""
class FailedDownloadError(web_util.FetchError):
class FailedDownloadError(spack.error.FetchError):
"""Raised when a download fails."""
def __init__(self, url, msg=""):
@@ -1700,23 +1704,23 @@ def __init__(self, url, msg=""):
self.url = url
class NoArchiveFileError(web_util.FetchError):
class NoArchiveFileError(spack.error.FetchError):
"""Raised when an archive file is expected but none exists."""
class NoDigestError(web_util.FetchError):
class NoDigestError(spack.error.FetchError):
"""Raised after attempt to checksum when URL has no digest."""
class ExtrapolationError(web_util.FetchError):
class ExtrapolationError(spack.error.FetchError):
"""Raised when we can't extrapolate a version for a package."""
class FetcherConflict(web_util.FetchError):
class FetcherConflict(spack.error.FetchError):
"""Raised for packages with invalid fetch attributes."""
class InvalidArgsError(web_util.FetchError):
class InvalidArgsError(spack.error.FetchError):
"""Raised when a version can't be deduced from a set of arguments."""
def __init__(self, pkg=None, version=None, **args):
@@ -1729,11 +1733,11 @@ def __init__(self, pkg=None, version=None, **args):
super().__init__(msg, long_msg)
class ChecksumError(web_util.FetchError):
class ChecksumError(spack.error.FetchError):
"""Raised when archive fails to checksum."""
class NoStageError(web_util.FetchError):
class NoStageError(spack.error.FetchError):
"""Raised when fetch operations are called before set_stage()."""
def __init__(self, method):

View File

@@ -531,7 +531,7 @@ def edge_entry(self, edge):
return (
edge.parent.dag_hash(),
edge.spec.dag_hash(),
f"[color=\"{':'.join(colormap[x] for x in edge.deptypes)}\"]",
f"[color=\"{':'.join(colormap[x] for x in dt.flag_to_tuple(edge.depflag))}\"]",
)

View File

@@ -79,8 +79,7 @@ class ElfFilesWithRPathVisitor(BaseDirectoryVisitor):
"""Visitor that collects all elf files that have an rpath"""
def __init__(self):
# Map from (ino, dev) -> path. We need 1 path per file, if there are hardlinks,
# we don't need to store the path multiple times.
# Keep track of what hardlinked files we've already visited.
self.visited = set()
def visit_file(self, root, rel_path, depth):
@@ -89,10 +88,10 @@ def visit_file(self, root, rel_path, depth):
identifier = (s.st_ino, s.st_dev)
# We're hitting a hardlink or symlink of an excluded lib, no need to parse.
if identifier in self.visited:
return
self.visited.add(identifier)
if s.st_nlink > 1:
if identifier in self.visited:
return
self.visited.add(identifier)
result = drop_redundant_rpaths(filepath)

View File

@@ -11,7 +11,6 @@
def _for_each_enabled(spec, method_name, explicit=None):
"""Calls a method for each enabled module"""
spack.modules.ensure_modules_are_enabled_or_warn()
set_names = set(spack.config.get("modules", {}).keys())
for name in set_names:
enabled = spack.config.get("modules:%s:enable" % name)

View File

@@ -17,6 +17,7 @@
import llnl.util.filesystem as fs
import llnl.util.tty as tty
from llnl.string import plural
from llnl.util.lang import nullcontext
from llnl.util.tty.color import colorize
@@ -26,7 +27,6 @@
from spack.installer import InstallError
from spack.spec import Spec
from spack.util.prefix import Prefix
from spack.util.string import plural
#: Stand-alone test failure info type
TestFailureType = Tuple[BaseException, str]

View File

@@ -131,12 +131,12 @@ def set_term_title(self, text: str):
if not sys.stdout.isatty():
return
status = "{0} {1}".format(text, self.get_progress())
sys.stdout.write("\033]0;Spack: {0}\007".format(status))
status = f"{text} {self.get_progress()}"
sys.stdout.write(f"\x1b]0;Spack: {status}\x07")
sys.stdout.flush()
def get_progress(self) -> str:
return "[{0}/{1}]".format(self.pkg_num, self.pkg_count)
return f"[{self.pkg_num}/{self.pkg_count}]"
class TermStatusLine:
@@ -175,7 +175,7 @@ def clear(self):
# Move the cursor to the beginning of the first "Waiting for" message and clear
# everything after it.
sys.stdout.write("\x1b[%sF\x1b[J" % lines)
sys.stdout.write(f"\x1b[{lines}F\x1b[J")
sys.stdout.flush()
@@ -220,14 +220,13 @@ def _handle_external_and_upstream(pkg: "spack.package_base.PackageBase", explici
# consists in module file generation and registration in the DB.
if pkg.spec.external:
_process_external_package(pkg, explicit)
_print_installed_pkg("{0} (external {1})".format(pkg.prefix, package_id(pkg)))
_print_installed_pkg(f"{pkg.prefix} (external {package_id(pkg)})")
return True
if pkg.spec.installed_upstream:
tty.verbose(
"{0} is installed in an upstream Spack instance at {1}".format(
package_id(pkg), pkg.spec.prefix
)
f"{package_id(pkg)} is installed in an upstream Spack instance at "
f"{pkg.spec.prefix}"
)
_print_installed_pkg(pkg.prefix)
@@ -296,7 +295,7 @@ def _packages_needed_to_bootstrap_compiler(
package is the bootstrap compiler (``True``) or one of its dependencies
(``False``). The list will be empty if there are no compilers.
"""
tty.debug("Bootstrapping {0} compiler".format(compiler))
tty.debug(f"Bootstrapping {compiler} compiler")
compilers = spack.compilers.compilers_for_spec(compiler, arch_spec=architecture)
if compilers:
return []
@@ -305,9 +304,9 @@ def _packages_needed_to_bootstrap_compiler(
# Set the architecture for the compiler package in a way that allows the
# concretizer to back off if needed for the older bootstrapping compiler
dep.constrain("platform=%s" % str(architecture.platform))
dep.constrain("os=%s" % str(architecture.os))
dep.constrain("target=%s:" % architecture.target.microarchitecture.family.name)
dep.constrain(f"platform={str(architecture.platform)}")
dep.constrain(f"os={str(architecture.os)}")
dep.constrain(f"target={architecture.target.microarchitecture.family.name}:")
# concrete CompilerSpec has less info than concrete Spec
# concretize as Spec to add that information
dep.concretize()
@@ -340,15 +339,15 @@ def _hms(seconds: int) -> str:
if m:
parts.append("%dm" % m)
if s:
parts.append("%.2fs" % s)
parts.append(f"{s:.2f}s")
return " ".join(parts)
def _log_prefix(pkg_name) -> str:
"""Prefix of the form "[pid]: [pkg name]: ..." when printing a status update during
the build."""
pid = "{0}: ".format(os.getpid()) if tty.show_pid() else ""
return "{0}{1}:".format(pid, pkg_name)
pid = f"{os.getpid()}: " if tty.show_pid() else ""
return f"{pid}{pkg_name}:"
def _print_installed_pkg(message: str) -> None:
@@ -375,9 +374,9 @@ def print_install_test_log(pkg: "spack.package_base.PackageBase") -> None:
def _print_timer(pre: str, pkg_id: str, timer: timer.BaseTimer) -> None:
phases = ["{}: {}.".format(p.capitalize(), _hms(timer.duration(p))) for p in timer.phases]
phases.append("Total: {}".format(_hms(timer.duration())))
tty.msg("{0} Successfully installed {1}".format(pre, pkg_id), " ".join(phases))
phases = [f"{p.capitalize()}: {_hms(timer.duration(p))}." for p in timer.phases]
phases.append(f"Total: {_hms(timer.duration())}")
tty.msg(f"{pre} Successfully installed {pkg_id}", " ".join(phases))
def _install_from_cache(
@@ -402,14 +401,14 @@ def _install_from_cache(
)
pkg_id = package_id(pkg)
if not installed_from_cache:
pre = "No binary for {0} found".format(pkg_id)
pre = f"No binary for {pkg_id} found"
if cache_only:
tty.die("{0} when cache-only specified".format(pre))
tty.die(f"{pre} when cache-only specified")
tty.msg("{0}: installing from source".format(pre))
tty.msg(f"{pre}: installing from source")
return False
t.stop()
tty.debug("Successfully extracted {0} from binary cache".format(pkg_id))
tty.debug(f"Successfully extracted {pkg_id} from binary cache")
_write_timer_json(pkg, t, True)
_print_timer(pre=_log_prefix(pkg.name), pkg_id=pkg_id, timer=t)
@@ -430,19 +429,19 @@ def _process_external_package(pkg: "spack.package_base.PackageBase", explicit: b
"""
assert pkg.spec.external, "Expected to post-install/register an external package."
pre = "{s.name}@{s.version} :".format(s=pkg.spec)
pre = f"{pkg.spec.name}@{pkg.spec.version} :"
spec = pkg.spec
if spec.external_modules:
tty.msg("{0} has external module in {1}".format(pre, spec.external_modules))
tty.debug("{0} is actually installed in {1}".format(pre, spec.external_path))
tty.msg(f"{pre} has external module in {spec.external_modules}")
tty.debug(f"{pre} is actually installed in {spec.external_path}")
else:
tty.debug("{0} externally installed in {1}".format(pre, spec.external_path))
tty.debug(f"{pre} externally installed in {spec.external_path}")
try:
# Check if the package was already registered in the DB.
# If this is the case, then only make explicit if required.
tty.debug("{0} already registered in DB".format(pre))
tty.debug(f"{pre} already registered in DB")
record = spack.store.STORE.db.get_record(spec)
if explicit and not record.explicit:
spack.store.STORE.db.update_explicit(spec, explicit)
@@ -451,11 +450,11 @@ def _process_external_package(pkg: "spack.package_base.PackageBase", explicit: b
# If not, register it and generate the module file.
# For external packages we just need to run
# post-install hooks to generate module files.
tty.debug("{0} generating module file".format(pre))
tty.debug(f"{pre} generating module file")
spack.hooks.post_install(spec, explicit)
# Add to the DB
tty.debug("{0} registering into DB".format(pre))
tty.debug(f"{pre} registering into DB")
spack.store.STORE.db.add(spec, None, explicit=explicit)
@@ -490,7 +489,7 @@ def _process_binary_cache_tarball(
if download_result is None:
return False
tty.msg("Extracting {0} from binary cache".format(package_id(pkg)))
tty.msg(f"Extracting {package_id(pkg)} from binary cache")
with timer.measure("install"), spack.util.path.filter_padding():
binary_distribution.extract_tarball(
@@ -522,7 +521,7 @@ def _try_install_from_binary_cache(
if not spack.mirror.MirrorCollection(binary=True):
return False
tty.debug("Searching for binary cache of {0}".format(package_id(pkg)))
tty.debug(f"Searching for binary cache of {package_id(pkg)}")
with timer.measure("search"):
matches = binary_distribution.get_mirrors_for_spec(pkg.spec, index_only=True)
@@ -590,9 +589,9 @@ def dump_packages(spec: "spack.spec.Spec", path: str) -> None:
source_repo = spack.repo.Repo(source_repo_root)
source_pkg_dir = source_repo.dirname_for_package_name(node.name)
except spack.repo.RepoError as err:
tty.debug("Failed to create source repo for {0}: {1}".format(node.name, str(err)))
tty.debug(f"Failed to create source repo for {node.name}: {str(err)}")
source_pkg_dir = None
tty.warn("Warning: Couldn't copy in provenance for {0}".format(node.name))
tty.warn(f"Warning: Couldn't copy in provenance for {node.name}")
# Create a destination repository
dest_repo_root = os.path.join(path, node.namespace)
@@ -632,7 +631,7 @@ def install_msg(name: str, pid: int, install_status: InstallStatus) -> str:
Return: Colorized installing message
"""
pre = "{0}: ".format(pid) if tty.show_pid() else ""
pre = f"{pid}: " if tty.show_pid() else ""
post = (
" @*{%s}" % install_status.get_progress()
if install_status and spack.config.get("config:install_status", True)
@@ -698,7 +697,7 @@ def log(pkg: "spack.package_base.PackageBase") -> None:
# in the stage tree (not arbitrary files)
abs_expr = os.path.realpath(glob_expr)
if os.path.realpath(pkg.stage.path) not in abs_expr:
errors.write("[OUTSIDE SOURCE PATH]: {0}\n".format(glob_expr))
errors.write(f"[OUTSIDE SOURCE PATH]: {glob_expr}\n")
continue
# Now that we are sure that the path is within the correct
# folder, make it relative and check for matches
@@ -718,14 +717,14 @@ def log(pkg: "spack.package_base.PackageBase") -> None:
# Here try to be conservative, and avoid discarding
# the whole install procedure because of copying a
# single file failed
errors.write("[FAILED TO ARCHIVE]: {0}".format(f))
errors.write(f"[FAILED TO ARCHIVE]: {f}")
if errors.getvalue():
error_file = os.path.join(target_dir, "errors.txt")
fs.mkdirp(target_dir)
with open(error_file, "w") as err:
err.write(errors.getvalue())
tty.warn("Errors occurred when archiving files.\n\t" "See: {0}".format(error_file))
tty.warn(f"Errors occurred when archiving files.\n\tSee: {error_file}")
dump_packages(pkg.spec, packages_dir)
@@ -761,11 +760,11 @@ def __init__(self, pkg: "spack.package_base.PackageBase", install_args: dict):
"""
# Ensure dealing with a package that has a concrete spec
if not isinstance(pkg, spack.package_base.PackageBase):
raise ValueError("{0} must be a package".format(str(pkg)))
raise ValueError(f"{str(pkg)} must be a package")
self.pkg = pkg
if not self.pkg.spec.concrete:
raise ValueError("{0} must have a concrete spec".format(self.pkg.name))
raise ValueError(f"{self.pkg.name} must have a concrete spec")
# Cache the package phase options with the explicit package,
# popping the options to ensure installation of associated
@@ -797,14 +796,14 @@ def __init__(self, pkg: "spack.package_base.PackageBase", install_args: dict):
def __repr__(self) -> str:
"""Returns a formal representation of the build request."""
rep = "{0}(".format(self.__class__.__name__)
rep = f"{self.__class__.__name__}("
for attr, value in self.__dict__.items():
rep += "{0}={1}, ".format(attr, value.__repr__())
return "{0})".format(rep.strip(", "))
rep += f"{attr}={value.__repr__()}, "
return f"{rep.strip(', ')})"
def __str__(self) -> str:
"""Returns a printable version of the build request."""
return "package={0}, install_args={1}".format(self.pkg.name, self.install_args)
return f"package={self.pkg.name}, install_args={self.install_args}"
def _add_default_args(self) -> None:
"""Ensure standard install options are set to at least the default."""
@@ -847,10 +846,11 @@ def get_depflags(self, pkg: "spack.package_base.PackageBase") -> int:
else:
cache_only = self.install_args.get("dependencies_cache_only")
# Include build dependencies if pkg is not installed and cache_only
# is False, or if build depdencies are explicitly called for
# by include_build_deps.
if include_build_deps or not (cache_only or pkg.spec.installed):
# 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
):
depflag |= dt.BUILD
if self.run_tests(pkg):
depflag |= dt.TEST
@@ -929,18 +929,18 @@ def __init__(
# Ensure dealing with a package that has a concrete spec
if not isinstance(pkg, spack.package_base.PackageBase):
raise ValueError("{0} must be a package".format(str(pkg)))
raise ValueError(f"{str(pkg)} must be a package")
self.pkg = pkg
if not self.pkg.spec.concrete:
raise ValueError("{0} must have a concrete spec".format(self.pkg.name))
raise ValueError(f"{self.pkg.name} must have a concrete spec")
# The "unique" identifier for the task's package
self.pkg_id = package_id(self.pkg)
# The explicit build request associated with the package
if not isinstance(request, BuildRequest):
raise ValueError("{0} must have a build request".format(str(pkg)))
raise ValueError(f"{str(pkg)} must have a build request")
self.request = request
@@ -948,8 +948,9 @@ def __init__(
# ensure priority queue invariants when tasks are "removed" from the
# queue.
if status == STATUS_REMOVED:
msg = "Cannot create a build task for {0} with status '{1}'"
raise InstallError(msg.format(self.pkg_id, status), pkg=pkg)
raise InstallError(
f"Cannot create a build task for {self.pkg_id} with status '{status}'", pkg=pkg
)
self.status = status
@@ -963,9 +964,9 @@ def __init__(
# to support tracking of parallel, multi-spec, environment installs.
self.dependents = set(get_dependent_ids(self.pkg.spec))
tty.debug("Pkg id {0} has the following dependents:".format(self.pkg_id))
tty.debug(f"Pkg id {self.pkg_id} has the following dependents:")
for dep_id in self.dependents:
tty.debug("- {0}".format(dep_id))
tty.debug(f"- {dep_id}")
# Set of dependencies
#
@@ -987,9 +988,9 @@ def __init__(
if not spack.compilers.compilers_for_spec(compiler_spec, arch_spec=arch_spec):
# The compiler is in the queue, identify it as dependency
dep = spack.compilers.pkg_spec_for_compiler(compiler_spec)
dep.constrain("platform=%s" % str(arch_spec.platform))
dep.constrain("os=%s" % str(arch_spec.os))
dep.constrain("target=%s:" % arch_spec.target.microarchitecture.family.name)
dep.constrain(f"platform={str(arch_spec.platform)}")
dep.constrain(f"os={str(arch_spec.os)}")
dep.constrain(f"target={arch_spec.target.microarchitecture.family.name}:")
dep.concretize()
dep_id = package_id(dep.package)
self.dependencies.add(dep_id)
@@ -1025,14 +1026,14 @@ def __ne__(self, other):
def __repr__(self) -> str:
"""Returns a formal representation of the build task."""
rep = "{0}(".format(self.__class__.__name__)
rep = f"{self.__class__.__name__}("
for attr, value in self.__dict__.items():
rep += "{0}={1}, ".format(attr, value.__repr__())
return "{0})".format(rep.strip(", "))
rep += f"{attr}={value.__repr__()}, "
return f"{rep.strip(', ')})"
def __str__(self) -> str:
"""Returns a printable version of the build task."""
dependencies = "#dependencies={0}".format(len(self.dependencies))
dependencies = f"#dependencies={len(self.dependencies)}"
return "priority={0}, status={1}, start={2}, {3}".format(
self.priority, self.status, self.start, dependencies
)
@@ -1055,7 +1056,7 @@ def add_dependent(self, pkg_id: str) -> None:
pkg_id: package identifier of the dependent package
"""
if pkg_id != self.pkg_id and pkg_id not in self.dependents:
tty.debug("Adding {0} as a dependent of {1}".format(pkg_id, self.pkg_id))
tty.debug(f"Adding {pkg_id} as a dependent of {self.pkg_id}")
self.dependents.add(pkg_id)
def flag_installed(self, installed: List[str]) -> None:
@@ -1069,9 +1070,8 @@ def flag_installed(self, installed: List[str]) -> None:
for pkg_id in now_installed:
self.uninstalled_deps.remove(pkg_id)
tty.debug(
"{0}: Removed {1} from uninstalled deps list: {2}".format(
self.pkg_id, pkg_id, self.uninstalled_deps
),
f"{self.pkg_id}: Removed {pkg_id} from uninstalled deps list: "
f"{self.uninstalled_deps}",
level=2,
)
@@ -1169,18 +1169,18 @@ def __init__(self, installs: List[Tuple["spack.package_base.PackageBase", dict]]
def __repr__(self) -> str:
"""Returns a formal representation of the package installer."""
rep = "{0}(".format(self.__class__.__name__)
rep = f"{self.__class__.__name__}("
for attr, value in self.__dict__.items():
rep += "{0}={1}, ".format(attr, value.__repr__())
return "{0})".format(rep.strip(", "))
rep += f"{attr}={value.__repr__()}, "
return f"{rep.strip(', ')})"
def __str__(self) -> str:
"""Returns a printable version of the package installer."""
requests = "#requests={0}".format(len(self.build_requests))
tasks = "#tasks={0}".format(len(self.build_tasks))
failed = "failed ({0}) = {1}".format(len(self.failed), self.failed)
installed = "installed ({0}) = {1}".format(len(self.installed), self.installed)
return "{0}: {1}; {2}; {3}; {4}".format(self.pid, requests, tasks, installed, failed)
requests = f"#requests={len(self.build_requests)}"
tasks = f"#tasks={len(self.build_tasks)}"
failed = f"failed ({len(self.failed)}) = {self.failed}"
installed = f"installed ({len(self.installed)}) = {self.installed}"
return f"{self.pid}: {requests}; {tasks}; {installed}; {failed}"
def _add_bootstrap_compilers(
self,
@@ -1225,9 +1225,7 @@ def _modify_existing_task(self, pkgid: str, attr, value) -> None:
for i, tup in enumerate(self.build_pq):
key, task = tup
if task.pkg_id == pkgid:
tty.debug(
"Modifying task for {0} to treat it as a compiler".format(pkgid), level=2
)
tty.debug(f"Modifying task for {pkgid} to treat it as a compiler", level=2)
setattr(task, attr, value)
self.build_pq[i] = (key, task)
@@ -1292,7 +1290,7 @@ def _check_deps_status(self, request: BuildRequest) -> None:
# Check for failure since a prefix lock is not required
if spack.store.STORE.failure_tracker.has_failed(dep):
action = "'spack install' the dependency"
msg = "{0} is marked as an install failure: {1}".format(dep_id, action)
msg = f"{dep_id} is marked as an install failure: {action}"
raise InstallError(err.format(request.pkg_id, msg), pkg=dep_pkg)
# Attempt to get a read lock to ensure another process does not
@@ -1300,7 +1298,7 @@ def _check_deps_status(self, request: BuildRequest) -> None:
# installed
ltype, lock = self._ensure_locked("read", dep_pkg)
if lock is None:
msg = "{0} is write locked by another process".format(dep_id)
msg = f"{dep_id} is write locked by another process"
raise InstallError(err.format(request.pkg_id, msg), pkg=request.pkg)
# Flag external and upstream packages as being installed
@@ -1319,7 +1317,7 @@ def _check_deps_status(self, request: BuildRequest) -> None:
or rec.installation_time > request.overwrite_time
)
):
tty.debug("Flagging {0} as installed per the database".format(dep_id))
tty.debug(f"Flagging {dep_id} as installed per the database")
self._flag_installed(dep_pkg)
else:
lock.release_read()
@@ -1355,9 +1353,9 @@ def _prepare_for_install(self, task: BuildTask) -> None:
# Ensure there is no other installed spec with the same prefix dir
if spack.store.STORE.db.is_occupied_install_prefix(task.pkg.spec.prefix):
raise InstallError(
"Install prefix collision for {0}".format(task.pkg_id),
long_msg="Prefix directory {0} already used by another "
"installed spec.".format(task.pkg.spec.prefix),
f"Install prefix collision for {task.pkg_id}",
long_msg=f"Prefix directory {task.pkg.spec.prefix} already "
"used by another installed spec.",
pkg=task.pkg,
)
@@ -1367,7 +1365,7 @@ def _prepare_for_install(self, task: BuildTask) -> None:
if not keep_prefix:
task.pkg.remove_prefix()
else:
tty.debug("{0} is partially installed".format(task.pkg_id))
tty.debug(f"{task.pkg_id} is partially installed")
# Destroy the stage for a locally installed, non-DIYStage, package
if restage and task.pkg.stage.managed_by_spack:
@@ -1412,9 +1410,8 @@ def _cleanup_failed(self, pkg_id: str) -> None:
lock = self.failed.get(pkg_id, None)
if lock is not None:
err = "{0} exception when removing failure tracking for {1}: {2}"
msg = "Removing failure mark on {0}"
try:
tty.verbose(msg.format(pkg_id))
tty.verbose(f"Removing failure mark on {pkg_id}")
lock.release_write()
except Exception as exc:
tty.warn(err.format(exc.__class__.__name__, pkg_id, str(exc)))
@@ -1441,19 +1438,19 @@ def _ensure_install_ready(self, pkg: "spack.package_base.PackageBase") -> None:
pkg: the package being locally installed
"""
pkg_id = package_id(pkg)
pre = "{0} cannot be installed locally:".format(pkg_id)
pre = f"{pkg_id} cannot be installed locally:"
# External packages cannot be installed locally.
if pkg.spec.external:
raise ExternalPackageError("{0} {1}".format(pre, "is external"))
raise ExternalPackageError(f"{pre} is external")
# Upstream packages cannot be installed locally.
if pkg.spec.installed_upstream:
raise UpstreamPackageError("{0} {1}".format(pre, "is upstream"))
raise UpstreamPackageError(f"{pre} is upstream")
# The package must have a prefix lock at this stage.
if pkg_id not in self.locks:
raise InstallLockError("{0} {1}".format(pre, "not locked"))
raise InstallLockError(f"{pre} not locked")
def _ensure_locked(
self, lock_type: str, pkg: "spack.package_base.PackageBase"
@@ -1480,14 +1477,14 @@ def _ensure_locked(
assert lock_type in [
"read",
"write",
], '"{0}" is not a supported package management lock type'.format(lock_type)
], f'"{lock_type}" is not a supported package management lock type'
pkg_id = package_id(pkg)
ltype, lock = self.locks.get(pkg_id, (lock_type, None))
if lock and ltype == lock_type:
return ltype, lock
desc = "{0} lock".format(lock_type)
desc = f"{lock_type} lock"
msg = "{0} a {1} on {2} with timeout {3}"
err = "Failed to {0} a {1} for {2} due to {3}: {4}"
@@ -1506,11 +1503,7 @@ def _ensure_locked(
op = "acquire"
lock = spack.store.STORE.prefix_locker.lock(pkg.spec, timeout)
if timeout != lock.default_timeout:
tty.warn(
"Expected prefix lock timeout {0}, not {1}".format(
timeout, lock.default_timeout
)
)
tty.warn(f"Expected prefix lock timeout {timeout}, not {lock.default_timeout}")
if lock_type == "read":
lock.acquire_read()
else:
@@ -1535,7 +1528,7 @@ def _ensure_locked(
tty.debug(msg.format("Upgrading to", desc, pkg_id, pretty_seconds(timeout or 0)))
op = "upgrade to"
lock.upgrade_read_to_write(timeout)
tty.debug("{0} is now {1} locked".format(pkg_id, lock_type))
tty.debug(f"{pkg_id} is now {lock_type} locked")
except (lk.LockDowngradeError, lk.LockTimeoutError) as exc:
tty.debug(err.format(op, desc, pkg_id, exc.__class__.__name__, str(exc)))
@@ -1560,14 +1553,14 @@ def _add_tasks(self, request: BuildRequest, all_deps):
all_deps (defaultdict(set)): dictionary of all dependencies and
associated dependents
"""
tty.debug("Initializing the build queue for {0}".format(request.pkg.name))
tty.debug(f"Initializing the build queue for {request.pkg.name}")
# Ensure not attempting to perform an installation when user didn't
# want to go that far for the requested package.
try:
_check_last_phase(request.pkg)
except BadInstallPhase as err:
tty.warn("Installation request refused: {0}".format(str(err)))
tty.warn(f"Installation request refused: {str(err)}")
return
# Skip out early if the spec is not being installed locally (i.e., if
@@ -1718,9 +1711,9 @@ def _install_task(self, task: BuildTask, install_status: InstallStatus) -> None:
# A StopPhase exception means that do_install was asked to
# stop early from clients, and is not an error at this point
spack.hooks.on_install_failure(task.request.pkg.spec)
pid = "{0}: ".format(self.pid) if tty.show_pid() else ""
tty.debug("{0}{1}".format(pid, str(e)))
tty.debug("Package stage directory: {0}".format(pkg.stage.source_path))
pid = f"{self.pid}: " if tty.show_pid() else ""
tty.debug(f"{pid}{str(e)}")
tty.debug(f"Package stage directory: {pkg.stage.source_path}")
def _next_is_pri0(self) -> bool:
"""
@@ -1815,7 +1808,7 @@ def _remove_task(self, pkg_id: str) -> Optional[BuildTask]:
pkg_id: identifier for the package to be removed
"""
if pkg_id in self.build_tasks:
tty.debug("Removing build task for {0} from list".format(pkg_id))
tty.debug(f"Removing build task for {pkg_id} from list")
task = self.build_tasks.pop(pkg_id)
task.status = STATUS_REMOVED
return task
@@ -1831,10 +1824,8 @@ def _requeue_task(self, task: BuildTask, install_status: InstallStatus) -> None:
"""
if task.status not in [STATUS_INSTALLED, STATUS_INSTALLING]:
tty.debug(
"{0} {1}".format(
install_msg(task.pkg_id, self.pid, install_status),
"in progress by another process",
)
f"{install_msg(task.pkg_id, self.pid, install_status)} "
"in progress by another process"
)
new_task = task.next_attempt(self.installed)
@@ -1851,7 +1842,7 @@ def _setup_install_dir(self, pkg: "spack.package_base.PackageBase") -> None:
"""
if not os.path.exists(pkg.spec.prefix):
path = spack.util.path.debug_padded_filter(pkg.spec.prefix)
tty.debug("Creating the installation directory {0}".format(path))
tty.debug(f"Creating the installation directory {path}")
spack.store.STORE.layout.create_install_directory(pkg.spec)
else:
# Set the proper group for the prefix
@@ -1887,8 +1878,8 @@ def _update_failed(
exc: optional exception if associated with the failure
"""
pkg_id = task.pkg_id
err = "" if exc is None else ": {0}".format(str(exc))
tty.debug("Flagging {0} as failed{1}".format(pkg_id, err))
err = "" if exc is None else f": {str(exc)}"
tty.debug(f"Flagging {pkg_id} as failed{err}")
if mark:
self.failed[pkg_id] = spack.store.STORE.failure_tracker.mark(task.pkg.spec)
else:
@@ -1897,14 +1888,14 @@ def _update_failed(
for dep_id in task.dependents:
if dep_id in self.build_tasks:
tty.warn("Skipping build of {0} since {1} failed".format(dep_id, pkg_id))
tty.warn(f"Skipping build of {dep_id} since {pkg_id} failed")
# Ensure the dependent's uninstalled dependents are
# up-to-date and their build tasks removed.
dep_task = self.build_tasks[dep_id]
self._update_failed(dep_task, mark)
self._remove_task(dep_id)
else:
tty.debug("No build task for {0} to skip since {1} failed".format(dep_id, pkg_id))
tty.debug(f"No build task for {dep_id} to skip since {pkg_id} failed")
def _update_installed(self, task: BuildTask) -> None:
"""
@@ -1934,23 +1925,21 @@ def _flag_installed(
# Already determined the package has been installed
return
tty.debug("Flagging {0} as installed".format(pkg_id))
tty.debug(f"Flagging {pkg_id} as installed")
self.installed.add(pkg_id)
# Update affected dependents
dependent_ids = dependent_ids or get_dependent_ids(pkg.spec)
for dep_id in set(dependent_ids):
tty.debug("Removing {0} from {1}'s uninstalled dependencies.".format(pkg_id, dep_id))
tty.debug(f"Removing {pkg_id} from {dep_id}'s uninstalled dependencies.")
if dep_id in self.build_tasks:
# Ensure the dependent's uninstalled dependencies are
# up-to-date. This will require requeueing the task.
dep_task = self.build_tasks[dep_id]
self._push_task(dep_task.next_attempt(self.installed))
else:
tty.debug(
"{0} has no build task to update for {1}'s success".format(dep_id, pkg_id)
)
tty.debug(f"{dep_id} has no build task to update for {pkg_id}'s success")
def _init_queue(self) -> None:
"""Initialize the build queue from the list of build requests."""
@@ -2031,8 +2020,8 @@ def install(self) -> None:
pkg, pkg_id, spec = task.pkg, task.pkg_id, task.pkg.spec
install_status.next_pkg(pkg)
install_status.set_term_title("Processing {0}".format(pkg.name))
tty.debug("Processing {0}: task={1}".format(pkg_id, task))
install_status.set_term_title(f"Processing {pkg.name}")
tty.debug(f"Processing {pkg_id}: task={task}")
# Ensure that the current spec has NO uninstalled dependencies,
# which is assumed to be reflected directly in its priority.
#
@@ -2044,24 +2033,19 @@ def install(self) -> None:
if task.priority != 0:
term_status.clear()
tty.error(
"Detected uninstalled dependencies for {0}: {1}".format(
pkg_id, task.uninstalled_deps
)
f"Detected uninstalled dependencies for {pkg_id}: " f"{task.uninstalled_deps}"
)
left = [dep_id for dep_id in task.uninstalled_deps if dep_id not in self.installed]
if not left:
tty.warn(
"{0} does NOT actually have any uninstalled deps" " left".format(pkg_id)
)
tty.warn(f"{pkg_id} does NOT actually have any uninstalled deps left")
dep_str = "dependencies" if task.priority > 1 else "dependency"
# Hook to indicate task failure, but without an exception
spack.hooks.on_install_failure(task.request.pkg.spec)
raise InstallError(
"Cannot proceed with {0}: {1} uninstalled {2}: {3}".format(
pkg_id, task.priority, dep_str, ",".join(task.uninstalled_deps)
),
f"Cannot proceed with {pkg_id}: {task.priority} uninstalled "
f"{dep_str}: {','.join(task.uninstalled_deps)}",
pkg=pkg,
)
@@ -2078,7 +2062,7 @@ def install(self) -> None:
# assume using a separate (failed) prefix lock file.
if pkg_id in self.failed or spack.store.STORE.failure_tracker.has_failed(spec):
term_status.clear()
tty.warn("{0} failed to install".format(pkg_id))
tty.warn(f"{pkg_id} failed to install")
self._update_failed(task)
# Mark that the package failed
@@ -2095,7 +2079,7 @@ def install(self) -> None:
# another process is likely (un)installing the spec or has
# determined the spec has already been installed (though the
# other process may be hung).
install_status.set_term_title("Acquiring lock for {0}".format(pkg.name))
install_status.set_term_title(f"Acquiring lock for {pkg.name}")
term_status.add(pkg_id)
ltype, lock = self._ensure_locked("write", pkg)
if lock is None:
@@ -2118,7 +2102,7 @@ def install(self) -> None:
task.request.overwrite_time = time.time()
# Determine state of installation artifacts and adjust accordingly.
install_status.set_term_title("Preparing {0}".format(pkg.name))
install_status.set_term_title(f"Preparing {pkg.name}")
self._prepare_for_install(task)
# Flag an already installed package
@@ -2164,7 +2148,7 @@ def install(self) -> None:
# Proceed with the installation since we have an exclusive write
# lock on the package.
install_status.set_term_title("Installing {0}".format(pkg.name))
install_status.set_term_title(f"Installing {pkg.name}")
try:
action = self._install_action(task)
@@ -2185,8 +2169,9 @@ def install(self) -> None:
except KeyboardInterrupt as exc:
# The build has been terminated with a Ctrl-C so terminate
# regardless of the number of remaining specs.
err = "Failed to install {0} due to {1}: {2}"
tty.error(err.format(pkg.name, exc.__class__.__name__, str(exc)))
tty.error(
f"Failed to install {pkg.name} due to " f"{exc.__class__.__name__}: {str(exc)}"
)
spack.hooks.on_install_cancel(task.request.pkg.spec)
raise
@@ -2195,9 +2180,10 @@ def install(self) -> None:
raise
# Checking hash on downloaded binary failed.
err = "Failed to install {0} from binary cache due to {1}:"
err += " Requeueing to install from source."
tty.error(err.format(pkg.name, str(exc)))
tty.error(
f"Failed to install {pkg.name} from binary cache due "
f"to {str(exc)}: Requeueing to install from source."
)
# this overrides a full method, which is ugly.
task.use_cache = False # type: ignore[misc]
self._requeue_task(task, install_status)
@@ -2215,13 +2201,12 @@ def install(self) -> None:
# lower levels -- skip printing if already printed.
# TODO: sort out this and SpackError.print_context()
tty.error(
"Failed to install {0} due to {1}: {2}".format(
pkg.name, exc.__class__.__name__, str(exc)
)
f"Failed to install {pkg.name} due to "
f"{exc.__class__.__name__}: {str(exc)}"
)
# Terminate if requested to do so on the first failure.
if self.fail_fast:
raise InstallError("{0}: {1}".format(fail_fast_err, str(exc)), pkg=pkg)
raise InstallError(f"{fail_fast_err}: {str(exc)}", pkg=pkg)
# Terminate at this point if the single explicit spec has
# failed to install.
@@ -2260,17 +2245,17 @@ def install(self) -> None:
if failed_explicits or missing:
for _, pkg_id, err in failed_explicits:
tty.error("{0}: {1}".format(pkg_id, err))
tty.error(f"{pkg_id}: {err}")
for _, pkg_id in missing:
tty.error("{0}: Package was not installed".format(pkg_id))
tty.error(f"{pkg_id}: Package was not installed")
if len(failed_explicits) > 0:
pkg = failed_explicits[0][0]
ids = [pkg_id for _, pkg_id, _ in failed_explicits]
tty.debug(
"Associating installation failure with first failed "
"explicit package ({0}) from {1}".format(ids[0], ", ".join(ids))
f"explicit package ({ids[0]}) from {', '.join(ids)}"
)
elif len(missing) > 0:
@@ -2278,7 +2263,7 @@ def install(self) -> None:
ids = [pkg_id for _, pkg_id in missing]
tty.debug(
"Associating installation failure with first "
"missing package ({0}) from {1}".format(ids[0], ", ".join(ids))
f"missing package ({ids[0]}) from {', '.join(ids)}"
)
raise InstallError(
@@ -2356,7 +2341,7 @@ def run(self) -> bool:
self.timer.stop("stage")
tty.debug(
"{0} Building {1} [{2}]".format(self.pre, self.pkg_id, self.pkg.build_system_class) # type: ignore[attr-defined] # noqa: E501
f"{self.pre} Building {self.pkg_id} [{self.pkg.build_system_class}]" # type: ignore[attr-defined] # noqa: E501
)
# get verbosity from do_install() parameter or saved value
@@ -2401,7 +2386,7 @@ def _install_source(self) -> None:
return
src_target = os.path.join(pkg.spec.prefix, "share", pkg.name, "src")
tty.debug("{0} Copying source to {1}".format(self.pre, src_target))
tty.debug(f"{self.pre} Copying source to {src_target}")
fs.install_tree(
pkg.stage.source_path, src_target, allow_broken_symlinks=(sys.platform != "win32")
@@ -2463,8 +2448,7 @@ def _real_install(self) -> None:
with logger.force_echo():
inner_debug_level = tty.debug_level()
tty.set_debug(debug_level)
msg = "{0} Executing phase: '{1}'"
tty.msg(msg.format(self.pre, phase_fn.name))
tty.msg(f"{self.pre} Executing phase: '{phase_fn.name}'")
tty.set_debug(inner_debug_level)
# Catch any errors to report to logging
@@ -2538,12 +2522,9 @@ def install(self):
except fs.CouldNotRestoreDirectoryBackup as e:
self.database.remove(self.task.pkg.spec)
tty.error(
"Recovery of install dir of {0} failed due to "
"{1}: {2}. The spec is now uninstalled.".format(
self.task.pkg.name,
e.outer_exception.__class__.__name__,
str(e.outer_exception),
)
f"Recovery of install dir of {self.task.pkg.name} failed due to "
f"{e.outer_exception.__class__.__name__}: {str(e.outer_exception)}. "
"The spec is now uninstalled."
)
# Unwrap the actual installation exception.
@@ -2566,7 +2547,7 @@ class BadInstallPhase(InstallError):
"""Raised for an install phase option is not allowed for a package."""
def __init__(self, pkg_name, phase):
super().__init__("'{0}' is not a valid phase for package {1}".format(phase, pkg_name))
super().__init__(f"'{phase}' is not a valid phase for package {pkg_name}")
class ExternalPackageError(InstallError):

View File

@@ -774,7 +774,7 @@ def _profile_wrapper(command, parser, args, unknown_args):
pr.disable()
# print out profile stats.
stats = pstats.Stats(pr)
stats = pstats.Stats(pr, stream=sys.stderr)
stats.sort_stats(*sortby)
stats.print_stats(nlines)

View File

@@ -7,15 +7,10 @@
include Tcl non-hierarchical modules, Lua hierarchical modules, and others.
"""
from .common import disable_modules, ensure_modules_are_enabled_or_warn
from .common import disable_modules
from .lmod import LmodModulefileWriter
from .tcl import TclModulefileWriter
__all__ = [
"TclModulefileWriter",
"LmodModulefileWriter",
"disable_modules",
"ensure_modules_are_enabled_or_warn",
]
__all__ = ["TclModulefileWriter", "LmodModulefileWriter", "disable_modules"]
module_types = {"tcl": TclModulefileWriter, "lmod": LmodModulefileWriter}

View File

@@ -33,10 +33,8 @@
import datetime
import inspect
import os.path
import pathlib
import re
import string
import warnings
from typing import Optional
import llnl.util.filesystem
@@ -820,43 +818,6 @@ def verbose(self):
return self.conf.verbose
def ensure_modules_are_enabled_or_warn():
"""Ensures that, if a custom configuration file is found with custom configuration for the
default tcl module set, then tcl module file generation is enabled. Otherwise, a warning
is emitted.
"""
# TODO (v0.21 - Remove this function)
# Check if TCL module generation is enabled, return early if it is
enabled = spack.config.get("modules:default:enable", [])
if "tcl" in enabled:
return
# Check if we have custom TCL module sections
for scope in spack.config.CONFIG.file_scopes:
# Skip default configuration
if scope.name.startswith("default"):
continue
data = spack.config.get("modules:default:tcl", scope=scope.name)
if data:
config_file = pathlib.Path(scope.path)
if not scope.name.startswith("env"):
config_file = config_file / "modules.yaml"
break
else:
return
# If we are here we have a custom "modules" section in "config_file"
msg = (
f"detected custom TCL modules configuration in {config_file}, while TCL module file "
f"generation for the default module set is disabled. "
f"In Spack v0.20 module file generation has been disabled by default. To enable "
f"it run:\n\n\t$ spack config add 'modules:default:enable:[tcl]'\n"
)
warnings.warn(msg)
class BaseModuleFileWriter:
def __init__(self, spec, module_set_name, explicit=None):
self.spec = spec

View File

@@ -142,6 +142,7 @@ def __init__(self):
"11": "bigsur",
"12": "monterey",
"13": "ventura",
"14": "sonoma",
}
version = macos_version()

View File

@@ -66,7 +66,6 @@
from spack.stage import DIYStage, ResourceStage, Stage, StageComposite, compute_stage_name
from spack.util.executable import ProcessError, which
from spack.util.package_hash import package_hash
from spack.util.web import FetchError
from spack.version import GitVersion, StandardVersion, Version
FLAG_HANDLER_RETURN_TYPE = Tuple[
@@ -1394,7 +1393,7 @@ def do_fetch(self, mirror_only=False):
tty.debug("Fetching with no checksum. {0}".format(ck_msg))
if not ignore_checksum:
raise FetchError(
raise spack.error.FetchError(
"Will not fetch %s" % self.spec.format("{name}{@version}"), ck_msg
)
@@ -1420,7 +1419,7 @@ def do_fetch(self, mirror_only=False):
tty.debug("Fetching deprecated version. {0}".format(dp_msg))
if not ignore_deprecation:
raise FetchError(
raise spack.error.FetchError(
"Will not fetch {0}".format(self.spec.format("{name}{@version}")), dp_msg
)
@@ -1447,7 +1446,7 @@ def do_stage(self, mirror_only=False):
self.stage.expand_archive()
if not os.listdir(self.stage.path):
raise FetchError("Archive was empty for %s" % self.name)
raise spack.error.FetchError("Archive was empty for %s" % self.name)
else:
# Support for post-install hooks requires a stage.source_path
fsys.mkdirp(self.stage.source_path)
@@ -2365,7 +2364,7 @@ def all_urls(self):
urls.append(args["url"])
return urls
def fetch_remote_versions(self, concurrency=128):
def fetch_remote_versions(self, concurrency=None):
"""Find remote versions of this package.
Uses ``list_url`` and any other URLs listed in the package file.

View File

@@ -73,10 +73,10 @@
#: Valid name for specs and variants. Here we are not using
#: the previous "w[\w.-]*" since that would match most
#: characters that can be part of a word in any language
IDENTIFIER = r"([a-zA-Z_0-9][a-zA-Z_0-9\-]*)"
DOTTED_IDENTIFIER = rf"({IDENTIFIER}(\.{IDENTIFIER})+)"
GIT_HASH = r"([A-Fa-f0-9]{40})"
GIT_VERSION = rf"((git\.({DOTTED_IDENTIFIER}|{IDENTIFIER}))|({GIT_HASH}))"
IDENTIFIER = r"(?:[a-zA-Z_0-9][a-zA-Z_0-9\-]*)"
DOTTED_IDENTIFIER = rf"(?:{IDENTIFIER}(?:\.{IDENTIFIER})+)"
GIT_HASH = r"(?:[A-Fa-f0-9]{40})"
GIT_VERSION = rf"(?:(?:git\.(?:{DOTTED_IDENTIFIER}|{IDENTIFIER}))|(?:{GIT_HASH}))"
NAME = r"[a-zA-Z_0-9][a-zA-Z_0-9\-.]*"
@@ -85,15 +85,15 @@
#: A filename starts either with a "." or a "/" or a "{name}/,
# or on Windows, a drive letter followed by a colon and "\"
# or "." or {name}\
WINDOWS_FILENAME = r"(\.|[a-zA-Z0-9-_]*\\|[a-zA-Z]:\\)([a-zA-Z0-9-_\.\\]*)(\.json|\.yaml)"
UNIX_FILENAME = r"(\.|\/|[a-zA-Z0-9-_]*\/)([a-zA-Z0-9-_\.\/]*)(\.json|\.yaml)"
WINDOWS_FILENAME = r"(?:\.|[a-zA-Z0-9-_]*\\|[a-zA-Z]:\\)(?:[a-zA-Z0-9-_\.\\]*)(?:\.json|\.yaml)"
UNIX_FILENAME = r"(?:\.|\/|[a-zA-Z0-9-_]*\/)(?:[a-zA-Z0-9-_\.\/]*)(?:\.json|\.yaml)"
if not IS_WINDOWS:
FILENAME = UNIX_FILENAME
else:
FILENAME = WINDOWS_FILENAME
VALUE = r"([a-zA-Z_0-9\-+\*.,:=\~\/\\]+)"
QUOTED_VALUE = r"[\"']+([a-zA-Z_0-9\-+\*.,:=\~\/\\\s]+)[\"']+"
VALUE = r"(?:[a-zA-Z_0-9\-+\*.,:=\~\/\\]+)"
QUOTED_VALUE = r"[\"']+(?:[a-zA-Z_0-9\-+\*.,:=\~\/\\\s]+)[\"']+"
VERSION = r"=?([a-zA-Z0-9_][a-zA-Z_0-9\-\.]*\b)"
VERSION_RANGE = rf"({VERSION}\s*:\s*{VERSION}(?!\s*=)|:\s*{VERSION}(?!\s*=)|{VERSION}\s*:|:)"
@@ -125,34 +125,34 @@ class TokenType(TokenBase):
"""
# Dependency
DEPENDENCY = r"(\^)"
DEPENDENCY = r"(?:\^)"
# Version
VERSION_HASH_PAIR = rf"(@({GIT_VERSION})=({VERSION}))"
VERSION = rf"(@\s*({VERSION_LIST}))"
VERSION_HASH_PAIR = rf"(?:@(?:{GIT_VERSION})=(?:{VERSION}))"
VERSION = rf"(?:@\s*(?:{VERSION_LIST}))"
# Variants
PROPAGATED_BOOL_VARIANT = rf"((\+\+|~~|--)\s*{NAME})"
BOOL_VARIANT = rf"([~+-]\s*{NAME})"
PROPAGATED_KEY_VALUE_PAIR = rf"({NAME}\s*==\s*({VALUE}|{QUOTED_VALUE}))"
KEY_VALUE_PAIR = rf"({NAME}\s*=\s*({VALUE}|{QUOTED_VALUE}))"
PROPAGATED_BOOL_VARIANT = rf"(?:(?:\+\+|~~|--)\s*{NAME})"
BOOL_VARIANT = rf"(?:[~+-]\s*{NAME})"
PROPAGATED_KEY_VALUE_PAIR = rf"(?:{NAME}\s*==\s*(?:{VALUE}|{QUOTED_VALUE}))"
KEY_VALUE_PAIR = rf"(?:{NAME}\s*=\s*(?:{VALUE}|{QUOTED_VALUE}))"
# Compilers
COMPILER_AND_VERSION = rf"(%\s*({NAME})([\s]*)@\s*({VERSION_LIST}))"
COMPILER = rf"(%\s*({NAME}))"
COMPILER_AND_VERSION = rf"(?:%\s*(?:{NAME})(?:[\s]*)@\s*(?:{VERSION_LIST}))"
COMPILER = rf"(?:%\s*(?:{NAME}))"
# FILENAME
FILENAME = rf"({FILENAME})"
FILENAME = rf"(?:{FILENAME})"
# Package name
FULLY_QUALIFIED_PACKAGE_NAME = rf"({DOTTED_IDENTIFIER})"
UNQUALIFIED_PACKAGE_NAME = rf"({IDENTIFIER})"
FULLY_QUALIFIED_PACKAGE_NAME = rf"(?:{DOTTED_IDENTIFIER})"
UNQUALIFIED_PACKAGE_NAME = rf"(?:{IDENTIFIER})"
# DAG hash
DAG_HASH = rf"(/({HASH}))"
DAG_HASH = rf"(?:/(?:{HASH}))"
# White spaces
WS = r"(\s+)"
WS = r"(?:\s+)"
class ErrorTokenType(TokenBase):
"""Enum with regexes for error analysis"""
# Unexpected character
UNEXPECTED = r"(.[\s]*)"
UNEXPECTED = r"(?:.[\s]*)"
class Token:

View File

@@ -76,7 +76,7 @@ def __init__(self, pkg, path_or_url, level, working_dir):
self.level = level
self.working_dir = working_dir
def apply(self, stage: spack.stage.Stage):
def apply(self, stage: "spack.stage.Stage"):
"""Apply a patch to source in a stage.
Arguments:
@@ -190,7 +190,7 @@ def __init__(self, pkg, url, level=1, working_dir=".", ordering_key=None, **kwar
if not self.sha256:
raise PatchDirectiveError("URL patches require a sha256 checksum")
def apply(self, stage: spack.stage.Stage):
def apply(self, stage: "spack.stage.Stage"):
assert self.stage.expanded, "Stage must be expanded before applying patches"
# Get the patch file.
@@ -312,21 +312,19 @@ def from_json(cls, stream, repository):
def to_json(self, stream):
sjson.dump({"patches": self.index}, stream)
def patch_for_package(self, sha256, pkg):
def patch_for_package(self, sha256: str, pkg):
"""Look up a patch in the index and build a patch object for it.
Arguments:
sha256 (str): sha256 hash to look up
sha256: sha256 hash to look up
pkg (spack.package_base.PackageBase): Package object to get patch for.
We build patch objects lazily because building them requires that
we have information about the package's location in its repo.
"""
we have information about the package's location in its repo."""
sha_index = self.index.get(sha256)
if not sha_index:
raise NoSuchPatchError(
"Couldn't find patch for package %s with sha256: %s" % (pkg.fullname, sha256)
raise PatchLookupError(
f"Couldn't find patch for package {pkg.fullname} with sha256: {sha256}"
)
# Find patches for this class or any class it inherits from
@@ -335,8 +333,8 @@ def patch_for_package(self, sha256, pkg):
if patch_dict:
break
else:
raise NoSuchPatchError(
"Couldn't find patch for package %s with sha256: %s" % (pkg.fullname, sha256)
raise PatchLookupError(
f"Couldn't find patch for package {pkg.fullname} with sha256: {sha256}"
)
# add the sha256 back (we take it out on write to save space,
@@ -405,5 +403,9 @@ class NoSuchPatchError(spack.error.SpackError):
"""Raised when a patch file doesn't exist."""
class PatchLookupError(NoSuchPatchError):
"""Raised when a patch file cannot be located from sha256."""
class PatchDirectiveError(spack.error.SpackError):
"""Raised when the wrong arguments are suppled to the patch directive."""

View File

@@ -24,8 +24,9 @@
import traceback
import types
import uuid
from typing import Any, Dict, List, Union
from typing import Any, Dict, List, Tuple, Union
import llnl.path
import llnl.util.filesystem as fs
import llnl.util.lang
import llnl.util.tty as tty
@@ -563,7 +564,7 @@ def __init__(
self.checker = package_checker
self.packages_path = self.checker.packages_path
if sys.platform == "win32":
self.packages_path = spack.util.path.convert_to_posix_path(self.packages_path)
self.packages_path = llnl.path.convert_to_posix_path(self.packages_path)
self.namespace = namespace
self.indexers: Dict[str, Indexer] = {}
@@ -744,10 +745,18 @@ def all_package_paths(self):
for name in self.all_package_names():
yield self.package_path(name)
def packages_with_tags(self, *tags):
def packages_with_tags(self, *tags, full=False):
"""Returns a list of packages matching any of the tags in input.
Args:
full: if True the package names in the output are fully-qualified
"""
r = set()
for repo in self.repos:
r |= set(repo.packages_with_tags(*tags))
current = repo.packages_with_tags(*tags)
if full:
current = [f"{repo.namespace}.{x}" for x in current]
r |= set(current)
return sorted(r)
def all_package_classes(self):
@@ -1123,7 +1132,8 @@ def extensions_for(self, extendee_spec):
def dirname_for_package_name(self, pkg_name):
"""Get the directory name for a particular package. This is the
directory that contains its package.py file."""
return os.path.join(self.packages_path, pkg_name)
_, unqualified_name = self.partition_package_name(pkg_name)
return os.path.join(self.packages_path, unqualified_name)
def filename_for_package_name(self, pkg_name):
"""Get the filename for the module we should load for a particular
@@ -1221,15 +1231,10 @@ def get_pkg_class(self, pkg_name):
package. Then extracts the package class from the module
according to Spack's naming convention.
"""
namespace, _, pkg_name = pkg_name.rpartition(".")
if namespace and (namespace != self.namespace):
raise InvalidNamespaceError(
"Invalid namespace for %s repo: %s" % (self.namespace, namespace)
)
namespace, pkg_name = self.partition_package_name(pkg_name)
class_name = nm.mod_to_class(pkg_name)
fullname = f"{self.full_namespace}.{pkg_name}"
fullname = "{0}.{1}".format(self.full_namespace, pkg_name)
try:
module = importlib.import_module(fullname)
except ImportError:
@@ -1240,7 +1245,7 @@ def get_pkg_class(self, pkg_name):
cls = getattr(module, class_name)
if not inspect.isclass(cls):
tty.die("%s.%s is not a class" % (pkg_name, class_name))
tty.die(f"{pkg_name}.{class_name} is not a class")
new_cfg_settings = (
spack.config.get("packages").get(pkg_name, {}).get("package_attributes", {})
@@ -1279,6 +1284,15 @@ def get_pkg_class(self, pkg_name):
return cls
def partition_package_name(self, pkg_name: str) -> Tuple[str, str]:
namespace, pkg_name = partition_package_name(pkg_name)
if namespace and (namespace != self.namespace):
raise InvalidNamespaceError(
f"Invalid namespace for the '{self.namespace}' repo: {namespace}"
)
return namespace, pkg_name
def __str__(self):
return "[Repo '%s' at '%s']" % (self.namespace, self.root)
@@ -1292,6 +1306,20 @@ def __contains__(self, pkg_name):
RepoType = Union[Repo, RepoPath]
def partition_package_name(pkg_name: str) -> Tuple[str, str]:
"""Given a package name that might be fully-qualified, returns the namespace part,
if present and the unqualified package name.
If the package name is unqualified, the namespace is an empty string.
Args:
pkg_name: a package name, either unqualified like "llvl", or
fully-qualified, like "builtin.llvm"
"""
namespace, _, pkg_name = pkg_name.rpartition(".")
return namespace, pkg_name
def create_repo(root, namespace=None, subdir=packages_dir_name):
"""Create a new repository in root with the specified namespace.

View File

@@ -68,12 +68,6 @@
"labels": {"type": "object"},
# Use a custom template to render the recipe
"template": {"type": "string", "default": None},
# Add a custom extra section at the bottom of a stage
"extra_instructions": {
"type": "object",
"additionalProperties": False,
"properties": {"build": {"type": "string"}, "final": {"type": "string"}},
},
# Reserved for properties that are specific to each format
"singularity": {
"type": "object",
@@ -89,15 +83,6 @@
"docker": {"type": "object", "additionalProperties": False, "default": {}},
"depfile": {"type": "boolean", "default": False},
},
"deprecatedProperties": {
"properties": ["extra_instructions"],
"message": (
"container:extra_instructions has been deprecated and will be removed "
"in Spack v0.21. Set container:template appropriately to use custom Jinja2 "
"templates instead."
),
"error": False,
},
}
properties = {"container": container_schema}

View File

@@ -13,7 +13,7 @@
import re
import types
import warnings
from typing import List, NamedTuple, Tuple, Union
from typing import List, NamedTuple, Optional, Sequence, Tuple, Union
import archspec.cpu
@@ -138,7 +138,15 @@ class RequirementKind(enum.Enum):
PACKAGE = enum.auto()
DeclaredVersion = collections.namedtuple("DeclaredVersion", ["version", "idx", "origin"])
class DeclaredVersion(NamedTuple):
"""Data class to contain information on declared versions used in the solve"""
#: String representation of the version
version: str
#: Unique index assigned to this version
idx: int
#: Provenance of the version
origin: Provenance
# Below numbers are used to map names of criteria to the order
@@ -785,7 +793,7 @@ def fact(self, head):
if choice:
self.assumptions.append(atom)
def solve(self, setup, specs, reuse=None, output=None, control=None):
def solve(self, setup, specs, reuse=None, output=None, control=None, allow_deprecated=False):
"""Set up the input and solve for dependencies of ``specs``.
Arguments:
@@ -796,6 +804,7 @@ def solve(self, setup, specs, reuse=None, output=None, control=None):
the output of this solve.
control (clingo.Control): configuration for the solver. If None,
default values will be used
allow_deprecated: if True, allow deprecated versions in the solve
Return:
A tuple of the solve result, the timer for the different phases of the
@@ -815,7 +824,7 @@ def solve(self, setup, specs, reuse=None, output=None, control=None):
timer.start("setup")
with self.control.backend() as backend:
self.backend = backend
setup.setup(self, specs, reuse=reuse)
setup.setup(self, specs, reuse=reuse, allow_deprecated=allow_deprecated)
timer.stop("setup")
timer.start("load")
@@ -1560,7 +1569,9 @@ def emit_facts_from_requirement_rules(self, rules: List[RequirementRule]):
)
except Exception as e:
if rule.kind != RequirementKind.DEFAULT:
raise RuntimeError("cannot emit requirements for the solver") from e
raise RuntimeError(
"cannot emit requirements for the solver: " + str(e)
) from e
continue
self.gen.fact(
@@ -1592,7 +1603,9 @@ def emit_facts_from_requirement_rules(self, rules: List[RequirementRule]):
# would be impaired. If a rule does not apply for a specific package, just
# discard it.
if rule.kind != RequirementKind.DEFAULT:
raise RuntimeError("cannot emit requirements for the solver") from e
raise RuntimeError(
"cannot emit requirements for the solver: " + str(e)
) from e
continue
self.gen.fact(fn.requirement_group_member(member_id, pkg_name, requirement_grp_id))
@@ -1898,7 +1911,7 @@ class Body:
return clauses
def define_package_versions_and_validate_preferences(
self, possible_pkgs, require_checksum: bool
self, possible_pkgs, *, require_checksum: bool, allow_deprecated: bool
):
"""Declare any versions in specs not declared in packages."""
packages_yaml = spack.config.get("packages")
@@ -1918,13 +1931,15 @@ def define_package_versions_and_validate_preferences(
]
for idx, (v, version_info) in enumerate(package_py_versions):
if version_info.get("deprecated", False):
self.deprecated_versions[pkg_name].add(v)
if not allow_deprecated:
continue
self.possible_versions[pkg_name].add(v)
self.declared_versions[pkg_name].append(
DeclaredVersion(version=v, idx=idx, origin=Provenance.PACKAGE_PY)
)
deprecated = version_info.get("deprecated", False)
if deprecated:
self.deprecated_versions[pkg_name].add(v)
if pkg_name not in packages_yaml or "version" not in packages_yaml[pkg_name]:
continue
@@ -1953,7 +1968,9 @@ def define_package_versions_and_validate_preferences(
)
self.possible_versions[pkg_name].add(vdef)
def define_ad_hoc_versions_from_specs(self, specs, origin, require_checksum: bool):
def define_ad_hoc_versions_from_specs(
self, specs, origin, *, allow_deprecated: bool, require_checksum: bool
):
"""Add concrete versions to possible versions from lists of CLI/dev specs."""
for s in traverse.traverse_nodes(specs):
# If there is a concrete version on the CLI *that we know nothing
@@ -1969,6 +1986,9 @@ def define_ad_hoc_versions_from_specs(self, specs, origin, require_checksum: boo
s.format("No matching version for constraint {name}{@versions}")
)
if not allow_deprecated and version in self.deprecated_versions[s.name]:
continue
declared = DeclaredVersion(version=version, idx=0, origin=origin)
self.declared_versions[s.name].append(declared)
self.possible_versions[s.name].add(version)
@@ -2333,7 +2353,14 @@ def define_concrete_input_specs(self, specs, possible):
if spec.concrete:
self._facts_from_concrete_spec(spec, possible)
def setup(self, driver, specs, reuse=None):
def setup(
self,
driver: PyclingoDriver,
specs: Sequence[spack.spec.Spec],
*,
reuse: Optional[List[spack.spec.Spec]] = None,
allow_deprecated: bool = False,
):
"""Generate an ASP program with relevant constraints for specs.
This calls methods on the solve driver to set up the problem with
@@ -2341,9 +2368,10 @@ def setup(self, driver, specs, reuse=None):
specs, as well as constraints from the specs themselves.
Arguments:
driver (PyclingoDriver): driver instance of this solve
specs (list): list of Specs to solve
reuse (None or list): list of concrete specs that can be reused
driver: driver instance of this solve
specs: list of Specs to solve
reuse: list of concrete specs that can be reused
allow_deprecated: if True adds deprecated versions into the solve
"""
self._condition_id_counter = itertools.count()
@@ -2369,10 +2397,13 @@ def setup(self, driver, specs, reuse=None):
# rules to generate an ASP program.
self.gen = driver
if not allow_deprecated:
self.gen.fact(fn.deprecated_versions_not_allowed())
# Calculate develop specs
# they will be used in addition to command line specs
# in determining known versions/targets/os
dev_specs = ()
dev_specs: Tuple[spack.spec.Spec, ...] = ()
env = ev.active_environment()
if env:
dev_specs = tuple(
@@ -2418,11 +2449,22 @@ def setup(self, driver, specs, reuse=None):
self.external_packages()
# TODO: make a config option for this undocumented feature
require_checksum = "SPACK_CONCRETIZER_REQUIRE_CHECKSUM" in os.environ
self.define_package_versions_and_validate_preferences(self.pkgs, require_checksum)
self.define_ad_hoc_versions_from_specs(specs, Provenance.SPEC, require_checksum)
self.define_ad_hoc_versions_from_specs(dev_specs, Provenance.DEV_SPEC, require_checksum)
self.validate_and_define_versions_from_requirements(require_checksum)
checksummed = "SPACK_CONCRETIZER_REQUIRE_CHECKSUM" in os.environ
self.define_package_versions_and_validate_preferences(
self.pkgs, allow_deprecated=allow_deprecated, require_checksum=checksummed
)
self.define_ad_hoc_versions_from_specs(
specs, Provenance.SPEC, allow_deprecated=allow_deprecated, require_checksum=checksummed
)
self.define_ad_hoc_versions_from_specs(
dev_specs,
Provenance.DEV_SPEC,
allow_deprecated=allow_deprecated,
require_checksum=checksummed,
)
self.validate_and_define_versions_from_requirements(
allow_deprecated=allow_deprecated, require_checksum=checksummed
)
self.gen.h1("Package Constraints")
for pkg in sorted(self.pkgs):
@@ -2471,7 +2513,9 @@ def literal_specs(self, specs):
if self.concretize_everything:
self.gen.fact(fn.solve_literal(idx))
def validate_and_define_versions_from_requirements(self, require_checksum: bool):
def validate_and_define_versions_from_requirements(
self, *, allow_deprecated: bool, require_checksum: bool
):
"""If package requirements mention concrete versions that are not mentioned
elsewhere, then we need to collect those to mark them as possible
versions. If they are abstract and statically have no match, then we
@@ -2504,6 +2548,9 @@ def validate_and_define_versions_from_requirements(self, require_checksum: bool)
if v in self.possible_versions[name]:
continue
if not allow_deprecated and v in self.deprecated_versions[name]:
continue
# If concrete an not yet defined, conditionally define it, like we do for specs
# from the command line.
if not require_checksum or _is_checksummed_git_version(v):
@@ -2548,6 +2595,7 @@ class SpecBuilder:
r"^node_compiler$",
r"^package_hash$",
r"^root$",
r"^variant_default_value_from_cli$",
r"^virtual_node$",
r"^virtual_root$",
]
@@ -2937,7 +2985,16 @@ def _reusable_specs(self, specs):
return reusable_specs
def solve(self, specs, out=None, timers=False, stats=False, tests=False, setup_only=False):
def solve(
self,
specs,
out=None,
timers=False,
stats=False,
tests=False,
setup_only=False,
allow_deprecated=False,
):
"""
Arguments:
specs (list): List of ``Spec`` objects to solve for.
@@ -2948,6 +3005,7 @@ def solve(self, specs, out=None, timers=False, stats=False, tests=False, setup_o
If a tuple of package names, concretize test dependencies for named
packages (defaults to False: do not concretize test dependencies).
setup_only (bool): if True, stop after setup and don't solve (default False).
allow_deprecated (bool): allow deprecated version in the solve
"""
# Check upfront that the variants are admissible
specs = [s.lookup_hash() for s in specs]
@@ -2955,10 +3013,14 @@ def solve(self, specs, out=None, timers=False, stats=False, tests=False, setup_o
reusable_specs.extend(self._reusable_specs(specs))
setup = SpackSolverSetup(tests=tests)
output = OutputConfiguration(timers=timers, stats=stats, out=out, setup_only=setup_only)
result, _, _ = self.driver.solve(setup, specs, reuse=reusable_specs, output=output)
result, _, _ = self.driver.solve(
setup, specs, reuse=reusable_specs, output=output, allow_deprecated=allow_deprecated
)
return result
def solve_in_rounds(self, specs, out=None, timers=False, stats=False, tests=False):
def solve_in_rounds(
self, specs, out=None, timers=False, stats=False, tests=False, allow_deprecated=False
):
"""Solve for a stable model of specs in multiple rounds.
This relaxes the assumption of solve that everything must be consistent and
@@ -2973,6 +3035,7 @@ def solve_in_rounds(self, specs, out=None, timers=False, stats=False, tests=Fals
timers (bool): print timing if set to True
stats (bool): print internal statistics if set to True
tests (bool): add test dependencies to the solve
allow_deprecated (bool): allow deprecated version in the solve
"""
specs = [s.lookup_hash() for s in specs]
reusable_specs = self._check_input_and_extract_concrete_specs(specs)
@@ -2986,7 +3049,11 @@ def solve_in_rounds(self, specs, out=None, timers=False, stats=False, tests=Fals
output = OutputConfiguration(timers=timers, stats=stats, out=out, setup_only=False)
while True:
result, _, _ = self.driver.solve(
setup, input_specs, reuse=reusable_specs, output=output
setup,
input_specs,
reuse=reusable_specs,
output=output,
allow_deprecated=allow_deprecated,
)
yield result

View File

@@ -20,7 +20,7 @@
% Integrity constraints on DAG nodes
:- attr("root", PackageNode), not attr("node", PackageNode).
:- attr("version", PackageNode), not attr("node", PackageNode).
:- attr("version", PackageNode, _), not attr("node", PackageNode), not attr("virtual_node", PackageNode).
:- attr("node_version_satisfies", PackageNode), not attr("node", PackageNode).
:- attr("hash", PackageNode, _), not attr("node", PackageNode).
:- attr("node_platform", PackageNode, _), not attr("node", PackageNode).
@@ -58,7 +58,6 @@ unification_set(SetID, ChildNode) :- attr("depends_on", ParentNode, ChildNode, T
unification_set(("build", node(X, Child)), node(X, Child))
:- attr("depends_on", ParentNode, node(X, Child), Type),
Type == "build",
SetID != "generic_build",
multiple_unification_sets(Child),
unification_set(SetID, ParentNode).
@@ -68,18 +67,18 @@ unification_set("generic_build", node(X, Child))
not multiple_unification_sets(Child),
unification_set(_, ParentNode).
% Any dependency of type "build" in a unification set that is in the leaf unification set,
% stays in that unification set
unification_set(SetID, ChildNode)
:- attr("depends_on", ParentNode, ChildNode, Type),
Type == "build",
SetID == "generic_build",
unification_set(SetID, ParentNode).
unification_set(SetID, VirtualNode)
:- provider(PackageNode, VirtualNode),
unification_set(SetID, PackageNode).
% Do not allow split dependencies, for now. This ensures that we don't construct graphs where e.g.
% a python extension depends on setuptools@63.4 as a run dependency, but uses e.g. setuptools@68
% as a build dependency.
%
% We'll need to relax the rule before we get to actual cross-compilation
:- depends_on(ParentNode, node(X, Dependency)), depends_on(ParentNode, node(Y, Dependency)), X < Y.
#defined multiple_unification_sets/1.
%----
@@ -196,6 +195,13 @@ attr("deprecated", node(ID, Package), Version) :-
attr("version", node(ID, Package), Version),
pkg_fact(Package, deprecated_version(Version)).
error(100, "Package '{0}' needs the deprecated version '{1}', and this is not allowed", Package, Version)
:- deprecated_versions_not_allowed(),
attr("version", node(ID, Package), Version),
not external(node(ID, Package)),
not concrete(node(ID, Package)),
pkg_fact(Package, deprecated_version(Version)).
possible_version_weight(node(ID, Package), Weight)
:- attr("version", node(ID, Package), Version),
pkg_fact(Package, version_declared(Version, Weight)).
@@ -252,6 +258,7 @@ attr("node_version_satisfies", node(ID, Package), Constraint)
pkg_fact(Package, version_satisfies(Constraint, Version)).
#defined version_satisfies/3.
#defined deprecated_versions_not_allowed/0.
#defined deprecated_version/2.
%-----------------------------------------------------------------------------
@@ -916,7 +923,8 @@ pkg_fact(Package, variant_single_value("dev_path"))
%-----------------------------------------------------------------------------
% if no platform is set, fall back to the default
:- attr("node_platform", _, Platform), not allowed_platform(Platform).
error(100, "platform '{0}' is not allowed on the current host", Platform)
:- attr("node_platform", _, Platform), not allowed_platform(Platform).
attr("node_platform", PackageNode, Platform)
:- attr("node", PackageNode),

View File

@@ -5,6 +5,8 @@
import collections
from typing import List, Set
from llnl.util import lang
import spack.deptypes as dt
import spack.package_base
import spack.repo
@@ -95,8 +97,17 @@ def _compute_cache_values(self):
)
self._link_run_virtuals.update(self._possible_virtuals)
for x in self._link_run:
current = spack.repo.PATH.get_pkg_class(x).dependencies_of_type(dt.BUILD)
self._direct_build.update(current)
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(

View File

@@ -54,10 +54,14 @@
import io
import itertools
import os
import platform
import re
import socket
import warnings
from typing import Callable, List, Optional, Tuple, Union
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
import llnl.path
import llnl.string
import llnl.util.filesystem as fs
import llnl.util.lang as lang
import llnl.util.tty as tty
@@ -70,6 +74,7 @@
import spack.deptypes as dt
import spack.error
import spack.hash_types as ht
import spack.patch
import spack.paths
import spack.platforms
import spack.provider_index
@@ -82,11 +87,9 @@
import spack.util.executable
import spack.util.hash
import spack.util.module_cmd as md
import spack.util.path as pth
import spack.util.prefix
import spack.util.spack_json as sjson
import spack.util.spack_yaml as syaml
import spack.util.string
import spack.variant as vt
import spack.version as vn
import spack.version.git_ref_lookup
@@ -740,7 +743,7 @@ def __init__(
self.parent = parent
self.spec = spec
self.depflag = depflag
self.virtuals = virtuals
self.virtuals = tuple(sorted(set(virtuals)))
def update_deptypes(self, depflag: dt.DepFlag) -> bool:
"""Update the current dependency types"""
@@ -1390,7 +1393,7 @@ def _format_module_list(modules):
@property
def external_path(self):
return pth.path_to_os_path(self._external_path)[0]
return llnl.path.path_to_os_path(self._external_path)[0]
@external_path.setter
def external_path(self, ext_path):
@@ -1602,13 +1605,20 @@ def _add_dependency(self, spec: "Spec", *, depflag: dt.DepFlag, virtuals: Tuple[
try:
dspec = next(dspec for dspec in orig if depflag == dspec.depflag)
except StopIteration:
raise DuplicateDependencyError("Cannot depend on '%s' twice" % spec)
current_deps = ", ".join(
dt.flag_to_chars(x.depflag) + " " + x.spec.short_spec for x in orig
)
raise DuplicateDependencyError(
f"{self.short_spec} cannot depend on '{spec.short_spec}' multiple times.\n"
f"\tRequired: {dt.flag_to_chars(depflag)}\n"
f"\tDependency: {current_deps}"
)
try:
dspec.spec.constrain(spec)
except spack.error.UnsatisfiableSpecError:
raise DuplicateDependencyError(
"Cannot depend on incompatible specs '%s' and '%s'" % (dspec.spec, spec)
f"Cannot depend on incompatible specs '{dspec.spec}' and '{spec}'"
)
def add_dependency_edge(
@@ -1799,7 +1809,7 @@ def prefix(self):
@prefix.setter
def prefix(self, value):
self._prefix = spack.util.prefix.Prefix(pth.convert_to_platform_path(value))
self._prefix = spack.util.prefix.Prefix(llnl.path.convert_to_platform_path(value))
def spec_hash(self, hash):
"""Utility method for computing different types of Spec hashes.
@@ -2924,8 +2934,9 @@ def _new_concretize(self, tests=False):
if self._concrete:
return
allow_deprecated = spack.config.get("config:deprecated", False)
solver = spack.solver.asp.Solver()
result = solver.solve([self], tests=tests)
result = solver.solve([self], tests=tests, allow_deprecated=allow_deprecated)
result.raise_if_unsat()
# take the best answer
@@ -3661,7 +3672,7 @@ def _autospec(self, spec_like):
return spec_like
return Spec(spec_like)
def intersects(self, other: "Spec", deps: bool = True) -> bool:
def intersects(self, other: Union[str, "Spec"], deps: bool = True) -> bool:
"""Return True if there exists at least one concrete spec that matches both
self and other, otherwise False.
@@ -3784,7 +3795,7 @@ def _intersects_dependencies(self, other):
return True
def satisfies(self, other: "Spec", deps: bool = True) -> bool:
def satisfies(self, other: Union[str, "Spec"], deps: bool = True) -> bool:
"""Return True if all concrete specs matching self also match other, otherwise False.
Args:
@@ -3896,7 +3907,15 @@ def patches(self):
for sha256 in self.variants["patches"]._patches_in_order_of_appearance:
index = spack.repo.PATH.patch_index
pkg_cls = spack.repo.PATH.get_pkg_class(self.name)
patch = index.patch_for_package(sha256, pkg_cls)
try:
patch = index.patch_for_package(sha256, pkg_cls)
except spack.patch.PatchLookupError as e:
raise spack.error.SpecError(
f"{e}. This usually means the patch was modified or removed. "
"To fix this, either reconcretize or use the original package "
"repository"
) from e
self._patches.append(patch)
return self._patches
@@ -5147,6 +5166,43 @@ def save_dependency_specfiles(root: Spec, output_directory: str, dependencies: L
fd.write(spec.to_json(hash=ht.dag_hash))
def get_host_environment_metadata() -> Dict[str, str]:
"""Get the host environment, reduce to a subset that we can store in
the install directory, and add the spack version.
"""
import spack.main
environ = get_host_environment()
return {
"host_os": environ["os"],
"platform": environ["platform"],
"host_target": environ["target"],
"hostname": environ["hostname"],
"spack_version": spack.main.get_version(),
"kernel_version": platform.version(),
}
def get_host_environment() -> Dict[str, Any]:
"""Return a dictionary (lookup) with host information (not including the
os.environ).
"""
host_platform = spack.platforms.host()
host_target = host_platform.target("default_target")
host_os = host_platform.operating_system("default_os")
arch_fmt = "platform={0} os={1} target={2}"
arch_spec = Spec(arch_fmt.format(host_platform, host_os, host_target))
return {
"target": str(host_target),
"os": str(host_os),
"platform": str(host_platform),
"arch": arch_spec,
"architecture": arch_spec,
"arch_str": str(arch_spec),
"hostname": socket.gethostname(),
}
class SpecParseError(spack.error.SpecError):
"""Wrapper for ParseError for when we're parsing specs."""
@@ -5207,7 +5263,7 @@ class InvalidDependencyError(spack.error.SpecError):
def __init__(self, pkg, deps):
self.invalid_deps = deps
super().__init__(
"Package {0} does not depend on {1}".format(pkg, spack.util.string.comma_or(deps))
"Package {0} does not depend on {1}".format(pkg, llnl.string.comma_or(deps))
)

View File

@@ -2,18 +2,20 @@
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import concurrent.futures
import errno
import getpass
import glob
import hashlib
import io
import os
import shutil
import stat
import sys
import tempfile
from typing import Dict, Iterable
from typing import Callable, Dict, Iterable, Optional, Set
import llnl.string
import llnl.util.lang
import llnl.util.tty as tty
from llnl.util.filesystem import (
@@ -26,6 +28,8 @@
partition_path,
remove_linked_tree,
)
from llnl.util.tty.colify import colify
from llnl.util.tty.color import colorize
import spack.caches
import spack.config
@@ -34,12 +38,14 @@
import spack.mirror
import spack.paths
import spack.spec
import spack.stage
import spack.util.lock
import spack.util.path as sup
import spack.util.pattern as pattern
import spack.util.url as url_util
from spack.util.crypto import bit_length, prefix_bits
from spack.util.web import FetchError
from spack.util.editor import editor, executable
from spack.version import StandardVersion, VersionList
# The well-known stage source subdirectory name.
_source_path_subdir = "spack-src"
@@ -241,10 +247,7 @@ class Stage:
similar, and are intended to persist for only one run of spack.
"""
"""Shared dict of all stage locks."""
stage_locks: Dict[str, spack.util.lock.Lock] = {}
"""Most staging is managed by Spack. DIYStage is one exception."""
#: Most staging is managed by Spack. DIYStage is one exception.
managed_by_spack = True
def __init__(
@@ -330,17 +333,12 @@ def __init__(
# details on this approach.
self._lock = None
if lock:
if self.name not in Stage.stage_locks:
sha1 = hashlib.sha1(self.name.encode("utf-8")).digest()
lock_id = prefix_bits(sha1, bit_length(sys.maxsize))
stage_lock_path = os.path.join(get_stage_root(), ".lock")
tty.debug("Creating stage lock {0}".format(self.name))
Stage.stage_locks[self.name] = spack.util.lock.Lock(
stage_lock_path, start=lock_id, length=1, desc=self.name
)
self._lock = Stage.stage_locks[self.name]
sha1 = hashlib.sha1(self.name.encode("utf-8")).digest()
lock_id = prefix_bits(sha1, bit_length(sys.maxsize))
stage_lock_path = os.path.join(get_stage_root(), ".lock")
self._lock = spack.util.lock.Lock(
stage_lock_path, start=lock_id, length=1, desc=self.name
)
# When stages are reused, we need to know whether to re-create
# it. This marks whether it has been created/destroyed.
@@ -522,7 +520,7 @@ def print_errors(errors):
self.fetcher = self.default_fetcher
default_msg = "All fetchers failed for {0}".format(self.name)
raise FetchError(err_msg or default_msg, None)
raise spack.error.FetchError(err_msg or default_msg, None)
print_errors(errors)
@@ -868,104 +866,283 @@ def purge():
os.remove(stage_path)
def get_checksums_for_versions(url_dict, name, **kwargs):
"""Fetches and checksums archives from URLs.
This function is called by both ``spack checksum`` and ``spack
create``. The ``first_stage_function`` argument allows the caller to
inspect the first downloaded archive, e.g., to determine the build
system.
def interactive_version_filter(
url_dict: Dict[StandardVersion, str],
known_versions: Iterable[StandardVersion] = (),
*,
url_changes: Set[StandardVersion] = set(),
input: Callable[..., str] = input,
) -> Optional[Dict[StandardVersion, str]]:
"""Interactively filter the list of spidered versions.
Args:
url_dict (dict): A dictionary of the form: version -> URL
name (str): The name of the package
first_stage_function (typing.Callable): function that takes a Stage and a URL;
this is run on the stage of the first URL downloaded
keep_stage (bool): whether to keep staging area when command completes
batch (bool): whether to ask user how many versions to fetch (false)
or fetch all versions (true)
fetch_options (dict): Options used for the fetcher (such as timeout
or cookies)
url_dict: Dictionary of versions to URLs
known_versions: Versions that can be skipped because they are already known
Returns:
(dict): A dictionary of the form: version -> checksum
Filtered dictionary of versions to URLs or None if the user wants to quit
"""
batch = kwargs.get("batch", False)
fetch_options = kwargs.get("fetch_options", None)
first_stage_function = kwargs.get("first_stage_function", None)
keep_stage = kwargs.get("keep_stage", False)
sorted_versions = sorted(url_dict.keys(), reverse=True)
# Find length of longest string in the list for padding
max_len = max(len(str(v)) for v in sorted_versions)
num_ver = len(sorted_versions)
tty.msg(
"Found {0} version{1} of {2}:".format(num_ver, "" if num_ver == 1 else "s", name),
"",
*llnl.util.lang.elide_list(
["{0:{1}} {2}".format(str(v), max_len, url_dict[v]) for v in sorted_versions]
),
)
print()
if batch:
archives_to_fetch = len(sorted_versions)
else:
archives_to_fetch = tty.get_number(
"How many would you like to checksum?", default=1, abort="q"
)
if not archives_to_fetch:
tty.die("Aborted.")
versions = sorted_versions[:archives_to_fetch]
urls = [url_dict[v] for v in versions]
tty.debug("Downloading...")
version_hashes = {}
i = 0
errors = []
for url, version in zip(urls, versions):
try:
if fetch_options:
url_or_fs = fs.URLFetchStrategy(url, fetch_options=fetch_options)
else:
url_or_fs = url
with Stage(url_or_fs, keep=keep_stage) as stage:
# Fetch the archive
stage.fetch()
if i == 0 and first_stage_function:
# Only run first_stage_function the first time,
# no need to run it every time
first_stage_function(stage, url)
# Checksum the archive and add it to the list
version_hashes[version] = spack.util.crypto.checksum(
hashlib.sha256, stage.archive_file
sorted_and_filtered = sorted(url_dict.keys(), reverse=True)
version_filter = VersionList([":"])
max_len = max(len(str(v)) for v in sorted_and_filtered)
orig_url_dict = url_dict # only copy when using editor to modify
print_header = True
VERSION_COLOR = spack.spec.VERSION_COLOR
while True:
if print_header:
has_filter = version_filter != VersionList([":"])
header = []
if len(sorted_and_filtered) == len(orig_url_dict):
header.append(
f"Selected {llnl.string.plural(len(sorted_and_filtered), 'version')}"
)
i += 1
except FailedDownloadError:
errors.append("Failed to fetch {0}".format(url))
except Exception as e:
tty.msg("Something failed on {0}, skipping. ({1})".format(url, e))
else:
header.append(
f"Selected {len(sorted_and_filtered)} of {len(orig_url_dict)} versions"
)
if known_versions:
num_new = sum(1 for v in sorted_and_filtered if v not in known_versions)
header.append(f"{llnl.string.plural(num_new, 'new version')}")
if has_filter:
header.append(colorize(f"Filtered by {VERSION_COLOR}{version_filter}@."))
for msg in errors:
tty.debug(msg)
version_with_url = [
colorize(
f"{VERSION_COLOR}{str(v):{max_len}}@. {url_dict[v]}"
f"{' @K{# NOTE: change of URL}' if v in url_changes else ''}"
)
for v in sorted_and_filtered
]
tty.msg(". ".join(header), *llnl.util.lang.elide_list(version_with_url))
print()
print_header = True
print("commands:")
commands = (
"@*b{[c]}hecksum",
"@*b{[e]}dit",
"@*b{[f]}ilter",
"@*b{[a]}sk each",
"@*b{[n]}ew only",
"@*b{[r]}estart",
"@*b{[q]}uit",
)
colify(list(map(colorize, commands)), indent=2)
try:
command = input(colorize("@*g{command>} ")).strip().lower()
except EOFError:
print()
command = "q"
if command == "c":
break
elif command == "e":
# Create a temporary file in the stage dir with lines of the form
# <version> <url>
# which the user can modify. Once the editor is closed, the file is
# read back in and the versions to url dict is updated.
# Create a temporary file by hashing its contents.
buffer = io.StringIO()
buffer.write("# Edit this file to change the versions and urls to fetch\n")
for v in sorted_and_filtered:
buffer.write(f"{str(v):{max_len}} {url_dict[v]}\n")
data = buffer.getvalue().encode("utf-8")
short_hash = hashlib.sha1(data).hexdigest()[:7]
filename = f"{spack.stage.stage_prefix}versions-{short_hash}.txt"
filepath = os.path.join(spack.stage.get_stage_root(), filename)
# Write contents
with open(filepath, "wb") as f:
f.write(data)
# Open editor
editor(filepath, exec_fn=executable)
# Read back in
with open(filepath, "r") as f:
orig_url_dict, url_dict = url_dict, {}
for line in f:
line = line.strip()
# Skip empty lines and comments
if not line or line.startswith("#"):
continue
try:
version, url = line.split(None, 1)
except ValueError:
tty.warn(f"Couldn't parse: {line}")
continue
try:
url_dict[StandardVersion.from_string(version)] = url
except ValueError:
tty.warn(f"Invalid version: {version}")
continue
sorted_and_filtered = sorted(url_dict.keys(), reverse=True)
os.unlink(filepath)
elif command == "f":
tty.msg(
colorize(
f"Examples filters: {VERSION_COLOR}1.2@. "
f"or {VERSION_COLOR}1.1:1.3@. "
f"or {VERSION_COLOR}=1.2, 1.2.2:@."
)
)
try:
# Allow a leading @ version specifier
filter_spec = input(colorize("@*g{filter>} ")).strip().lstrip("@")
except EOFError:
print()
continue
try:
version_filter.intersect(VersionList([filter_spec]))
except ValueError:
tty.warn(f"Invalid version specifier: {filter_spec}")
continue
# Apply filter
sorted_and_filtered = [v for v in sorted_and_filtered if v.satisfies(version_filter)]
elif command == "a":
i = 0
while i < len(sorted_and_filtered):
v = sorted_and_filtered[i]
try:
answer = input(f" {str(v):{max_len}} {url_dict[v]} [Y/n]? ").strip().lower()
except EOFError:
# If ^D, don't fully exit, but go back to the command prompt, now with possibly
# fewer versions
print()
break
if answer in ("n", "no"):
del sorted_and_filtered[i]
elif answer in ("y", "yes", ""):
i += 1
else:
# Went over each version, so go to checksumming
break
elif command == "n":
sorted_and_filtered = [v for v in sorted_and_filtered if v not in known_versions]
elif command == "r":
url_dict = orig_url_dict
sorted_and_filtered = sorted(url_dict.keys(), reverse=True)
version_filter = VersionList([":"])
elif command == "q":
try:
if input("Really quit [y/N]? ").strip().lower() in ("y", "yes"):
return None
except EOFError:
print()
return None
else:
tty.warn(f"Ignoring invalid command: {command}")
print_header = False
continue
return {v: url_dict[v] for v in sorted_and_filtered}
def get_checksums_for_versions(
url_by_version: Dict[str, str],
package_name: str,
*,
first_stage_function: Optional[Callable[[Stage, str], None]] = None,
keep_stage: bool = False,
concurrency: Optional[int] = None,
fetch_options: Optional[Dict[str, str]] = None,
) -> Dict[str, str]:
"""Computes the checksums for each version passed in input, and returns the results.
Archives are fetched according to the usl dictionary passed as input.
The ``first_stage_function`` argument allows the caller to inspect the first downloaded
archive, e.g., to determine the build system.
Args:
url_by_version: URL keyed by version
package_name: name of the package
first_stage_function: function that takes a Stage and a URL; this is run on the stage
of the first URL downloaded
keep_stage: whether to keep staging area when command completes
batch: whether to ask user how many versions to fetch (false) or fetch all versions (true)
fetch_options: options used for the fetcher (such as timeout or cookies)
concurrency: maximum number of workers to use for retrieving archives
Returns:
A dictionary mapping each version to the corresponding checksum
"""
versions = sorted(url_by_version.keys(), reverse=True)
search_arguments = [(url_by_version[v], v) for v in versions]
version_hashes, errors = {}, []
# Don't spawn 16 processes when we need to fetch 2 urls
if concurrency is not None:
concurrency = min(concurrency, len(search_arguments))
else:
concurrency = min(os.cpu_count() or 1, len(search_arguments))
# The function might have side effects in memory, that would not be reflected in the
# parent process, if run in a child process. If this pattern happens frequently, we
# can move this function call *after* having distributed the work to executors.
if first_stage_function is not None:
(url, version), search_arguments = search_arguments[0], search_arguments[1:]
checksum, error = _fetch_and_checksum(url, fetch_options, keep_stage, first_stage_function)
if error is not None:
errors.append(error)
if checksum is not None:
version_hashes[version] = checksum
with concurrent.futures.ProcessPoolExecutor(max_workers=concurrency) as executor:
results = []
for url, version in search_arguments:
future = executor.submit(_fetch_and_checksum, url, fetch_options, keep_stage)
results.append((version, future))
for version, future in results:
checksum, error = future.result()
if error is not None:
errors.append(error)
continue
version_hashes[version] = checksum
for msg in errors:
tty.debug(msg)
if not version_hashes:
tty.die("Could not fetch any versions for {0}".format(name))
tty.die(f"Could not fetch any versions for {package_name}")
num_hash = len(version_hashes)
tty.debug(
"Checksummed {0} version{1} of {2}:".format(num_hash, "" if num_hash == 1 else "s", name)
)
tty.debug(f"Checksummed {num_hash} version{'' if num_hash == 1 else 's'} of {package_name}:")
return version_hashes
def _fetch_and_checksum(url, options, keep_stage, action_fn=None):
try:
url_or_fs = url
if options:
url_or_fs = fs.URLFetchStrategy(url, fetch_options=options)
with Stage(url_or_fs, keep=keep_stage) as stage:
# Fetch the archive
stage.fetch()
if action_fn is not None:
# Only run first_stage_function the first time,
# no need to run it every time
action_fn(stage, url)
# Checksum the archive and add it to the list
checksum = spack.util.crypto.checksum(hashlib.sha256, stage.archive_file)
return checksum, None
except FailedDownloadError:
return None, f"[WORKER] Failed to fetch {url}"
except Exception as e:
return None, f"[WORKER] Something failed on {url}, skipping. ({e})"
class StageError(spack.error.SpackError):
""" "Superclass for all errors encountered during staging."""

View File

@@ -899,22 +899,21 @@ def test_tarball_doesnt_include_buildinfo_twice(tmpdir):
tarball = str(tmpdir.join("prefix.tar.gz"))
bindist._do_create_tarball(
tarfile_path=tarball,
binaries_dir=str(p),
pkg_dir="my-pkg-prefix",
buildinfo={"metadata": "new"},
tarfile_path=tarball, binaries_dir=p.strpath, buildinfo={"metadata": "new"}
)
expected_prefix = p.strpath.lstrip("/")
# Verify we don't have a repeated binary_distribution file,
# and that the tarball contains the new one, not the old one.
with tarfile.open(tarball) as tar:
assert syaml.load(tar.extractfile("my-pkg-prefix/.spack/binary_distribution")) == {
assert syaml.load(tar.extractfile(f"{expected_prefix}/.spack/binary_distribution")) == {
"metadata": "new"
}
assert tar.getnames() == [
"my-pkg-prefix",
"my-pkg-prefix/.spack",
"my-pkg-prefix/.spack/binary_distribution",
f"{expected_prefix}",
f"{expected_prefix}/.spack",
f"{expected_prefix}/.spack/binary_distribution",
]
@@ -935,15 +934,17 @@ def test_reproducible_tarball_is_reproducible(tmpdir):
# Create a tarball with a certain mtime of bin/app
os.utime(app, times=(0, 0))
bindist._do_create_tarball(tarball_1, binaries_dir=p, pkg_dir="pkg", buildinfo=buildinfo)
bindist._do_create_tarball(tarball_1, binaries_dir=p.strpath, buildinfo=buildinfo)
# Do it another time with different mtime of bin/app
os.utime(app, times=(10, 10))
bindist._do_create_tarball(tarball_2, binaries_dir=p, pkg_dir="pkg", buildinfo=buildinfo)
bindist._do_create_tarball(tarball_2, binaries_dir=p.strpath, buildinfo=buildinfo)
# They should be bitwise identical:
assert filecmp.cmp(tarball_1, tarball_2, shallow=False)
expected_prefix = p.strpath.lstrip("/")
# Sanity check for contents:
with tarfile.open(tarball_1, mode="r") as f:
for m in f.getmembers():
@@ -951,11 +952,11 @@ def test_reproducible_tarball_is_reproducible(tmpdir):
assert m.uname == m.gname == ""
assert set(f.getnames()) == {
"pkg",
"pkg/bin",
"pkg/bin/app",
"pkg/.spack",
"pkg/.spack/binary_distribution",
f"{expected_prefix}",
f"{expected_prefix}/bin",
f"{expected_prefix}/bin/app",
f"{expected_prefix}/.spack",
f"{expected_prefix}/.spack/binary_distribution",
}
@@ -979,21 +980,23 @@ def test_tarball_normalized_permissions(tmpdir):
with open(data, "w", opener=lambda path, flags: os.open(path, flags, 0o477)) as f:
f.write("hello world")
bindist._do_create_tarball(tarball, binaries_dir=p, pkg_dir="pkg", buildinfo={})
bindist._do_create_tarball(tarball, binaries_dir=p.strpath, buildinfo={})
expected_prefix = p.strpath.lstrip("/")
with tarfile.open(tarball) as tar:
path_to_member = {member.name: member for member in tar.getmembers()}
# directories should have 0o755
assert path_to_member["pkg"].mode == 0o755
assert path_to_member["pkg/bin"].mode == 0o755
assert path_to_member["pkg/.spack"].mode == 0o755
assert path_to_member[f"{expected_prefix}"].mode == 0o755
assert path_to_member[f"{expected_prefix}/bin"].mode == 0o755
assert path_to_member[f"{expected_prefix}/.spack"].mode == 0o755
# executable-by-user files should be 0o755
assert path_to_member["pkg/bin/app"].mode == 0o755
assert path_to_member[f"{expected_prefix}/bin/app"].mode == 0o755
# not-executable-by-user files should be 0o644
assert path_to_member["pkg/share/file"].mode == 0o644
assert path_to_member[f"{expected_prefix}/share/file"].mode == 0o644
def test_tarball_common_prefix(dummy_prefix, tmpdir):
@@ -1062,3 +1065,50 @@ def test_tarfile_with_files_outside_common_prefix(tmpdir, dummy_prefix):
ValueError, match="Tarball contains file /etc/config_file outside of prefix"
):
bindist._ensure_common_prefix(tarfile.open("broken.tar", mode="r"))
def test_tarfile_of_spec_prefix(tmpdir):
"""Tests whether hardlinks, symlinks, files and dirs are added correctly,
and that the order of entries is correct."""
prefix = tmpdir.mkdir("prefix")
prefix.ensure("a_directory", dir=True).join("file").write("hello")
prefix.ensure("c_directory", dir=True).join("file").write("hello")
prefix.ensure("b_directory", dir=True).join("file").write("hello")
prefix.join("file").write("hello")
os.symlink(prefix.join("file"), prefix.join("symlink"))
os.link(prefix.join("file"), prefix.join("hardlink"))
file = tmpdir.join("example.tar")
with tarfile.open(file, mode="w") as tar:
bindist.tarfile_of_spec_prefix(tar, prefix.strpath)
expected_prefix = prefix.strpath.lstrip("/")
with tarfile.open(file, mode="r") as tar:
# Verify that entries are added in depth-first pre-order, files preceding dirs,
# entries ordered alphabetically
assert tar.getnames() == [
f"{expected_prefix}",
f"{expected_prefix}/file",
f"{expected_prefix}/hardlink",
f"{expected_prefix}/symlink",
f"{expected_prefix}/a_directory",
f"{expected_prefix}/a_directory/file",
f"{expected_prefix}/b_directory",
f"{expected_prefix}/b_directory/file",
f"{expected_prefix}/c_directory",
f"{expected_prefix}/c_directory/file",
]
# Check that the types are all correct
assert tar.getmember(f"{expected_prefix}").isdir()
assert tar.getmember(f"{expected_prefix}/file").isreg()
assert tar.getmember(f"{expected_prefix}/hardlink").islnk()
assert tar.getmember(f"{expected_prefix}/symlink").issym()
assert tar.getmember(f"{expected_prefix}/a_directory").isdir()
assert tar.getmember(f"{expected_prefix}/a_directory/file").isreg()
assert tar.getmember(f"{expected_prefix}/b_directory").isdir()
assert tar.getmember(f"{expected_prefix}/b_directory/file").isreg()
assert tar.getmember(f"{expected_prefix}/c_directory").isdir()
assert tar.getmember(f"{expected_prefix}/c_directory/file").isreg()

View File

@@ -9,6 +9,7 @@
import pytest
from llnl.path import Path, convert_to_platform_path
from llnl.util.filesystem import HeaderList, LibraryList
import spack.build_environment
@@ -21,7 +22,6 @@
from spack.util.cpus import determine_number_of_jobs
from spack.util.environment import EnvironmentModifications
from spack.util.executable import Executable
from spack.util.path import Path, convert_to_platform_path
def os_pathsep_join(path, *pths):

View File

@@ -7,13 +7,14 @@
import pytest
from llnl.path import convert_to_posix_path
import spack.bootstrap
import spack.bootstrap.core
import spack.config
import spack.environment as ev
import spack.main
import spack.mirror
from spack.util.path import convert_to_posix_path
_bootstrap = spack.main.SpackCommand("bootstrap")
@@ -168,7 +169,7 @@ def test_remove_and_add_a_source(mutable_config):
assert not sources
# Add it back and check we restored the initial state
_bootstrap("add", "github-actions", "$spack/share/spack/bootstrap/github-actions-v0.3")
_bootstrap("add", "github-actions", "$spack/share/spack/bootstrap/github-actions-v0.5")
sources = spack.bootstrap.core.bootstrapping_sources()
assert len(sources) == 1

View File

@@ -7,12 +7,12 @@
import pytest
import llnl.util.tty as tty
import spack.cmd.checksum
import spack.repo
import spack.spec
from spack.main import SpackCommand
from spack.stage import interactive_version_filter
from spack.version import Version
spack_checksum = SpackCommand("checksum")
@@ -56,18 +56,134 @@ def test_checksum(arguments, expected, mock_packages, mock_clone_repo, mock_stag
assert "version(" in output
@pytest.mark.not_on_windows("Not supported on Windows (yet)")
def test_checksum_interactive(mock_packages, mock_fetch, mock_stage, monkeypatch):
# TODO: mock_fetch doesn't actually work with stage, working around with ignoring
# fail_on_error for now
def _get_number(*args, **kwargs):
return 1
def input_from_commands(*commands):
"""Create a function that returns the next command from a list of inputs for interactive spack
checksum. If None is encountered, this is equivalent to EOF / ^D."""
commands = iter(commands)
monkeypatch.setattr(tty, "get_number", _get_number)
def _input(prompt):
cmd = next(commands)
if cmd is None:
raise EOFError
assert isinstance(cmd, str)
return cmd
output = spack_checksum("preferred-test", fail_on_error=False)
assert "version of preferred-test" in output
assert "version(" in output
return _input
def test_checksum_interactive_filter():
# Filter effectively by 1:1.0, then checksum.
input = input_from_commands("f", "@1:", "f", "@:1.0", "c")
assert interactive_version_filter(
{
Version("1.1"): "https://www.example.com/pkg-1.1.tar.gz",
Version("1.0.1"): "https://www.example.com/pkg-1.0.1.tar.gz",
Version("1.0"): "https://www.example.com/pkg-1.0.tar.gz",
Version("0.9"): "https://www.example.com/pkg-0.9.tar.gz",
},
input=input,
) == {
Version("1.0.1"): "https://www.example.com/pkg-1.0.1.tar.gz",
Version("1.0"): "https://www.example.com/pkg-1.0.tar.gz",
}
def test_checksum_interactive_return_from_filter_prompt():
# Enter and then exit filter subcommand.
input = input_from_commands("f", None, "c")
assert interactive_version_filter(
{
Version("1.1"): "https://www.example.com/pkg-1.1.tar.gz",
Version("1.0.1"): "https://www.example.com/pkg-1.0.1.tar.gz",
Version("1.0"): "https://www.example.com/pkg-1.0.tar.gz",
Version("0.9"): "https://www.example.com/pkg-0.9.tar.gz",
},
input=input,
) == {
Version("1.1"): "https://www.example.com/pkg-1.1.tar.gz",
Version("1.0.1"): "https://www.example.com/pkg-1.0.1.tar.gz",
Version("1.0"): "https://www.example.com/pkg-1.0.tar.gz",
Version("0.9"): "https://www.example.com/pkg-0.9.tar.gz",
}
def test_checksum_interactive_quit_returns_none():
# Quit after filtering something out (y to confirm quit)
input = input_from_commands("f", "@1:", "q", "y")
assert (
interactive_version_filter(
{
Version("1.1"): "https://www.example.com/pkg-1.1.tar.gz",
Version("1.0"): "https://www.example.com/pkg-1.0.tar.gz",
Version("0.9"): "https://www.example.com/pkg-0.9.tar.gz",
},
input=input,
)
is None
)
def test_checksum_interactive_reset_resets():
# Filter 1:, then reset, then filter :0, should just given 0.9 (it was filtered out
# before reset)
input = input_from_commands("f", "@1:", "r", "f", ":0", "c")
assert interactive_version_filter(
{
Version("1.1"): "https://www.example.com/pkg-1.1.tar.gz",
Version("1.0"): "https://www.example.com/pkg-1.0.tar.gz",
Version("0.9"): "https://www.example.com/pkg-0.9.tar.gz",
},
input=input,
) == {Version("0.9"): "https://www.example.com/pkg-0.9.tar.gz"}
def test_checksum_interactive_ask_each():
# Ask each should run on the filtered list. First select 1.x, then select only the second
# entry, which is 1.0.1.
input = input_from_commands("f", "@1:", "a", "n", "y", "n")
assert interactive_version_filter(
{
Version("1.1"): "https://www.example.com/pkg-1.1.tar.gz",
Version("1.0.1"): "https://www.example.com/pkg-1.0.1.tar.gz",
Version("1.0"): "https://www.example.com/pkg-1.0.tar.gz",
Version("0.9"): "https://www.example.com/pkg-0.9.tar.gz",
},
input=input,
) == {Version("1.0.1"): "https://www.example.com/pkg-1.0.1.tar.gz"}
def test_checksum_interactive_quit_from_ask_each():
# Enter ask each mode, select the second item, then quit from submenu, then checksum, which
# should still include the last item at which ask each stopped.
input = input_from_commands("a", "n", "y", None, "c")
assert interactive_version_filter(
{
Version("1.1"): "https://www.example.com/pkg-1.1.tar.gz",
Version("1.0"): "https://www.example.com/pkg-1.0.tar.gz",
Version("0.9"): "https://www.example.com/pkg-0.9.tar.gz",
},
input=input,
) == {
Version("1.0"): "https://www.example.com/pkg-1.0.tar.gz",
Version("0.9"): "https://www.example.com/pkg-0.9.tar.gz",
}
def test_checksum_interactive_new_only():
# The 1.0 version is known already, and should be dropped on `n`.
input = input_from_commands("n", "c")
assert interactive_version_filter(
{
Version("1.1"): "https://www.example.com/pkg-1.1.tar.gz",
Version("1.0"): "https://www.example.com/pkg-1.0.tar.gz",
Version("0.9"): "https://www.example.com/pkg-0.9.tar.gz",
},
known_versions=[Version("1.0")],
input=input,
) == {
Version("1.1"): "https://www.example.com/pkg-1.1.tar.gz",
Version("0.9"): "https://www.example.com/pkg-0.9.tar.gz",
}
def test_checksum_versions(mock_packages, mock_clone_repo, mock_fetch, mock_stage):

View File

@@ -1990,8 +1990,7 @@ def test_ci_reproduce(
ci_cmd("generate", "--output-file", pipeline_path, "--artifacts-root", artifacts_root)
target_name = spack.platforms.test.Test.default
job_name = ci.get_job_name(job_spec, "test-debian6-%s" % target_name, None)
job_name = ci.get_job_name(job_spec)
repro_file = os.path.join(working_dir.strpath, "repro.json")
repro_details = {

View File

@@ -120,8 +120,9 @@ def test_find_external_cmd_not_buildable(mutable_config, working_env, mock_execu
"names,tags,exclude,expected",
[
# find --all
(None, ["detectable"], [], ["find-externals1"]),
(None, ["detectable"], [], ["builtin.mock.find-externals1"]),
# find --all --exclude find-externals1
(None, ["detectable"], ["builtin.mock.find-externals1"], []),
(None, ["detectable"], ["find-externals1"], []),
# find cmake (and cmake is not detectable)
(["cmake"], ["detectable"], [], []),
@@ -202,19 +203,6 @@ def fail():
assert "Skipping manifest and continuing" in output
def test_find_external_nonempty_default_manifest_dir(
mutable_database, mutable_mock_repo, tmpdir, monkeypatch, directory_with_manifest
):
"""The user runs 'spack external find'; the default manifest directory
contains a manifest file. Ensure that the specs are read.
"""
monkeypatch.setenv("PATH", "")
monkeypatch.setattr(spack.cray_manifest, "default_path", str(directory_with_manifest))
external("find")
specs = spack.store.STORE.db.query("hwloc")
assert any(x.dag_hash() == "hwlocfakehashaaa" for x in specs)
def test_find_external_merge(mutable_config, mutable_mock_repo):
"""Check that 'spack find external' doesn't overwrite an existing spec
entry in packages.yaml.

View File

@@ -14,7 +14,6 @@
import spack.spec
import spack.store
from spack.main import SpackCommand, SpackCommandError
from spack.util.web import FetchError
pytestmark = pytest.mark.usefixtures("config", "mutable_mock_repo")
@@ -208,7 +207,7 @@ def test_env_aware_spec(mutable_mock_env_path):
[
("develop-branch-version", "f3c7206350ac8ee364af687deaae5c574dcfca2c=develop", None),
("develop-branch-version", "git." + "a" * 40 + "=develop", None),
("callpath", "f3c7206350ac8ee364af687deaae5c574dcfca2c=1.0", FetchError),
("callpath", "f3c7206350ac8ee364af687deaae5c574dcfca2c=1.0", spack.error.FetchError),
("develop-branch-version", "git.foo=0.2.15", None),
],
)

View File

@@ -1356,15 +1356,15 @@ def test_multivalued_variants_from_cli(self, spec_str, expected_dict):
[
# Version 1.1.0 is deprecated and should not be selected, unless we
# explicitly asked for that
("deprecated-versions", ["deprecated-versions@1.0.0"]),
("deprecated-versions@1.1.0", ["deprecated-versions@1.1.0"]),
("deprecated-versions", "deprecated-versions@1.0.0"),
("deprecated-versions@=1.1.0", "deprecated-versions@1.1.0"),
],
)
@pytest.mark.only_clingo("Use case not supported by the original concretizer")
def test_deprecated_versions_not_selected(self, spec_str, expected):
s = Spec(spec_str).concretized()
for abstract_spec in expected:
assert abstract_spec in s
with spack.config.override("config:deprecated", True):
s = Spec(spec_str).concretized()
s.satisfies(expected)
@pytest.mark.regression("24196")
def test_version_badness_more_important_than_default_mv_variants(self):
@@ -2121,12 +2121,9 @@ def duplicates_test_repository():
@pytest.mark.usefixtures("mutable_config", "duplicates_test_repository")
@pytest.mark.only_clingo("Not supported by the original concretizer")
class TestConcretizeSeparately:
@pytest.mark.parametrize("strategy", ["minimal", "full"])
@pytest.mark.skipif(
os.environ.get("SPACK_TEST_SOLVER") == "original",
reason="Not supported by the original concretizer",
)
def test_two_gmake(self, strategy):
"""Tests that we can concretize a spec with nodes using the same build
dependency pinned at different versions.
@@ -2151,10 +2148,6 @@ def test_two_gmake(self, strategy):
assert len(pinned_gmake) == 1 and pinned_gmake[0].satisfies("@=3.0")
@pytest.mark.parametrize("strategy", ["minimal", "full"])
@pytest.mark.skipif(
os.environ.get("SPACK_TEST_SOLVER") == "original",
reason="Not supported by the original concretizer",
)
def test_two_setuptools(self, strategy):
"""Tests that we can concretize separate build dependencies, when we are dealing
with extensions.
@@ -2191,10 +2184,6 @@ def test_two_setuptools(self, strategy):
gmake = s["python"].dependencies(name="gmake", deptype="build")
assert len(gmake) == 1 and gmake[0].satisfies("@=3.0")
@pytest.mark.skipif(
os.environ.get("SPACK_TEST_SOLVER") == "original",
reason="Not supported by the original concretizer",
)
def test_solution_without_cycles(self):
"""Tests that when we concretize a spec with cycles, a fallback kicks in to recompute
a solution without cycles.
@@ -2207,6 +2196,21 @@ def test_solution_without_cycles(self):
assert s["cycle-a"].satisfies("~cycle")
assert s["cycle-b"].satisfies("+cycle")
@pytest.mark.parametrize("strategy", ["minimal", "full"])
def test_pure_build_virtual_dependency(self, strategy):
"""Tests that we can concretize a pure build virtual dependency, and ensures that
pure build virtual dependencies are accounted in the list of possible virtual
dependencies.
virtual-build@1.0
| [type=build, virtual=pkgconfig]
pkg-config@1.0
"""
spack.config.CONFIG.set("concretizer:duplicates:strategy", strategy)
s = Spec("virtual-build").concretized()
assert s["pkgconfig"].name == "pkg-config"
@pytest.mark.parametrize(
"v_str,v_opts,checksummed",

View File

@@ -543,21 +543,37 @@ def test_reuse_oneof(concretize_scope, create_test_repo, mutable_database, fake_
assert not s2.satisfies("@2.5 %gcc")
def test_requirements_are_higher_priority_than_deprecation(concretize_scope, test_repo):
"""Test that users can override a deprecated version with a requirement."""
# @2.3 is a deprecated versions. Ensure that any_of picks both constraints,
@pytest.mark.parametrize(
"allow_deprecated,expected,not_expected",
[(True, ["@=2.3", "%gcc"], []), (False, ["%gcc"], ["@=2.3"])],
)
def test_requirements_and_deprecated_versions(
allow_deprecated, expected, not_expected, concretize_scope, test_repo
):
"""Tests the expected behavior of requirements and deprecated versions.
If deprecated versions are not allowed, concretization should just pick
the other requirement.
If deprecated versions are allowed, both requirements are honored.
"""
# 2.3 is a deprecated versions. Ensure that any_of picks both constraints,
# since they are possible
conf_str = """\
packages:
y:
require:
- any_of: ["@2.3", "%gcc"]
- any_of: ["@=2.3", "%gcc"]
"""
update_packages_config(conf_str)
s1 = Spec("y").concretized()
assert s1.satisfies("@2.3")
assert s1.satisfies("%gcc")
with spack.config.override("config:deprecated", allow_deprecated):
s1 = Spec("y").concretized()
for constrain in expected:
assert s1.satisfies(constrain)
for constrain in not_expected:
assert not s1.satisfies(constrain)
@pytest.mark.parametrize("spec_str,requirement_str", [("x", "%gcc"), ("x", "%clang")])

View File

@@ -36,6 +36,7 @@
import spack.database
import spack.directory_layout
import spack.environment as ev
import spack.error
import spack.package_base
import spack.package_prefs
import spack.paths
@@ -52,7 +53,6 @@
import spack.util.url as url_util
from spack.fetch_strategy import URLFetchStrategy
from spack.util.pattern import Bunch
from spack.util.web import FetchError
def ensure_configuration_fixture_run_before(request):
@@ -472,7 +472,7 @@ def fetcher(self, target_path, digest, **kwargs):
class MockCacheFetcher:
def fetch(self):
raise FetchError("Mock cache always fails for tests")
raise spack.error.FetchError("Mock cache always fails for tests")
def __str__(self):
return "[mock fetch cache]"
@@ -1714,17 +1714,6 @@ def brand_new_binary_cache():
)
@pytest.fixture
def directory_with_manifest(tmpdir):
"""Create a manifest file in a directory. Used by 'spack external'."""
with tmpdir.as_cwd():
test_db_fname = "external-db.json"
with open(test_db_fname, "w") as db_file:
json.dump(spack.test.cray_manifest.create_manifest_content(), db_file)
yield str(tmpdir)
@pytest.fixture()
def noncyclical_dir_structure(tmpdir):
"""

View File

@@ -82,23 +82,6 @@ def test_strip_is_set_from_config(minimal_configuration):
assert writer.strip is False
def test_extra_instructions_is_set_from_config(minimal_configuration):
writer = writers.create(minimal_configuration)
assert writer.extra_instructions == (None, None)
test_line = "RUN echo Hello world!"
e = minimal_configuration["spack"]["container"]
e["extra_instructions"] = {}
e["extra_instructions"]["build"] = test_line
writer = writers.create(minimal_configuration)
assert writer.extra_instructions == (test_line, None)
e["extra_instructions"]["final"] = test_line
del e["extra_instructions"]["build"]
writer = writers.create(minimal_configuration)
assert writer.extra_instructions == (None, test_line)
def test_custom_base_images(minimal_configuration):
"""Test setting custom base images from configuration file"""
minimal_configuration["spack"]["container"]["images"] = {

View File

@@ -23,53 +23,6 @@
import spack.store
from spack.cray_manifest import compiler_from_entry, entries_to_specs
example_x_json_str = """\
{
"name": "packagex",
"hash": "hash-of-x",
"prefix": "/path/to/packagex-install/",
"version": "1.0",
"arch": {
"platform": "linux",
"platform_os": "centos8",
"target": {
"name": "haswell"
}
},
"compiler": {
"name": "gcc",
"version": "10.2.0.cray"
},
"dependencies": {
"packagey": {
"hash": "hash-of-y",
"type": ["link"]
}
},
"parameters": {
"precision": ["double", "float"]
}
}
"""
example_compiler_entry = """\
{
"name": "gcc",
"prefix": "/path/to/compiler/",
"version": "7.5.0",
"arch": {
"os": "centos8",
"target": "x86_64"
},
"executables": {
"cc": "/path/to/compiler/cc",
"cxx": "/path/to/compiler/cxx",
"fc": "/path/to/compiler/fc"
}
}
"""
class JsonSpecEntry:
def __init__(self, name, hash, prefix, version, arch, compiler, dependencies, parameters):
@@ -104,16 +57,19 @@ def __init__(self, platform, os, target):
self.os = os
self.target = target
def to_dict(self):
def spec_json(self):
return {"platform": self.platform, "platform_os": self.os, "target": {"name": self.target}}
def compiler_json(self):
return {"os": self.os, "target": self.target}
class JsonCompilerEntry:
def __init__(self, name, version, arch=None, executables=None):
self.name = name
self.version = version
if not arch:
arch = {"os": "centos8", "target": "x86_64"}
arch = JsonArchEntry("anyplatform", "anyos", "anytarget")
if not executables:
executables = {
"cc": "/path/to/compiler/cc",
@@ -127,7 +83,7 @@ def compiler_json(self):
return {
"name": self.name,
"version": self.version,
"arch": self.arch,
"arch": self.arch.compiler_json(),
"executables": self.executables,
}
@@ -138,22 +94,58 @@ def spec_json(self):
return {"name": self.name, "version": self.version}
_common_arch = JsonArchEntry(platform="linux", os="centos8", target="haswell").to_dict()
# Intended to match example_compiler_entry above
_common_compiler = JsonCompilerEntry(
name="gcc",
version="10.2.0.cray",
arch={"os": "centos8", "target": "x86_64"},
executables={
"cc": "/path/to/compiler/cc",
"cxx": "/path/to/compiler/cxx",
"fc": "/path/to/compiler/fc",
},
)
@pytest.fixture
def _common_arch(test_platform):
return JsonArchEntry(
platform=test_platform.name,
os=test_platform.front_os,
target=test_platform.target("fe").name,
)
def test_compatibility():
@pytest.fixture
def _common_compiler(_common_arch):
return JsonCompilerEntry(
name="gcc",
version="10.2.0.2112",
arch=_common_arch,
executables={
"cc": "/path/to/compiler/cc",
"cxx": "/path/to/compiler/cxx",
"fc": "/path/to/compiler/fc",
},
)
@pytest.fixture
def _other_compiler(_common_arch):
return JsonCompilerEntry(
name="clang",
version="3.0.0",
arch=_common_arch,
executables={
"cc": "/path/to/compiler/clang",
"cxx": "/path/to/compiler/clang++",
"fc": "/path/to/compiler/flang",
},
)
@pytest.fixture
def _raw_json_x(_common_arch):
return {
"name": "packagex",
"hash": "hash-of-x",
"prefix": "/path/to/packagex-install/",
"version": "1.0",
"arch": _common_arch.spec_json(),
"compiler": {"name": "gcc", "version": "10.2.0.2112"},
"dependencies": {"packagey": {"hash": "hash-of-y", "type": ["link"]}},
"parameters": {"precision": ["double", "float"]},
}
def test_manifest_compatibility(_common_arch, _common_compiler, _raw_json_x):
"""Make sure that JsonSpecEntry outputs the expected JSON structure
by comparing it with JSON parsed from an example string. This
ensures that the testing objects like JsonSpecEntry produce the
@@ -164,7 +156,7 @@ def test_compatibility():
hash="hash-of-y",
prefix="/path/to/packagey-install/",
version="1.0",
arch=_common_arch,
arch=_common_arch.spec_json(),
compiler=_common_compiler.spec_json(),
dependencies={},
parameters={},
@@ -175,23 +167,44 @@ def test_compatibility():
hash="hash-of-x",
prefix="/path/to/packagex-install/",
version="1.0",
arch=_common_arch,
arch=_common_arch.spec_json(),
compiler=_common_compiler.spec_json(),
dependencies=dict([y.as_dependency(deptypes=["link"])]),
parameters={"precision": ["double", "float"]},
)
x_from_entry = x.to_dict()
x_from_str = json.loads(example_x_json_str)
assert x_from_entry == x_from_str
assert x_from_entry == _raw_json_x
def test_compiler_from_entry():
compiler_data = json.loads(example_compiler_entry)
compiler_from_entry(compiler_data)
compiler_data = json.loads(
"""\
{
"name": "gcc",
"prefix": "/path/to/compiler/",
"version": "7.5.0",
"arch": {
"os": "centos8",
"target": "x86_64"
},
"executables": {
"cc": "/path/to/compiler/cc",
"cxx": "/path/to/compiler/cxx",
"fc": "/path/to/compiler/fc"
}
}
"""
)
compiler = compiler_from_entry(compiler_data, "/example/file")
assert compiler.cc == "/path/to/compiler/cc"
assert compiler.cxx == "/path/to/compiler/cxx"
assert compiler.fc == "/path/to/compiler/fc"
assert compiler.operating_system == "centos8"
def generate_openmpi_entries():
@pytest.fixture
def generate_openmpi_entries(_common_arch, _common_compiler):
"""Generate two example JSON entries that refer to an OpenMPI
installation and a hwloc dependency.
"""
@@ -202,7 +215,7 @@ def generate_openmpi_entries():
hash="hwlocfakehashaaa",
prefix="/path/to/hwloc-install/",
version="2.0.3",
arch=_common_arch,
arch=_common_arch.spec_json(),
compiler=_common_compiler.spec_json(),
dependencies={},
parameters={},
@@ -216,26 +229,25 @@ def generate_openmpi_entries():
hash="openmpifakehasha",
prefix="/path/to/openmpi-install/",
version="4.1.0",
arch=_common_arch,
arch=_common_arch.spec_json(),
compiler=_common_compiler.spec_json(),
dependencies=dict([hwloc.as_dependency(deptypes=["link"])]),
parameters={"internal-hwloc": False, "fabrics": ["psm"], "missing_variant": True},
)
return [openmpi, hwloc]
return list(x.to_dict() for x in [openmpi, hwloc])
def test_generate_specs_from_manifest():
def test_generate_specs_from_manifest(generate_openmpi_entries):
"""Given JSON entries, check that we can form a set of Specs
including dependency references.
"""
entries = list(x.to_dict() for x in generate_openmpi_entries())
specs = entries_to_specs(entries)
specs = entries_to_specs(generate_openmpi_entries)
(openmpi_spec,) = list(x for x in specs.values() if x.name == "openmpi")
assert openmpi_spec["hwloc"]
def test_translate_cray_platform_to_linux(monkeypatch):
def test_translate_cray_platform_to_linux(monkeypatch, _common_compiler):
"""Manifests might list specs on newer Cray platforms as being "cray",
but Spack identifies such platforms as "linux". Make sure we
automaticaly transform these entries.
@@ -247,13 +259,13 @@ def the_host_is_linux():
monkeypatch.setattr(spack.platforms, "host", the_host_is_linux)
cray_arch = JsonArchEntry(platform="cray", os="rhel8", target="x86_64").to_dict()
cray_arch = JsonArchEntry(platform="cray", os="rhel8", target="x86_64")
spec_json = JsonSpecEntry(
name="cray-mpich",
hash="craympichfakehashaaa",
prefix="/path/to/cray-mpich/",
version="1.0.0",
arch=cray_arch,
arch=cray_arch.spec_json(),
compiler=_common_compiler.spec_json(),
dependencies={},
parameters={},
@@ -263,14 +275,15 @@ def the_host_is_linux():
assert spec.architecture.platform == "linux"
def test_translate_compiler_name():
def test_translate_compiler_name(_common_arch):
nvidia_compiler = JsonCompilerEntry(
name="nvidia",
version="19.1",
arch=_common_arch,
executables={"cc": "/path/to/compiler/nvc", "cxx": "/path/to/compiler/nvc++"},
)
compiler = compiler_from_entry(nvidia_compiler.compiler_json())
compiler = compiler_from_entry(nvidia_compiler.compiler_json(), "/example/file")
assert compiler.name == "nvhpc"
spec_json = JsonSpecEntry(
@@ -278,7 +291,7 @@ def test_translate_compiler_name():
hash="hwlocfakehashaaa",
prefix="/path/to/hwloc-install/",
version="2.0.3",
arch=_common_arch,
arch=_common_arch.spec_json(),
compiler=nvidia_compiler.spec_json(),
dependencies={},
parameters={},
@@ -288,18 +301,18 @@ def test_translate_compiler_name():
assert spec.compiler.name == "nvhpc"
def test_failed_translate_compiler_name():
def test_failed_translate_compiler_name(_common_arch):
unknown_compiler = JsonCompilerEntry(name="unknown", version="1.0")
with pytest.raises(spack.compilers.UnknownCompilerError):
compiler_from_entry(unknown_compiler.compiler_json())
compiler_from_entry(unknown_compiler.compiler_json(), "/example/file")
spec_json = JsonSpecEntry(
name="packagey",
hash="hash-of-y",
prefix="/path/to/packagey-install/",
version="1.0",
arch=_common_arch,
arch=_common_arch.spec_json(),
compiler=unknown_compiler.spec_json(),
dependencies={},
parameters={},
@@ -309,7 +322,8 @@ def test_failed_translate_compiler_name():
entries_to_specs([spec_json])
def create_manifest_content():
@pytest.fixture
def manifest_content(generate_openmpi_entries, _common_compiler, _other_compiler):
return {
# Note: the cray_manifest module doesn't use the _meta section right
# now, but it is anticipated to be useful
@@ -319,43 +333,70 @@ def create_manifest_content():
"schema-version": "1.3",
"cpe-version": "22.06",
},
"specs": list(x.to_dict() for x in generate_openmpi_entries()),
"compilers": [_common_compiler.compiler_json()],
"specs": generate_openmpi_entries,
"compilers": [_common_compiler.compiler_json(), _other_compiler.compiler_json()],
}
@pytest.mark.only_original(
"The ASP-based concretizer is currently picky about OS matching and will fail."
)
def test_read_cray_manifest(tmpdir, mutable_config, mock_packages, mutable_database):
def test_read_cray_manifest(
tmpdir, mutable_config, mock_packages, mutable_database, manifest_content
):
"""Check that (a) we can read the cray manifest and add it to the Spack
Database and (b) we can concretize specs based on that.
"""
with tmpdir.as_cwd():
test_db_fname = "external-db.json"
with open(test_db_fname, "w") as db_file:
json.dump(create_manifest_content(), db_file)
json.dump(manifest_content, db_file)
cray_manifest.read(test_db_fname, True)
query_specs = spack.store.STORE.db.query("openmpi")
assert any(x.dag_hash() == "openmpifakehasha" for x in query_specs)
concretized_specs = spack.cmd.parse_specs(
"depends-on-openmpi %gcc@4.5.0 arch=test-redhat6-x86_64" " ^/openmpifakehasha".split(),
concretize=True,
"depends-on-openmpi ^/openmpifakehasha".split(), concretize=True
)
assert concretized_specs[0]["hwloc"].dag_hash() == "hwlocfakehashaaa"
@pytest.mark.only_original(
"The ASP-based concretizer is currently picky about OS matching and will fail."
)
def test_read_cray_manifest_add_compiler_failure(
tmpdir, mutable_config, mock_packages, mutable_database, manifest_content, monkeypatch
):
"""Check that cray manifest can be read even if some compilers cannot
be added.
"""
orig_add_compilers_to_config = spack.compilers.add_compilers_to_config
class fail_for_clang:
def __init__(self):
self.called_with_clang = False
def __call__(self, compilers, **kwargs):
if any(x.name == "clang" for x in compilers):
self.called_with_clang = True
raise Exception()
return orig_add_compilers_to_config(compilers, **kwargs)
checker = fail_for_clang()
monkeypatch.setattr(spack.compilers, "add_compilers_to_config", checker)
with tmpdir.as_cwd():
test_db_fname = "external-db.json"
with open(test_db_fname, "w") as db_file:
json.dump(manifest_content, db_file)
cray_manifest.read(test_db_fname, True)
query_specs = spack.store.STORE.db.query("openmpi")
assert any(x.dag_hash() == "openmpifakehasha" for x in query_specs)
assert checker.called_with_clang
def test_read_cray_manifest_twice_no_compiler_duplicates(
tmpdir, mutable_config, mock_packages, mutable_database
tmpdir, mutable_config, mock_packages, mutable_database, manifest_content
):
with tmpdir.as_cwd():
test_db_fname = "external-db.json"
with open(test_db_fname, "w") as db_file:
json.dump(create_manifest_content(), db_file)
json.dump(manifest_content, db_file)
# Read the manifest twice
cray_manifest.read(test_db_fname, True)
@@ -363,7 +404,7 @@ def test_read_cray_manifest_twice_no_compiler_duplicates(
compilers = spack.compilers.all_compilers()
filtered = list(
c for c in compilers if c.spec == spack.spec.CompilerSpec("gcc@=10.2.0.cray")
c for c in compilers if c.spec == spack.spec.CompilerSpec("gcc@=10.2.0.2112")
)
assert len(filtered) == 1
@@ -423,3 +464,27 @@ def test_convert_validation_error(tmpdir, mutable_config, mock_packages, mutable
with pytest.raises(cray_manifest.ManifestValidationError) as e:
cray_manifest.read(invalid_schema_path, True)
str(e)
@pytest.fixture
def directory_with_manifest(tmpdir, manifest_content):
"""Create a manifest file in a directory. Used by 'spack external'."""
with tmpdir.as_cwd():
test_db_fname = "external-db.json"
with open(test_db_fname, "w") as db_file:
json.dump(manifest_content, db_file)
yield str(tmpdir)
def test_find_external_nonempty_default_manifest_dir(
mutable_database, mutable_mock_repo, tmpdir, monkeypatch, directory_with_manifest
):
"""The user runs 'spack external find'; the default manifest directory
contains a manifest file. Ensure that the specs are read.
"""
monkeypatch.setenv("PATH", "")
monkeypatch.setattr(spack.cray_manifest, "default_path", str(directory_with_manifest))
spack.cmd.external._collect_and_consume_cray_manifest_files(ignore_default_dir=False)
specs = spack.store.STORE.db.query("hwloc")
assert any(x.dag_hash() == "hwlocfakehashaaa" for x in specs)

View File

@@ -1,5 +1,5 @@
bootstrap:
sources:
- name: 'github-actions'
metadata: $spack/share/spack/bootstrap/github-actions-v0.3
metadata: $spack/share/spack/bootstrap/github-actions-v0.5
trusted: {}

Some files were not shown because too many files have changed in this diff Show More