Compare commits

...

516 Commits

Author SHA1 Message Date
Todd Gamblin
3985b307a1 concretizer: add --minimal configuration option
The reusing concretizer minimizes builds, but it still preserves
defaults from packages and preferences while doing that. We can be
more aggressive by making minimization the top priority, at the
expense of "weird" concretizations.

This can be advantageous: if you write your packages as explicitly
as possible, then you can use that with `--minimal` to get the
smallest possible package configuration (at least in terms of the
number of packages in the build).  Conversely, you can use minimal
concretization as kind of a worst case to ensure that you have the
"right" constraints on your dependencies.

Example for intuition: `cmake` can optionally build without openssl, but
it's enabled by default because many builds use that functionality. Using
`minimal: true` will build `cmake~openssl` unless the user asks for
`cmake+openssl` explicitly.

- [x] add `minimal` option to `concretizer.yaml`
- [x] add `--minimal` CLI option to concretizer arguments
- [x] wire everything up
- [x] add some tests
2022-05-24 14:52:17 -04:00
Seth R. Johnson
6a57aede57 environments: fail gracefully on missing keys (#26378) 2022-05-24 08:52:40 -07:00
edwardsp
ba701a7cf8 Update regex to correctly identify quoted args (#23494)
Previously the regex was only checking for presence of quotes as a beginning
or end character and not a matching set.  This erroneously identified the
following *single* argument as being quoted:

    source bashenvfile &> /dev/null && python3 -c "import os, json; print(json.dumps(dict(os.environ)))"
2022-05-24 08:26:07 -07:00
Matthias Wolf
557845cccc apptainer: new package (#30745) 2022-05-24 16:01:46 +02:00
iarspider
c5297523af vdt: add preload variant (#30030) 2022-05-24 12:19:09 +02:00
Evan Bollig
6883868896 libfabric has needed rdma-core for efa since 1.10.0 (#30798) 2022-05-24 04:17:47 -06:00
Satish Balay
1c5587f72d petsc: update rocrand location wrt rocm@5.1.0 (#30790)
rocm-5.1.0 removed librocrand.so from ROCM_DIR/rocrand/lib location (but  includes are still at this location)

/opt/rocm-5.0.2/lib/librocrand.so
/opt/rocm-5.0.2/rocrand/lib/librocrand.so
/opt/rocm-5.1.0/lib/librocrand.so

drwxr-xr-x 2 root root 617 Mar  8 08:20 /opt/rocm-5.0.2/rocrand/include
drwxr-xr-x 2 root root 617 Mar 31 09:48 /opt/rocm-5.1.0/rocrand/include
2022-05-24 11:54:29 +02:00
Mr-Timn
6e7eb49888 su2: add v7.3.1 (#30794) 2022-05-24 10:50:16 +02:00
Paul Wolfenbarger
3df4a32c4f trilinos: add adelus, aprepro and teuchos variants (#28935) 2022-05-24 09:49:33 +01:00
Adam J. Stewart
95b03e7bc9 gplates: add v2.3.0 (#30676) 2022-05-24 08:02:39 +02:00
Greg Becker
817ee81eaa compiler flags: imposed hashes impose the lack of additional compiler flags (#30797) 2022-05-24 01:22:29 -04:00
Tom Scogland
330832c22c strip -Werror: all specific or none (#30284)
Add a config option to strip `-Werror*` or `-Werror=*` from compile lines everywhere.

```yaml
config:
    keep_werror: false
```

By default, we strip all `-Werror` arguments out of compile lines, to avoid unwanted
failures when upgrading compilers.  You can re-enable `-Werror` in your builds if
you really want to, with either:

```yaml
config:
    keep_werror: all
```

or to keep *just* specific `-Werror=XXX` args:

```yaml
config:
    keep_werror: specific
```

This should make swapping in newer versions of compilers much smoother when
maintainers have decided to enable `-Werror` by default.
2022-05-24 00:57:09 -04:00
Todd Gamblin
306bed48d7 specs: emit better parsing errors for specs. (#24860)
Parse error information is kept for specs, but it doesn't seem like we propagate it
to the user when we encounter an error.  This fixes that.

e.g., for this error in a package:

```python
    depends_on("python@:3.8", when="0.900:")
```

Before, with no context and no clue that it's even from a particular spec:

```
==> Error: Unexpected token: ':'
```

With this PR:

```
==> Error: Unexpected token: ':'
  Encountered when parsing spec:
    0.900:
         ^
```
2022-05-24 03:33:43 +00:00
Scott Wittenburg
63402c512b Revert "Added cloud_pipline for E4S on Amazon Linux (#29522)" (#30796)
This reverts commit 07e9c0695a.
2022-05-23 21:12:48 -06:00
Brian Van Essen
736fddc079 Bugfix hwloc find cuda (#30788)
* Added autotools configure flags to ensure that hwloc finds the correct
version of CUDA that it was concretized against, rather than the first
one that package config finds.

* Added support for finding the correct version of ROCm libraries.  Fixed Flake8.

* Fixed guard on finding ROCm library
2022-05-23 20:17:46 -06:00
Jen Herting
036048c26f [py-h2] added version 3.2.0 and 4.1.0 (#29804)
* [py-h2] py-wheel is implied by PythonPackage

* [py-h2] python dependencies should be type=('build', 'run')

* [py-h2] fixed dependencies for py-h2@4.0.0

* [py-h2] added version 3.2.0

* [py-h2] added version 4.1.0

* [py-h2] Older version requires py-enum34 for older versions of python
2022-05-23 17:56:45 -07:00
Greg Becker
8616ba04db Documentation and new method for CachedCMakePackage build system (#22706)
Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja>
2022-05-23 22:48:12 +00:00
Evan Bollig
07e9c0695a Added cloud_pipline for E4S on Amazon Linux (#29522)
Add two new cloud pipelines for E4S on Amazon Linux, include arm and x86 (v3 + v4) stacks.

Notes:
- Updated mpark-variant to remove conflict that no longer exists in Amazon Linux
- Which command on Amazon Linux prefixes on all results when padded_length is too high. In this case, padded_length<=503 works as expected. Chose conservative length of 384.
2022-05-23 15:33:38 -06:00
snehring
f24886acb5 usearch: adding in new version, updating checksums (#30776) 2022-05-23 13:50:50 -07:00
snehring
5031578c39 genemark-et: updating to 4.69 (#30793) 2022-05-23 13:36:26 -07:00
Massimiliano Culpo
7c4cc1c71c archspec: add oneapi and dpcpp flag support (#30783) 2022-05-23 13:28:54 -07:00
Harmen Stoppels
f7258e246f Deprecate spack:concretization over concretizer:unify (#30038)
* Introduce concretizer:unify option to replace spack:concretization

* Deprecate concretization

* Make spack:concretization overrule concretize:unify for now

* Add environment update logic to move from spack:concretization to spack:concretizer:reuse

* Migrate spack:concretization to spack:concretize:unify in all locations

* For new environments make concretizer:unify explicit, so that defaults can be changed in 0.19
2022-05-23 13:20:34 -07:00
Maciej Wójcik
ff980a1452 plumed: add versions up to v2.8.0 (#30787) 2022-05-23 20:07:47 +00:00
Chuck Atkins
51130abf86 ci: Map visit to huge instance for the data-vis-sdk pipeline (#30779) 2022-05-23 14:16:24 -04:00
marcus-elia
383356452b abseil-cpp: add v20211102 (#30785) 2022-05-23 18:52:39 +02:00
Cody Balos
5fc1547886 xsdk-examples: add v0.3.0 (#30770)
Co-authored-by: Satish Balay <balay@mcs.anl.gov>
Co-authored-by: Veselin Dobrev <dobrev@llnl.gov>
2022-05-23 18:45:11 +02:00
Manuela Kuhn
68cd6c72c7 py-rnc2rng: fix 2.6.5 and add 2.6.6 (#30784) 2022-05-23 08:02:13 -07:00
Jean Luca Bez
3d2ff57e7b hdf5-vol-async: update new version, tests, and runtime envs (#30713)
* Update h5bench maintainers and versions

* Include version 1.1 for h5bench

* Correct release hash and set default version

* Update .tar.gz version

* Include new version and update runtime

* Update year

* Update package.py

* Update package.py
2022-05-23 09:28:26 -04:00
Massimiliano Culpo
3bc656808c llvm: make "omp_as_runtime" variant conditional (#30782)
fixes #30700

To avoid clingo adding penalties for not using the
default value for a variant, it's better to model
the variant as conditional where possible.
2022-05-23 14:21:11 +02:00
Ben Bergen
7ded692a76 gdb: add v11.2 (#30780)
- This resolves bug https://sourceware.org/PR28302
2022-05-23 12:18:26 +02:00
MichaelLaufer
aa3c7a138a py-pyfr: Add v1.14.0, add LIBXSMM variant (#30612)
* Update PyFR, Gimmik versions. Add PyFR LIBXSMM variant

* Fixes

* Changes to variants

* Update py-gimmik version requirement in py-pyfr

* Revert "Update py-gimmik version requirement in py-pyfr"

This reverts commit 3b3fde3042.

* Update libxsmm conflicts
2022-05-22 12:01:21 -06:00
Paul Kuberry
42441cddcc Add Teuchos patch that fixes implicit casting of complex numbers (#30777) 2022-05-22 09:26:33 -04:00
Abhik Sarkar
b78025345b Feature/composed boost pkg deps p3 (#28961)
* This commit removes the Boost.with_default_variants to variants that packages are precisely dependant upon. This is the third batch of 16 packages with modified boost dependencies.

* style fix

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

Co-authored-by: Tim Haines <thaines.astro@gmail.com>

* fix style

* Apply suggestions from code review

Co-authored-by: Tim Haines <thaines.astro@gmail.com>

* Fix Trilinos boost deps

* Fix style

Co-authored-by: Tim Haines <thaines.astro@gmail.com>
Co-authored-by: Tom Scogland <tom.scogland@gmail.com>
2022-05-21 15:57:59 -07:00
Harmen Stoppels
2113b625d1 gcc: add build_type and profiled variants (#30660)
Add a `build_type` variant, which allows building optimized compilers,
as well as target libraries (libstdc++ and friends).

The default is `build_type=RelWithDebInfo`, which corresponds to GCC's
default of -O2 -g.

When building with `+bootstrap %gcc`, also add Spack's arch specific
flags using the common denominator between host and new GCC.

It is done by creating a config/spack.mk file in def patch, that looks
as follows:
```
BOOT_CFLAGS := $(filter-out -O% -g%, $(BOOT_CFLAGS)) -O2 -g -march=znver2 -mtune=znver2
CFLAGS_FOR_TARGET := $(filter-out -O% -g%, $(CFLAGS_FOR_TARGET)) -O2 -g -march=znver2 -mtune=znver2
CXXFLAGS_FOR_TARGET := $(filter-out -O% -g%, $(CXXFLAGS_FOR_TARGET)) -O2 -g -march=znver2 -mtune=znver2
```
2022-05-21 23:44:51 +02:00
Jen Herting
c6c3d243e1 New package: py-motor (#30763)
* New package: py-motor

* Fixed dependency errors

* Fixed flake style errors

* Fixed linked issue

Co-authored-by: Viv Eric Hafener <vehrc@sporcbuild.rc.rit.edu>
2022-05-21 11:36:37 -05:00
Manuela Kuhn
870b997cb6 py-ww: add new package (#30767)
* py-ww: add new package

* Add missing py-pytest-runner dependency
2022-05-21 11:28:53 -05:00
snehring
c9492f1cd4 paml: add v4.10.3 (#30772) 2022-05-21 09:47:38 +02:00
dependabot[bot]
24f370491e build(deps): bump actions/upload-artifact from 3 to 3.1.0 (#30778)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 3.1.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...3cea5372237819ed00197afe530f5a7ea3e805c8)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  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>
2022-05-21 08:57:19 +02:00
Glenn Johnson
d688a699fa Fix toolchain detection for oneapi/dpcpp compilers (#30775)
The oneapi and dpcpp compilers are essentially the same except for which
binary is used foc CXX. Spack will detect them as "mixed toolchain" and
not inject compiler optimization flags. This will be needed once
archspec has entries for the oneapi and dpcpp compilers. This PR detects
when dpcpp and oneapi are in the toolchains list and explicitly sets
`is_mixed_toolchain` to `False`.
2022-05-21 08:38:01 +02:00
Chuck Atkins
4fbb822072 visit: Overhaul to build in the DAV SDK (#30594)
* mesa-glu and mesa-demos: Fix conflicts with glu and osmesa

* visit: Update visit dependencies

* ecp-data-vis-sdk: Enable +visit

* ci[data-vis-sdk]: Enable +visit
2022-05-20 19:17:30 -04:00
Sreenivasa Murthy Kolam
f86c481280 update checksum and url for mlirmiopen recipe (#30771) 2022-05-20 21:29:58 +00:00
Jen Herting
91a99882b3 [py-openslide-python] added verion 1.1.2 (#30722)
* [py-openslide-python] added verion 1.1.2 and set max py-setuptools version for 1.1.1

* [py-openslide-python]

- setuptools required for all possible newer versions
- python is type build run

* [py-openslide-python] use pil provider
2022-05-20 19:25:20 +00:00
Manuela Kuhn
74bef2105a py-formatizer: add new package (#30755) 2022-05-20 10:37:55 -07:00
Manuela Kuhn
630ebb9d8b py-pybids: add 0.8.0 and 0.15.1 (#30756) 2022-05-20 10:37:01 -07:00
iarspider
183465321e DWZ: use virtual "elf" package (#30761) 2022-05-20 10:29:11 -07:00
Nate deVelder
580f9ec86e Add newer openfast versions and preliminary OpenMP compile support (#30752)
* Add version 3.0 and 3.1 and prelim OpenMP support

* Fix flag handler missing spec variable

* Use self.compiler.openmp_flag instead of -fopenmp

* Fix whitespace
2022-05-20 10:27:47 -07:00
Jordan Galby
0b0920bc90 qt: Qt 5.15.0 requires OpenSSL 1.1.1 (#30754)
Fixes qt configure errors with external openssl on older systems (rhel7)

See
efc02f9cc3/dist/changes-5.15.0 (L346)

This means for now on, `qt ^openssl@1.0` gets you `qt@5.15.4 ~ssl`:
clingo chooses latest qt version **but disables ssl support**.
2022-05-20 18:24:30 +02:00
Greg Becker
ee04a1ab0b errors: model error messages as an optimization problem (#30669)
Error messages for the clingo concretizer have proven challenging. The current messages are incredibly vague and often don't help users at all. Unsat cores in clingo are not guaranteed to be minimal, and lead to cores that are either not useful or need to be post-processed for hours to reach a minimal core.

Following up on an idea from a slack conversation with kwryankrattiger on slack, this PR takes a new approach. We eliminate most integrity constraints and minima/maxima on choice rules in clingo, and instead force invalid states to imply an error predicate. The error predicate can include context on the cause of the error (Package, Version, etc). These error predicates are then heavily optimized against, to ensure that we do not include error facts in the solution when a solution with no error facts could be generated. When post-processing the clingo solution to construct specs, any error facts cause the program to raise an exception. This leads to much more legible error messages. Each error predicate includes a priority and an error message. The error message is formatted by the remaining arguments to produce the error message. The priority is used to ensure that when clingo has a choice of which rules to violate, it chooses the one which will be most informative to the user.

Performance:

"fresh" concretizations appear to suffer a ~20% performance penalty under this branch, while "reuse" concretizations see a speedup of around 33%. 

Possible optimizations if users still see unhelpful messages:

There are currently 3 levels of priority of the error messages. Additional priorities are possible, and can allow us finer granularity to ensure more informative error messages are provided in lieu of less informative ones.

Future work:

Improve tests to ensure that every possible rule implying an error message is exercised
2022-05-20 08:27:07 -07:00
Peter Scheibel
55f4950ed4 Petsc: fix enable-x for virtuals (#30749)
* If direct dependencies provide virtuals, add those virtual names as well
* Also refer to package by virtual name for jpeg
2022-05-20 03:15:44 +00:00
Manuela Kuhn
23960ed623 py-fracridge: add new package (#30739) 2022-05-19 17:28:39 -07:00
iarspider
fb2730d87f Update py-onnx-runtime to 1.10; update CMS patch (#30725)
* Update py-onnx-runtime to 1.10; update CMS patch

* Update package.py
2022-05-19 17:24:18 -07:00
Wileam Y. Phan
30f2394782 Run scheduled CI workflows only in the main repo (#30729)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-05-19 21:35:52 +02:00
Jordan Galby
262c3f07bf Non-existent upstream is not fatal (#30746)
A non-existent upstream should not be fatal: it could only mean it is
not deployed yet. In the meantime, it should not block the user to
rebuild anything it needs.

A warning is still emitted, to let the user decide if this is ok or not.
2022-05-19 18:27:43 +00:00
Harmen Stoppels
b018eb041f python: more +optimizations (#30742) 2022-05-19 12:25:36 -06:00
Matthew Archer
3f4398dd67 fenicsx: update to v0.4 (#30661)
* Fix for xtensor-xsimd

* Add sha256 for all new releases

* renamed ufcx package

* Update sha for ffcx

* fixed hashes and modified fenics-dolfinx to depend on ufcx

* cleaned and fixed dependency types

* use spec.satisfies in cmake_args

* bumped to ufcx@0.4.1

* address PR comments

* fix hashes

* update parmetis in cmake_args to reflect default setting

* update versions

* renamed ufcx package

* fixed hashes and modified fenics-dolfinx to depend on ufcx

* cleaned and fixed dependency types

* use spec.satisfies in cmake_args

* bumped to ufcx@0.4.1

* address PR comments

* fix hashes

* update parmetis in cmake_args to reflect default setting

* update versions

* Add dependency fix

* bump basix to 0.4.2 and address PR comments

* Versioning fixes

* Use xtensor-0.24: and loosen pybind11

* Add conflicts for partitioners

* Updates on partitioners

* use define_from_variant

* Tidy up some dependencies

* Work on multi-variants for graph partitioners

* Fix KaHIP issue.

KaHIP changed the name of its library from 'interface' to 'kahip'. Pin earlier versions of DOLFINx to earlier verisons of KaHIP for proper detection.

Co-authored-by: Chris Richardson <chris@bpi.cam.ac.uk>
Co-authored-by: Garth N. Wells <gnw20@cam.ac.uk>
2022-05-19 18:22:09 +00:00
kwryankrattiger
a225a5b276 Ascent: Add variant to disable blt_find_mpi (#30735)
This is needed to find MPI correctly on cray systems and similar.
2022-05-19 10:06:31 -07:00
iarspider
c9cfc548da Update millepede recipe (#30737) 2022-05-19 10:03:31 -07:00
Rémi Lacroix
3b30886a3a libtheora: fix the hash of a patch. (#30740)
Cosmetic changes only, probably because gitlab.xiph.org got updated.
2022-05-19 09:59:12 -07:00
Jordan Galby
c2fd98ccd2 Fix spack install chgrp on symlinks (#30743)
Fixes missing chgrp on symlinks in package installations, and errors on
symlinks referencing non-existent or non-writable locations.

Note: `os.chown(.., follow_symlinks=False)` is python3 only, but
`os.lchown` exists in both versions.
2022-05-19 08:50:24 -07:00
Valentin Volkl
a0fe6ab2ed cuda: use stage dir instead of /tmp during install (#29584) 2022-05-19 17:18:18 +02:00
Harmen Stoppels
c3be777ea8 tar: add compress deps (#30641)
* remove spack dependency from package

* tar: fix compression programs, use pigz by default instead of gzip on -z
2022-05-19 11:15:13 -04:00
Jordan Galby
8fe39be3df Don't try to mkdir upstream directory when nonexistent (#30744)
When an upstream is specified but the directory does not exist, don't
create the directory for it, it might not be yours.
2022-05-19 14:45:18 +00:00
Tiziano Müller
f5250da611 cp2k: fix unbound var use without cuda (#30736)
fixes #30631
2022-05-19 11:38:00 +02:00
David Beckingsale
c2af154cd2 RAJA and associated packages: add v2022.03.0 (#30047)
* Add raja@2022.03.0
* Add camp@2022.03.0
* Add chai@2022.03.0
* Add umpire@2022.03.1
* Latest chai, raja, umpire versions don't need submodules
* Latest chai, raja, umpire versions update CMake option names
* New umpire +device_alloc option (for latest version)
* All versions of dray are now required to build with raja@:0.14

Co-authored-by: Marty McFadden <mcfadden8@users.noreply.github.com>
2022-05-18 22:48:22 -07:00
robgics
1f6b880fff Add license dir to config (#30135)
* Change license dir from hard-coded to a configurable item

* Change config item to be a string not an array

Co-authored-by: Todd Gamblin <tgamblin@llnl.gov>
2022-05-18 18:26:42 -07:00
Teodor Nikolov
2c211d95ee Catch2: update to 3.0.1 (#30732)
Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
2022-05-19 00:47:20 +00:00
Asher Mancinelli
c46f673c16 ExaSGD bugfixes (#30731)
* Small bug fixes for ExaSGD packages

* Add Slaven as maint for both exago and hiop
2022-05-18 15:25:24 -07:00
Todd Gamblin
8ff2b4b747 bugfix: handle new dag_hash() on old concrete specs gracefully. (#30678)
Trying to compute `dag_hash()` or `package_hash()` on a concrete spec that doesn't have
a `_package_hash` attribute would attempt to recompute the package hash.

This most commonly manifests as a failed lookup of a namespace if you attempt to uninstall
or compute the hashes of packages in exsternal repositories that aren't registered, e.g.:

```console
> spack spec --json c/htno
==> Error: Unknown namespace: myrepo
```

While it wouldn't change the already-assigned `dag_hash` value, this behavior is
incorrect, since the package file for a previously concrete spec:
  1. might have changed since concretization,
  2. might not exist anymore, or
  3. might just not be findable by Spack.

This PR ensures that the package hash can't be computed on older concrete specs. Instead
of calling `package_hash()` from within `to_node_dict()`, we now check for the `_package_hash`
attribute and only add the package_hash to the spec record if it's there.

This PR also handles the tricky semantics of computing `package_hash()` at concretization
time. We have to compute it *before* marking the spec concrete so that `to_node_dict` can
use it. But this means that the logic for `package_hash()` can't rely on `spec.concrete`,
as it is called *during* concretization. Instead of checking for concreteness, `package_hash()`
now checks `_patches_assigned()` to determine whether it should add them to the package
hash.

- [x] Add an assert to `package_hash()` so it can't be called on specs for which it
      would be wrong.
- [x] Add an `_assign_hash()` method to handle tricky semantics of `package_hash`
      and `dag_hash`.
- [x] Rework concretization to call `_assign_hash()` before and after marking specs
      concrete.
- [x] Rework content hash part of package hash to check for `_patches_assigned()`
      instead of `spec.concrete`.
- [x] regression test
2022-05-18 22:21:22 +00:00
Michael Kuhn
9e05dde28c harfbuzz: add gobject-introspection dependency (#30715)
Fixes #30706
2022-05-18 15:13:36 -06:00
Jen Herting
b1ef5a75f0 [py-tensorflow-hub] applied patch for newer version of zlib (#30664)
* [py-tensorflow-hub] applied patch for newer version of zlib

* [py-tensorflow-hub] patch also applies to 0.11.0

* [py-tensorflow-hub] Audit fix

1. patch URL in package py-tensorflow-hub must end with ?full_index=1
2022-05-18 13:21:21 -07:00
Timothy Brown
f9aa7c611c [WGRIB2] Pinning Jasper to v2. (#30726)
If we use v3 of Jasper, WGRIB2 fails to build due to not
finding `jpc_encode` and `jpc_decode`.
2022-05-18 09:34:22 -07:00
Timothy Brown
9a2e01e22d [G2] Pinning Jasper to version 2. (#30728) 2022-05-18 09:33:05 -07:00
Alberto Invernizzi
2090351d7f Add hip dependency for roc-obj-ls + add perl-uri-encode (#30721)
* add perl-uri-encode package

* add dependencies in hip for roc-obj-ls
2022-05-18 16:24:35 +02:00
Massimiliano Culpo
c775c322ec vendored externals: update archspec (#30683)
- Better support for 164fx
- Better support for Apple M1(pro)
2022-05-18 11:31:20 +02:00
Harmen Stoppels
1185eb9199 Compiler wrapper: fix globbing and debug out.log bell chars (#30699)
* Disable globbing

* Split on bell char when dumping cmd to out.log
2022-05-18 09:06:54 +02:00
Ryan Marcellino
51fa8e7b5e py-pytecplot: new package (#30708)
* py-pytecplot: new package

* fix copyright year

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

* use one variant for all extras

Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
2022-05-18 01:47:17 +00:00
Mikael Simberg
f505c50770 Add tracy (#30588)
Co-authored-by: Mikael Simberg <mikael.simberg@iki.if>
2022-05-17 18:10:45 -07:00
Mark W. Krentel
2fdc817f03 hpctoolkit: add version 2022.05.15 (#30710) 2022-05-17 18:05:12 -07:00
Michael Kuhn
e1d0b35d5b gobject-introspection: add 1.72.0 (#30714)
Newer versions of gobject-introspection require Meson to build. Convert
the package into a hybrid one that still supports older versions using
Autotools.
2022-05-17 17:59:54 -07:00
Sreenivasa Murthy Kolam
ace5a7c4bf deprecate rocm releases-ROCm-4.2.0,ROCm-4.3.0,ROCm-4.3.1 (#30709) 2022-05-17 14:11:32 -07:00
kwryankrattiger
a91ae8cafe ecp-data-vis-sdk: Drop fortran from ascent spec. (#30707) 2022-05-17 16:53:52 -04:00
Chuck Atkins
b9e3ee6dd0 glew: Fix glu and glx dependencies (#30705) 2022-05-17 10:19:19 -07:00
iarspider
10ea0a2a3e Update rivet to 3.1.6, yoda to 1.9.5; fix recipes (#30702)
* Update rivet to 3.1.6, yoda to 1.9.5; fix recipes

* Use filter_compiler_wrappers instead of custom post-install step
2022-05-17 10:17:24 -07:00
Harmen Stoppels
d6f8ffc6bc add julia 1.6.6 (#30703) 2022-05-17 09:52:46 -07:00
haralmha
02be2f27d1 flatbuffers: Add version 2.0.6 (#30704) 2022-05-17 09:51:02 -07:00
Adam J. Stewart
dfd0702aec GDAL: deprecate 2.X (#30668) 2022-05-17 08:45:55 -07:00
Massimiliano Culpo
f454a683b5 Mark test_repo_last_mtime xfail on Python < 3.5 (#30696) 2022-05-17 12:45:52 +02:00
Chuck Atkins
d7d0c892d8 silo: Make HDF5 version deps more robust (#30693) 2022-05-17 04:26:35 -04:00
snehring
d566330a33 pindel: fixing compilation issues for gcc5+ (#28387) 2022-05-17 09:45:08 +02:00
Alex Hedges
446cbf4b5a sed: add v4.8.0, set gnu_mirror_path per version (#30666) 2022-05-17 09:43:01 +02:00
Tim Haines
5153c9e98c boost: constrain context-impl variant (#30654) 2022-05-17 09:42:19 +02:00
h-murai
d74f2d0be5 petsc: fix an error about handling a provider of Scalapack. (#30682) 2022-05-17 09:33:49 +02:00
Jianshen Liu
021b65d76f cppcheck: add v2.7 (#30698) 2022-05-17 07:29:46 +00:00
Adam J. Stewart
45312d49be Bazel: remove maintainer (#30697) 2022-05-17 09:29:22 +02:00
Chuck Atkins
3fcd85efe9 autoconf-archive: Patch for nvhpc support and propagate search dirs (#30692) 2022-05-17 03:29:42 +00:00
Alberto Madonna
6f3a082c3e runc: symlink sbin to bin to find it in $PATH (#30691) 2022-05-17 02:48:04 +02:00
stepanvanecek
23e2820547 sys-sage: new spack package (#30570)
* sys-sage - adding new package

* sys-sage: updated release verison

* sys-sage: remove FIXMEs from the package

* add libllvm dependency

* sys-sage: remove unnecessary libllvm dependency

Co-authored-by: Stepan Vanecek <stepan.vanecek@tum.de>
2022-05-16 17:01:34 -07:00
Sreenivasa Murthy Kolam
22b999fcd4 Add miopentensile-new recipe for ROCm-5.0.0 . ROCm-5.1.0 release (#29313)
* miopentensile-new recipe for rocm-5.0.0 release

* fix style checks

* update the version for 5.1.0 release, avoid git download
2022-05-16 16:19:35 -07:00
Michael Kuhn
1df7de62ca py-cffconvert: new package (#30694) 2022-05-16 23:16:32 +00:00
andymwood
97ec8f1d19 Avoid calling a method on a NoneType object (#30637) 2022-05-16 21:59:08 +00:00
iarspider
63b6e484fc sigcpp: protect from missing prefix.share folder (#30686) 2022-05-16 13:34:57 -07:00
Nick Forrington
2b12d19314 arm-forge: Versions up to 22.0.1 + minor updates (#30689)
* arm-forge: Download via HTTPS

Update download URL to use HTTPS (rather than HTTP)

* arm-forge: Allow +probe to depend on python3

Allow python dependency required for arm-forge+probe to be python3 as
well as 2.7.x

* arm-forge: Add versions up to 22.0.1
2022-05-16 14:30:19 -06:00
Francesco Giordano
c37fcccd7c aws-parallelcluster: add v2.11.7 (#30685) 2022-05-16 14:29:53 -06:00
Michael Kuhn
6034b5afc2 fix pkgconfig dependencies (#30688)
pkgconfig is the correct dependency, pkg-config is a provider of it.
2022-05-16 14:01:41 -06:00
Michael Kuhn
17bc937083 libfuse: add utils variant (#30675)
By default, libfuse install helper programs like `fusermount3`, which
are mostly useless if not installed with setuid (that is, `+useroot`).

However, their presence makes it complicated to use globally installed
versions, which can be combined with a Spack-installed FUSE library.

In particular, on systems that have a setuid fusermount3 binary, but no
libfuse-dev installed, it is nice to be able to build libfuse with Spack, and
have it call the system setuid executable.
2022-05-16 13:01:44 -06:00
renjithravindrankannath
ad8db0680d Correcting include and library paths using patch file for RVS (#30294)
* Correcting include and library paths using patch file for RVS to build
following library files in spack.
libperf.so.0.0
libpebb.so.0.0
libiet.so.0.0
libgst.so.0.0
libpqt.so.0.0
libmem.so.0.0
libbabel.so.0.0

* Correcting include and library paths using patch file for RVS to build
following library files in spack.
libperf.so.0.0
libpebb.so.0.0
libiet.so.0.0
libgst.so.0.0
libpqt.so.0.0
libmem.so.0.0
libbabel.so.0.0

* Replacing ROCM_PATH with RPATH in the deviceid.sh before installing in Spack build.

* Reducing multiple enviroment variable for HIP and HSA path
2022-05-16 09:44:59 -07:00
estewart08
4f033b155b [AMD][rocm-openmp-extras] - Update versions 5.0.0 through 5.1.0. (#30501)
- Removed gl dependency.
- Specify clang as cmake compiler as gcc was being
  improperly picked up. As a result, ffi include
  path was needed in C/CXX flags.

Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
2022-05-16 09:22:48 -07:00
Sreenivasa Murthy Kolam
ad829ccee1 Apply cyclades removal patch for the llvm-amdgpu package (#29376)
* apply cyclades removal patch for the llvm-amdgpu spack package

* update the changes with develop branch
2022-05-16 09:15:26 -07:00
Tom Vander Aa
4b60a17174 Extrae: add support for Intel OneAPI (#30684) 2022-05-16 09:02:00 -06:00
Ethan Stam
edb91f4077 ParaView: -no-ipo for intel builds (#18193) 2022-05-16 08:01:34 -06:00
Todd Gamblin
0fdc3bf420 bugfix: use deterministic edge order for spack graph (#30681)
Previously we sorted by hash values for `spack graph`, but changing hashes can make the
test brittle and the node order seem nondeterministic to users.

- [x] Sort nodes in `spack graph` by the default edge order, which takes into account
      parent and child names as well as dependency types.
- [x] Update ASCII test output for new order.
2022-05-16 11:36:41 +02:00
Francine Lapid
8b34cabb16 subversion: added apxs support (#30381) 2022-05-16 10:42:15 +02:00
haralmha
77fb651e01 frontier-client: adapt pacparser_setmyip function to new pacparser release (#29936) 2022-05-16 10:41:21 +02:00
Harmen Stoppels
35ed7973e2 eccodes, fix jasper again (#30635)
* eccodes: jasper@:2

* Revert "jasper: avoid --gc-sections / hidden symbols"

This reverts commit d1bc0f39c516a7dc1e941aa4a804b7468a200b75.

* bump ecbuild, drop cmake constraint for newer versions

* add ecbuild dep to eccodes@develop
2022-05-16 10:40:35 +02:00
snehring
e73b19024f bpp-suite and deps: urls to GitHub (#30665)
* bpp-core: moving url to github. Fixing compilation issue.

* bpp-phyl: moving url to github.

* bpp-seq: moving url to github

* bpp-popgen: new package

* bpp-suite: moving url to github, new version.

* bpp-popgen: removing unused cmake_args.
2022-05-16 10:23:39 +02:00
Alex Hedges
7803bc9e5f screen: add v4.9.0, add required build deps (#30667) 2022-05-16 10:11:02 +02:00
dlkuehn
55c400297c treesub: change jdk dependency to java, add build to java dep. type (#30672)
Co-authored-by: David Kuehn <las_dkuehn@iastate.edu>
2022-05-16 10:06:09 +02:00
Umar Arshad
8686e18494 clblast: add new package (#30677) 2022-05-16 10:03:15 +02:00
Diego Alvarez
d28967bbf3 nextflow: add v22.04.1 (#30679) 2022-05-16 09:01:15 +02:00
Diego Alvarez
5f928f71c0 openjdk: add 11.0.15+10, 17.0.3+7 (#30680) 2022-05-16 08:58:51 +02:00
Ken Raffenetti
dc7bdf5f24 mpich: add support for Mellanox HCOLL (#30662)
Co-authored-by: Federico Ficarelli <federico.ficarelli@pm.me>
2022-05-15 14:14:47 +02:00
Danny McClanahan
a681fd7b42 Introduce GroupedExceptionHandler and use it to simplify bootstrap error handling (#30192) 2022-05-15 10:59:11 +00:00
Alberto Invernizzi
f40f1b5c7c Fix for spack stage command not extracting packages in custom paths (#30448) 2022-05-15 12:13:42 +02:00
Michael Kuhn
edd3cf0b17 qt: add 5.15.4 (#30656) 2022-05-14 23:34:06 -06:00
Michael Kuhn
ff03e2ef4c uninstall: fix dependency check (#30674)
The dependency check currently checks whether there are only build
dependencies left for a particular package. However, the database also
contains uninstalled packages, which can cause the check to fail.

For instance, with `bison` and `flex` having already been uninstalled,
`m4` will have the following dependents:
```
bison ('build', 'run')--> m4
flex ('build',)--> m4
libnl ('build',)--> m4
```
`bison` and `flex` should be ignored in this case because they are not
installed anymore.

Fixes #30673
2022-05-14 18:01:29 -07:00
Zack Galbreath
bee311edf3 Update GitLab environment variable name (#30671)
Use the IAM credentials that correspond to our new binary mirror
(s3://spack-binaries vs. s3://spack-binaries-develop)
2022-05-14 16:33:32 -06:00
Jen Herting
73b69cfeec [py-pyworld] Limiting numpy version. See: https://zenn.dev/ymd_h/articles/934a90e1468a05 (#30670) 2022-05-14 09:22:31 -05:00
Cameron Smith
4a1041dbc3 CEED v5.0 release (#29710)
* ceed50: add ceed 5.0.0 and pumi 2.2.7

* libceed-0.10

* ceed50: add omegah

* omega-h: mpi and cuda builds work

* omega-h: fix style

* New package: libfms

* New version: gslib@1.0.7

CEED: add some TODO items for the 5.0 release

* ceed: variant name consistent with package name

* LAGHOS: allow newer versions of MFEM to be used with v3.1

* LIBCEED: add missing 'install' target in 'install_targets'

* CEED: address some TODO items + some tweaks

* MFEM: add new variant for FMS (libfms)

* CEED: v5.0.0 depends on 'libfms' and 'mfem+fms'

* RATEL: add missing 'install' target in 'install_targets'

* CEED: add dependency for v5.0.0 on Ratel v0.1.2

* CEED: add Nek-related dependencies for ceed@5.0.0

* CEED: v5.0.0 depends on MAGMA v2.6.2

* libCEED: set the `CUDA_ARCH` makefile parameter

* libCEED: set the `HIP_ARCH` makefile parameter

Co-authored-by: Jed Brown <jed@jedbrown.org>
Co-authored-by: Veselin Dobrev <dobrev@llnl.gov>
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2022-05-13 18:29:02 -07:00
Jen Herting
ccab7bf4fd New package: py-pyworld (#28641)
* espnet first build with depends

* added cython>=0.24.0' and type='build'

* [py-pyworld] updated copyright

Co-authored-by: Sid Pendelberry <sid@rit.edu>
2022-05-13 17:19:58 -05:00
John W. Parent
e24e71be6a Preserve Permissions on .zip extraction (#30407)
#24556 merged in support for Python's .zip file support via ZipFile.
However as per #30200 ZipFile does not preserve file permissions of
the extracted contents. This PR returns to using the `unzip`
executable on non-Windows systems (as was the case before #24556)
and now uses `tar` on Windows to extract .zip files.
2022-05-13 13:38:05 -07:00
kwryankrattiger
72d83a6f94 Ascent: Patch 0.8.0 for finding ADIOS2. (#30609) 2022-05-13 13:26:53 -07:00
Todd Gamblin
5cb40cbcd2 directory_layout: remove outdated checks for old DAG hash
We previously had checks in `directory_layout` to check for build-dependency
conflicts when we weren't storing build dependencies.  We don't need
those anymore; we can just rely on the DAG hash now that it includes everything
we know about each spec.

- [x] Remove vestigial code for checking installed spec against concrete spec
      in `ensure_installed()`
- [x] Remove `SpecHashCollisionError` -- if specs have the same hash now, they're
      the same as far as `DirectoryLayout` should be concerned.
- [x] Convert spec comparison to `dag_hash()` comparison when adding extensions.
2022-05-13 10:45:12 -07:00
Todd Gamblin
c93e465134 full hash: fix uninstall and gc with full hash DB
The database now stores full hashes, so we need to adjust the criteria we use to
determine if something can be uninstalled. Specifically, it's ok to uninstall thing that
have remaining build-only dependents.
2022-05-13 10:45:12 -07:00
Todd Gamblin
521c206030 concretizer: enable hash reuse with full hash
With the original DAG hash, we did not store build dependencies in the database, but
with the full DAG hash, we do. Previously, we'd never tell the concretizer about build
dependencies of things used by hash, because we never had them. Now, we have to avoid
telling the concretizer about them, or they'll unnecessarily constrain build
dependencies for new concretizations.

- [x] Make database track all dependencies included in the `dag_hash`
- [x] Modify spec_clauses so that build dependency information is optional
      and off by default.
- [x] `spack diff` asks `spec_clauses` for build dependencies for completeness
- [x] Modify `concretize.lp` so that reuse optimization doesn't affect fresh
      installations.
- [x] Modify concretizer setup so that it does *not* prioritize installed versions
      over package versions. We don't need this with reuse, so they're low priority.
- [x] Fix `test_installed_deps` for full hash and new concretizer (does not work
      for old concretizer with full hash -- leave this for later if we need it)
- [x] Move `test_installed_deps` mock packages to `builtin.mock` for easier debugging
      with `spack -m`.
- [x] Fix `test_reuse_installed_packages_when_package_def_changes` for full hash
2022-05-13 10:45:12 -07:00
Todd Gamblin
15eb98368d bugfix: tests trying to ignore package changes should use build_hash
- [x] update test to use `build_hash` instead of `dag_hash`, as we're testing for
      graph structure, and specifically NOT testing for package changes.
- [x] make hash descriptors callable on specs to simplify syntax for invoking them
- [x] make `Spec.spec_hash()` public
2022-05-13 10:45:12 -07:00
Todd Gamblin
7c1d566959 Remove all uses of runtime_hash; document lockfile formats and fix tests
This removes all but one usage of runtime hash. The runtime hash was being used to write
historical lockfiles for tests, but we don't need it for that; we can just save those
lockfiles.

- [x] add legacy lockfiles for v1, v2, v3
- [x] fix bugs with v1 lockfile tests (the dummy lockfile we were writing was not actually
      a v1 lockfile because it used the new spec file format).
- [x] remove all but one runtime_hash usage -- that one needs a small rework of the
      concretizer to really fix, as it's about separate concretization of build
      dependencies.
- [x] Document the history of the lockfile format in `environment/__init__.py`
2022-05-13 10:45:12 -07:00
Todd Gamblin
7ab46e26b5 content_hash(): make it work on abstract specs
Some test cases had to be modified in a kludgy way so that abstract specs made
concrete would have versions on them. We shouldn't *need* to do this, as the
only reason we care is because the content hash has to be able to get an archive
for a version.

This modifies the content hash so that it can be called on abstract specs,
including only relevant content.

This does NOT add a partial content hash to the DAG hash, as we do not really
want that -- we don't need in-memory spec hashes to need to load package files.
It just makes `Package.content_hash()` less prickly and tests easier to
understand.
2022-05-13 10:45:12 -07:00
Todd Gamblin
6db215dd89 spec: fix serialization, avoid double call to node_dict_with_hashes 2022-05-13 10:45:12 -07:00
Todd Gamblin
72b38851eb hashes: revert spack monitor hash changes to preserve original protocol
`spack monitor` expects a field called `spec_full_hash`, so we shouldn't change that.
Instead, we can pass a `dag_hash` (which is now the full hash) but not change the field
name.
2022-05-13 10:45:12 -07:00
Todd Gamblin
9d9e970367 fix full hash calls in spack graph 2022-05-13 10:45:12 -07:00
Todd Gamblin
283a4e6068 remove no longer needed full hash check 2022-05-13 10:45:12 -07:00
Todd Gamblin
d20cc7b124 spec: remove hashes_final as it's no longer needed.
`hashes_final` was used to indicate when a spec was concrete but possibly lacked
`full_hash` or `build_hash` fields. This was only necessary because older Spacks
didn't generate them, and we want to avoid recomputing them, as we likely do not
have the same package files as existed at concretization time.

Now, we don't need to do that -- there is only the DAG hash and specs are either
concrete and have a `dag_hash`, or not concrete and have no `dag_hash`. There's
no middle ground.
2022-05-13 10:45:12 -07:00
Scott Wittenburg
0dd373846f gitlab ci: switch over to new bucket for all stacks 2022-05-13 10:45:12 -07:00
Scott Wittenburg
c202953528 gitlab ci: Docstring methods or make them private 2022-05-13 10:45:12 -07:00
Scott Wittenburg
be0e3f4458 binary_distribution: Refactor index generation into smaller methods 2022-05-13 10:45:12 -07:00
Scott Wittenburg
fd3bb5177b env: Use order of roots to resolve DAG hash conflicts in legacy lockfiles 2022-05-13 10:45:12 -07:00
Scott Wittenburg
9de61c0197 env: enforce predictable ordering when reading lockfile
Without some enforcement of spec ordering, python 2 produced
different results in the affected test than did python 3.  This
change makes the arbitrary but reproducible decision to sort
the specs by their lockfile key alphabetically.
2022-05-13 10:45:12 -07:00
Scott Wittenburg
84cfb3b7fe spec: fix infinite recursion when computing package hash
Issue described in the following PR comment:

https://github.com/spack/spack/pull/28504#issuecomment-1051835568

Solution described in subsequent comment:

https://github.com/spack/spack/pull/28504#issuecomment-1053986132
2022-05-13 10:45:12 -07:00
Scott Wittenburg
cb0d12b9d5 Fix how environments are read from lockfile 2022-05-13 10:45:12 -07:00
Scott Wittenburg
f6e7c0b740 hashes: remove full_hash and build_hash from spack 2022-05-13 10:45:12 -07:00
Scott Wittenburg
512645ff2e environment: key by dag_hash instead of build_hash 2022-05-13 10:45:12 -07:00
Scott Wittenburg
32a2c22b2b tests: fix failing test_hash_change
The full hash appears twice in the spec dict now, replacing just
the value replaces it under "hash" and "full_hash".  Only replace
the one that appears after "full_hash".

I'm actually not sure what purpose this test served, so maybe it
could be removed, as it may be testing some distinction between
full and dag hash which no longer exists.
2022-05-13 10:45:12 -07:00
Todd Gamblin
e02020c80a Include all deps and package content in the dag_hash()
For a long time, Spack has used a coarser hash to identify packages
than it likely should. Packages are identified by `dag_hash()`, which
includes only link and run dependencies. Build dependencies are
stripped before hashing, and we have notincluded hashes of build
artifacts or the `package.py` files used to build.  This means the
DAG hash actually doesn't represent all the things Spack can build,
and it reduces reproducibility.

We did this because, in the early days, users were (rightly) annoyed
when a new version of CMake, autotools, or some other build dependency
would necessitate a rebuild of their entire stack. Coarsening the hash
avoided this issue and enabled a modicum of stability when only reusing
packages by hash match.

Now that we have `--reuse`, we don't need to be so careful. Users can
avoid unnecessary rebuilds much more easily, and we can add more
provenance to the spec without worrying that frequent hash changes
will cause too many rebuilds.

This commit starts the refactor with the following major change:

- [x] Make `Spec.dag_hash()` include build, run, and link
      dependencides and the package hash (it is now equivalent to
      `full_hash()`).

It also adds a couple of bugfixes for problems discovered during
the switch:

- [x] Don't add a `package_hash()` in `to_node_dict()` unless
      the spec is concrete (fixes breaks on abstract specs)

- [x] Don't add source ids to the package hash for packages without
      a known fetch strategy (may mock packages are like this)

- [x] Change how `Spec.patches` is memoized. Using
      `llnl.util.lang.memoized` on `Spec` objects causes specs to
      be stored in a `dict`, which means they need a hash.  But,
      `dag_hash()` now includes patch `sha256`'s via the package
      hash, which can lead to infinite recursion
2022-05-13 10:45:12 -07:00
Massimiliano Culpo
d900ac2003 Reuse concretization by default (#30396)
* Enable reuse by default in Spack
* Update documentation to match new default
* Configure pipelines not to reuse software
2022-05-13 09:11:10 -07:00
Teodor Nikolov
faa277778e sarus: fix dependency on boost (#30659)
The program_options variant is disabled by default in Boost and
has to be enabled explicitly.
2022-05-13 08:41:41 -06:00
Harmen Stoppels
b60d3dcd29 libtree: add v3.0.4, v3.1.1 (#30658) 2022-05-13 11:35:06 +00:00
Todd Gamblin
e0bed2d6a7 tutorial stack: allow deprecated versions (#30648)
For tutorial builds, we should continue to allow deprecated builds to be installed. We
can update them as needed when we update the tutorial, but we don't need to correct them
immediately on deprecation in CI.

- [x] add `deprecated:true` to tutorial `spack.yaml` config.
2022-05-13 04:09:39 -06:00
Massimiliano Culpo
745c191d73 Gitlab pipelines: add a small legend in the logs to interpret "[x]" (#30643) 2022-05-12 21:46:35 +02:00
Chuck Atkins
42e9430fbc silo: Cleanup the HDF5 dependency specs (#30593) 2022-05-12 15:43:11 -04:00
Chuck Atkins
f11572166f vtk: fix hdf5 version specification (#30592) 2022-05-12 21:16:57 +02:00
Adam J. Stewart
aa6665d5ee py-scikit-learn: add v1.1.0 (#30649) 2022-05-12 12:50:26 -06:00
Simon Pintarelli
3e8f31a068 atompaw: add version 4.2.0.0 (#30650) 2022-05-12 18:09:30 +00:00
Massimiliano Culpo
3625ea4726 Revert "atompaw: add new package (#30619)" (#30647)
This reverts commit 12b0278f08.
2022-05-12 19:47:47 +02:00
snehring
245b95223d soapdenovo-trans: add v1.0.5 (#30629) 2022-05-12 19:14:49 +02:00
Max Zeyen
e00c8a7d98 code-server: add new versions (#30646) 2022-05-12 10:08:02 -07:00
Adam J. Stewart
97792f04e9 py-netcdf4: add v1.5.8 (#30598) 2022-05-12 09:02:27 -05:00
Frédéric Simonis
ca069f6906 precice: add v2.4.0 (#30633) 2022-05-12 15:57:53 +02:00
Qian Jianhua
35a91bdd72 fakexrandr: remove 'ldconfig' from Makefile (#30632) 2022-05-12 14:55:45 +02:00
Mikael Simberg
c866a50446 Add patch for compiling llvm ~omp_as_runtime (#30583) 2022-05-12 05:49:39 -06:00
Harmen Stoppels
3033abb5bd Add cuda 11.7 compat bounds for gcc/clang (#30639) 2022-05-12 10:41:30 +00:00
Harmen Stoppels
d37f439557 pigz: add v2.7 (#30640) 2022-05-12 10:39:08 +00:00
dlkuehn
18710936f1 platypus: limit install to Python2 (#30624)
Co-authored-by: David Kuehn <las_dkuehn@iastate.edu>
2022-05-12 09:30:45 +02:00
Simon Pintarelli
12b0278f08 atompaw: add new package (#30619) 2022-05-12 09:24:38 +02:00
Eureka Hwang
34fd6e36ce cuda: add v11.7 (#30630) 2022-05-12 09:20:42 +02:00
marcosmazz
363536fd92 quantum-espresso: add gipaw variant (#30628)
Co-authored-by: Marcos Mazzini - <mmazzini@serafin.ccad.unc.edu.ar>
2022-05-11 18:31:19 -07:00
Abhik Sarkar
d57d343b6d This commit removes the Boost.with_default_variants to variants (#28960)
that packages are precisely dependant upon. This is the second batch
of 20 packages with modified boost dependencies.
2022-05-11 17:16:19 -07:00
Tamara Dahlgren
1b254d19c4 Allow read-only access to file cache (when needed) (#29693)
* Allow read-only access to file cache (when needed)
* Tweaked and added unit tests
* Skip test_cache_init_entry_fails for windows
2022-05-11 16:25:06 -07:00
shanedsnyder
82b916be36 add darshan-3.4.0-pre1 release (#30569)
include new dependencies on autotools/m4/etc.
2022-05-11 16:21:56 -06:00
snehring
66d3648200 bamutil: updating to 1.0.15 (#30623)
* bamutil: updating to 1.0.15

* bamutil: switching to github archive
2022-05-11 22:12:32 +00:00
AMD Toolchain Support
d2fc7b9f7d lammps: updating googletest version to 1.11 to avoid GTEST_DISALLOW_ASSIGN_Error (#30563)
* updating googletest version to 1.11 to avoid GTEST_DISALLOW_ASSIGN_ error

* limiting the version scope

* modified the version limit

Co-authored-by: mohan babu <mohbabul@amd.com>
2022-05-11 13:17:47 -06:00
Wouter Deconinck
1067749371 assimp: add v5.2.3 (#29629) 2022-05-11 20:03:07 +02:00
snehring
8bd893367d sentieon-genomics: add version 202112.02, remove manual download (#30145) 2022-05-11 19:38:24 +02:00
Mikael Simberg
2ed542b744 Add conflict for ROCm and asio in HPX package (#30620) 2022-05-11 10:33:16 -07:00
Stephen Hudson
5cb7a5db45 libEnsemble: add v0.9.1 (#30621) 2022-05-11 16:41:45 +00:00
Cory Bloor
f84991b5a8 rocfft: add spack build test support (#29957)
* rocfft: add spack build test support

* Style cleanup for variant specs
2022-05-11 09:37:22 -07:00
Hadrien G
928ecd1f4e [acts] Add version 19 (#30615)
No build system visible changes, so AFAIK this should Just Work
2022-05-11 09:13:27 -07:00
Thomas Dickerson
72e594fb10 Fix default buildcache location (#30230)
Resolve path/URL parsing issues introduced by #27021
2022-05-11 17:50:04 +02:00
Vasileios Karakasis
f9d701f9cf ReFrame: add v3.11.0 (#30578) 2022-05-11 08:41:40 -06:00
Harmen Stoppels
63f7053fe8 eccodes: add v2.25.0 (#30618) 2022-05-11 12:04:43 +00:00
Harmen Stoppels
1c51d6313b jasper: avoid --gc-sections / hidden symbols (#30617)
Jasper v3.x changed a default to hide hidden symbols, but apparently
eccodes relies on those symbols and fails to link otherwise.
2022-05-11 11:52:54 +00:00
Harmen Stoppels
c164e6fe03 jasper: update cmake dependency (#30616) 2022-05-11 13:33:46 +02:00
Gregory Lee
2d823dcf90 gobject-introspection: add libffi dependency (#30601) 2022-05-11 13:29:54 +02:00
Tom Scogland
a12c638224 Neovim luajit (#28855)
Upstream neovim builds with luajit-openresty or luajit in almost all
cases.  To support the current usage, a user can specify that they want
lua, but this will allow the use of the normal (faster, better tested
and better maintained) setup.
2022-05-11 05:01:35 -06:00
Richard Berger
0739691688 flecsi: add GPU dependencies and refactor (#30543) 2022-05-11 12:51:21 +02:00
Seth R. Johnson
62ffc8c1dd vecgeom: new version 1.2.0 (#30586) 2022-05-11 10:49:14 +00:00
Wouter Deconinck
61969566f8 pango: updated versions with MesonPackage (#30591) 2022-05-11 12:48:07 +02:00
Ida Mjelde
49948bb3e7 root: changes due to var name webui->webgui from version 6.17.02 (#29964) 2022-05-11 10:44:17 +00:00
Harmen Stoppels
c9c347f0f0 jasper: add 3.0.x (#30614) 2022-05-11 12:26:23 +02:00
Dan Bonachea
ee9b61be7a upcxx,gasnet: Add a note to the +cuda variant description (#30602)
Resolves issue #30589
2022-05-10 22:45:32 -06:00
snehring
be45292a9c last: updating to 1282 (#30606) 2022-05-11 00:26:54 +00:00
HELICS-bot
61f8c97bb7 helics: Add version 3.2.0 (#30604)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-05-10 23:02:08 +00:00
Adam J. Stewart
b0403624cf py-scikit-learn: add v1.1.0rc1 (#30600) 2022-05-10 21:50:56 +00:00
Adam J. Stewart
4baed234be py-xarray: add v2022.3.0 (#30599) 2022-05-10 21:45:55 +00:00
Adam J. Stewart
9de1edee80 py-geopandas: add v0.10.X (#30597) 2022-05-10 21:32:12 +00:00
Harmen Stoppels
9ce726eed5 openmpi: only set variants when condition is met (#30585) 2022-05-10 13:05:44 -06:00
Harmen Stoppels
c45ee381bd hyperfine: add v1.13.0 (#30584) 2022-05-10 18:05:13 +00:00
Sergey Kosukhin
56d76766b7 cray-mpich: add variant 'wrappers' (#30249) 2022-05-10 12:22:04 -05:00
Andrea Valenzuela
6c309bbb32 Add checksum for py-pylint@2.13.5 (#30356)
* Add checksum for py-pylint@2.13.5

* Update dependencies

* Add checksum for py-astroid@2.11.4

* Correct py-toml addition and add py-tomli dependency

* Remove py-pytoml dependency for versions @2.13:

* Modify py-astroid version range

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

* Discontinue py-astroid dependency @2.8.0:2.8 for new versions

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

* Discontinue py-mccabe dependency @0.6.0:0.6 for new versions

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

* Remove mccabe and setuptools-scm dependencies

* Update astroid dependencies

* Extend py-typed-ast version range to future releases

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

* py-dill only required for version 2.13.5 and above

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

* Add maccabe dependency and correct setuptools run dependency

* Setuptools fix

* Add setuptools as run dependency

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2022-05-10 11:21:48 -06:00
Chris White
cfed42ecfc guard against SPACK_FC possibly not being defined (#30581) 2022-05-10 12:19:03 -05:00
haralmha
01b79abcdf py-pyarrow: Add versions 8.0.0 and 7.0.0 (#30524)
* py-pyarrow: Add version 7.0.0

* Add version constraints on dependencies

* Add version 8.0.0

* arrow: Add version 8.0.0

* py-pyarrow: Allow version 8.0.0 of arrow
2022-05-10 12:16:55 -05:00
G-Ragghianti
4d84c774d1 Added dependency on hipify-clang and fixed hipify-clang package (#30576) 2022-05-10 09:38:16 -07:00
Sreenivasa Murthy Kolam
00e9780136 Update ROCm recipes for rocm-5.1.0 release (#30027)
* Bump up rocm release version to rocm-5.1.0
* update rocm-opencl for rocm-5.1.0 release
* update the migraphx,miopen(hip,opencl),mivisionx,rocm-tensile
* update the mlirmiopen checksum version
2022-05-10 08:42:22 -07:00
Scott Wittenburg
a65e00392c gitlab ci: do not override .generate tags for e4s (#30571) 2022-05-10 08:05:19 -07:00
Wouter Deconinck
250fa6dada libxkbcommon: new version 1.4.0, support for newer meson build system (#30420) 2022-05-10 09:59:26 -05:00
Danny McClanahan
dd7822fdf7 depend on gettext in subversion when +nls is enabled (#30573) 2022-05-10 09:58:35 -05:00
Todd Gamblin
555202833f bootstrap: clean up CI workflows a bit (#30574)
- [x] Add `mkdir -p` and `chmod` to ensure `/home/spack-test` exists and
      has correct permissions.
- [x] Remove version comments from dependabot-managed action commits
- [x] Don't duplicate comment describing required fixes for distros with
      patched git
2022-05-10 16:27:37 +02:00
Valentin Volkl
b76fc61deb agile: add new package (#30244)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-05-10 12:40:04 +00:00
Ida Mjelde
186abe525e gitconddb: add v0.2.0 and v0.1 patch releases (#29965)
Co-authored-by: Harmen Stoppels <harmenstoppels@gmail.com>
2022-05-10 11:13:06 +00:00
Dom Heinzeller
31d8607b3c hdf: build on Ubuntu 20.04 aarch64 (#30522) 2022-05-10 10:47:04 +02:00
Brice Videau
622841063c userspace-rcu: add versions up to v0.13.1 (#30534) 2022-05-10 08:57:08 +02:00
mcuma
23b7071bb0 wi4mpi: fix a missed conversion to string (#30541) 2022-05-10 07:42:21 +02:00
Erik Schnetter
359229f5f8 memkind: conflicts with jemalloc (#30070) 2022-05-10 07:41:01 +02:00
JDBetteridge
2db545ffdc libflame: fix for linking with BLIS library (#30527) 2022-05-10 07:39:02 +02:00
Ryan Mulhall
3986ac3828 fms: add versions and expose more CMake build options (#28966)
Co-authored-by: rem1776 <Ryan.Mulhall@lscamd50-d.gfdl.noaa.gov>
2022-05-10 07:28:23 +02:00
Robert Cohn
c47c5d75e4 oneapi: add v2022.2 (#30531) 2022-05-10 07:25:06 +02:00
Todd Gamblin
a0d4630448 bugfix: spack pkg list should be more picky about what's a package (#30577)
`spack pkg list` tests were broken by #29593 for cases when your `builtin.mock` repo
still has stale backup files (or, really, stale directories) sitting around. This
happens if you switch branches a lot. In this case, things like this were causing
erroneous packages in the mock listing:

```
var/spack/repos/builtin.mock/packages/
    foo/
        package.py~
```

- [x] make `list_packages` consider only directories with one-deep `package.py` files.
2022-05-10 04:57:58 +00:00
Tom Scogland
7f1659786b Add a Lua build-system (#28854)
Reworking lua to allow easier substitution of the base lua implementation.

Also adding in a maintained version of luajit and re-factoring the entire stack 
to use a custom build-system to centralize functionality like environment 
variable management and luarocks installation.

The `lua-lang` virtual is now versioned so that a package that requires 
Lua 5.1 semantics can get any lua, but one that requires 5.2 will only 
get upstream lua.

The luaposix package requires lua-bit32, but only when built with a 
lua conforming to version 5.1.  This adds the package, and the 
dependencies, but exposed a problem with luarocks dependency 
detection.  Since we're  installing each package in its own "tree" and 
there's no environment  variable to list extra trees, spack now 
generates a luarocks config  file that lists all the trees of all the 
dependencies, and references  it by setting `LUAROCKS_CONFIG` 
in the build environment of every LuaPackage.  This allows luarocks 
to find the spack installed  dependencies correctly rather than 
trying (and failing) to download them.

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
Co-authored-by: Tom Scogland <tscogland@llnl.gov>
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-05-10 06:54:38 +02:00
Sam Grayson
b5da0d02bf Fix py-numpy #30373 by backporting Numpy PR (#30486)
* Fix py-numpy #30373

* Update `when` for patch.
2022-05-09 22:13:39 -06:00
eugeneswalker
8575afac4e e4s on mac ci: set SPACK_DISABLE_LOCAL_CONFIG=1 (#30568)
* e4s on mac ci: set SPACK_DISABLE_LOCAL_CONFIG=1
* export SPACK_USER_CACHE_PATH so that ~/.spack/... isn't used
2022-05-09 21:13:34 -06:00
Todd Gamblin
7997dfcf80 tests: fix references to hard-coded master branch in git tests (#30572)
Some of our `git` tests still fail when `init.defaultBranch` is set to something other
than `master`.

- [x] get rid of all hard-coded `master` refs
- [x] Use `'default'` to key tests that use the default branch
2022-05-09 16:42:25 -07:00
Erik Schnetter
19c8e02e32 sqlite: New version 3.38.5 (#30556) 2022-05-09 16:25:39 -06:00
sabrivatansever
320e6e06e6 Cutlang: Create package.py (#30535) 2022-05-09 20:39:53 +00:00
Adam J. Stewart
d7b66dd286 Python: add v3.8.13 and v3.7.13 (#30553)
Co-authored-by: Harmen Stoppels <harmenstoppels@gmail.com>
2022-05-09 13:49:41 -06:00
Rebecca Haluska
70a8b91ec2 sina: add 1.11 version (#27161)
* sina: add 1.11 version

* Moved 1.11 above 1.10
2022-05-09 19:27:59 +00:00
Douglas Thain
1883fedae7 cctools: add 7.4.2 (#28766)
* Update to cctools-7.4.2
* Add simple patch to remove broken test cases.
* import unlink
* add maintainers
2022-05-09 10:50:00 -07:00
Sergei Shudler
c4412306da Added a new patched version for parallelmergetree (#29499)
* Added a new patched version for parallelmergetree

* Retain older versions instead of replacing them
2022-05-09 10:47:34 -07:00
Dom Heinzeller
c49508648a Get timeout for web requests with urllib from spack config, same as for curl (#30468) 2022-05-09 10:35:17 -07:00
John W. Parent
9bcf496f21 Windows permissions: uninstalling and cleaning stages (#29714)
When running on Windows, Spack may generate files in the stage/install
prefixes that do not have write permissions, which prevents the
removal of those directories (e.g. when cleaning stages or uninstalling).
There should be a refactoring to avoid this in the first place, but that
is assumed to be longer term, so the temporary fix is to make such files
writable if they are not. This PR:

* Automatically handles these permissions errors when uninstalling
  packages from the Spack root (makes then writable)
* Updates similar already-existing logic when removing Spack-managed
  stage directories (the error-handling was assuming all errors were
  permissions errors and was therefore handling other errors
  inappropriately)

Note: these permissions issues only appear on Windows so this logic is
only applied there (permissions are not modified for this purpose on
Linux etc.).

This also adds special handling for a case where calling `isdir`
on an `os.DirEntry` object would fail for improperly-created symlinks
(e.g. on Windows, using `os.symlink` without `target_is_directory=True`).
Note this specific issue only came up when enabling link_tree tests
(specifically `source_merge_visitor_cant_be_cyclical`).
2022-05-09 10:28:14 -07:00
Will Saunders
060e88387e hipsycl: add v0.9.2 (#30566) 2022-05-09 17:54:14 +02:00
Oliver Perks
a24bae1986 Updated ACfL package to 22.0.1, removing 21 package, as no licence required is now false. (#30562) 2022-05-09 15:12:08 +02:00
Erik Schnetter
d08520cb15 mpitrampoline: Correct build environment (#30549) 2022-05-09 13:40:10 +02:00
Erik Schnetter
5397dcee51 simulationio: add v9.0.2 (#30550) 2022-05-09 13:39:18 +02:00
Adam J. Stewart
d62e4b1d66 py-radiant-mlhub: add new versions (#30555) 2022-05-09 12:44:49 +02:00
Adam J. Stewart
9ed1c76486 py-cartopy: add new versions (#30554) 2022-05-09 12:44:33 +02:00
Adam J. Stewart
10efbc071f py-geocube: add v0.3.1 (#30558) 2022-05-09 12:44:01 +02:00
Massimiliano Culpo
d517dcdc71 tcl: add v8.6.12 (#30560) 2022-05-09 11:12:16 +02:00
Massimiliano Culpo
104d60887f CI: fix bootstrapping on Fedora (#30559)
Fedora updated git, so we need to apply, again, the
workaround for CVE-2022-24765
2022-05-09 09:11:03 +00:00
Erik Schnetter
1bde91735b mpitrampoline: New version 4.0.2 (#30548) 2022-05-09 10:01:41 +02:00
Erik Schnetter
335083d2dc openssl: Update to 1.1.1o (#30551) 2022-05-08 22:57:37 -06:00
Peter Scheibel
0858c281e4 Cray manifest file: accept "nvidia" as "nvhpc" (#30428)
* create function for translating compiler names on specs/compiler entries in manifest

* add tests for translating compiler names on spec/compiler entries

* use higher-level function in test and add comment to prefer testing via higher-level function

* opensuse clingo check should not fail on account of this pr, but I cannot get it to pass by restarting via CI UI
2022-05-08 17:51:27 -07:00
Erik Schnetter
adc8a2ca00 curl: New version 7.83.0 (#30552) 2022-05-09 00:36:03 +02:00
Derek Ryan Strong
dc6d45c8b4 Add latest Lmod 8.6, 8.7 (#30542)
Co-authored-by: Harmen Stoppels <harmenstoppels@gmail.com>
2022-05-07 20:04:10 -06:00
Harmen Stoppels
fcaf9c8cdf gcc: version 12.1.0 (#30537) 2022-05-07 19:28:54 -06:00
Phil Carns
1f74dc63dc Add mochi-margo 0.9.9 (#30539)
- necessary for compatibility with upcoming Mercury 2.2.0 release
2022-05-07 19:28:36 -06:00
Francesco Di Natale
ceaad43e54 Addition of 1.1.9dev version for py-maestrowf (#30523)
* Addition of 1.1.9dev version.

* Small style fix -- extra blank line.

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

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

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

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

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

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

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

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

* Additional dependencies and version constraints.

* Revert to py-poetry.

* Remove run from cryptography (build only).

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2022-05-07 19:28:23 -06:00
Erik
4c8eb92314 Put make() inside a self.run_test call (#30536) 2022-05-07 18:45:57 -06:00
Ryan Marcellino
89775e32c0 vim: add +gtk variant to pair with +gui (#30520)
* vim: add +gtk3 variant to pair with +gui

* address review comments
2022-05-07 17:49:33 -06:00
Robert Pavel
5ab526185a Force GCC to always provide a C++14 flag (#29781)
* Force GCC to always provide a C++14 flag

Updated gnu logic so that the c++14 flag for g++ is always propagated.
This fixes issues with build systems that error out if passed an empty
string for a flag.

Engaging in the best kind of software engineering by updating the unit
test to pass with the value it is now passed. This should better match
the expected flag for g++ compiling with the C++14 standard
2022-05-07 13:09:20 -04:00
WYF
654a07d642 nmap: fix build issue (#30429) 2022-05-07 03:02:26 +02:00
JDBetteridge
dfdbd1151d Eigen: turn on BUILD_TESTING for build to complete (#30528)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-05-06 16:28:33 -06:00
Sebastian Schmitt
22f3ef0a21 Add sphinx-tabs package (#27698)
* Add py-docutils@0.16

* Add sphinx-tabs package

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

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

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

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

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

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2022-05-06 10:33:38 -05:00
Jim Galarowicz
165bcf5cc3 openspeedshop: fix missing import statement (#30506) 2022-05-06 10:27:09 -05:00
Greg Becker
27462bc982 Fix improper type for InvalidDependencyError argument (#30504) 2022-05-06 16:23:12 +02:00
eugeneswalker
c2afb4b916 arborx: inherit from CudaPackage, ROCmPackage (#30490) 2022-05-06 16:18:06 +02:00
Thomas Dickerson
6c6685b5fa boost: add support for alternate boost-context backends (#30496)
The fcontext backend is the default high-performance backend.
The ucontext backend is needed when using Boost context in conjunction with ASAN.
The WinFibers backend...also exists.

https://www.boost.org/doc/libs/1_79_0/libs/context/doc/html/context/cc/implementations__fcontext_t__ucontext_t_and_winfiber.html
2022-05-06 16:14:45 +02:00
Ken Raffenetti
17c32811fb level-zero: add new package (#30253)
Co-authored-by: Robert Cohn <rscohn2@gmail.com>
Co-authored-by: Robert Cohn <robert.s.cohn@intel.com>
Co-authored-by: John Mellor-Crummey <johnmc@rice.edu>
2022-05-06 16:12:23 +02:00
WYF
ad1391db75 gdb: fix run issue with v9.2 (#30491) 2022-05-06 07:53:40 -06:00
Chuck Atkins
d8e010a9f5 ci: Enable the ParaView GUI in the DAVSDK pipeline (#30473)
* ci: Enable the ParaView GUI in the DAVSDK pipeline

* qt: Patch for long paths in ci
2022-05-06 09:36:56 -04:00
Seth R. Johnson
5a55e78073 py-qrcode: new package (#30529) 2022-05-06 07:05:53 -06:00
Todd Gamblin
c1007efe5a slurm: add new versions to address CVEs 2022-29500, 2022-29501 and 2022-29502 (#30525)
Due to CVE 2022-29500, CVE 2022-29501, and CVE 2022-29502, SLURM versions prior to
21.08.8 and 20.11.9 are deprecated.

See:
* https://www.schedmd.com/news.php?id=260#OPT_260
* https://cve.report/CVE-2022-29500
* https://cve.report/CVE-2022-29501
* https://cve.report/CVE-2022-29502

- [x] Deprecate versions prior to 21.08.8 and 20.11.9
- [x] Add 21-08-8-1, 21-08-8-2, and 20-11-9-1
2022-05-06 07:05:41 -06:00
Harmen Stoppels
2f14695882 docs: jobserver & generated makefiles (#30526) 2022-05-06 14:04:48 +02:00
Brian Van Essen
afc2d4284a Added a version for a tag that sets a stable version of master to pull (#30511) 2022-05-06 01:45:38 -06:00
dependabot[bot]
999eee64b8 build(deps): bump docker/build-push-action from 2.10.0 to 3 (#30515)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 2.10.0 to 3.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](ac9327eae2...e551b19e49)

---
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>
2022-05-06 08:38:07 +02:00
dependabot[bot]
5d0f2bb461 build(deps): bump docker/setup-qemu-action from 1.2.0 to 2 (#30518)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 1.2.0 to 2.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](27d0a4f181...8b122486ce)

---
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>
2022-05-06 08:37:34 +02:00
dependabot[bot]
ec295a13fd build(deps): bump docker/setup-buildx-action from 1.7.0 to 2 (#30517)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 1.7.0 to 2.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](f211e3e9de...dc7b9719a9)

---
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>
2022-05-06 08:37:11 +02:00
dependabot[bot]
1b1770ea9e build(deps): bump docker/login-action from 1.14.1 to 2 (#30516)
Bumps [docker/login-action](https://github.com/docker/login-action) from 1.14.1 to 2.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](dd4fa0671b...49ed152c8e)

---
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>
2022-05-06 08:36:50 +02:00
Tom Scogland
d3a0ac1c0a Preserve jobserver file descriptors into build environment (#30302)
This ensures that multiple spack instances called from `make` will respect the maximum number of jobs in the POSIX jobserver across packages.

Co-authored-by: Harmen Stoppels <harmenstoppels@gmail.com>
2022-05-06 04:09:58 +00:00
Jim Galarowicz
3137e7c61b Add two critical fixes and update for version 1.0.4 (#30507) 2022-05-05 18:37:52 -06:00
Mark Grondona
202214d855 flux-sched: add patch for signedness compare issue on gcc@9.40 (#30514)
Problem: GCC 9.4.0 catches a bad integer comparison in
resource/hlapi/bindings/c++/reapi_cli_impl.hpp in flux-sched@0.22.0
and current master.

Add a patch to work around the problem until an upstream fix is
available.
2022-05-06 00:11:04 +00:00
Ken Raffenetti
b6e1cbd86d mpich: Add ROCm variant (#30502)
* mpich: Add ROCm variant

* fixup
2022-05-05 15:49:41 -06:00
Gregory Lee
e6d1c2d9f3 updated stat build dep requirements (#30505) 2022-05-05 20:24:43 +00:00
Niclas Jansson
1a368419da neko: Add version 0.3.2 (#30497)
* neko: Add version 0.3.2

* Switch to sha256

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

* Fix url pattern

Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
2022-05-05 20:12:48 +00:00
Tom Scogland
6898b7c2f6 harden unit tests, enable basic parallelism (#29593)
* use the init.defaultBranch name, not master

* make tcl and modules/common independent

Both used to use not just the same directory, but the same *file* for
their outputs.  In parallel this can cause problems, but it can also
accidentally allow expected failures to pass if the file is left around
by mistake.

* use a non-global misc_cache in tests

* make pkg tests resilient to gitignore

* make source cache and module directories non-global
2022-05-05 11:48:16 -07:00
Harmen Stoppels
2836648904 Makefile generator for parallel spack install of environments (#30254)
`make` solves a lot of headaches that would otherwise have to be implemented in Spack:

1. Parallelism over packages through multiple `spack install` processes
2. Orderly output of parallel package installs thanks to `make --sync-output=recurse` or `make -Orecurse` (works well in GNU Make 4.3; macOS is unfortunately on a 16 years old 3.x version, but it's one `spack install gmake` away...)
3. Shared jobserver across packages, which means a single `-j` to rule them all, instead of manually finding a balance between `#spack install processes` & `#jobs per package` (See #30302).

This pr adds the `spack env depfile` command that generates a Makefile with dag hashes as
targets, and dag hashes of dependencies as prerequisites, and a command
along the lines of `spack install --only=packages /hash` to just install
a single package.

It exposes two convenient phony targets: `all`, `fetch-all`. The former installs the environment, the latter just fetches all sources. So one can either use `make all -j16` directly or run `make fetch-all -j16` on a login node and `make all -j16` on a compute node. 

Example:

```yaml
spack:
  specs: [perl]
  view: false
```

running

```
$ spack -e . env depfile --make-target-prefix env | tee Makefile
```
generates

```Makefile
SPACK ?= spack

.PHONY: env/all env/fetch-all env/clean

env/all: env/env

env/fetch-all: env/fetch

env/env: env/.install/cdqldivylyxocqymwnfzmzc5sx2zwvww
	@touch $@

env/fetch: env/.fetch/cdqldivylyxocqymwnfzmzc5sx2zwvww env/.fetch/gv5kin2xnn33uxyfte6k4a3bynhmtxze env/.fetch/cuymc7e5gupwyu7vza5d4vrbuslk277p env/.fetch/7vangk4jvsdgw6u6oe6ob63pyjl5cbgk env/.fetch/hyb7ehxxyqqp2hiw56bzm5ampkw6cxws env/.fetch/yfz2agazed7ohevqvnrmm7jfkmsgwjao env/.fetch/73t7ndb5w72hrat5hsax4caox2sgumzu env/.fetch/trvdyncxzfozxofpm3cwgq4vecpxixzs env/.fetch/sbzszb7v557ohyd6c2ekirx2t3ctxfxp env/.fetch/c4go4gxlcznh5p5nklpjm644epuh3pzc
	@touch $@

env/dirs:
	@mkdir -p env/.fetch env/.install

env/.fetch/%: | env/dirs
	$(info Fetching $(SPEC))
	$(SPACK) -e '/tmp/tmp.7PHPSIRACv' fetch $(SPACK_FETCH_FLAGS) /$(notdir $@) && touch $@

env/.install/%: env/.fetch/%
	$(info Installing $(SPEC))
	+$(SPACK) -e '/tmp/tmp.7PHPSIRACv' install $(SPACK_INSTALL_FLAGS) --only-concrete --only=package --no-add /$(notdir $@) && touch $@

# Set the human-readable spec for each target
env/%/cdqldivylyxocqymwnfzmzc5sx2zwvww: SPEC = perl@5.34.1%gcc@10.3.0+cpanm+shared+threads arch=linux-ubuntu20.04-zen2
env/%/gv5kin2xnn33uxyfte6k4a3bynhmtxze: SPEC = berkeley-db@18.1.40%gcc@10.3.0+cxx~docs+stl patches=b231fcc arch=linux-ubuntu20.04-zen2
env/%/cuymc7e5gupwyu7vza5d4vrbuslk277p: SPEC = bzip2@1.0.8%gcc@10.3.0~debug~pic+shared arch=linux-ubuntu20.04-zen2
env/%/7vangk4jvsdgw6u6oe6ob63pyjl5cbgk: SPEC = diffutils@3.8%gcc@10.3.0 arch=linux-ubuntu20.04-zen2
env/%/hyb7ehxxyqqp2hiw56bzm5ampkw6cxws: SPEC = libiconv@1.16%gcc@10.3.0 libs=shared,static arch=linux-ubuntu20.04-zen2
env/%/yfz2agazed7ohevqvnrmm7jfkmsgwjao: SPEC = gdbm@1.19%gcc@10.3.0 arch=linux-ubuntu20.04-zen2
env/%/73t7ndb5w72hrat5hsax4caox2sgumzu: SPEC = readline@8.1%gcc@10.3.0 arch=linux-ubuntu20.04-zen2
env/%/trvdyncxzfozxofpm3cwgq4vecpxixzs: SPEC = ncurses@6.2%gcc@10.3.0~symlinks+termlib abi=none arch=linux-ubuntu20.04-zen2
env/%/sbzszb7v557ohyd6c2ekirx2t3ctxfxp: SPEC = pkgconf@1.8.0%gcc@10.3.0 arch=linux-ubuntu20.04-zen2
env/%/c4go4gxlcznh5p5nklpjm644epuh3pzc: SPEC = zlib@1.2.12%gcc@10.3.0+optimize+pic+shared patches=0d38234 arch=linux-ubuntu20.04-zen2

# Install dependencies
env/.install/cdqldivylyxocqymwnfzmzc5sx2zwvww: env/.install/gv5kin2xnn33uxyfte6k4a3bynhmtxze env/.install/cuymc7e5gupwyu7vza5d4vrbuslk277p env/.install/yfz2agazed7ohevqvnrmm7jfkmsgwjao env/.install/c4go4gxlcznh5p5nklpjm644epuh3pzc
env/.install/cuymc7e5gupwyu7vza5d4vrbuslk277p: env/.install/7vangk4jvsdgw6u6oe6ob63pyjl5cbgk
env/.install/7vangk4jvsdgw6u6oe6ob63pyjl5cbgk: env/.install/hyb7ehxxyqqp2hiw56bzm5ampkw6cxws
env/.install/yfz2agazed7ohevqvnrmm7jfkmsgwjao: env/.install/73t7ndb5w72hrat5hsax4caox2sgumzu
env/.install/73t7ndb5w72hrat5hsax4caox2sgumzu: env/.install/trvdyncxzfozxofpm3cwgq4vecpxixzs
env/.install/trvdyncxzfozxofpm3cwgq4vecpxixzs: env/.install/sbzszb7v557ohyd6c2ekirx2t3ctxfxp

env/clean:
	rm -f -- env/env env/fetch env/.fetch/cdqldivylyxocqymwnfzmzc5sx2zwvww env/.fetch/gv5kin2xnn33uxyfte6k4a3bynhmtxze env/.fetch/cuymc7e5gupwyu7vza5d4vrbuslk277p env/.fetch/7vangk4jvsdgw6u6oe6ob63pyjl5cbgk env/.fetch/hyb7ehxxyqqp2hiw56bzm5ampkw6cxws env/.fetch/yfz2agazed7ohevqvnrmm7jfkmsgwjao env/.fetch/73t7ndb5w72hrat5hsax4caox2sgumzu env/.fetch/trvdyncxzfozxofpm3cwgq4vecpxixzs env/.fetch/sbzszb7v557ohyd6c2ekirx2t3ctxfxp env/.fetch/c4go4gxlcznh5p5nklpjm644epuh3pzc env/.install/cdqldivylyxocqymwnfzmzc5sx2zwvww env/.install/gv5kin2xnn33uxyfte6k4a3bynhmtxze env/.install/cuymc7e5gupwyu7vza5d4vrbuslk277p env/.install/7vangk4jvsdgw6u6oe6ob63pyjl5cbgk env/.install/hyb7ehxxyqqp2hiw56bzm5ampkw6cxws env/.install/yfz2agazed7ohevqvnrmm7jfkmsgwjao env/.install/73t7ndb5w72hrat5hsax4caox2sgumzu env/.install/trvdyncxzfozxofpm3cwgq4vecpxixzs env/.install/sbzszb7v557ohyd6c2ekirx2t3ctxfxp env/.install/c4go4gxlcznh5p5nklpjm644epuh3pzc
```

Then with `make -O` you get very nice orderly output when packages are built in parallel:
```console
$ make -Orecurse -j16
spack -e . install --only-concrete --only=package /c4go4gxlcznh5p5nklpjm644epuh3pzc && touch c4go4gxlcznh5p5nklpjm644epuh3pzc
==> Installing zlib-1.2.12-c4go4gxlcznh5p5nklpjm644epuh3pzc
...
  Fetch: 0.00s.  Build: 0.88s.  Total: 0.88s.
[+] /tmp/tmp.b1eTyAOe85/store/linux-ubuntu20.04-zen2/gcc-10.3.0/zlib-1.2.12-c4go4gxlcznh5p5nklpjm644epuh3pzc
spack -e . install --only-concrete --only=package /sbzszb7v557ohyd6c2ekirx2t3ctxfxp && touch sbzszb7v557ohyd6c2ekirx2t3ctxfxp
==> Installing pkgconf-1.8.0-sbzszb7v557ohyd6c2ekirx2t3ctxfxp
...
  Fetch: 0.00s.  Build: 3.96s.  Total: 3.96s.
[+] /tmp/tmp.b1eTyAOe85/store/linux-ubuntu20.04-zen2/gcc-10.3.0/pkgconf-1.8.0-sbzszb7v557ohyd6c2ekirx2t3ctxfxp
```

For Perl, at least for me, using `make -j16` versus `spack -e . install -j16` speeds up the builds from 3m32.623s to 2m22.775s, as some configure scripts run in parallel.

Another nice feature is you can do Makefile "metaprogramming" and depend on packages built by Spack. This example fetches all sources (in parallel) first, print a message, and only then build packages (in parallel).

```Makefile
SPACK ?= spack

.PHONY: env

all: env

spack.lock: spack.yaml
	$(SPACK) -e . concretize -f

env.mk: spack.lock
	$(SPACK) -e . env depfile -o $@ --make-target-prefix spack

fetch: spack/fetch
	@echo Fetched all packages && touch $@

env: fetch spack/env
	@echo This executes after the environment has been installed

clean:
	rm -rf spack/ env.mk spack.lock

ifeq (,$(filter clean,$(MAKECMDGOALS)))
include env.mk
endif
```
2022-05-05 10:45:21 -07:00
Brian Van Essen
0dd9e5c86f Enable PyTorch 1.10.x to build on Power systems (#30494)
* Use patches from IBM's Open CE project to enable PyTorch to build on
Power systems.

Cherry-pick a patch to allow earlier versions of PyTorch to build with
CUDA 11.4.

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

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2022-05-05 16:38:45 +00:00
Tamara Dahlgren
011a491b16 package audit: ensure stand-alone test method not include in build-phase testing (#30352) 2022-05-05 18:04:16 +02:00
Massimiliano Culpo
c9714533f3 clingo: add v5.5.2 (#30495)
* clingo add v5.5.2

* Unify dependencies for @spack and @master
2022-05-05 08:58:23 -07:00
David
faeffdfaf2 Update totalview package.py with new version and maintainer (#30341)
* Update totalview package.py with new version and maintainer

* Update totalview/package.py version order

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

Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
2022-05-05 08:37:56 -07:00
Dom Heinzeller
a15a69a769 Bug fix for mesa-glu: if gl is provided by mesa, need to specify argument to ./configure (#30082) 2022-05-05 08:35:54 -07:00
Hans Fangohr
9a33121859 octopus: update to 11.4 and add tests (#30321)
* octopus: adding versions up to 11.4

* octopus: add smoke tests

* octopus: add necessary flags for gcc@10

* octopus: update to compilation and dependencies

* octopus: adding new variants

* octopus: remove 'poke' (as this poke is not in spack [yet])

* octopus: allow compilation from git repo develop branch

* octopus: adapt to spack style requirements

* octopus: add maintainer

* octopus: make tests after install optional

Thank you @tldahlgren

* octopus: follow recommended practice for test input data

Move the two configuration files we use for smoke tests into `test`
subdirectory. Thanks @tldahlgren.

* Adding maintainer

with their agreement by email

* octopus: reduce duplication of flags

- part of code review

* octopus: https is preferred over http

* octopus: remove .99 from versioning information

Thanks to https://github.com/spack/spack/pull/26402, we can drop the
"2:3.99" notation when we mean all versions 2.x and 3.x

Examples: b9e72557e8 (diff-b8373d30b3a141c495c2281273ee6184fc513413142afaf2adac1f406cd6b0d7)

(from review)

* octopus: args.extend([x]) -> args.append(x)

(hint from review)
2022-05-05 08:33:16 -07:00
Ken Raffenetti
e88396e5ed yaksa: Add support for cuda_arch variants (#30471) 2022-05-05 08:12:21 -07:00
Harmen Stoppels
dcd2f8a4ed ucx: overhaul package recipe (#30215)
- hyphens to underscore in variant names (e.g. `~ib_hw_tm` instead of `~ib-hw-tm`)
- disable docs, disable go, drop the unused `doc` variant
- `+static +shared` => `libs=static,shared`
- `vfs` support (add libfuse@3: dep)
- fix `backtrace_detail` for UCX 1.12+ (`--enable-backtrace-detail` => `--with-bfd`)
- group variants and sort
2022-05-05 15:07:34 +02:00
Valentin Volkl
381ec8abac baurmc: add new package (#30245)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-05-05 13:30:45 +02:00
Jennifer Green
fd6d226524 git: adding subtree support, post-install step, reordered deps (#30400) 2022-05-05 11:08:51 +02:00
Adam J. Stewart
cef9245ee1 LAPACK: add API compatibility versions (#29828) 2022-05-05 10:38:20 +02:00
dlkuehn
24fecdc738 rnaz: add version 2.1.1 and git repository to newest version. (#30349)
Co-authored-by: David Kuehn <las_dkuehn@iastate.edu>
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-05-05 10:32:41 +02:00
snehring
4a228055e2 trimmomatic: adding more flexible java dep (#30488) 2022-05-05 10:21:20 +02:00
Wouter Deconinck
17ede26cea flatbufffers: patches are in v2.0.0 (#30492) 2022-05-05 10:14:10 +02:00
SXS Bot
8bcccbeac7 spectre: add v2022.05.05 (#30493)
Co-authored-by: sxs-bot <sxs-bot@users.noreply.github.com>
2022-05-05 09:49:25 +02:00
Greg Becker
e6346eb033 spack external find: add search path customization (#30479) 2022-05-05 08:59:44 +02:00
Seth R. Johnson
a5d06325e7 qt: fix ~opengl and use_spack_dep (#30487) 2022-05-04 22:41:37 -04:00
Dan Bonachea
9bb23a7f46 UPC++: minor packaging improvements (#30482)
* upcxx: Add `spack external find` support

* upcxx: Minor tweaks to Shasta support
2022-05-04 15:27:21 -07:00
Andrea Valenzuela
5a434cb840 Add scitokens-cpp recipe and also as a variant for xrootd (#30362)
* Add scitokens-cpp recipe

* Add scitokens-cpp variant in xrootd

* Fix typo

* Fix flake8 style errors

* Update license date

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

Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
2022-05-04 13:03:50 -07:00
iarspider
0be5dea13f Fix professor recipe (#30002)
* [WIP] Cleanup professor dependencies

* Add dependency on ROOT
* Remove direct dependency on wxwidgets
    * `prof-I` tool requires matplotlib with wxwidgets backend, made that optional

* Update package.py

* Update package.py (#38)

* Update package.py

* Update package.py
2022-05-04 11:19:43 -07:00
David
b6f2a70f7b Update gtk-doc depends for tce findings (#30337)
gtk-doc can call pkg-config when used at runtime, so pkgconfig needs
to be a runtime requirement.

itstool needs to be a build-time requirement.
2022-05-04 11:17:34 -07:00
Olivier Cessenat
0d3d1ea7d0 gxsview: vtk9 no longer builds libvtkjpeg... (#30340) 2022-05-04 11:12:49 -07:00
Andrea Valenzuela
39c4a66e5b Add checksum for py-prompt-toolkit@3.0.29 (#30330)
Co-authored-by: aandvalenzuela <andrea.valenzuela.ramirez@cern.ch>
2022-05-04 11:53:53 -06:00
Carlos Bederián
0bd0ba53a3 curl: tls=mbedtls requires fPIC (#30447) 2022-05-04 10:53:33 -07:00
snehring
e24373f262 gatk: updating and expanding java dependency (#30476) 2022-05-04 17:51:44 +00:00
Adam J. Stewart
b7f33fb393 Python package: add backup BINDIR setting (#30408) 2022-05-04 10:50:18 -07:00
Chuck Atkins
250d5d2c00 qt: Assimp dependency specificationa is more nuanced (#30460)
libassimp has been a dependency for all of 5.x but expressing that has
varied significantly throughout the 5.x lifecycle:

  v5.0:  qt3d uses internal-only libassimp
  v5.5:  external-only libassimp
  v5.6:  either internal or external libassimp via autodetection
  v5.9:  user-selectable internal-vs-external via -assimp
  v5.14: additional qtquick3d module uses -assimp
  v5.15: qtquick3d switches to the -quick3d-assimp option
    * current bug where the incorrect target is setup
2022-05-04 13:30:15 -04:00
Sergey Kosukhin
8b0f6187e0 bugfix: fix filter_compiler_wrappers for Cray compiler (#29786) 2022-05-04 10:13:12 -07:00
Adam J. Stewart
8bf988abb9 GDAL: add v3.4.3 (#30474) 2022-05-04 16:34:17 +00:00
Bitllion
aab7dcaad9 add package: abacus (#30416)
* add pacakge: abacus

* rename

* fix some style bugs

* update package:abacus

* fix some style bugs

* format code

* Delete a line of useless comments

* updatee abacus
2022-05-04 09:29:08 -07:00
Mikael Simberg
5b68fa1ecb Add mimalloc package with use in HPX and pika (#30457)
* Add mimalloc package

* Add mimalloc as allocator option to pika

* Add mimalloc as allocator option to hpx

* Set git property globally instead of per-version in pika, hpx, and mimalloc packages

Co-authored-by: Mikael Simberg <mikael.simberg@iki.if>
2022-05-04 09:19:15 -07:00
acastanedam
4d03a2768e gpi-2_fix_deps: setup 'gawk' and 'sed' dependencies (#29740)
Strictly, `sed` is a `build` and `run` dependency in all gpi-2
versions, whereas `gawk` is a `run` (`build` and `run`) dependency for
gpi-2 versions greater or equal (less) than 1.4.0
2022-05-04 09:14:21 -07:00
Scott Wittenburg
6b6147d5a0 gitlab: Remove temporary storage url from all stacks (#29949)
Gitlab pipelines run for spack already have other S3 storage locations
configured for storage of binaries, so this PR removes the redundant
per-pipeline mirror.  As a result, the "cleanup" jobs will no longer be
generated at the end of each pipeline, removing one possible point of
pipeline failure.
2022-05-04 09:18:47 -06:00
Andrea Valenzuela
6702e87ee4 Add checksum for version 1.1.13 and update dependencies (#30470) 2022-05-04 10:08:43 -05:00
fpruvost
7ad5ca2cc3 chameleon: add maintainers information (#30472) 2022-05-04 08:57:44 -06:00
Auriane R
2418cfb79b pika: Add 0.4.0 release (#30469) 2022-05-04 16:29:30 +02:00
Ross Miller
9486c76d70 Use gccgo to bootstrap go on aarch64 (#30350)
The go-bootstrap package doesn't work on aarch64 platforms, so the only way
to build Go is to use gccgo.

Also, some versions of gccgo have a bug that prevents them from compiling
go (see golang/go#47771), so this patch limits gcc to versions newer than
10.4.0 or 11.3.0.

Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-05-04 16:16:53 +02:00
fpruvost
dc99fe98b9 chameleon: add new package (#30368) 2022-05-04 08:09:54 -06:00
Andrea Valenzuela
cb97b25646 Add checksum for py-plac@1.3.5 (#30327)
Co-authored-by: aandvalenzuela <andrea.valenzuela.ramirez@cern.ch>
2022-05-04 08:06:11 -06:00
Andrea Valenzuela
a84593a510 Add checksum for py-networkx@2.7.1 and fix python dependency (#30326)
Co-authored-by: aandvalenzuela <andrea.valenzuela.ramirez@cern.ch>
2022-05-04 08:05:51 -06:00
Paul Ferrell
2f6556ea82 mesa: intel needs c99 standard specified under intel. (#30334) 2022-05-04 14:21:25 +02:00
snehring
b4213b2c60 maq: adding perl dep, addressing gcc errors (#30312) 2022-05-04 14:07:02 +02:00
lpoirel
e378d96d15 namd: place an upper bound on the charmpp dependency version (#30397)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-05-04 13:58:25 +02:00
Axel Huebl
715686f0ec WarpX: add v22.05 (#30467)
Update `warpx` & `py-warpx` to the latest release, `22.05`.
2022-05-04 00:57:42 -06:00
snehring
d0fdaf6d03 igv: changing to 'all platforms' version. Adding igvtools variant. (#30379) 2022-05-04 08:29:06 +02:00
Adam J. Stewart
b8ebaa0813 py-shapely: add v1.8.2 (#30466) 2022-05-04 07:43:52 +02:00
Massimiliano Culpo
5c7d6c6e10 Remove deprecated "--run-tests" option of "spack install" (#30461) 2022-05-04 07:43:29 +02:00
eugeneswalker
96f9a1d88b boost: fix v1.78 build with oneapi (#30463) 2022-05-03 23:29:37 -06:00
Carlos Bederián
f5eb9fb501 autodock-vina: add versions up to v1.2.3, fixes (#30443)
* C++ package, use spack_cxx
* download from github, add 1.2.x versions
* remove patches already present in 1.1.2-boost-new release
* specify boost dependencies
2022-05-04 06:24:15 +02:00
Paul Ferrell
dd8f533e97 paraview: add LANL/TCE used variants for Paraview (#30336)
- Added +eyedomelighting
- Added +pagosa
- Added +fortran
- Added pandas dependency and min version
2022-05-04 06:18:35 +02:00
Glenn Johnson
bab41de538 ncl: constrain hdf5 dependency to version 1.10 (#29607) 2022-05-03 23:11:34 -05:00
Harsh Bhatia
17c1808ef7 new package: py-pytaridx (#30444)
* new package: pytaridx

* fixed copyright year

* Update git link

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

* added type in python depends

* added pypi link

* Update package.py

* Update package.py

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2022-05-03 23:10:49 -05:00
snehring
157ee3458f ea-utils: new version, cleanup, and newer gcc compat (#30204) 2022-05-04 06:06:59 +02:00
dependabot[bot]
3ce8bff22e build(deps): bump docker/setup-buildx-action from 1.6.0 to 1.7.0 (#30387)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](94ab11c41e...f211e3e9de)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  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>
2022-05-04 06:04:38 +02:00
Ethan Stam
281165693a ParaView: let paraview build its own verdict tpl (#30332) 2022-05-04 06:03:52 +02:00
eugeneswalker
f8653dfb9b mesa@22: gallium-xlib -> xlib (#30465) 2022-05-04 05:53:09 +02:00
Frank Willmore
a6589daa87 Vacuumms 1.1.1 (#30458)
* adding updated package for vacuumms

* deprecating old version

* add link to DOI

* style: trailing whitespace

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

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

Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
2022-05-03 19:13:43 -06:00
Richard Berger
43a503c195 flcl: add new versions (#30363)
* flcl: add new versions

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

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

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

Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>
2022-05-03 19:01:32 -06:00
Keita Iwabuchi
1eff83990b Metall Package: add v0.20 (#30446)
* Metall package: add dependency to GCC for build test

* Package Metall: add v.017

* Package Metall: update the package file

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

Co-authored-by: Bernhard Kaindl <43588962+bernhardkaindl@users.noreply.github.com>

* Metall package: add v0.18 and v0.19

* Metall Package: add v0.20

Co-authored-by: Bernhard Kaindl <43588962+bernhardkaindl@users.noreply.github.com>
2022-05-03 16:46:04 -07:00
Lucas Frérot
17e71a675a tamaas: new package (#30449)
* tamaas: added new package

* tamaas: passing dependency prefixes to build

* tamaas: Python 3.7 dependency

* tamaas: compiler conflicts and correct ~python

* tamaas: no newline in docstring

* tamaas: correct python build dep. when ~python
2022-05-03 16:17:17 -07:00
Adam J. Stewart
872aa32a00 py-matplotlib: add v3.5.2 (#30459) 2022-05-03 17:06:04 -06:00
Ken Raffenetti
4c19410669 mpich: add datatype engine variant (#30257)
Starting with MPICH 3.4, we offer different datatype engine options
(dataloop or yaksa). The default is 'auto', which will choose based on
the device configuration. Starting with MPICH 4.0, building against an
external yaksa library is supported.

Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-05-03 22:12:19 +02:00
Massimiliano Culpo
a5e92893d3 Simplify fixture used to test spack info (#30456) 2022-05-03 09:39:00 -07:00
Chuck Atkins
bdef031d4e opengl: Fix opengl concretization issues from missing versions (#30331) 2022-05-03 10:51:41 -05:00
asesidaa
a10f5656ab Add detection for hpcx-mpi in esmf (#30280) 2022-05-03 17:45:04 +02:00
Olivier Cessenat
653ed78645 keepassxc: add v2.7.1 (#30450) 2022-05-03 16:54:04 +02:00
haralmha
bc7fc8f456 flatbuffers: add v2.0.0 (#30455) 2022-05-03 16:53:24 +02:00
Ken Raffenetti
55bbbe8657 yaksa: add ROCm variant (#30222) 2022-05-03 16:52:31 +02:00
Mosè Giordano
a6dcce4cf2 swiftsim: do not build with -Werror (#30454) 2022-05-03 07:50:23 -07:00
Seth R. Johnson
e301de98cb Revert "qt: Fix the assimp dependency specification (#30435)" (#30451)
This reverts commit 4219b89faa.
2022-05-03 10:16:56 -04:00
Chris Richardson
6ecee4e6d5 Fix install of xsimd with xtensor (#30196) 2022-05-03 15:03:28 +02:00
Olivier Cessenat
2d89bc350c htop: add v3.2.0 (#30452) 2022-05-03 06:38:14 -05:00
Sinan
14e5497758 postgresql: add libs property (#30392)
Co-authored-by: sbulut <sbulut@3vgeomatics.com>
Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2022-05-03 09:24:59 +02:00
Brian Van Essen
4576fbe648 OpenCV and OpenBLAS: add external find support (#30240)
Added support for finding the OpenCV package via the find external
command. Included support for identifying variants based on available
shared libraries.

Added support to finding the OpenBLAS package via the find external
command.

Enabled packages to show that they can be discovered via the find
external command in the info message.

Updated the OpenCV and OpenBLAS packages to use the extensible search
mechanism for library extensions on multiple OS platforms.

Corrected how find externals works on Darwin for OpenCV and OpenBLAS
to accommodate that the version numbers are placed before the file
extension instead of after it, as on Linux.

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-05-03 09:04:50 +02:00
Sinan
84611b5f29 package/gdal fix config issue with +pg for newer gdal (#30421)
* package/gdal fix config issue with +pg for newer gdal

* fix version logic

* improve style

Co-authored-by: sbulut <sbulut@3vgeomatics.com>
2022-05-02 22:06:42 -05:00
Harsh Bhatia
cbf0c3a8c4 update version of py-mock, py-msgpack, py-gridformats, py-pyrsistent (#30445)
* add v3.0.3 for py-mock

* added v0.6.0 and 0.6.1 for py-msgpack

* added v0.4.0 for py-gridformats

* added v0.16.0 for py-pyrsistent
2022-05-02 20:17:54 -06:00
Chuck Atkins
d6c1619b67 mesa: Add v22.0.2 (#30439)
This adds v22.0.2 which also drops swr support.
2022-05-02 20:13:47 -06:00
Michele Martone
d23d611f35 librsb: added v1.3.0.1 (#30425)
* librsb: added v1.2.0.10 (#26043)

* librsb: add v1.2.0.11/v1.3.0.0 (#28636)

* librsb: add v1.3.0.1 (#30424)

* unconflict clang

* address apparent style issues

given
 https://github.com/spack/spack/runs/6248126997?check_suite_focus=true
and its excerpt

  var/spack/repos/builtin/packages/librsb/package.py:27: [E265] block comment should start with '# '
  var/spack/repos/builtin/packages/librsb/package.py:52: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:53: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:53: [E501] line too long (89 > 88 characters)
  var/spack/repos/builtin/packages/librsb/package.py:54: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:55: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:56: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:57: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:59: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:60: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:62: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:63: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:64: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:66: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:68: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:70: [E211] whitespace before '('
  var/spack/repos/builtin/packages/librsb/package.py:71: [E211] whitespace before '('

let these changes flow in.

* +asan+native: mark as conflict; thanks @tldahlgren

* +asan conflict grouped with other conflicts

As suggested as good Spack style by @tldahlgren .
2022-05-02 16:41:43 -06:00
Weiqun Zhang
8ed8922af5 amrex: add v22.05 (#30441) 2022-05-02 15:17:48 -06:00
laestrada
01c17562f5 gchp: added version 13.4.0 (#30442) 2022-05-02 13:55:50 -07:00
dlkuehn
c97d931ea7 masurca: add version 4.0.9 (#30440)
Co-authored-by: David Kuehn <las_dkuehn@iastate.edu>
2022-05-02 14:50:10 -06:00
Massimiliano Culpo
21bf0cf43c Fix issue in CI with Git 2.35 (#30436) 2022-05-02 20:49:53 +00:00
Ken Raffenetti
e2c72e583f spack ci: Fix typo in error message (#30438) 2022-05-02 20:33:54 +00:00
Chuck Atkins
4219b89faa qt: Fix the assimp dependency specification (#30435) 2022-05-02 16:22:13 -04:00
Carlos Bederián
253b208537 mesa: add 21.3.8 (#30412) 2022-05-02 12:40:30 -04:00
Kyle Gerheiser
4509e96704 git-lfs: add build-tools tag (#30431)
Let Spack find external git-lfs by default. There seemed to be agreement to add git-lfs to the build tools in https://github.com/spack/spack/pull/29031.
2022-05-02 09:02:42 -06:00
Stephen Hudson
f0bb7c74a9 libEnsemble: add v0.9.0 (#30409) 2022-05-02 08:26:36 -06:00
Erik Schnetter
c93fd4c600 netlib-lapack: add v3.10.1 (#30198) 2022-05-02 16:11:37 +02:00
Hadrien G
76d9df2cf1 acts: add v18.0.0 (#30219)
- Keep long lists in alphabetical order for easier reading
- Add a placeholder for Exa.TrkX plugin since we're missing a dep on the
  Spack side
- Add support for the ONNX plugin since Spack now has an ONNX runtime
  package
- Use spack's pybind11 package now that we're given the option to do so
2022-05-02 16:02:04 +02:00
Valentin Volkl
d2f67ff7b9 lcio: fix possible issue with root's cxxstd (#30241) 2022-05-02 15:55:15 +02:00
Jean-Paul Pelteret
b5b62b0c82 ADOL-C: Add a patch to force Colpack detection to fail (#30413) 2022-05-02 15:52:38 +02:00
eugeneswalker
e691d6df64 binutils@2.38 %gcc: add -fPIC -fcommon -Wl,-z,notext (#30345) 2022-05-02 15:38:07 +02:00
Luc Berger
25206c86c4 kokkos-kernels: add v3.6.00 (#30316) 2022-05-02 15:31:44 +02:00
Xavier Delaruelle
144d7cd932 environment-modules: add v5.1.0 (#30419) 2022-05-02 08:57:19 +02:00
Sebastian Ehlert
e7eceaf4e6 dftd4: add v3.4.0 (#30423) 2022-05-02 08:56:43 +02:00
Wouter Deconinck
f943cc0149 root: add v6.26.02 (#30426) 2022-05-02 08:55:57 +02:00
Wouter Deconinck
879949b78e gaudi: add v36.5 (#30427) 2022-05-02 08:54:50 +02:00
Michael Kuhn
38e5b96431 sysstat: add 12.4.5 and fix build failures (#30121)
This adds the newest stable version (and removes old development
versions), a few missing dependencies and workarounds for build
failures. Without the environment variables, sysstat will try creating
directories in `/var/log`, and without `--disable-file-attr`, sysstat
will try to change file ownership.
2022-05-02 08:24:11 +02:00
Todd Gamblin
9a028e3b15 bugfix: don't calculate spack tutorial version from version info
A recent switch to the way we do `develop` versioning broke this.  We
should hard-code the latest tutorial version.
2022-05-01 23:13:50 -07:00
Harmen Stoppels
f2c1b40e58 libxml2: new url, add 2.9.13 (#30401) 2022-04-29 23:22:24 -06:00
snehring
06b5217c01 hapcut2: adding new version 1.3.1 (#30383) 2022-04-29 16:06:47 -06:00
Paul R. C. Kent
52bf7f4157 Add 3.14.0 (#30384) 2022-04-29 14:23:12 -07:00
snehring
31eb759892 beagle: adding 5.4, making java dep more flexible. (#30354) 2022-04-29 14:11:20 -07:00
Cody Balos
b5f2c20f74 sundials: add 6.2.0 and logging-level variant (#30353) 2022-04-29 14:07:55 -07:00
Dan Bonachea
cf48588c45 Upcxx 2022.3.0 update (#30393)
* upcxx,gasnet: Add 2022.3.0 version hashes
* gasnet: Add ofi and ucx experimental conduits
* gasnet: Add CUDA and ROCm/HIP variants
* upcxx: Add Cray EX/Shasta detection and auto-config
* upcxx: Add ROCm/HIP support
* Use implicit dependencies from CudaPackage, ROCmPackage
2022-04-29 20:56:21 +00:00
Erik Schnetter
e59cde9b7f gsl: New version 2.7.1 (#30364) 2022-04-29 13:32:27 -07:00
snehring
7e54bddc0c gdal: changing behavior of configure for +xml2 with 3.0+ (#30405)
* gdal: changing behavior of configure for +xml2 with 3.0+

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

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2022-04-29 20:11:46 +00:00
snehring
7f1411d131 diamond: updating to 2.0.15 (#30386) 2022-04-29 13:58:30 -06:00
dmentock
f0afceeb9c added libpng version 1.5.30 to libpng package (#30395) 2022-04-29 12:43:30 -07:00
Satish Balay
7ee15553e4 petsc, py-petsc4py: add 3.17.1 (#30399) 2022-04-29 12:40:44 -07:00
haralmha
d062d2e92b hto4l: Set GSL_HOME (#30402) 2022-04-29 12:32:40 -07:00
Erik Schnetter
7c631d1c55 autoconf-archive: New version 2022.02.11 (#30403) 2022-04-29 12:31:23 -07:00
Asher Mancinelli
6df71118fb Pass blas flags to hsl lflags when ^coinhsl+blas (#30309) 2022-04-29 12:46:43 -06:00
Erik Schnetter
ed7812b8be sqlite: New version 3.38.3 (#30370) 2022-04-29 12:02:55 -06:00
agoodLANL
ff03ac3e06 itstool: version 2.0.7 and py2 dependency (#30375)
* Added version 2.0.7 and a conflict

* added maintainer
2022-04-29 10:43:18 -06:00
Erik Schnetter
b6ae2436be libjpeg-turbo: New version 2.1.3 (#30366) 2022-04-29 10:42:55 -06:00
Andrea Valenzuela
ec266a86b6 Add checksum for py-prettytable@3.2.0 (#30329)
* Add checksum for py-more-itertools@8.12.0 and fix python dependency

* Add checksum for py-prettytable@3.2.0

* Package version 8.11.0 is the only version that requires python 3.6+

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

* Add reference to python@3.6 support when 8.11

* Revert "Add reference to python@3.6 support when 8.11"

This reverts commit 0ba0002193.

* Add python 3.7: requirement

* Revert range for python 3.6

* Revert py-more-itertools modifications

Co-authored-by: aandvalenzuela <andrea.valenzuela.ramirez@cern.ch>
Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2022-04-29 10:33:04 -05:00
Jennifer Green
ecbac17217 htop: new variants (#30398)
* htop variants for debug, hwloc, unicode support

* removed redundant ncurses dep
2022-04-29 08:42:42 -06:00
Erik Schnetter
43a84f58e9 libjpeg: New version 9e (#30365) 2022-04-29 06:46:34 -06:00
Harmen Stoppels
9ed37742e9 squashfs: new version, deprecated older versions (#30361) 2022-04-29 11:17:44 +02:00
Harmen Stoppels
dbe2c44a25 netcdf-fortran: add compat bound for netcdf-c (#30358) 2022-04-29 11:16:51 +02:00
luker
f40780310b CrayPE_binutils package fix for CCE (#30338) 2022-04-29 09:36:52 +02:00
Massimiliano Culpo
c06f69d0bf spack.yaml: add concretizer.yaml to the schema (#30376) 2022-04-29 01:06:36 -06:00
Sinan
8a6b73bb2c package/kealib: add libs property (#30391)
Co-authored-by: sbulut <sbulut@3vgeomatics.com>
2022-04-29 02:38:19 +00:00
lpoirel
9e6298569e Delocalize type output for bash completion (#30360) 2022-04-28 23:24:10 +00:00
Sergey Kosukhin
ad0430f463 netcdf-fortran: do not build with MPI wrappers (#30371) 2022-04-29 01:19:42 +02:00
Erik Schnetter
7d26d56e59 meson: New version 0.62.1 (#30367) 2022-04-28 14:26:36 -06:00
Erik Schnetter
06988c38fd reprimand: New version 1.4 (#30369) 2022-04-28 12:58:11 -07:00
kwryankrattiger
f6d2b07368 SDK: Require paraview@5.10: in the ECP SDK (#30372)
* SDK: Require paraview@5.10: in the ECP SDK

* SDK: Updated dev src conflicts to be more explicit
2022-04-28 13:38:42 -06:00
Peter Scheibel
bb43308c44 Add command for reading JSON-based DB description (now with more tests) (#29652)
This is an amended version of https://github.com/spack/spack/pull/24894 (reverted in https://github.com/spack/spack/pull/29603). https://github.com/spack/spack/pull/24894
broke all instances of `spack external find` (namely when it is invoked without arguments/options)
because it was mandating the presence of a file which most systems would not have.
This allows `spack external find` to proceed if that file is not present and adds tests for this.

- [x] Add a test which confirms that `spack external find` successfully reads a manifest file
      if present in the default manifest path

--- Original commit message ---

Adds `spack external read-cray-manifest`, which reads a json file that describes a
set of package DAGs. The parsed results are stored directly in the database. A user
can see these installed specs with `spack find` (like any installed spec). The easiest
way to use them right now as dependencies is to run
`spack spec ... ^/hash-of-external-package`.

Changes include:

* `spack external read-cray-manifest --file <path/to/file>` will add all specs described
  in the file to Spack's installation DB and will also install described compilers to the
  compilers configuration (the expected format of the file is described in this PR as well including examples of the file)
* Database records now may include an "origin" (the command added in this PR
  registers the origin as "external-db"). In the future, it is assumed users may want
  to be able to treat installs registered with this command differently (e.g. they may
  want to uninstall all specs added with this command)
* Hash properties are now always preserved when copying specs if the source spec
  is concrete
  * I don't think the hashes of installed-and-concrete specs should change and this
    was the easiest way to handle that
  * also specs that are concrete preserve their `.normal` property when copied
    (external specs may mention compilers that are not registered, and without this
    change they would fail in `normalize` when calling `validate_or_raise`)
  * it might be this should only be the case if the spec was installed

- [x] Improve testing
- [x] Specifically mark DB records added with this command (so that users can do
      something like "uninstall all packages added with `spack read-external-db`)
  * This is now possible with `spack uninstall --all --origin=external-db` (this will
    remove all specs added from manifest files)
- [x] Strip variants that are listed in json entries but don't actually exist for the package
2022-04-28 10:56:26 -07:00
Massimiliano Culpo
6a9df34abd ASP-based solver: discard unknown packages from reuse (#30357)
* ASP-based solver: discard unknown packages from reuse

This is an add-on to #28259 that cover for the case of
a single package.py being removed from a repository,
rather than an entire custom repository being removed.

* Add unit test
2022-04-28 10:40:28 -07:00
Frédéric Simonis
1006dd54de Add BUILD_TESTING to standard CMake arguments (#30374)
CTest determines whether to enable tests using the BUILD_TESTING variable.
This should be used by projects to conditionally enable the compilation of tests.
Spack knowns which packages have to run tests and can thus automatically define this variable.
2022-04-28 17:03:13 +00:00
Andrea Valenzuela
cf905ec14a Add checksum for py-poetry-core@1.0.8 (#30359)
Co-authored-by: aandvalenzuela <andrea.valenzuela.ramirez@cern.ch>
2022-04-28 11:24:08 -05:00
Andrea Valenzuela
19bb4bdeb8 Add checksum for py-more-itertools@8.12.0 and fix python dependency (#30325)
* Add checksum for py-more-itertools@8.12.0 and fix python dependency

* Package version 8.11.0 is the only version that requires python 3.6+

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

* Add reference to python 3.6 dependency

Co-authored-by: aandvalenzuela <andrea.valenzuela.ramirez@cern.ch>
Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2022-04-28 10:23:10 -06:00
Andrew Davison
47f9e71302 py-quantities: add versions from 0.12.2-13.0 (#28586)
* py-quantities: add versions from 0.12.2-13.0

* Attempt to fix the version specification

* add maintainer, implement suggestions from reviewer
2022-04-28 11:14:50 -05:00
Chris White
2e9da47a2d Ascent/Conduit: re-add fortran compiler that was mistakenly removed (#30351) 2022-04-28 07:09:40 -07:00
Greg Becker
3e863848f8 build_env/test_env: add concretizer args (#30289) 2022-04-28 11:37:15 +02:00
Harmen Stoppels
e7a0b952ab install --overwrite: use rename instead of tmpdir (#29746)
I tried to use --overwrite on nvhpc, but nvhpc's install size is 16GB. Seems
better to do os.rename in the same directory than moving the directory to
`/tmp`.

- [x] install --overwrite: use rename instead of tmpdir
- [x] use tempfile
2022-04-28 01:42:42 -06:00
Patrick Broderick
8b85b33ba5 Add spiral fftx (#28583)
* add fftx package; rename spiral to spiral-software and add spiral-package-*
* Update year in copyright notice
* Add package description to FFTX/package.py
* Changes to package files for SPIRAL & FFTX for PR
* Update package definitions
* remove unnecessary lines
2022-04-27 22:26:44 -07:00
Larry Knox
90dafdd9f0 Add HDF5 version 1.12.2. (#30348) 2022-04-27 22:50:28 -06:00
Paul R. C. Kent
d989478154 llvm: Add 14.0.1 14.0.2 (#30347) 2022-04-27 20:22:40 -06:00
Wileam Y. Phan
ebd930ace9 Add Python chmod +x equivalent in fpm package (#30342) 2022-04-28 00:16:19 +00:00
Erik Schnetter
53e0e7aabe z3: New version 4.8.16 (#30328) 2022-04-27 17:10:15 -07:00
dlkuehn
27cbc4ebc8 tcsh: add version 6.24.00 (#30346)
Co-authored-by: David Kuehn <las_dkuehn@iastate.edu>
2022-04-27 23:43:06 +00:00
Asher Mancinelli
2515cafb9c hiop: Enable barebones testing (#30313)
* Enable barebones testing

Run 6 test cases representative of the entire HiOp test suite.

* Apply style changes

* Dont use unpacking for py2 compat
2022-04-27 23:08:33 +00:00
Annop Wongwathanarat
5593611b5e armpl: add new package (#30305)
Co-authored-by: Annop Wongwathanarat <annop.wongwathanarat@arm.com>
2022-04-27 15:25:47 -07:00
dlkuehn
f544b051c4 orthofinder: add version 2.5.4 (#30344)
Co-authored-by: David Kuehn <las_dkuehn@iastate.edu>
2022-04-27 22:23:34 +00:00
Luc Berger
c534e70950 Kokkos: update package for release 3.6.00 (#30315) 2022-04-27 13:52:15 -07:00
Paul Ferrell
9ffb3b4ac0 mvapich2 MPI_ROOT needed in modules (#30335)
We've found that when using mvapich2 via modules, we need to set the MPI_ROOT
environment variable.
2022-04-27 13:41:06 -07:00
kwryankrattiger
893c5271ac Update ascent and deps for 0.8.x (#29954)
* Update package versions for Ascent/SDK

* Umpire build static for cuda from dray

* Propagate cuda_arch for ascent and dray packages.

* Ascent: Update dependency versions for ascent@0.8:

* VTK-h: Patch +shared+cuda for VTK-h 0.8.x

* Ascent: Patch to allow @0.8: +shared+cuda

* Turn off building ascent tests.

* Update ascent patch

* WIP: Ascent: Update patch to configure MPI build with CUDA

* Ascent: Tests require vtk-m+testlib

* WIP: Ascent: Constrain 0.7 for vtk-h

* Ascent: Directly depend on VTK-m
2022-04-27 13:39:18 -06:00
eugeneswalker
f7a9456553 e4s ci: uncomment umpire (#29776) 2022-04-27 18:22:46 +00:00
kwryankrattiger
8250235207 Mesa: Constrain compatible LLVM version (#30102)
Base on release date, not actual compatibility, because LLVM
version compatibility is not documented clearly in Mesa for
upper version limits.
2022-04-27 12:03:02 -06:00
Lucas Frérot
eb51591b02 SCons: added versions 4.0.0-4.3.0 (#30296)
* SCons: added versions 4.0.0-4.3.0

* scons: correct package name casing in url_for_version
2022-04-27 11:08:30 -05:00
Brian Van Essen
06e7249850 Allow PyTorch to forward gcc-toolchain cxxcflag to CUDA toolchains (#30318) 2022-04-27 10:48:06 -05:00
Martin Diehl
c4ad003af2 damask-*: add v3.0.0alpha6 (#30124) 2022-04-27 16:01:36 +02:00
dependabot[bot]
1243717012 build(deps): bump actions/checkout from 2 to 3.0.2 (#30235)
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.0.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...2541b1294d2704b0964813337f33b291d3f8596b)

---
updated-dependencies:
- dependency-name: actions/checkout
  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>
2022-04-27 13:47:50 +02:00
snehring
da3d315cba blat: add v37 (#30166) 2022-04-27 12:26:57 +02:00
Michael Kuhn
48ff4c7679 rust: add 1.60.0 and fix libgit2 incompatibility (#30123) 2022-04-27 12:22:52 +02:00
liuyangzhuan
9fc6494a28 Added GPTune v3.0.0 and its dependency py-pymoo (#30119) 2022-04-27 12:21:44 +02:00
Valentin Volkl
9d4cedac51 tauola: fix ~lhapdf (#30190) 2022-04-27 12:16:08 +02:00
Derek Ryan Strong
f66139dfe4 Add fix for binutils 2.38 +gas makeinfo issue (#30209)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-04-27 12:11:48 +02:00
nfurmento
79e0a3dad0 Starpu and Fxt: new packages (#29285) 2022-04-27 12:10:09 +02:00
dependabot[bot]
3dbbf3a101 build(deps): bump codecov/codecov-action from 3.0.0 to 3.1.0 (#30234)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md)
- [Commits](e3c560433a...81cd2dc814)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  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>
2022-04-27 11:26:19 +02:00
Harmen Stoppels
f273e7d329 openmpi: add toggle for rsh plm (#30251)
By default `openmpi` needs `rsh` from `openssh`, which is a somewhat
redundant dependency for clusters using slurm. This PR adds a toggle to
allow users to disable the ssh/rsh plm altogether.
2022-04-27 11:15:48 +02:00
snehring
351072cd9f gcta: rework package recipe (#30286) 2022-04-27 08:56:31 +00:00
Adam J. Stewart
0b23f1be05 py-pil: deprecate package (#30308) 2022-04-27 02:34:29 -06:00
Glenn Johnson
b8015a71e9 relion: add altcpu variant and fix fftw (#30097)
This package was not setting FFTW when +mklfft was used with +cuda.
Since both were set to 'True', the default build was not linked to
any FFTW, leading to a run time error. It seems MKL support was
conflated with alternative CPU acceleration support. This PR does the
following:

- adds the altcpu variant to specify non-GPU/CPU acceleration
- sets a conflict between +altcpu and +cuda
- sets an FFTW implementation
- sets fltk+xft when +gui to get a decent looking GUI interface
- sets tbb dependency only when +altcpu
- adds dependency on ctffind
- adds variant and dependency on motioncor2
- sets defaults for
    - qsub template location
    - ctffind location
    - motioncor2 location

Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-04-27 10:30:39 +02:00
snehring
739f040fa8 bucky: fix compile errors with newer gccs (#30314) 2022-04-27 02:11:02 -06:00
Massimiliano Culpo
d5fc859f46 ASP-based solver: handle installed specs from unknown namespaces (#30092)
fixes #28259

This commit discard specs from unknown namespaces from the
ones that can be "reused" during concretization. Previously
Spack would just error out when encountering them.
2022-04-27 02:10:46 -06:00
Erik Schnetter
753f4a4bc3 reprimand: update requests on boost (#30109) 2022-04-27 09:46:22 +02:00
Lhxone
8c280d98ca suntans: add new package (#30149) 2022-04-27 09:35:40 +02:00
eugeneswalker
d5e1fa5771 py-cryptography@35: tell cargo to use cli git, not cargo internal git… (#30307) 2022-04-26 20:58:28 -06:00
Michael Kuhn
f30b79b2c5 libgit2: add 1.4.3 and 1.3.1 (#30122) 2022-04-26 20:54:30 -06:00
Erik Schnetter
54146d44f9 fossil: New package (#30311)
* fossil: new package

* fossil: Format code
2022-04-27 00:47:24 +00:00
Tamara Dahlgren
0c31ab87c9 Feature: Allow re-use of run_test() in install_time_test_callbacks (#26594)
Allow re-use of run_test() in install_time_test_callbacks

Co-authored-by: Greg Becker <becker33@llnl.gov>
2022-04-26 17:40:05 -07:00
Lhxone
e49cccb0d9 New package: CaNS (#30218) 2022-04-27 00:33:36 +00:00
haralmha
7a1841c464 hadoop: Update url and add version 3.3.2 (#29812)
* hadoop: Update url and add version 3.3.2

* Update url
2022-04-26 17:26:28 -07:00
haralmha
40ebeb2dc8 arrow: Add version 7.0.0 (#29962) 2022-04-26 16:57:56 -07:00
Lhxone
e5444b9a77 New package: Swan (#30217) 2022-04-26 16:32:19 -07:00
haralmha
89cc16a9cd gnuplot: Add version 5.4.3 and add workaround for not found DSO (#30163) 2022-04-26 16:03:36 -07:00
Ken Raffenetti
a24070d532 docs: Fix ROCmPackage example syntax (#30168) 2022-04-26 16:00:40 -07:00
Kyle Gerheiser
f473fd8084 Add g2tmpl versions 1.10.2 and 1.10.1 (#30202) 2022-04-26 15:56:06 -07:00
John Hodrien
5055f5e3e2 Power9 build fix for ctffind4 (#30300)
Only tested against the latest version, which is why it only applies the patch
when using 4.1.14.

Fix comes from:

https://grigoriefflab.umassmed.edu/forum/software/ctffind_ctftilt/installing_ctffind_4114_ibm_power9
2022-04-26 17:13:37 -05:00
Joel Falcou
0b26103c07 EVE now use main instead of develop as main branch (#30220) 2022-04-26 15:34:45 -06:00
Greg Becker
f99614be02 old concretizer: update deprecation warning (#30227) 2022-04-26 14:17:17 -07:00
Mark W. Krentel
c02e83092e intel-xed: add version 2022.04.17 (#30239)
1. Add version 2022.04.17 (new numbering scheme) and update mbuild resource.
2. Branch 'master' is now 'main'.
3. Old rev 10.2019.03 needs a patch for python vs python3.
2022-04-26 14:15:10 -07:00
Kyle Gerheiser
85e99fa154 Add NCIO v1.1.0 (#30306)
See release notes https://github.com/NOAA-EMC/NCEPLIBS-ncio/releases/tag/v1.1.0
2022-04-26 21:03:26 +00:00
John W. Parent
83b91246b1 Windows: fix termination of process output redirection (#29923)
The parent thread in the process stdout redirection logic on Windows
was closing a file that was being read in child thread, which lead to
error-based termination of the reader thread. This updates the
interaction to avoid the error.
2022-04-26 12:56:13 -07:00
Andrea Valenzuela
0f4b228eff Add checksum for py-ipywidgets@7.7.0 (#30155)
* Add checksum for py-ipywidgets@7.7.0

* Correct py-widgetsnbextension and py-ipython dependencies

* Update widgetsnbextension dependency to 3.6

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

* Allow requirement to next versions

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

* Revert ipyhton dependencies

* Add widgetsnbextension@3.6.0 checksum

Co-authored-by: aandvalenzuela <andrea.valenzuela.ramirez@cern.ch>
Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2022-04-26 14:48:53 -05:00
Lucas Frérot
2abbad1ca5 thrust: added version 1.12.1-1.16.0 (#30292) 2022-04-26 11:27:25 -07:00
Lucas Frérot
43d8fe212f py-uvw: updated versions (#30297) 2022-04-26 10:06:41 -07:00
Valentin Volkl
84befcdfe2 opendatadetector: add new package (#30298)
* opendatadetector: add new package

* style

* opendatadetector: add hep tag
2022-04-26 09:25:41 -07:00
Tamara Dahlgren
def8fce250 ginkgo: fix stand-alone test directory / install_test (#28412) 2022-04-26 09:20:10 -07:00
lorddavidiii
3a0aba0835 spack spec: add '--format' argument (#27908) 2022-04-26 09:08:56 -07:00
snehring
254cd624fe exabayes: specify c++11 (#30282) 2022-04-26 17:22:27 +02:00
Erik Schnetter
802a48fb43 boost: update list of modules (#30104)
Co-authored-by: Tim Haines <thaines.astro@gmail.com>
2022-04-26 17:12:47 +02:00
Mark W. Krentel
c81affa551 setup_package: don't unload modules on Cray when run with --dirty (#30261)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-04-26 16:53:10 +02:00
Simon Pintarelli
3e51304b68 spfft: pass cuda_arch to cmake (#30295) 2022-04-26 14:59:48 +02:00
snehring
62abbeaf6f express: specify patch version range (#30283) 2022-04-26 11:27:32 +02:00
H. Joe Lee
80e24f3f69 googletest: change "master" to "main" (#30285)
There's no master branch on GitHub for googletest.
2022-04-26 11:27:08 +02:00
dlkuehn
24f5069584 snpeff: change jdk dependency to java (#30048)
Co-authored-by: David Kuehn <las_dkuehn@iastate.edu>
2022-04-26 11:25:03 +02:00
Kevin Huck
5da78991d4 apex: add v2.5.1 (#30287) 2022-04-26 11:19:07 +02:00
Asher Mancinelli
cfb5d5f988 hiop: add v0.6.1, add new variant "cusolver" (#30288) 2022-04-26 11:12:14 +02:00
Michael Kuhn
a10d262f5f glib: add 2.72.1 and 2.70.5 (#30274) 2022-04-26 11:10:34 +02:00
Harmen Stoppels
16e926d374 gawk: drop gettext by default (#30290)
Reduces the number of packages to bootstrap gcc (which actually has
--disable-nls).
2022-04-26 11:02:03 +02:00
Massimiliano Culpo
b9d6a5103d ASP-based solver: allow configuring target selection (#29835)
* ASP-based solver: allow configuring target selection

This commit adds a new "concretizer:targets" configuration
section, and two options under it.

 - "concretizer:targets:granularity" allows switching from
considering only generic targets to consider all possible
microarchitectures.

 - "concretizer:targets:host_compatible" instead controls
whether we can concretize for microarchitectures that
are incompatible with the current host.

* Add documentation

* Add unit-tests
2022-04-25 17:19:51 -07:00
iarspider
834f8e04ca Environments: add flag to skip printing concretized specs (#30272)
With an active environment, you can now run "spack concretize --quiet"
and it will suppress printing the concretized specs.
2022-04-25 15:54:54 -07:00
Rohit Goswami
3ade5516a2 MAINT: Add a debug variant to PyTorch (#30267)
* MAINT: Add a debug flag

* MAINT: Apply suggestions from code review

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

Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
2022-04-25 15:33:37 -05:00
eugeneswalker
b41de6d86b exago +cuda, +rocm: pass amdgpu_target, cuda_arch to dependencies, as appropriate (#30259)
* exago +rocm: pass amdgpu_target to raja, hiop dependencies

* +cuda builds: pass cuda_arch to dependencies

* hiop: pass cuda_arch to dependencies
2022-04-25 19:48:35 +00:00
Erik Schnetter
c72fba7e4c gcc: Make gcc 11.3 build on Darwin (#30278)
Don't apply a Darwin-specific patch that doesn't work on 11.3 any more.

Closes https://github.com/spack/spack/issues/30264.
2022-04-25 20:15:51 +02:00
Erik Schnetter
96113a5dc6 gcc: Make gcc 11.3 build on Darwin (#30278)
Don't apply a Darwin-specific patch that doesn't work on 11.3 any more.

Closes https://github.com/spack/spack/issues/30264.
2022-04-25 20:15:31 +02:00
Seth R. Johnson
db0335fa54 OpenMPI: improve PMix handling (#29449)
* openmpi: always require pmix for 4:

`~pmix` is not applicable to version 4+, since it always builds a vendored
copy of pmix (currently 3.2.3).

* pmix: relax version requirements

When the version range was specified, newer versions didn't exist.
Also use normalized spack versions rather than artificial .9.9 /.0.0.

* openmpi: restrict pmix versions

pmix option isn't available for OpenMPI@1, and according to
https://github.com/open-mpi/ompi/issues/7988 , OpenMPI 4.0.1 will not
build with pmix@3.1.5.

* pmix: add newer versions

* OpenMPI: re-express conflicts/configure logic as conditional variants

This relies partly on `self.enable_or_disable` and its ilk to emit an
empty list when the variant isn't applicable.
2022-04-25 11:54:20 -06:00
Massimiliano Culpo
268c671dc8 ASP-based solver: always consider version of installed packages (#29933)
* ASP-based solver: always consider version of installed packages

fixes #29201

Explicitly add facts for versions of installed software when
using the --reuse option, so that we could consider versions
that are not declared in package.py
2022-04-25 10:09:49 -07:00
Harmen Stoppels
3dd4999fd7 spec.py: make parser select from environment (#30276)
The parser is already committing a crime of querying the database for
specs when it encounters a `/hash`. It's helpful, but unfortunately not
helpful when trying to install a specific spec in an environment by
hash. Therefore, consider the environment first, then the database.

This allows the following:

```console
$ spack -e . concretize
==> Starting concretization
==> Environment concretized in 0.27 seconds.
==> Concretized diffutils
 -   7vangk4  diffutils@3.8%gcc@10.3.0 arch=linux-ubuntu20.04-zen2
 -   hyb7ehx      ^libiconv@1.16%gcc@10.3.0 libs=shared,static arch=linux-ubuntu20.04-zen2

$ spack -e . install /hyb7ehx
==> Installing libiconv-1.16-hyb7ehxxyqqp2hiw56bzm5ampkw6cxws
...
==> libiconv: Successfully installed libiconv-1.16-hyb7ehxxyqqp2hiw56bzm5ampkw6cxws
  Fetch: 0.01s.  Build: 17.54s.  Total: 17.55s.
[+] /tmp/tmp.VpvYApofVm/store/linux-ubuntu20.04-zen2/gcc-10.3.0/libiconv-1.16-hyb7ehxxyqqp2hiw56bzm5ampkw6cxws
```
2022-04-25 08:41:48 -07:00
Hervé Yviquel
c1ed51e767 mpich: add variant to enable per VCI critical sections (#27840) 2022-04-25 17:31:13 +02:00
Theofilos Manitaras
2a8a0aa156 Add libfabric version 1.14.1 (#30275) 2022-04-25 08:51:12 -06:00
eugeneswalker
5073613c6e slepc +rocm: pass amdgpu_target to dep (#30252) 2022-04-25 08:50:49 -06:00
Vicente Bolea
4a76ca1f5e vtk-m: add v1.8.0-rc1 (#30233) 2022-04-25 16:49:38 +02:00
Mark W. Krentel
878e6b6712 hpctoolkit: add version 2022.04.15, update recipe (#30258)
1. update for rocm 4.5 and drop support for earlier rocm.
2. no longer use mbedtls or gotcha, they are only for old revs.
3. update version requirements for dyninst and libmonitor
4. begin to deprecate old versions
2022-04-25 16:40:00 +02:00
Erik Schnetter
aeba9daea6 mpiwrapper: add new package (#30107)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
2022-04-25 15:01:39 +02:00
Matthew Archer
25d115ba1a ufcx: add new package (#29861) 2022-04-25 14:50:45 +02:00
Adam J. Stewart
f37e07a882 GDAL: don't add system paths to env vars (#30229) 2022-04-25 14:48:46 +02:00
Seth R. Johnson
4c0cc5a295 testu01: new package (#30266) 2022-04-25 14:46:52 +02:00
Qian Jianhua
57968e7ad4 fakexrandr: mkdir for install (#29845) 2022-04-25 14:42:15 +02:00
Qian Jianhua
02a7fc69ed pgplot: fix syntax error in recipe (#30270) 2022-04-25 14:32:04 +02:00
Todd Gamblin
d729b4e72b bugfix: installed and installed_upstream should not assert (#30271)
Fix bug introduced in #30191. `Spec.installed` and `Spec.installed_upstream` should just return
`False` for abstract specs, as they can be called in that context.

- [x] `Spec.installed` returns `False` now instead of asserting that the `Spec`
      is concrete.
- [x] `Spec.installed_upstream` returns `False` now instead of asserting that the `Spec`
      is concrete.
- [x] `Spec.installed_upstream` no longer caches its result, as install status seems
      like a bad thing to cache -- it can easily be invalidated. Calling code should
      use transactions if there are peformance issues, as with other places in Spack.
- [x] add tests for `Spec.installed` and `Spec.installed_upstream`
2022-04-25 07:46:21 +00:00
Mark W. Krentel
35a4c2325e hpcviewer: add version 2022.03 (#30255) 2022-04-25 09:40:43 +02:00
Diego Alvarez
6253445b13 Added nextflow 22.04.0 (#30265) 2022-04-23 14:17:41 -07:00
H. Joe Lee
dea5fe87f7 Hermes: new package (#29863) 2022-04-23 06:38:14 -06:00
QuellynSnead
6162ea95b0 trilinos: limit secas patch range for cce (#30205)
The cray_secas.patch no longer appears to be necessary
with cce 13.x. Limit its application to cce 12.14.1 - 12.99.99.
2022-04-23 07:01:13 -04:00
Erik Schnetter
44b409d696 memkind: Don't use -Werror when building (#30071) 2022-04-23 09:16:47 +02:00
Massimiliano Culpo
a9fbc0175d Move "installed" and "installed_upstream" from PackageBase to Spec (#30191)
This PR moves the `installed` and `installed_upstream` properties from `PackageBase` to `Spec` and is a step towards being able to reuse specs for which we don't have a `package.py` available. It _should_ be sufficient to complete the concretization step and see the spec in the concretized DAG.

To fully reuse a spec without a package.py though we need a way to serialize enough data to reconstruct the results of calls to:
- `Spec.libs`, `Spec.headers` and `Spec.ommand`
- `Package.setup_dependent_*_environment` and `Package.setup_run_environment`

- [x] Add stub methods to packages with warnings
- [x] Add a missing "root=False" in cmd/fetch.py
- [x] Assert that a spec is concrete before checking installation status
2022-04-22 16:46:45 -07:00
699 changed files with 17440 additions and 4728 deletions

View File

@@ -24,6 +24,7 @@ jobs:
fedora-clingo-sources:
runs-on: ubuntu-latest
container: "fedora:latest"
if: github.repository == 'spack/spack'
steps:
- name: Install dependencies
run: |
@@ -31,14 +32,20 @@ jobs:
bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \
make patch unzip which xz python3 python3-devel tree \
cmake bison bison-devel libstdc++-static
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- name: Setup repo and non-root user
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- name: Setup non-root user
run: |
# See [1] below
git config --global --add safe.directory /__w/spack/spack
useradd spack-test && mkdir -p ~spack-test
chown -R spack-test . ~spack-test
- name: Setup repo
shell: runuser -u spack-test -- bash {0}
run: |
git --version
git fetch --unshallow
. .github/workflows/setup_git.sh
useradd spack-test
chown -R spack-test .
- name: Bootstrap clingo
shell: runuser -u spack-test -- bash {0}
run: |
@@ -51,6 +58,7 @@ jobs:
ubuntu-clingo-sources:
runs-on: ubuntu-latest
container: "ubuntu:latest"
if: github.repository == 'spack/spack'
steps:
- name: Install dependencies
env:
@@ -61,22 +69,20 @@ jobs:
bzip2 curl file g++ gcc gfortran git gnupg2 gzip \
make patch unzip xz-utils python3 python3-dev tree \
cmake bison
- name: Work around CVE-2022-24765
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- name: Setup non-root user
run: |
# Apparently Ubuntu patched git v2.25.1 with a security patch that introduces
# a breaking behavior. See:
# - https://github.blog/2022-04-12-git-security-vulnerability-announced/
# - https://github.com/actions/checkout/issues/760
# - http://changelogs.ubuntu.com/changelogs/pool/main/g/git/git_2.25.1-1ubuntu3.3/changelog
# See [1] below
git config --global --add safe.directory /__w/spack/spack
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- name: Setup repo and non-root user
useradd spack-test && mkdir -p ~spack-test
chown -R spack-test . ~spack-test
- name: Setup repo
shell: runuser -u spack-test -- bash {0}
run: |
git --version
git fetch --unshallow
. .github/workflows/setup_git.sh
useradd -m spack-test
chown -R spack-test .
- name: Bootstrap clingo
shell: runuser -u spack-test -- bash {0}
run: |
@@ -89,6 +95,7 @@ jobs:
ubuntu-clingo-binaries-and-patchelf:
runs-on: ubuntu-latest
container: "ubuntu:latest"
if: github.repository == 'spack/spack'
steps:
- name: Install dependencies
env:
@@ -98,22 +105,20 @@ jobs:
apt-get install -y \
bzip2 curl file g++ gcc gfortran git gnupg2 gzip \
make patch unzip xz-utils python3 python3-dev tree
- name: Work around CVE-2022-24765
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- name: Setup non-root user
run: |
# Apparently Ubuntu patched git v2.25.1 with a security patch that introduces
# a breaking behavior. See:
# - https://github.blog/2022-04-12-git-security-vulnerability-announced/
# - https://github.com/actions/checkout/issues/760
# - http://changelogs.ubuntu.com/changelogs/pool/main/g/git/git_2.25.1-1ubuntu3.3/changelog
# See [1] below
git config --global --add safe.directory /__w/spack/spack
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- name: Setup repo and non-root user
useradd spack-test && mkdir -p ~spack-test
chown -R spack-test . ~spack-test
- name: Setup repo
shell: runuser -u spack-test -- bash {0}
run: |
git --version
git fetch --unshallow
. .github/workflows/setup_git.sh
useradd -m spack-test
chown -R spack-test .
- name: Bootstrap clingo
shell: runuser -u spack-test -- bash {0}
run: |
@@ -121,10 +126,10 @@ jobs:
spack -d solve zlib
tree ~/.spack/bootstrap/store/
opensuse-clingo-sources:
runs-on: ubuntu-latest
container: "opensuse/leap:latest"
if: github.repository == 'spack/spack'
steps:
- name: Install dependencies
run: |
@@ -134,9 +139,12 @@ jobs:
bzip2 curl file gcc-c++ gcc gcc-fortran tar git gpg2 gzip \
make patch unzip which xz python3 python3-devel tree \
cmake bison
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- name: Setup repo and non-root user
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- name: Setup repo
run: |
# See [1] below
git config --global --add safe.directory /__w/spack/spack
git --version
git fetch --unshallow
. .github/workflows/setup_git.sh
@@ -150,11 +158,13 @@ jobs:
macos-clingo-sources:
runs-on: macos-latest
if: github.repository == 'spack/spack'
steps:
- name: Install dependencies
run: |
brew install cmake bison@2.7 tree
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- name: Bootstrap clingo
run: |
source share/spack/setup-env.sh
@@ -169,12 +179,14 @@ jobs:
strategy:
matrix:
python-version: ['3.5', '3.6', '3.7', '3.8', '3.9', '3.10']
if: github.repository == 'spack/spack'
steps:
- name: Install dependencies
run: |
brew install tree
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6 # @v2
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6
with:
python-version: ${{ matrix.python-version }}
- name: Bootstrap clingo
@@ -189,12 +201,14 @@ jobs:
strategy:
matrix:
python-version: ['2.7', '3.5', '3.6', '3.7', '3.8', '3.9', '3.10']
if: github.repository == 'spack/spack'
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6 # @v2
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6
with:
python-version: ${{ matrix.python-version }}
- name: Setup repo and non-root user
- name: Setup repo
run: |
git --version
git fetch --unshallow
@@ -209,6 +223,7 @@ jobs:
ubuntu-gnupg-binaries:
runs-on: ubuntu-latest
container: "ubuntu:latest"
if: github.repository == 'spack/spack'
steps:
- name: Install dependencies
env:
@@ -218,22 +233,20 @@ jobs:
apt-get install -y \
bzip2 curl file g++ gcc patchelf gfortran git gzip \
make patch unzip xz-utils python3 python3-dev tree
- name: Work around CVE-2022-24765
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- name: Setup non-root user
run: |
# Apparently Ubuntu patched git v2.25.1 with a security patch that introduces
# a breaking behavior. See:
# - https://github.blog/2022-04-12-git-security-vulnerability-announced/
# - https://github.com/actions/checkout/issues/760
# - http://changelogs.ubuntu.com/changelogs/pool/main/g/git/git_2.25.1-1ubuntu3.3/changelog
# See [1] below
git config --global --add safe.directory /__w/spack/spack
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Setup repo and non-root user
useradd spack-test && mkdir -p ~spack-test
chown -R spack-test . ~spack-test
- name: Setup repo
shell: runuser -u spack-test -- bash {0}
run: |
git --version
git fetch --unshallow
. .github/workflows/setup_git.sh
useradd -m spack-test
chown -R spack-test .
- name: Bootstrap GnuPG
shell: runuser -u spack-test -- bash {0}
run: |
@@ -245,6 +258,7 @@ jobs:
ubuntu-gnupg-sources:
runs-on: ubuntu-latest
container: "ubuntu:latest"
if: github.repository == 'spack/spack'
steps:
- name: Install dependencies
env:
@@ -255,22 +269,20 @@ jobs:
bzip2 curl file g++ gcc patchelf gfortran git gzip \
make patch unzip xz-utils python3 python3-dev tree \
gawk
- name: Work around CVE-2022-24765
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- name: Setup non-root user
run: |
# Apparently Ubuntu patched git v2.25.1 with a security patch that introduces
# a breaking behavior. See:
# - https://github.blog/2022-04-12-git-security-vulnerability-announced/
# - https://github.com/actions/checkout/issues/760
# - http://changelogs.ubuntu.com/changelogs/pool/main/g/git/git_2.25.1-1ubuntu3.3/changelog
# See [1] below
git config --global --add safe.directory /__w/spack/spack
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Setup repo and non-root user
useradd spack-test && mkdir -p ~spack-test
chown -R spack-test . ~spack-test
- name: Setup repo
shell: runuser -u spack-test -- bash {0}
run: |
git --version
git fetch --unshallow
. .github/workflows/setup_git.sh
useradd -m spack-test
chown -R spack-test .
- name: Bootstrap GnuPG
shell: runuser -u spack-test -- bash {0}
run: |
@@ -282,13 +294,15 @@ jobs:
macos-gnupg-binaries:
runs-on: macos-latest
if: github.repository == 'spack/spack'
steps:
- name: Install dependencies
run: |
brew install tree
# Remove GnuPG since we want to bootstrap it
sudo rm -rf /usr/local/bin/gpg
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- name: Bootstrap GnuPG
run: |
source share/spack/setup-env.sh
@@ -298,13 +312,15 @@ jobs:
macos-gnupg-sources:
runs-on: macos-latest
if: github.repository == 'spack/spack'
steps:
- name: Install dependencies
run: |
brew install gawk tree
# Remove GnuPG since we want to bootstrap it
sudo rm -rf /usr/local/bin/gpg
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- name: Bootstrap GnuPG
run: |
source share/spack/setup-env.sh
@@ -312,3 +328,11 @@ jobs:
spack bootstrap untrust github-actions-v0.2
spack -d gpg list
tree ~/.spack/bootstrap/store/
# [1] Distros that have patched git to resolve CVE-2022-24765 (e.g. Ubuntu patching v2.25.1)
# introduce breaking behaviorso we have to set `safe.directory` in gitconfig ourselves.
# See:
# - https://github.blog/2022-04-12-git-security-vulnerability-announced/
# - https://github.com/actions/checkout/issues/760
# - http://changelogs.ubuntu.com/changelogs/pool/main/g/git/git_2.25.1-1ubuntu3.3/changelog

View File

@@ -43,9 +43,10 @@ jobs:
[ubuntu-focal, 'linux/amd64,linux/arm64,linux/ppc64le', 'ubuntu:20.04'],
[ubuntu-jammy, 'linux/amd64,linux/arm64,linux/ppc64le', 'ubuntu:22.04']]
name: Build ${{ matrix.dockerfile[0] }}
if: github.repository == 'spack/spack'
steps:
- name: Checkout
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
- name: Set Container Tag Normal (Nightly)
run: |
@@ -75,33 +76,33 @@ jobs:
fi
- name: Upload Dockerfile
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8
with:
name: dockerfiles
path: dockerfiles
- name: Set up QEMU
uses: docker/setup-qemu-action@27d0a4f181a40b142cce983c5393082c365d1480 # @v1
uses: docker/setup-qemu-action@8b122486cedac8393e77aa9734c3528886e4a1a8 # @v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@94ab11c41e45d028884a99163086648e898eed25 # @v1
uses: docker/setup-buildx-action@dc7b9719a96d48369863986a06765841d7ea23f6 # @v1
- name: Log in to GitHub Container Registry
uses: docker/login-action@dd4fa0671be5250ee6f50aedf4cb05514abda2c7 # @v1
uses: docker/login-action@49ed152c8eca782a232dede0303416e8f356c37b # @v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to DockerHub
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@dd4fa0671be5250ee6f50aedf4cb05514abda2c7 # @v1
if: github.event_name != 'pull_request'
uses: docker/login-action@49ed152c8eca782a232dede0303416e8f356c37b # @v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build & Deploy ${{ matrix.dockerfile[0] }}
uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a # @v2
uses: docker/build-push-action@e551b19e49efd4e98792db7592c17c09b89db8d8 # @v2
with:
context: dockerfiles/${{ matrix.dockerfile[0] }}
platforms: ${{ matrix.dockerfile[1] }}

View File

@@ -22,9 +22,10 @@ on:
jobs:
install_gcc:
name: gcc with clang
if: github.repository == 'spack/spack'
runs-on: macos-latest
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6 # @v2
with:
python-version: 3.9
@@ -36,10 +37,11 @@ jobs:
install_jupyter_clang:
name: jupyter
if: github.repository == 'spack/spack'
runs-on: macos-latest
timeout-minutes: 700
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6 # @v2
with:
python-version: 3.9
@@ -50,9 +52,10 @@ jobs:
install_scipy_clang:
name: scipy, mpl, pd
if: github.repository == 'spack/spack'
runs-on: macos-latest
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6 # @v2
with:
python-version: 3.9

View File

@@ -15,7 +15,7 @@ jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6 # @v2
with:
python-version: '3.10'
@@ -31,7 +31,7 @@ jobs:
style:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
with:
fetch-depth: 0
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6 # @v2
@@ -57,7 +57,7 @@ jobs:
packages: ${{ steps.filter.outputs.packages }}
with_coverage: ${{ steps.coverage.outputs.with_coverage }}
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
if: ${{ github.event_name == 'push' }}
with:
fetch-depth: 0
@@ -106,7 +106,7 @@ jobs:
- python-version: 3.9
concretizer: original
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
with:
fetch-depth: 0
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6 # @v2
@@ -162,7 +162,7 @@ jobs:
SPACK_TEST_SOLVER: ${{ matrix.concretizer }}
run: |
share/spack/qa/run-unit-tests
- uses: codecov/codecov-action@e3c560433a6cc60aec8812599b7844a7b4fa0d71 # @v2.1.0
- uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # @v2.1.0
if: ${{ needs.changes.outputs.with_coverage == 'true' }}
with:
flags: unittests,linux,${{ matrix.concretizer }}
@@ -171,7 +171,7 @@ jobs:
needs: [ validate, style, changes ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
with:
fetch-depth: 0
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6 # @v2
@@ -200,7 +200,7 @@ jobs:
COVERAGE: true
run: |
share/spack/qa/run-shell-tests
- uses: codecov/codecov-action@e3c560433a6cc60aec8812599b7844a7b4fa0d71 # @v2.1.0
- uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # @v2.1.0
if: ${{ needs.changes.outputs.with_coverage == 'true' }}
with:
flags: shelltests,linux
@@ -218,7 +218,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@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
- name: Setup repo and non-root user
run: |
git --version
@@ -237,7 +237,7 @@ jobs:
needs: [ validate, style, changes ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
with:
fetch-depth: 0
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6 # @v2
@@ -274,7 +274,7 @@ jobs:
SPACK_TEST_SOLVER: clingo
run: |
share/spack/qa/run-unit-tests
- uses: codecov/codecov-action@e3c560433a6cc60aec8812599b7844a7b4fa0d71 # @v2.1.0
- uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # @v2.1.0
if: ${{ needs.changes.outputs.with_coverage == 'true' }}
with:
flags: unittests,linux,clingo
@@ -286,7 +286,7 @@ jobs:
matrix:
python-version: [3.8]
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
with:
fetch-depth: 0
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6 # @v2
@@ -320,7 +320,7 @@ jobs:
echo "ONLY PACKAGE RECIPES CHANGED [skipping coverage]"
$(which spack) unit-test -x -m "not maybeslow" -k "package_sanity"
fi
- uses: codecov/codecov-action@e3c560433a6cc60aec8812599b7844a7b4fa0d71 # @v2.1.0
- uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # @v2.1.0
if: ${{ needs.changes.outputs.with_coverage == 'true' }}
with:
files: ./coverage.xml
@@ -331,7 +331,7 @@ jobs:
needs: [ validate, style, changes ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # @v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6 # @v2
with:
python-version: '3.10'
@@ -350,7 +350,7 @@ jobs:
run: |
. share/spack/setup-env.sh
$(which spack) audit packages
- uses: codecov/codecov-action@e3c560433a6cc60aec8812599b7844a7b4fa0d71 # @v2.1.0
- uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # @v2.1.0
if: ${{ needs.changes.outputs.with_coverage == 'true' }}
with:
flags: unittests,linux,audits

View File

@@ -17,7 +17,7 @@ jobs:
validate:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6
with:
python-version: 3.9
@@ -33,7 +33,7 @@ jobs:
style:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
with:
fetch-depth: 0
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6
@@ -55,7 +55,7 @@ jobs:
needs: [ validate, style ]
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
with:
fetch-depth: 0
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6
@@ -75,7 +75,7 @@ jobs:
needs: [ validate, style ]
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
with:
fetch-depth: 0
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6
@@ -95,7 +95,7 @@ jobs:
needs: [ validate, style ]
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
with:
fetch-depth: 0
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6
@@ -120,7 +120,7 @@ jobs:
git config --global core.symlinks false
shell:
powershell
- uses: actions/checkout@v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
with:
fetch-depth: 0
- uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6
@@ -139,11 +139,11 @@ jobs:
echo "installer_root=$((pwd).Path)" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
env:
ProgressPreference: SilentlyContinue
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8
with:
name: Windows Spack Installer Bundle
path: ${{ env.installer_root }}\pkg\Spack.exe
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8
with:
name: Windows Spack Installer
path: ${{ env.installer_root}}\pkg\Spack.msi

View File

@@ -14,4 +14,39 @@ concretizer:
# concretizing specs. If `true`, we'll try to use as many installs/binaries
# as possible, rather than building. If `false`, we'll always give you a fresh
# concretization.
reuse: false
reuse: true
# If `true`, Spack will consider minimizing builds its *topmost* priority.
# Note that this can result in weird package configurations. In particular,
# Spack will disable variants and might downgrade versions to avoid building
# new packages for an install. By default, Spack respects defaults from
# packages and preferences *before* minimizing the number of builds.
#
# Example for intuition: `cmake` can optionally build without openssl, but
# it's enabled by default because many builds use that functionality. Using
# `minimal: true` will build `cmake~openssl` unless the user asks for
# `cmake+openssl` explicitly.
minimal: false
# Options that tune which targets are considered for concretization. The
# concretization process is very sensitive to the number targets, and the time
# needed to reach a solution increases noticeably with the number of targets
# considered.
targets:
# Determine whether we want to target specific or generic microarchitectures.
# An example of the first kind might be for instance "skylake" or "bulldozer",
# while generic microarchitectures are for instance "aarch64" or "x86_64_v4".
granularity: microarchitectures
# If "false" allow targets that are incompatible with the current host (for
# instance concretize with target "icelake" while running on "haswell").
# If "true" only allow targets that are compatible with the host.
host_compatible: true
# When "true" concretize root specs of environments together, so that each unique
# package in an environment corresponds to one concrete spec. This ensures
# environments can always be activated. When "false" perform concretization separately
# on each root spec, allowing different versions and variants of the same package in
# an environment.
unify: false

View File

@@ -33,6 +33,9 @@ config:
template_dirs:
- $spack/share/spack/templates
# Directory where licenses should be located
license_dir: $spack/etc/spack/licenses
# Temporary locations Spack can try to use for builds.
#
# Recommended options are given below.

View File

@@ -35,7 +35,8 @@ packages:
jpeg: [libjpeg-turbo, libjpeg]
lapack: [openblas, amdlibflame]
libllvm: [llvm, llvm-amdgpu]
lua-lang: [lua, lua-luajit]
lua-lang: [lua, lua-luajit-openresty, lua-luajit]
luajit: [lua-luajit-openresty, lua-luajit]
mariadb-client: [mariadb-c-client, mariadb]
mkl: [intel-mkl]
mpe: [mpe2]

View File

@@ -192,32 +192,32 @@ you can use them to customize an installation in :ref:`sec-specs`.
Reusing installed dependencies
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. warning::
By default, when you run ``spack install``, Spack tries hard to reuse existing installations
as dependencies, either from a local store or from remote buildcaches if configured.
This minimizes unwanted rebuilds of common dependencies, in particular if
you update Spack frequently.
The ``--reuse`` option described here will become the default installation
method in the next Spack version, and you will be able to get the current
behavior by using ``spack install --fresh``.
By default, when you run ``spack install``, Spack tries to build a new
version of the package you asked for, along with updated versions of
its dependencies. This gets you the latest versions and configurations,
but it can result in unwanted rebuilds if you update Spack frequently.
If you want Spack to try hard to reuse existing installations as dependencies,
you can add the ``--reuse`` option:
In case you want the latest versions and configurations to be installed instead,
you can add the ``--fresh`` option:
.. code-block:: console
$ spack install --reuse mpich
$ spack install --fresh mpich
This will not do anything if ``mpich`` is already installed. If ``mpich``
is not installed, but dependencies like ``hwloc`` and ``libfabric`` are,
the ``mpich`` will be build with the installed versions, if possible.
You can use the :ref:`spack spec -I <cmd-spack-spec>` command to see what
Reusing installations in this mode is "accidental", and happening only if
there's a match between existing installations and what Spack would have installed
anyhow.
You can use the ``spack spec -I mpich`` command to see what
will be reused and what will be built before you install.
You can configure Spack to use the ``--reuse`` behavior by default in
``concretizer.yaml``.
You can configure Spack to use the ``--fresh`` behavior by default in
``concretizer.yaml``:
.. code-block:: yaml
concretizer:
reuse: false
.. _cmd-spack-uninstall:

View File

@@ -219,33 +219,65 @@ Concretizer options
but you can also use ``concretizer.yaml`` to customize aspects of the
algorithm it uses to select the dependencies you install:
.. _code-block: yaml
.. 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 ``concretization.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:
# Whether to consider installed packages or packages from buildcaches when
# concretizing specs. If `true`, we'll try to use as many installs/binaries
# as possible, rather than building. If `false`, we'll always give you a fresh
# concretization.
reuse: false
targets:
granularity: microarchitectures
^^^^^^^^^^^^^^^^
``reuse``
^^^^^^^^^^^^^^^^
Spack will consider all the microarchitectures known to ``archspec`` to label nodes for
compatibility. If instead the option is set to:
This 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``). .
.. code-block:: yaml
You can use ``spack install --reuse`` to enable reuse for a single installation,
and you can use ``spack install --fresh`` to do a fresh install if ``reuse`` is
enabled by default.
concretizer:
targets:
granularity: generic
.. note::
``reuse: false`` is the current default, but ``reuse: true`` will be the default
in the next Spack release. You will still be able to use ``spack install --fresh``
to get the old behavior.
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-preferences:

View File

@@ -39,6 +39,7 @@ on these ideas for each distinct build system that Spack supports:
build_systems/autotoolspackage
build_systems/cmakepackage
build_systems/cachedcmakepackage
build_systems/mesonpackage
build_systems/qmakepackage
build_systems/sippackage
@@ -47,6 +48,7 @@ on these ideas for each distinct build system that Spack supports:
:maxdepth: 1
:caption: Language-specific
build_systems/luapackage
build_systems/octavepackage
build_systems/perlpackage
build_systems/pythonpackage

View File

@@ -0,0 +1,123 @@
.. Copyright 2013-2021 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)
.. _cachedcmakepackage:
------------------
CachedCMakePackage
------------------
The CachedCMakePackage base class is used for CMake-based workflows
that create a CMake cache file prior to running ``cmake``. This is
useful for packages with arguments longer than the system limit, and
for reproducibility.
The documentation for this class assumes that the user is familiar with
the ``CMakePackage`` class from which it inherits. See the documentation
for :ref:`CMakePackage <cmakepackage>`.
^^^^^^
Phases
^^^^^^
The ``CachedCMakePackage`` base class comes with the following phases:
#. ``initconfig`` - generate the CMake cache file
#. ``cmake`` - generate the Makefile
#. ``build`` - build the package
#. ``install`` - install the package
By default, these phases run:
.. code-block:: console
$ mkdir spack-build
$ cd spack-build
$ cat << EOF > name-arch-compiler@version.cmake
# Write information on compilers and dependencies
# includes information on mpi and cuda if applicable
$ cmake .. -DCMAKE_INSTALL_PREFIX=/path/to/installation/prefix -C name-arch-compiler@version.cmake
$ make
$ make test # optional
$ make install
The ``CachedCMakePackage`` class inherits from the ``CMakePackage``
class, and accepts all of the same options and adds all of the same
flags to the ``cmake`` command. Similar to the ``CMakePAckage`` class,
you may need to add a few arguments yourself, and the
``CachedCMakePackage`` provides the same interface to add those
flags.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Adding entries to the CMake cache
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In addition to adding flags to the ``cmake`` command, you may need to
add entries to the CMake cache in the ``initconfig`` phase. This can
be done by overriding one of four methods:
#. ``CachedCMakePackage.initconfig_compiler_entries``
#. ``CachedCMakePackage.initconfig_mpi_entries``
#. ``CachedCMakePackage.initconfig_hardware_entries``
#. ``CachedCMakePackage.initconfig_package_entries``
Each of these methods returns a list of CMake cache strings. The
distinction between these methods is merely to provide a
well-structured and legible cmake cache file -- otherwise, entries
from each of these methods are handled identically.
Spack also provides convenience methods for generating CMake cache
entries. These methods are available at module scope in every Spack
package. Because CMake parses boolean options, strings, and paths
differently, there are three such methods:
#. ``cmake_cache_option``
#. ``cmake_cache_string``
#. ``cmake_cache_path``
These methods each accept three parameters -- the name of the CMake
variable associated with the entry, the value of the entry, and an
optional comment -- and return strings in the appropriate format to be
returned from any of the ``initconfig*`` methods. Additionally, these
methods may return comments beginning with the ``#`` character.
A typical usage of these methods may look something like this:
.. code-block:: python
def initconfig_mpi_entries(self)
# Get existing MPI configurations
entries = super(self, Foo).initconfig_mpi_entries()
# The existing MPI configurations key on whether ``mpi`` is in the spec
# This spec has an MPI variant, and we need to enable MPI when it is on.
# This hypothetical package controls MPI with the ``FOO_MPI`` option to
# cmake.
if '+mpi' in self.spec:
entries.append(cmake_cache_option('FOO_MPI', True, "enable mpi"))
else:
entries.append(cmake_cache_option('FOO_MPI', False, "disable mpi"))
def initconfig_package_entries(self):
# Package specific options
entries = []
entries.append('#Entries for build options')
bar_on = '+bar' in self.spec
entries.append(cmake_cache_option('FOO_BAR', bar_on, 'toggle bar'))
entries.append('#Entries for dependencies')
if self.spec['blas'].name == 'baz': # baz is our blas provider
entries.append(cmake_cache_string('FOO_BLAS', 'baz', 'Use baz'))
entries.append(cmake_cache_path('BAZ_PREFIX', self.spec['baz'].prefix))
^^^^^^^^^^^^^^^^^^^^^^
External documentation
^^^^^^^^^^^^^^^^^^^^^^
For more information on CMake cache files, see:
https://cmake.org/cmake/help/latest/manual/cmake.1.html

View File

@@ -0,0 +1,105 @@
.. Copyright 2013-2022 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)
.. _luapackage:
------------
LuaPackage
------------
LuaPackage is a helper for the common case of Lua packages that provide
a rockspec file. This is not meant to take a rock archive, but to build
a source archive or repository that provides a rockspec, which should cover
most lua packages. In the case a Lua package builds by Make rather than
luarocks, prefer MakefilePackage.
^^^^^^
Phases
^^^^^^
The ``LuaPackage`` base class comes with the following phases:
#. ``unpack`` - if using a rock, unpacks the rock and moves into the source directory
#. ``preprocess`` - adjust sources or rockspec to fix build
#. ``install`` - install the project
By default, these phases run:
.. code-block:: console
# If the archive is a source rock
$ luarocks unpack <archive>.src.rock
$ # preprocess is a noop by default
$ luarocks make <name>.rockspec
Any of these phases can be overridden in your package as necessary.
^^^^^^^^^^^^^^^
Important files
^^^^^^^^^^^^^^^
Packages that use the Lua/LuaRocks build system can be identified by the
presence of a ``*.rockspec`` file in their sourcetree, or can be fetched as
a source rock archive (``.src.rock``). This file declares things like build
instructions and dependencies, the ``.src.rock`` also contains all code.
It is common for the rockspec file to list the lua version required in
a dependency. The LuaPackage class adds appropriate dependencies on a Lua
implementation, but it is a good idea to specify the version required with
a ``depends_on`` statement. The block normally will be a table definition like
this:
.. code-block:: lua
dependencies = {
"lua >= 5.1",
}
The LuaPackage class supports source repositories and archives containing
a rockspec and directly downloading source rock files. It *does not* support
downloading dependencies listed inside a rockspec, and thus does not support
directly downloading a rockspec as an archive.
^^^^^^^^^^^^^^^^^^^^^^^^^
Build system dependencies
^^^^^^^^^^^^^^^^^^^^^^^^^
All base dependencies are added by the build system, but LuaRocks is run to
avoid downloading extra Lua dependencies during build. If the package needs
Lua libraries outside the standard set, they should be added as dependencies.
To specify a Lua version constraint but allow all lua implementations, prefer
to use ``depends_on("lua-lang@5.1:5.1.99")`` to express any 5.1 compatible
version. If the package requires LuaJit rather than Lua,
a ``depends_on("luajit")`` should be used to ensure a LuaJit distribution is
used instead of the Lua interpreter. Alternately, if only interpreted Lua will
work ``depends_on("lua")`` will express that.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Passing arguments to luarocks make
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you need to pass any arguments to the ``luarocks make`` call, you can
override the ``luarocks_args`` method like so:
.. code-block:: python
def luarocks_args(self):
return ['flag1', 'flag2']
One common use of this is to override warnings or flags for newer compilers, as in:
.. code-block:: python
def luarocks_args(self):
return ["CFLAGS='-Wno-error=implicit-function-declaration'"]
^^^^^^^^^^^^^^^^^^^^^^
External documentation
^^^^^^^^^^^^^^^^^^^^^^
For more information on the LuaRocks build system, see:
https://luarocks.org/

View File

@@ -95,7 +95,7 @@ class of your package. For example, you can add it to your
# Set up the hip macros needed by the build
args.extend([
'-DENABLE_HIP=ON',
'-DHIP_ROOT_DIR={0}'.format(spec['hip'].prefix])
'-DHIP_ROOT_DIR={0}'.format(spec['hip'].prefix)])
rocm_archs = spec.variants['amdgpu_target'].value
if 'none' not in rocm_archs:
args.append('-DHIP_HIPCC_FLAGS=--amdgpu-target={0}'

View File

@@ -23,7 +23,10 @@
import sys
from glob import glob
from docutils.statemachine import StringList
from sphinx.domains.python import PythonDomain
from sphinx.ext.apidoc import main as sphinx_apidoc
from sphinx.parsers import RSTParser
# -- Spack customizations -----------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
@@ -82,9 +85,6 @@
#
# Disable duplicate cross-reference warnings.
#
from sphinx.domains.python import PythonDomain
class PatchedPythonDomain(PythonDomain):
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
if 'refspecific' in node:
@@ -92,8 +92,20 @@ def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
return super(PatchedPythonDomain, self).resolve_xref(
env, fromdocname, builder, typ, target, node, contnode)
#
# Disable tabs to space expansion in code blocks
# since Makefiles require tabs.
#
class NoTabExpansionRSTParser(RSTParser):
def parse(self, inputstring, document):
if isinstance(inputstring, str):
lines = inputstring.splitlines()
inputstring = StringList(lines, document.current_source)
super().parse(inputstring, document)
def setup(sphinx):
sphinx.add_domain(PatchedPythonDomain, override=True)
sphinx.add_source_parser(NoTabExpansionRSTParser, override=True)
# -- General configuration -----------------------------------------------------

View File

@@ -59,7 +59,8 @@ other techniques to minimize the size of the final image:
&& echo " specs:" \
&& echo " - gromacs+mpi" \
&& echo " - mpich" \
&& echo " concretization: together" \
&& echo " concretizer: together" \
&& echo " unify: true" \
&& echo " config:" \
&& echo " install_tree: /opt/software" \
&& echo " view: /opt/view") > /opt/spack-environment/spack.yaml
@@ -245,7 +246,8 @@ software is respectively built and installed:
&& echo " specs:" \
&& echo " - gromacs+mpi" \
&& echo " - mpich" \
&& echo " concretization: together" \
&& echo " concretizer:" \
&& echo " unify: true" \
&& echo " config:" \
&& echo " install_tree: /opt/software" \
&& echo " view: /opt/view") > /opt/spack-environment/spack.yaml
@@ -366,7 +368,8 @@ produces, for instance, the following ``Dockerfile``:
&& echo " externals:" \
&& echo " - spec: cuda%gcc" \
&& echo " prefix: /usr/local/cuda" \
&& echo " concretization: together" \
&& echo " concretizer:" \
&& echo " unify: true" \
&& echo " config:" \
&& echo " install_tree: /opt/software" \
&& echo " view: /opt/view") > /opt/spack-environment/spack.yaml

View File

@@ -281,8 +281,8 @@ need to be installed alongside each other. Central installations done
at HPC centers by system administrators or user support groups
are a common case that fits in this behavior.
Environments *can also be configured to concretize all
the root specs in a self-consistent way* to ensure that
each package in the environment comes with a single configuration. This
the root specs in a unified way* to ensure that
each package in the environment corresponds to a single concrete spec. This
mode of operation is usually what is required by software developers that
want to deploy their development environment.
@@ -349,6 +349,24 @@ If the Environment has been concretized, Spack will install the
concretized specs. Otherwise, ``spack install`` will first concretize
the Environment and then install the concretized specs.
.. note::
Every ``spack install`` process builds one package at a time with multiple build
jobs, controlled by the ``-j`` flag and the ``config:build_jobs`` option
(see :ref:`build-jobs`). To speed up environment builds further, independent
packages can be installed in parallel by launching more Spack instances. For
example, the following will build at most four packages in parallel using
three background jobs:
.. code-block:: console
[myenv]$ spack install & spack install & spack install & spack install
Another option is to generate a ``Makefile`` and run ``make -j<N>`` to control
the number of parallel install processes. See :ref:`env-generate-depfile`
for details.
As it installs, ``spack install`` creates symbolic links in the
``logs/`` directory in the Environment, allowing for easy inspection
of build logs related to that environment. The ``spack install``
@@ -481,7 +499,7 @@ Spec concretization
Specs can be concretized separately or together, as already
explained in :ref:`environments_concretization`. The behavior active
under any environment is determined by the ``concretization`` property:
under any environment is determined by the ``concretizer:unify`` property:
.. code-block:: yaml
@@ -491,10 +509,15 @@ under any environment is determined by the ``concretization`` property:
- netcdf
- nco
- py-sphinx
concretization: together
concretizer:
unify: true
which can currently take either one of the two allowed values ``together`` or ``separately``
(the default).
.. note::
The ``concretizer:unify`` config option was introduced in Spack 0.18 to
replace the ``concretization`` property. For reference,
``concretization: separately`` is replaced by ``concretizer:unify:true``,
and ``concretization: together`` is replaced by ``concretizer:unify:false``.
.. admonition:: Re-concretization of user specs
@@ -910,3 +933,93 @@ environment.
The ``spack env deactivate`` command will remove the default view of
the environment from the user's path.
.. _env-generate-depfile:
------------------------------------------
Generating Depfiles from Environments
------------------------------------------
Spack can generate ``Makefile``\s to make it easier to build multiple
packages in an environment in parallel. Generated ``Makefile``\s expose
targets that can be included in existing ``Makefile``\s, to allow
other targets to depend on the environment installation.
A typical workflow is as follows:
.. code:: console
spack env create -d .
spack -e . add perl
spack -e . concretize
spack -e . env depfile > Makefile
make -j64
This generates a ``Makefile`` from a concretized environment in the
current working directory, and ``make -j64`` installs the environment,
exploiting parallelism across packages as much as possible. Spack
respects the Make jobserver and forwards it to the build environment
of packages, meaning that a single ``-j`` flag is enough to control the
load, even when packages are built in parallel.
By default the following phony convenience targets are available:
- ``make all``: installs the environment (default target);
- ``make fetch-all``: only fetch sources of all packages;
- ``make clean``: cleans files used by make, but does not uninstall packages.
.. tip::
GNU Make version 4.3 and above have great support for output synchronization
through the ``-O`` and ``--output-sync`` flags, which ensure that output is
printed orderly per package install. To get synchronized output with colors,
use ``make -j<N> SPACK_COLOR=always --output-sync=recurse``.
The following advanced example shows how generated targets can be used in a
``Makefile``:
.. code:: Makefile
SPACK ?= spack
.PHONY: all clean fetch env
all: env
spack.lock: spack.yaml
$(SPACK) -e . concretize -f
env.mk: spack.lock
$(SPACK) -e . env depfile -o $@ --make-target-prefix spack
fetch: spack/fetch
$(info Environment fetched!)
env: spack/env
$(info Environment installed!)
clean:
rm -rf spack.lock env.mk spack/
ifeq (,$(filter clean,$(MAKECMDGOALS)))
include env.mk
endif
When ``make`` is invoked, it first "remakes" the missing include ``env.mk``
from its rule, which triggers concretization. When done, the generated targets
``spack/fetch`` and ``spack/env`` are available. In the above
example, the ``env`` target uses the latter as a prerequisite, meaning
that it can make use of the installed packages in its commands.
As it is typically undesirable to remake ``env.mk`` as part of ``make clean``,
the include is conditional.
.. note::
When including generated ``Makefile``\s, it is important to use
the ``--make-target-prefix`` flag and use the non-phony targets
``<target-prefix>/env`` and ``<target-prefix>/fetch`` as
prerequisites, instead of the phony targets ``<target-prefix>/all``
and ``<target-prefix>/fetch-all`` respectively.

View File

@@ -115,7 +115,8 @@ And here's the spack environment built by the pipeline represented as a
spack:
view: false
concretization: separately
concretizer:
unify: false
definitions:
- pkgs:

View File

@@ -61,7 +61,7 @@ You can see the packages we added earlier in the ``specs:`` section. If you
ever want to add more packages, you can either use ``spack add`` or manually
edit this file.
We also need to change the ``concretization:`` option. By default, Spack
We also need to change the ``concretizer:unify`` option. By default, Spack
concretizes each spec *separately*, allowing multiple versions of the same
package to coexist. Since we want a single consistent environment, we want to
concretize all of the specs *together*.
@@ -78,7 +78,8 @@ Here is what your ``spack.yaml`` looks like with this new setting:
# add package specs to the `specs` list
specs: [bash@5, python, py-numpy, py-scipy, py-matplotlib]
view: true
concretization: together
concretizer:
unify: true
^^^^^^^^^^^^^^^^
Symlink location

View File

@@ -25,4 +25,5 @@ spack:
- subversion
# Plotting
- graphviz
concretization: together
concretizer:
unify: true

32
lib/spack/env/cc vendored
View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/sh -f
# shellcheck disable=SC2034 # evals in this script fool shellcheck
#
# Copyright 2013-2022 Lawrence Livermore National Security, LLC and other
@@ -401,7 +401,8 @@ input_command="$*"
# command line and recombine them with Spack arguments later. We
# parse these out so that we can make sure that system paths come
# last, that package arguments come first, and that Spack arguments
# are injected properly.
# are injected properly. Based on configuration, we also strip -Werror
# arguments.
#
# All other arguments, including -l arguments, are treated as
# 'other_args' and left in their original order. This ensures that
@@ -440,6 +441,29 @@ while [ $# -ne 0 ]; do
continue
fi
if [ -n "${SPACK_COMPILER_FLAGS_KEEP}" ] ; then
# NOTE: the eval is required to allow `|` alternatives inside the variable
eval "\
case '$1' in
$SPACK_COMPILER_FLAGS_KEEP)
append other_args_list "$1"
shift
continue
;;
esac
"
fi
if [ -n "${SPACK_COMPILER_FLAGS_REMOVE}" ] ; then
eval "\
case '$1' in
$SPACK_COMPILER_FLAGS_REMOVE)
shift
continue
;;
esac
"
fi
case "$1" in
-isystem*)
arg="${1#-isystem}"
@@ -768,7 +792,9 @@ if [ "$SPACK_DEBUG" = TRUE ]; then
input_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_DEBUG_LOG_ID.in.log"
output_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_DEBUG_LOG_ID.out.log"
echo "[$mode] $command $input_command" >> "$input_log"
echo "[$mode] ${full_command_list}" >> "$output_log"
IFS="$lsep"
echo "[$mode] "$full_command_list >> "$output_log"
unset IFS
fi
# Execute the full command, preserving spaces with IFS set

View File

@@ -18,7 +18,7 @@
* Homepage: https://pypi.python.org/pypi/archspec
* Usage: Labeling, comparison and detection of microarchitectures
* Version: 0.1.2 (commit 85757b6666422fca86aa882a769bf78b0f992f54)
* Version: 0.1.4 (commit 53fc4ac91e9b4c5e4079f15772503a80bece72ad)
argparse
--------

View File

@@ -61,7 +61,7 @@ def proc_cpuinfo():
``/proc/cpuinfo``
"""
info = {}
with open("/proc/cpuinfo") as file:
with open("/proc/cpuinfo") as file: # pylint: disable=unspecified-encoding
for line in file:
key, separator, value = line.partition(":")
@@ -80,26 +80,46 @@ def proc_cpuinfo():
def _check_output(args, env):
output = subprocess.Popen(args, stdout=subprocess.PIPE, env=env).communicate()[0]
output = subprocess.Popen( # pylint: disable=consider-using-with
args, stdout=subprocess.PIPE, env=env
).communicate()[0]
return six.text_type(output.decode("utf-8"))
def _machine():
""" "Return the machine architecture we are on"""
operating_system = platform.system()
# If we are not on Darwin, trust what Python tells us
if operating_system != "Darwin":
return platform.machine()
# On Darwin it might happen that we are on M1, but using an interpreter
# built for x86_64. In that case "platform.machine() == 'x86_64'", so we
# need to fix that.
#
# See: https://bugs.python.org/issue42704
output = _check_output(
["sysctl", "-n", "machdep.cpu.brand_string"], env=_ensure_bin_usrbin_in_path()
).strip()
if "Apple" in output:
# Note that a native Python interpreter on Apple M1 would return
# "arm64" instead of "aarch64". Here we normalize to the latter.
return "aarch64"
return "x86_64"
@info_dict(operating_system="Darwin")
def sysctl_info_dict():
"""Returns a raw info dictionary parsing the output of sysctl."""
# Make sure that /sbin and /usr/sbin are in PATH as sysctl is
# usually found there
child_environment = dict(os.environ.items())
search_paths = child_environment.get("PATH", "").split(os.pathsep)
for additional_path in ("/sbin", "/usr/sbin"):
if additional_path not in search_paths:
search_paths.append(additional_path)
child_environment["PATH"] = os.pathsep.join(search_paths)
child_environment = _ensure_bin_usrbin_in_path()
def sysctl(*args):
return _check_output(["sysctl"] + list(args), env=child_environment).strip()
if platform.machine() == "x86_64":
if _machine() == "x86_64":
flags = (
sysctl("-n", "machdep.cpu.features").lower()
+ " "
@@ -125,6 +145,18 @@ def sysctl(*args):
return info
def _ensure_bin_usrbin_in_path():
# Make sure that /sbin and /usr/sbin are in PATH as sysctl is
# usually found there
child_environment = dict(os.environ.items())
search_paths = child_environment.get("PATH", "").split(os.pathsep)
for additional_path in ("/sbin", "/usr/sbin"):
if additional_path not in search_paths:
search_paths.append(additional_path)
child_environment["PATH"] = os.pathsep.join(search_paths)
return child_environment
def adjust_raw_flags(info):
"""Adjust the flags detected on the system to homogenize
slightly different representations.
@@ -184,12 +216,7 @@ def compatible_microarchitectures(info):
Args:
info (dict): dictionary containing information on the host cpu
"""
architecture_family = platform.machine()
# On Apple M1 platform.machine() returns "arm64" instead of "aarch64"
# so we should normalize the name here
if architecture_family == "arm64":
architecture_family = "aarch64"
architecture_family = _machine()
# If a tester is not registered, be conservative and assume no known
# target is compatible with the host
tester = COMPATIBILITY_CHECKS.get(architecture_family, lambda x, y: False)
@@ -244,12 +271,7 @@ def compatibility_check(architecture_family):
architecture_family = (architecture_family,)
def decorator(func):
# pylint: disable=fixme
# TODO: on removal of Python 2.6 support this can be re-written as
# TODO: an update + a dict comprehension
for arch_family in architecture_family:
COMPATIBILITY_CHECKS[arch_family] = func
COMPATIBILITY_CHECKS.update({family: func for family in architecture_family})
return func
return decorator
@@ -288,7 +310,7 @@ def compatibility_check_for_x86_64(info, target):
arch_root = TARGETS[basename]
return (
(target == arch_root or arch_root in target.ancestors)
and (target.vendor == vendor or target.vendor == "generic")
and target.vendor in (vendor, "generic")
and target.features.issubset(features)
)
@@ -303,8 +325,9 @@ def compatibility_check_for_aarch64(info, target):
arch_root = TARGETS[basename]
return (
(target == arch_root or arch_root in target.ancestors)
and (target.vendor == vendor or target.vendor == "generic")
and target.features.issubset(features)
and target.vendor in (vendor, "generic")
# On macOS it seems impossible to get all the CPU features with syctl info
and (target.features.issubset(features) or platform.system() == "Darwin")
)

View File

@@ -11,7 +11,7 @@
try:
from collections.abc import MutableMapping # novm
except ImportError:
from collections import MutableMapping
from collections import MutableMapping # pylint: disable=deprecated-class
class LazyDictionary(MutableMapping):
@@ -56,7 +56,7 @@ def _load_json_file(json_file):
def _factory():
filename = os.path.join(json_dir, json_file)
with open(filename, "r") as file:
with open(filename, "r") as file: # pylint: disable=unspecified-encoding
return json.load(file)
return _factory

View File

@@ -88,6 +88,20 @@
"name": "pentium4",
"flags": "-march={name} -mtune=generic"
}
],
"oneapi": [
{
"versions": ":",
"name": "pentium4",
"flags": "-march={name} -mtune=generic"
}
],
"dpcpp": [
{
"versions": ":",
"name": "pentium4",
"flags": "-march={name} -mtune=generic"
}
]
}
},
@@ -291,6 +305,20 @@
"name": "pentium4",
"flags": "-march={name} -mtune=generic"
}
],
"oneapi": [
{
"versions": ":",
"name": "pentium4",
"flags": "-march={name} -mtune=generic"
}
],
"dpcpp": [
{
"versions": ":",
"name": "pentium4",
"flags": "-march={name} -mtune=generic"
}
]
}
},
@@ -333,6 +361,18 @@
"versions": "16.0:",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -384,6 +424,20 @@
"name": "corei7",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"name": "corei7",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"name": "corei7",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -432,6 +486,20 @@
"name": "corei7",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"name": "corei7",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"name": "corei7",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -490,6 +558,18 @@
"versions": "18.0:",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -550,6 +630,18 @@
"versions": "18.0:",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -615,6 +707,18 @@
"versions": "18.0:",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -672,6 +776,18 @@
"versions": "18.0:",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -732,6 +848,18 @@
"versions": "18.0:",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -798,6 +926,20 @@
"name": "knl",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"name": "knl",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"name": "knl",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -868,6 +1010,20 @@
"name": "skylake-avx512",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"name": "skylake-avx512",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"name": "skylake-avx512",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -937,6 +1093,18 @@
"versions": "18.0:",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -1004,6 +1172,18 @@
"versions": "19.0.1:",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -1098,6 +1278,20 @@
"name": "icelake-client",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"name": "icelake-client",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"name": "icelake-client",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -1142,6 +1336,20 @@
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"flags": "-msse2"
}
],
"oneapi": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"flags": "-msse2"
}
],
"dpcpp": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"flags": "-msse2"
}
]
}
},
@@ -1192,6 +1400,20 @@
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"flags": "-msse3"
}
],
"oneapi": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"flags": "-msse3"
}
],
"dpcpp": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"flags": "-msse3"
}
]
}
},
@@ -1246,6 +1468,20 @@
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"flags": "-msse3"
}
],
"oneapi": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"flags": "-msse3"
}
],
"dpcpp": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"flags": "-msse3"
}
]
}
},
@@ -1301,6 +1537,20 @@
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"flags": "-msse4.2"
}
],
"oneapi": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"flags": "-msse4.2"
}
],
"dpcpp": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"flags": "-msse4.2"
}
]
}
},
@@ -1360,6 +1610,22 @@
"name": "core-avx2",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"name": "core-avx2",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"name": "core-avx2",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -1422,6 +1688,22 @@
"name": "core-avx2",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"name": "core-avx2",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"name": "core-avx2",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -1485,6 +1767,22 @@
"name": "core-avx2",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"name": "core-avx2",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"name": "core-avx2",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -1543,6 +1841,30 @@
"name": "znver3",
"flags": "-march={name} -mtune={name}"
}
],
"intel": [
{
"versions": "16.0:",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"name": "core-avx2",
"flags": "-march={name} -mtune={name}"
}
],
"oneapi": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"name": "core-avx2",
"flags": "-march={name} -mtune={name}"
}
],
"dpcpp": [
{
"versions": ":",
"warnings": "Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors",
"name": "core-avx2",
"flags": "-march={name} -mtune={name}"
}
]
}
},
@@ -1788,7 +2110,6 @@
"fp",
"asimd",
"evtstrm",
"aes",
"pmull",
"sha1",
"sha2",
@@ -1821,18 +2142,26 @@
"flags": "-march=armv8.2-a+crc+crypto+fp16"
},
{
"versions": "8:",
"flags": "-march=armv8.2-a+crc+aes+sha2+fp16+sve -msve-vector-bits=512"
"versions": "8:10.2",
"flags": "-march=armv8.2-a+crc+sha2+fp16+sve -msve-vector-bits=512"
},
{
"versions": "10.3:",
"flags": "-mcpu=a64fx -msve-vector-bits=512"
}
],
"clang": [
{
"versions": "3.9:4.9",
"flags": "-march=armv8.2-a+crc+crypto+fp16"
"flags": "-march=armv8.2-a+crc+sha2+fp16"
},
{
"versions": "5:",
"flags": "-march=armv8.2-a+crc+crypto+fp16+sve"
"versions": "5:10",
"flags": "-march=armv8.2-a+crc+sha2+fp16+sve"
},
{
"versions": "11:",
"flags": "-mcpu=a64fx"
}
],
"arm": [
@@ -1954,7 +2283,40 @@
"m1": {
"from": ["aarch64"],
"vendor": "Apple",
"features": [],
"features": [
"fp",
"asimd",
"evtstrm",
"aes",
"pmull",
"sha1",
"sha2",
"crc32",
"atomics",
"fphp",
"asimdhp",
"cpuid",
"asimdrdm",
"jscvt",
"fcma",
"lrcpc",
"dcpop",
"sha3",
"asimddp",
"sha512",
"asimdfhm",
"dit",
"uscat",
"ilrcpc",
"flagm",
"ssbs",
"sb",
"paca",
"pacg",
"dcpodp",
"flagm2",
"frint"
],
"compilers": {
"gcc": [
{
@@ -1964,14 +2326,22 @@
],
"clang" : [
{
"versions": "9.0:",
"versions": "9.0:12.0",
"flags" : "-march=armv8.4-a"
},
{
"versions": "13.0:",
"flags" : "-mcpu=apple-m1"
}
],
"apple-clang": [
{
"versions": "11.0:",
"versions": "11.0:12.5",
"flags" : "-march=armv8.4-a"
},
{
"versions": "13.0:",
"flags" : "-mcpu=apple-m1"
}
]
}

View File

@@ -64,6 +64,7 @@
'is_exe',
'join_path',
'last_modification_time_recursive',
'library_extensions',
'mkdirp',
'partition_path',
'prefixes',
@@ -109,12 +110,15 @@ def path_contains_subdirectory(path, root):
return norm_path.startswith(norm_root)
#: This generates the library filenames that may appear on any OS.
library_extensions = ['a', 'la', 'so', 'tbd', 'dylib']
def possible_library_filenames(library_names):
"""Given a collection of library names like 'libfoo', generate the set of
library filenames that may be found on the system (e.g. libfoo.so). This
generates the library filenames that may appear on any OS.
library filenames that may be found on the system (e.g. libfoo.so).
"""
lib_extensions = ['a', 'la', 'so', 'tbd', 'dylib']
lib_extensions = library_extensions
return set(
'.'.join((lib, extension)) for lib, extension in
itertools.product(library_names, lib_extensions))
@@ -363,7 +367,7 @@ def group_ids(uid=None):
@system_path_filter(arg_slice=slice(1))
def chgrp(path, group):
def chgrp(path, group, follow_symlinks=True):
"""Implement the bash chgrp function on a single path"""
if is_windows:
raise OSError("Function 'chgrp' is not supported on Windows")
@@ -372,7 +376,10 @@ def chgrp(path, group):
gid = grp.getgrnam(group).gr_gid
else:
gid = group
os.chown(path, -1, gid)
if follow_symlinks:
os.chown(path, -1, gid)
else:
os.lchown(path, -1, gid)
@system_path_filter(arg_slice=slice(1))
@@ -764,39 +771,36 @@ def __init__(self, inner_exception, outer_exception):
@contextmanager
@system_path_filter
def replace_directory_transaction(directory_name, tmp_root=None):
"""Moves a directory to a temporary space. If the operations executed
within the context manager don't raise an exception, the directory is
deleted. If there is an exception, the move is undone.
def replace_directory_transaction(directory_name):
"""Temporarily renames a directory in the same parent dir. If the operations
executed within the context manager don't raise an exception, the renamed directory
is deleted. If there is an exception, the move is undone.
Args:
directory_name (path): absolute path of the directory name
tmp_root (path): absolute path of the parent directory where to create
the temporary
Returns:
temporary directory where ``directory_name`` has been moved
"""
# Check the input is indeed a directory with absolute path.
# Raise before anything is done to avoid moving the wrong directory
assert os.path.isdir(directory_name), \
'Invalid directory: ' + directory_name
assert os.path.isabs(directory_name), \
'"directory_name" must contain an absolute path: ' + directory_name
directory_name = os.path.abspath(directory_name)
assert os.path.isdir(directory_name), 'Not a directory: ' + directory_name
directory_basename = os.path.basename(directory_name)
# Note: directory_name is normalized here, meaning the trailing slash is dropped,
# so dirname is the directory's parent not the directory itself.
tmpdir = tempfile.mkdtemp(
dir=os.path.dirname(directory_name),
prefix='.backup')
if tmp_root is not None:
assert os.path.isabs(tmp_root)
tmp_dir = tempfile.mkdtemp(dir=tmp_root)
tty.debug('Temporary directory created [{0}]'.format(tmp_dir))
shutil.move(src=directory_name, dst=tmp_dir)
tty.debug('Directory moved [src={0}, dest={1}]'.format(directory_name, tmp_dir))
# We have to jump through hoops to support Windows, since
# os.rename(directory_name, tmpdir) errors there.
backup_dir = os.path.join(tmpdir, 'backup')
os.rename(directory_name, backup_dir)
tty.debug('Directory moved [src={0}, dest={1}]'.format(directory_name, backup_dir))
try:
yield tmp_dir
yield backup_dir
except (Exception, KeyboardInterrupt, SystemExit) as inner_exception:
# Try to recover the original directory, if this fails, raise a
# composite exception.
@@ -804,10 +808,7 @@ def replace_directory_transaction(directory_name, tmp_root=None):
# Delete what was there, before copying back the original content
if os.path.exists(directory_name):
shutil.rmtree(directory_name)
shutil.move(
src=os.path.join(tmp_dir, directory_basename),
dst=os.path.dirname(directory_name)
)
os.rename(backup_dir, directory_name)
except Exception as outer_exception:
raise CouldNotRestoreDirectoryBackup(inner_exception, outer_exception)
@@ -815,8 +816,8 @@ def replace_directory_transaction(directory_name, tmp_root=None):
raise
else:
# Otherwise delete the temporary directory
shutil.rmtree(tmp_dir, ignore_errors=True)
tty.debug('Temporary directory deleted [{0}]'.format(tmp_dir))
shutil.rmtree(tmpdir, ignore_errors=True)
tty.debug('Temporary directory deleted [{0}]'.format(tmpdir))
@system_path_filter
@@ -1097,7 +1098,32 @@ def visit_directory_tree(root, visitor, rel_path='', depth=0):
for f in dir_entries:
if sys.version_info >= (3, 5, 0):
rel_child = os.path.join(rel_path, f.name)
islink, isdir = f.is_symlink(), f.is_dir()
islink = f.is_symlink()
# On Windows, symlinks to directories are distinct from
# symlinks to files, and it is possible to create a
# broken symlink to a directory (e.g. using os.symlink
# without `target_is_directory=True`), invoking `isdir`
# on a symlink on Windows that is broken in this manner
# will result in an error. In this case we can work around
# the issue by reading the target and resolving the
# directory ourselves
try:
isdir = f.is_dir()
except OSError as e:
if is_windows and hasattr(e, 'winerror')\
and e.winerror == 5 and islink:
# if path is a symlink, determine destination and
# evaluate file vs directory
link_target = resolve_link_target_relative_to_the_link(f)
# link_target might be relative but
# resolve_link_target_relative_to_the_link
# will ensure that if so, that it is relative
# to the CWD and therefore
# makes sense
isdir = os.path.isdir(link_target)
else:
raise e
else:
rel_child = os.path.join(rel_path, f)
lexists, islink, isdir = lexists_islink_isdir(os.path.join(dir, f))
@@ -1105,7 +1131,7 @@ def visit_directory_tree(root, visitor, rel_path='', depth=0):
continue
if not isdir:
# Handle files
# handle files
visitor.visit_file(root, rel_child, depth)
elif not islink and visitor.before_visit_dir(root, rel_child, depth):
# Handle ordinary directories
@@ -1180,6 +1206,35 @@ def remove_if_dead_link(path):
os.unlink(path)
def readonly_file_handler(ignore_errors=False):
# TODO: generate stages etc. with write permissions wherever
# so this callback is no-longer required
"""
Generate callback for shutil.rmtree to handle permissions errors on
Windows. Some files may unexpectedly lack write permissions even
though they were generated by Spack on behalf of the user (e.g. the
stage), so this callback will detect such cases and modify the
permissions if that is the issue. For other errors, the fallback
is either to raise (if ignore_errors is False) or ignore (if
ignore_errors is True). This is only intended for Windows systems
and will raise a separate error if it is ever invoked (by accident)
on a non-Windows system.
"""
def error_remove_readonly(func, path, exc):
if not is_windows:
raise RuntimeError("This method should only be invoked on Windows")
excvalue = exc[1]
if is_windows and func in (os.rmdir, os.remove, os.unlink) and\
excvalue.errno == errno.EACCES:
# change the file to be readable,writable,executable: 0777
os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
# retry
func(path)
elif not ignore_errors:
raise
return error_remove_readonly
@system_path_filter
def remove_linked_tree(path):
"""Removes a directory and its contents.
@@ -1187,23 +1242,18 @@ def remove_linked_tree(path):
If the directory is a symlink, follows the link and removes the real
directory before removing the link.
This method will force-delete files on Windows
Parameters:
path (str): Directory to be removed
"""
# On windows, cleaning a Git stage can be an issue
# as git leaves readonly files that Python handles
# poorly on Windows. Remove readonly status and try again
def onerror(func, path, exe_info):
os.chmod(path, stat.S_IWUSR)
try:
func(path)
except Exception as e:
tty.warn(e)
pass
kwargs = {'ignore_errors': True}
# Windows readonly files cannot be removed by Python
# directly.
if is_windows:
kwargs = {'onerror': onerror}
kwargs['ignore_errors'] = False
kwargs['onerror'] = readonly_file_handler(ignore_errors=True)
if os.path.exists(path):
if os.path.islink(path):

View File

@@ -11,7 +11,9 @@
import os
import re
import sys
import traceback
from datetime import datetime, timedelta
from typing import List, Tuple
import six
from six import string_types
@@ -1009,3 +1011,64 @@ def __repr__(self):
def __str__(self):
return str(self.data)
class GroupedExceptionHandler(object):
"""A generic mechanism to coalesce multiple exceptions and preserve tracebacks."""
def __init__(self):
self.exceptions = [] # type: List[Tuple[str, Exception, List[str]]]
def __bool__(self):
"""Whether any exceptions were handled."""
return bool(self.exceptions)
def forward(self, context):
# type: (str) -> GroupedExceptionForwarder
"""Return a contextmanager which extracts tracebacks and prefixes a message."""
return GroupedExceptionForwarder(context, self)
def _receive_forwarded(self, context, exc, tb):
# type: (str, Exception, List[str]) -> None
self.exceptions.append((context, exc, tb))
def grouped_message(self, with_tracebacks=True):
# type: (bool) -> str
"""Print out an error message coalescing all the forwarded errors."""
each_exception_message = [
'{0} raised {1}: {2}{3}'.format(
context,
exc.__class__.__name__,
exc,
'\n{0}'.format(''.join(tb)) if with_tracebacks else '',
)
for context, exc, tb in self.exceptions
]
return 'due to the following failures:\n{0}'.format(
'\n'.join(each_exception_message)
)
class GroupedExceptionForwarder(object):
"""A contextmanager to capture exceptions and forward them to a
GroupedExceptionHandler."""
def __init__(self, context, handler):
# type: (str, GroupedExceptionHandler) -> None
self._context = context
self._handler = handler
def __enter__(self):
return None
def __exit__(self, exc_type, exc_value, tb):
if exc_value is not None:
self._handler._receive_forwarded(
self._context,
exc_value,
traceback.format_tb(tb),
)
# Suppress any exception from being re-raised:
# https://docs.python.org/3/reference/datamodel.html#object.__exit__.
return True

View File

@@ -809,19 +809,23 @@ def __enter__(self):
def background_reader(reader, echo_writer, _kill):
# for each line printed to logfile, read it
# if echo: write line to user
while True:
is_killed = _kill.wait(.1)
self.stderr.flush()
self.stdout.flush()
line = reader.readline()
while line:
if self.echo:
self.echo_writer.write('{0}'.format(line.decode()))
self.echo_writer.flush()
line = reader.readline()
try:
while True:
is_killed = _kill.wait(.1)
# Flush buffered build output to file
# stdout/err fds refer to log file
self.stderr.flush()
self.stdout.flush()
if is_killed:
break
line = reader.readline()
if self.echo and line:
echo_writer.write('{0}'.format(line.decode()))
echo_writer.flush()
if is_killed:
break
finally:
reader.close()
self._active = True
with replace_environment(self.env):
@@ -837,7 +841,6 @@ def __exit__(self, exc_type, exc_val, exc_tb):
self._ioflag = False
else:
self.writer.close()
self.reader.close()
self.echo_writer.flush()
self.stdout.flush()
self.stderr.flush()
@@ -853,10 +856,7 @@ def force_echo(self):
if not self._active:
raise RuntimeError(
"Can't call force_echo() outside log_output region!")
try:
yield self
finally:
pass
yield
def _writer_daemon(stdin_multiprocess_fd, read_multiprocess_fd, write_fd, echo,

View File

@@ -276,6 +276,24 @@ def _search_duplicate_specs_in_externals(error_cls):
)
@package_directives
def _check_build_test_callbacks(pkgs, error_cls):
"""Ensure stand-alone test method is not included in build-time callbacks"""
errors = []
for pkg_name in pkgs:
pkg = spack.repo.get(pkg_name)
test_callbacks = pkg.build_time_test_callbacks
if test_callbacks and 'test' in test_callbacks:
msg = ('{0} package contains "test" method in '
'build_time_test_callbacks')
instr = ('Remove "test" from: [{0}]'
.format(', '.join(test_callbacks)))
errors.append(error_cls(msg.format(pkg.name), [instr]))
return errors
@package_directives
def _check_patch_urls(pkgs, error_cls):
"""Ensure that patches fetched from GitHub have stable sha256 hashes."""

View File

@@ -27,7 +27,6 @@
import spack.config as config
import spack.database as spack_db
import spack.fetch_strategy as fs
import spack.hash_types as ht
import spack.hooks
import spack.hooks.sbang
import spack.mirror
@@ -182,7 +181,6 @@ def _associate_built_specs_with_mirror(self, cache_key, mirror_url):
for indexed_spec in spec_list:
dag_hash = indexed_spec.dag_hash()
full_hash = indexed_spec._full_hash
if dag_hash not in self._mirrors_for_spec:
self._mirrors_for_spec[dag_hash] = []
@@ -190,11 +188,8 @@ def _associate_built_specs_with_mirror(self, cache_key, mirror_url):
for entry in self._mirrors_for_spec[dag_hash]:
# A binary mirror can only have one spec per DAG hash, so
# if we already have an entry under this DAG hash for this
# mirror url, we may need to replace the spec associated
# with it (but only if it has a different full_hash).
# mirror url, we're done.
if entry['mirror_url'] == mirror_url:
if full_hash and full_hash != entry['spec']._full_hash:
entry['spec'] = indexed_spec
break
else:
self._mirrors_for_spec[dag_hash].append({
@@ -403,6 +398,11 @@ def _fetch_and_cache_index(self, mirror_url, expect_hash=None):
hash_fetch_url = url_util.join(
mirror_url, _build_cache_relative_path, 'index.json.hash')
if not web_util.url_exists(index_fetch_url):
# A binary mirror is not required to have an index, so avoid
# raising FetchCacheError in that case.
return False
old_cache_key = None
fetched_hash = None
@@ -762,6 +762,62 @@ def sign_tarball(key, force, specfile_path):
spack.util.gpg.sign(key, specfile_path, '%s.asc' % specfile_path)
def _fetch_spec_from_mirror(spec_url):
s = None
tty.debug('fetching {0}'.format(spec_url))
_, _, spec_file = web_util.read_from_url(spec_url)
spec_file_contents = codecs.getreader('utf-8')(spec_file).read()
# Need full spec.json name or this gets confused with index.json.
if spec_url.endswith('.json'):
s = Spec.from_json(spec_file_contents)
elif spec_url.endswith('.yaml'):
s = Spec.from_yaml(spec_file_contents)
return s
def _read_specs_and_push_index(file_list, cache_prefix, db, db_root_dir):
for file_path in file_list:
try:
s = _fetch_spec_from_mirror(url_util.join(cache_prefix, file_path))
except (URLError, web_util.SpackWebError) as url_err:
tty.error('Error reading specfile: {0}'.format(file_path))
tty.error(url_err)
if s:
db.add(s, None)
db.mark(s, 'in_buildcache', True)
# Now generate the index, compute its hash, and push the two files to
# the mirror.
index_json_path = os.path.join(db_root_dir, 'index.json')
with open(index_json_path, 'w') as f:
db._write_to_file(f)
# Read the index back in and compute its hash
with open(index_json_path) as f:
index_string = f.read()
index_hash = compute_hash(index_string)
# Write the hash out to a local file
index_hash_path = os.path.join(db_root_dir, 'index.json.hash')
with open(index_hash_path, 'w') as f:
f.write(index_hash)
# Push the index itself
web_util.push_to_url(
index_json_path,
url_util.join(cache_prefix, 'index.json'),
keep_original=False,
extra_args={'ContentType': 'application/json'})
# Push the hash
web_util.push_to_url(
index_hash_path,
url_util.join(cache_prefix, 'index.json.hash'),
keep_original=False,
extra_args={'ContentType': 'text/plain'})
def generate_package_index(cache_prefix):
"""Create the build cache index page.
@@ -790,35 +846,6 @@ def generate_package_index(cache_prefix):
tty.debug('Retrieving spec descriptor files from {0} to build index'.format(
cache_prefix))
all_mirror_specs = {}
for file_path in file_list:
try:
spec_url = url_util.join(cache_prefix, file_path)
tty.debug('fetching {0}'.format(spec_url))
_, _, spec_file = web_util.read_from_url(spec_url)
spec_file_contents = codecs.getreader('utf-8')(spec_file).read()
# Need full spec.json name or this gets confused with index.json.
if spec_url.endswith('.json'):
spec_dict = sjson.load(spec_file_contents)
s = Spec.from_json(spec_file_contents)
elif spec_url.endswith('.yaml'):
spec_dict = syaml.load(spec_file_contents)
s = Spec.from_yaml(spec_file_contents)
all_mirror_specs[s.dag_hash()] = {
'spec_url': spec_url,
'spec': s,
'num_deps': len(list(s.traverse(root=False))),
'binary_cache_checksum': spec_dict['binary_cache_checksum'],
'buildinfo': spec_dict['buildinfo'],
}
except (URLError, web_util.SpackWebError) as url_err:
tty.error('Error reading specfile: {0}'.format(file_path))
tty.error(url_err)
sorted_specs = sorted(all_mirror_specs.keys(),
key=lambda k: all_mirror_specs[k]['num_deps'])
tmpdir = tempfile.mkdtemp()
db_root_dir = os.path.join(tmpdir, 'db_root')
db = spack_db.Database(None, db_dir=db_root_dir,
@@ -826,85 +853,7 @@ def generate_package_index(cache_prefix):
record_fields=['spec', 'ref_count', 'in_buildcache'])
try:
tty.debug('Specs sorted by number of dependencies:')
for dag_hash in sorted_specs:
spec_record = all_mirror_specs[dag_hash]
s = spec_record['spec']
num_deps = spec_record['num_deps']
tty.debug(' {0}/{1} -> {2}'.format(
s.name, dag_hash[:7], num_deps))
if num_deps > 0:
# Check each of this spec's dependencies (which we have already
# processed), as they are the source of truth for their own
# full hash. If the full hash we have for any deps does not
# match what those deps have themselves, then we need to splice
# this spec with those deps, and push this spliced spec
# (spec.json file) back to the mirror, as well as update the
# all_mirror_specs dictionary with this spliced spec.
to_splice = []
for dep in s.dependencies():
dep_dag_hash = dep.dag_hash()
if dep_dag_hash in all_mirror_specs:
true_dep = all_mirror_specs[dep_dag_hash]['spec']
if true_dep.full_hash() != dep.full_hash():
to_splice.append(true_dep)
if to_splice:
tty.debug(' needs the following deps spliced:')
for true_dep in to_splice:
tty.debug(' {0}/{1}'.format(
true_dep.name, true_dep.dag_hash()[:7]))
s = s.splice(true_dep, True)
# Push this spliced spec back to the mirror
spliced_spec_dict = s.to_dict(hash=ht.full_hash)
for key in ['binary_cache_checksum', 'buildinfo']:
spliced_spec_dict[key] = spec_record[key]
temp_json_path = os.path.join(tmpdir, 'spliced.spec.json')
with open(temp_json_path, 'w') as fd:
fd.write(sjson.dump(spliced_spec_dict))
spliced_spec_url = spec_record['spec_url']
web_util.push_to_url(
temp_json_path, spliced_spec_url, keep_original=False)
tty.debug(' spliced and wrote {0}'.format(
spliced_spec_url))
spec_record['spec'] = s
db.add(s, None)
db.mark(s, 'in_buildcache', True)
# Now that we have fixed any old specfiles that might have had the wrong
# full hash for their dependencies, we can generate the index, compute
# the hash, and push those files to the mirror.
index_json_path = os.path.join(db_root_dir, 'index.json')
with open(index_json_path, 'w') as f:
db._write_to_file(f)
# Read the index back in and compute it's hash
with open(index_json_path) as f:
index_string = f.read()
index_hash = compute_hash(index_string)
# Write the hash out to a local file
index_hash_path = os.path.join(db_root_dir, 'index.json.hash')
with open(index_hash_path, 'w') as f:
f.write(index_hash)
# Push the index itself
web_util.push_to_url(
index_json_path,
url_util.join(cache_prefix, 'index.json'),
keep_original=False,
extra_args={'ContentType': 'application/json'})
# Push the hash
web_util.push_to_url(
index_hash_path,
url_util.join(cache_prefix, 'index.json.hash'),
keep_original=False,
extra_args={'ContentType': 'text/plain'})
_read_specs_and_push_index(file_list, cache_prefix, db, db_root_dir)
except Exception as err:
msg = 'Encountered problem pushing package index to {0}: {1}'.format(
cache_prefix, err)
@@ -1568,12 +1517,11 @@ def install_root_node(spec, allow_root, unsigned=False, force=False, sha256=None
sha256 (str): optional sha256 of the binary package, to be checked
before installation
"""
package = spack.repo.get(spec)
# Early termination
if spec.external or spec.virtual:
warnings.warn("Skipping external or virtual package {0}".format(spec.format()))
return
elif spec.concrete and package.installed and not force:
elif spec.concrete and spec.installed and not force:
warnings.warn("Package for spec {0} already installed.".format(spec.format()))
return
@@ -1611,16 +1559,14 @@ def install_single_spec(spec, allow_root=False, unsigned=False, force=False):
install_root_node(node, allow_root=allow_root, unsigned=unsigned, force=force)
def try_direct_fetch(spec, full_hash_match=False, mirrors=None):
def try_direct_fetch(spec, mirrors=None):
"""
Try to find the spec directly on the configured mirrors
"""
deprecated_specfile_name = tarball_name(spec, '.spec.yaml')
specfile_name = tarball_name(spec, '.spec.json')
specfile_is_json = True
lenient = not full_hash_match
found_specs = []
spec_full_hash = spec.full_hash()
for mirror in spack.mirror.MirrorCollection(mirrors=mirrors).values():
buildcache_fetch_url_yaml = url_util.join(
@@ -1650,29 +1596,21 @@ def try_direct_fetch(spec, full_hash_match=False, mirrors=None):
fetched_spec = Spec.from_yaml(specfile_contents)
fetched_spec._mark_concrete()
# Do not recompute the full hash for the fetched spec, instead just
# read the property.
if lenient or fetched_spec._full_hash == spec_full_hash:
found_specs.append({
'mirror_url': mirror.fetch_url,
'spec': fetched_spec,
})
found_specs.append({
'mirror_url': mirror.fetch_url,
'spec': fetched_spec,
})
return found_specs
def get_mirrors_for_spec(spec=None, full_hash_match=False,
mirrors_to_check=None, index_only=False):
def get_mirrors_for_spec(spec=None, mirrors_to_check=None, index_only=False):
"""
Check if concrete spec exists on mirrors and return a list
indicating the mirrors on which it can be found
Args:
spec (spack.spec.Spec): The spec to look for in binary mirrors
full_hash_match (bool): If True, only includes mirrors where the spec
full hash matches the locally computed full hash of the ``spec``
argument. If False, any mirror which has a matching DAG hash
is included in the results.
mirrors_to_check (dict): Optionally override the configured mirrors
with the mirrors in this dictionary.
index_only (bool): Do not attempt direct fetching of ``spec.json``
@@ -1689,29 +1627,14 @@ def get_mirrors_for_spec(spec=None, full_hash_match=False,
tty.debug("No Spack mirrors are currently configured")
return {}
results = []
lenient = not full_hash_match
spec_full_hash = spec.full_hash()
def filter_candidates(candidate_list):
filtered_candidates = []
for candidate in candidate_list:
candidate_full_hash = candidate['spec']._full_hash
if lenient or spec_full_hash == candidate_full_hash:
filtered_candidates.append(candidate)
return filtered_candidates
candidates = binary_index.find_built_spec(spec)
if candidates:
results = filter_candidates(candidates)
results = binary_index.find_built_spec(spec)
# Maybe we just didn't have the latest information from the mirror, so
# try to fetch directly, unless we are only considering the indices.
if not results and not index_only:
results = try_direct_fetch(spec,
full_hash_match=full_hash_match,
mirrors=mirrors_to_check)
results = try_direct_fetch(spec, mirrors=mirrors_to_check)
# We found a spec by the direct fetch approach, we might as well
# add it to our mapping.
if results:
binary_index.update_spec(spec, results)
@@ -1861,124 +1784,35 @@ def push_keys(*mirrors, **kwargs):
shutil.rmtree(tmpdir)
def needs_rebuild(spec, mirror_url, rebuild_on_errors=False):
def needs_rebuild(spec, mirror_url):
if not spec.concrete:
raise ValueError('spec must be concrete to check against mirror')
pkg_name = spec.name
pkg_version = spec.version
pkg_hash = spec.dag_hash()
pkg_full_hash = spec.full_hash()
tty.debug('Checking {0}-{1}, dag_hash = {2}, full_hash = {3}'.format(
pkg_name, pkg_version, pkg_hash, pkg_full_hash))
tty.debug('Checking {0}-{1}, dag_hash = {2}'.format(
pkg_name, pkg_version, pkg_hash))
tty.debug(spec.tree())
# Try to retrieve the specfile directly, based on the known
# format of the name, in order to determine if the package
# needs to be rebuilt.
cache_prefix = build_cache_prefix(mirror_url)
specfile_is_json = True
specfile_name = tarball_name(spec, '.spec.json')
deprecated_specfile_name = tarball_name(spec, '.spec.yaml')
specfile_path = os.path.join(cache_prefix, specfile_name)
deprecated_specfile_path = os.path.join(cache_prefix,
deprecated_specfile_name)
result_of_error = 'Package ({0}) will {1}be rebuilt'.format(
spec.short_spec, '' if rebuild_on_errors else 'not ')
try:
_, _, spec_file = web_util.read_from_url(specfile_path)
except (URLError, web_util.SpackWebError) as url_err:
try:
_, _, spec_file = web_util.read_from_url(deprecated_specfile_path)
specfile_is_json = False
except (URLError, web_util.SpackWebError) as url_err_y:
err_msg = [
'Unable to determine whether {0} needs rebuilding,',
' caught exception attempting to read from {1} or {2}.',
]
tty.error(''.join(err_msg).format(
spec.short_spec,
specfile_path,
deprecated_specfile_path))
tty.debug(url_err)
tty.debug(url_err_y)
tty.warn(result_of_error)
return rebuild_on_errors
spec_file_contents = codecs.getreader('utf-8')(spec_file).read()
if not spec_file_contents:
tty.error('Reading {0} returned nothing'.format(
specfile_path if specfile_is_json else deprecated_specfile_path))
tty.warn(result_of_error)
return rebuild_on_errors
spec_dict = (sjson.load(spec_file_contents)
if specfile_is_json else syaml.load(spec_file_contents))
try:
nodes = spec_dict['spec']['nodes']
except KeyError:
# Prior node dict format omitted 'nodes' key
nodes = spec_dict['spec']
name = spec.name
# In the old format:
# The "spec" key represents a list of objects, each with a single
# key that is the package name. While the list usually just contains
# a single object, we iterate over the list looking for the object
# with the name of this concrete spec as a key, out of an abundance
# of caution.
# In format version 2:
# ['spec']['nodes'] is still a list of objects, but with a
# multitude of keys. The list will commonly contain many objects, and in the
# case of build specs, it is highly likely that the same name will occur
# once as the actual package, and then again as the build provenance of that
# same package. Hence format version 2 matches on the dag hash, not name.
if nodes and 'name' not in nodes[0]:
# old style
cached_pkg_specs = [item[name] for item in nodes if name in item]
elif nodes and spec_dict['spec']['_meta']['version'] == 2:
cached_pkg_specs = [item for item in nodes
if item[ht.dag_hash.name] == spec.dag_hash()]
cached_target = cached_pkg_specs[0] if cached_pkg_specs else None
# If either the full_hash didn't exist in the specfile, or it
# did, but didn't match the one we computed locally, then we should
# just rebuild. This can be simplified once the dag_hash and the
# full_hash become the same thing.
rebuild = False
if not cached_target:
reason = 'did not find spec in specfile contents'
rebuild = True
elif ht.full_hash.name not in cached_target:
reason = 'full_hash was missing from remote specfile'
rebuild = True
else:
full_hash = cached_target[ht.full_hash.name]
if full_hash != pkg_full_hash:
reason = 'hash mismatch, remote = {0}, local = {1}'.format(
full_hash, pkg_full_hash)
rebuild = True
if rebuild:
tty.msg('Rebuilding {0}, reason: {1}'.format(
spec.short_spec, reason))
tty.msg(spec.tree())
return rebuild
# Only check for the presence of the json version of the spec. If the
# mirror only has the yaml version, or doesn't have the spec at all, we
# need to rebuild.
return not web_util.url_exists(specfile_path)
def check_specs_against_mirrors(mirrors, specs, output_file=None,
rebuild_on_errors=False):
def check_specs_against_mirrors(mirrors, specs, output_file=None):
"""Check all the given specs against buildcaches on the given mirrors and
determine if any of the specs need to be rebuilt. Reasons for needing to
rebuild include binary cache for spec isn't present on a mirror, or it is
present but the full_hash has changed since last time spec was built.
determine if any of the specs need to be rebuilt. Specs need to be rebuilt
when their hash doesn't exist in the mirror.
Arguments:
mirrors (dict): Mirrors to check against
@@ -1986,8 +1820,6 @@ def check_specs_against_mirrors(mirrors, specs, output_file=None,
output_file (str): Path to output file to be written. If provided,
mirrors with missing or out-of-date specs will be formatted as a
JSON object and written to this file.
rebuild_on_errors (bool): Treat any errors encountered while
checking specs as a signal to rebuild package.
Returns: 1 if any spec was out-of-date on any mirror, 0 otherwise.
@@ -1999,7 +1831,7 @@ def check_specs_against_mirrors(mirrors, specs, output_file=None,
rebuild_list = []
for spec in specs:
if needs_rebuild(spec, mirror.fetch_url, rebuild_on_errors):
if needs_rebuild(spec, mirror.fetch_url):
rebuild_list.append({
'short_spec': spec.short_spec,
'hash': spec.dag_hash()

View File

@@ -21,6 +21,7 @@
import llnl.util.filesystem as fs
import llnl.util.tty as tty
from llnl.util.lang import GroupedExceptionHandler
import spack.binary_distribution
import spack.config
@@ -417,11 +418,10 @@ def _make_bootstrapper(conf):
return _bootstrap_methods[btype](conf)
def _source_is_trusted(conf):
def _validate_source_is_trusted(conf):
trusted, name = spack.config.get('bootstrap:trusted'), conf['name']
if name not in trusted:
return False
return trusted[name]
raise ValueError('source is not trusted')
def spec_for_current_python():
@@ -488,34 +488,25 @@ def ensure_module_importable_or_raise(module, abstract_spec=None):
abstract_spec = abstract_spec or module
source_configs = spack.config.get('bootstrap:sources', [])
errors = {}
h = GroupedExceptionHandler()
for current_config in source_configs:
if not _source_is_trusted(current_config):
msg = ('[BOOTSTRAP MODULE {0}] Skipping source "{1}" since it is '
'not trusted').format(module, current_config['name'])
tty.debug(msg)
continue
with h.forward(current_config['name']):
_validate_source_is_trusted(current_config)
b = _make_bootstrapper(current_config)
try:
b = _make_bootstrapper(current_config)
if b.try_import(module, abstract_spec):
return
except Exception as e:
msg = '[BOOTSTRAP MODULE {0}] Unexpected error "{1}"'
tty.debug(msg.format(module, str(e)))
errors[current_config['name']] = e
# We couldn't import in any way, so raise an import error
msg = 'cannot bootstrap the "{0}" Python module'.format(module)
assert h, 'expected at least one exception to have been raised at this point: while bootstrapping {0}'.format(module) # noqa: E501
msg = 'cannot bootstrap the "{0}" Python module '.format(module)
if abstract_spec:
msg += ' from spec "{0}"'.format(abstract_spec)
msg += ' due to the following failures:\n'
for method in errors:
err = errors[method]
msg += " '{0}' raised {1}: {2}\n".format(
method, err.__class__.__name__, str(err))
msg += ' Please run `spack -d spec zlib` for more verbose error messages'
msg += 'from spec "{0}" '.format(abstract_spec)
if tty.is_debug():
msg += h.grouped_message(with_tracebacks=True)
else:
msg += h.grouped_message(with_tracebacks=False)
msg += '\nRun `spack --debug ...` for more detailed errors'
raise ImportError(msg)
@@ -539,15 +530,14 @@ def ensure_executables_in_path_or_raise(executables, abstract_spec):
executables_str = ', '.join(executables)
source_configs = spack.config.get('bootstrap:sources', [])
for current_config in source_configs:
if not _source_is_trusted(current_config):
msg = ('[BOOTSTRAP EXECUTABLES {0}] Skipping source "{1}" since it is '
'not trusted').format(executables_str, current_config['name'])
tty.debug(msg)
continue
b = _make_bootstrapper(current_config)
try:
h = GroupedExceptionHandler()
for current_config in source_configs:
with h.forward(current_config['name']):
_validate_source_is_trusted(current_config)
b = _make_bootstrapper(current_config)
if b.try_search_path(executables, abstract_spec):
# Additional environment variables needed
concrete_spec, cmd = b.last_search['spec'], b.last_search['command']
@@ -562,14 +552,16 @@ def ensure_executables_in_path_or_raise(executables, abstract_spec):
)
cmd.add_default_envmod(env_mods)
return cmd
except Exception as e:
msg = '[BOOTSTRAP EXECUTABLES {0}] Unexpected error "{1}"'
tty.debug(msg.format(executables_str, str(e)))
# We couldn't import in any way, so raise an import error
msg = 'cannot bootstrap any of the {0} executables'.format(executables_str)
assert h, 'expected at least one exception to have been raised at this point: while bootstrapping {0}'.format(executables_str) # noqa: E501
msg = 'cannot bootstrap any of the {0} executables '.format(executables_str)
if abstract_spec:
msg += ' from spec "{0}"'.format(abstract_spec)
msg += 'from spec "{0}" '.format(abstract_spec)
if tty.is_debug():
msg += h.grouped_message(with_tracebacks=True)
else:
msg += h.grouped_message(with_tracebacks=False)
msg += '\nRun `spack --debug ...` for more detailed errors'
raise RuntimeError(msg)

View File

@@ -111,6 +111,20 @@
dso_suffix = 'dylib' if sys.platform == 'darwin' else 'so'
def should_set_parallel_jobs(jobserver_support=False):
"""Returns true in general, except when:
- The env variable SPACK_NO_PARALLEL_MAKE=1 is set
- jobserver_support is enabled, and a jobserver was found.
"""
if (
jobserver_support and
'MAKEFLAGS' in os.environ and
'--jobserver' in os.environ['MAKEFLAGS']
):
return False
return not env_flag(SPACK_NO_PARALLEL_MAKE)
class MakeExecutable(Executable):
"""Special callable executable object for make so the user can specify
parallelism options on a per-invocation basis. Specifying
@@ -120,9 +134,6 @@ class MakeExecutable(Executable):
call will name an environment variable which will be set to the
parallelism level (without affecting the normal invocation with
-j).
Note that if the SPACK_NO_PARALLEL_MAKE env var is set it overrides
everything.
"""
def __init__(self, name, jobs):
@@ -133,9 +144,8 @@ def __call__(self, *args, **kwargs):
"""parallel, and jobs_env from kwargs are swallowed and used here;
remaining arguments are passed through to the superclass.
"""
disable = env_flag(SPACK_NO_PARALLEL_MAKE)
parallel = (not disable) and kwargs.pop('parallel', self.jobs > 1)
parallel = should_set_parallel_jobs(jobserver_support=True) and \
kwargs.pop('parallel', self.jobs > 1)
if parallel:
args = ('-j{0}'.format(self.jobs),) + args
@@ -181,7 +191,7 @@ def clean_environment():
env.unset('PYTHONPATH')
# Affects GNU make, can e.g. indirectly inhibit enabling parallel build
env.unset('MAKEFLAGS')
# env.unset('MAKEFLAGS')
# Avoid that libraries of build dependencies get hijacked.
env.unset('LD_PRELOAD')
@@ -232,6 +242,17 @@ def clean_environment():
# show useful matches.
env.set('LC_ALL', build_lang)
remove_flags = set()
keep_flags = set()
if spack.config.get('config:flags:keep_werror') == 'all':
keep_flags.add('-Werror*')
else:
if spack.config.get('config:flags:keep_werror') == 'specific':
keep_flags.add('-Werror=*')
remove_flags.add('-Werror*')
env.set('SPACK_COMPILER_FLAGS_KEEP', '|'.join(keep_flags))
env.set('SPACK_COMPILER_FLAGS_REMOVE', '|'.join(remove_flags))
# Remove any macports installs from the PATH. The macports ld can
# cause conflicts with the built-in linker on el capitan. Solves
# assembler issues, e.g.:
@@ -829,7 +850,7 @@ def setup_package(pkg, dirty, context='build'):
# PrgEnv modules on cray platform. Module unload does no damage when
# unnecessary
on_cray, _ = _on_cray()
if on_cray:
if on_cray and not dirty:
for mod in ['cray-mpich', 'cray-libsci']:
module('unload', mod)
@@ -1028,7 +1049,7 @@ def get_cmake_prefix_path(pkg):
def _setup_pkg_and_run(serialized_pkg, function, kwargs, child_pipe,
input_multiprocess_fd):
input_multiprocess_fd, jsfd1, jsfd2):
context = kwargs.get('context', 'build')
@@ -1135,6 +1156,8 @@ def child_fun():
"""
parent_pipe, child_pipe = multiprocessing.Pipe()
input_multiprocess_fd = None
jobserver_fd1 = None
jobserver_fd2 = None
serialized_pkg = spack.subprocess_context.PackageInstallContext(pkg)
@@ -1144,11 +1167,17 @@ def child_fun():
'fileno'):
input_fd = os.dup(sys.stdin.fileno())
input_multiprocess_fd = MultiProcessFd(input_fd)
mflags = os.environ.get('MAKEFLAGS', False)
if mflags:
m = re.search(r'--jobserver-[^=]*=(\d),(\d)', mflags)
if m:
jobserver_fd1 = MultiProcessFd(int(m.group(1)))
jobserver_fd2 = MultiProcessFd(int(m.group(2)))
p = multiprocessing.Process(
target=_setup_pkg_and_run,
args=(serialized_pkg, function, kwargs, child_pipe,
input_multiprocess_fd))
input_multiprocess_fd, jobserver_fd1, jobserver_fd2))
p.start()

View File

@@ -210,6 +210,10 @@ def std_initconfig_entries(self):
"#------------------{0}\n".format("-" * 60),
]
def initconfig_package_entries(self):
"""This method is to be overwritten by the package"""
return []
def initconfig(self, spec, prefix):
cache_entries = (self.std_initconfig_entries() +
self.initconfig_compiler_entries() +

View File

@@ -176,6 +176,7 @@ def _std_args(pkg):
'-G', generator,
define('CMAKE_INSTALL_PREFIX', convert_to_posix_path(pkg.prefix)),
define('CMAKE_BUILD_TYPE', build_type),
define('BUILD_TESTING', pkg.run_tests),
]
# CMAKE_INTERPROCEDURAL_OPTIMIZATION only exists for CMake >= 3.9
@@ -361,6 +362,7 @@ def cmake_args(self):
* CMAKE_INSTALL_PREFIX
* CMAKE_BUILD_TYPE
* BUILD_TESTING
which will be set automatically.

View File

@@ -107,10 +107,10 @@ def cuda_flags(arch_list):
# each release of a new cuda minor version.
conflicts('%gcc@10:', when='+cuda ^cuda@:11.0')
conflicts('%gcc@11:', when='+cuda ^cuda@:11.4.0')
conflicts('%gcc@12:', when='+cuda ^cuda@:11.6')
conflicts('%gcc@12:', when='+cuda ^cuda@:11.7')
conflicts('%clang@12:', when='+cuda ^cuda@:11.4.0')
conflicts('%clang@13:', when='+cuda ^cuda@:11.5')
conflicts('%clang@14:', when='+cuda ^cuda@:11.6')
conflicts('%clang@14:', when='+cuda ^cuda@:11.7')
# https://gist.github.com/ax3l/9489132#gistcomment-3860114
conflicts('%gcc@10', when='+cuda ^cuda@:11.4.0')

View File

@@ -0,0 +1,102 @@
# Copyright 2013-2022 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)
import os
from llnl.util.filesystem import find
from spack.directives import depends_on, extends
from spack.multimethod import when
from spack.package import PackageBase
from spack.util.executable import Executable
class LuaPackage(PackageBase):
"""Specialized class for lua packages"""
phases = ['unpack', 'generate_luarocks_config', 'preprocess', 'install']
#: This attribute is used in UI queries that need to know the build
#: system base class
build_system_class = 'LuaPackage'
list_depth = 1 # LuaRocks requires at least one level of spidering to find versions
depends_on('lua-lang')
extends('lua', when='^lua')
with when('^lua-luajit'):
extends('lua-luajit')
depends_on('luajit')
depends_on('lua-luajit+lualinks')
with when('^lua-luajit-openresty'):
extends('lua-luajit-openresty')
depends_on('luajit')
depends_on('lua-luajit-openresty+lualinks')
def unpack(self, spec, prefix):
if os.path.splitext(self.stage.archive_file)[1] == '.rock':
directory = self.luarocks('unpack', self.stage.archive_file, output=str)
dirlines = directory.split('\n')
# TODO: figure out how to scope this better
os.chdir(dirlines[2])
def _generate_tree_line(self, name, prefix):
return """{{ name = "{name}", root = "{prefix}" }};""".format(
name=name,
prefix=prefix,
)
def _luarocks_config_path(self):
return os.path.join(self.stage.source_path, 'spack_luarocks.lua')
def generate_luarocks_config(self, spec, prefix):
spec = self.spec
table_entries = []
for d in spec.traverse(
deptypes=("build", "run"), deptype_query="run"
):
if d.package.extends(self.extendee_spec):
table_entries.append(self._generate_tree_line(d.name, d.prefix))
path = self._luarocks_config_path()
with open(path, 'w') as config:
config.write(
"""
deps_mode="all"
rocks_trees={{
{}
}}
""".format(
"\n".join(table_entries)
)
)
return path
def setup_build_environment(self, env):
env.set('LUAROCKS_CONFIG', self._luarocks_config_path())
def preprocess(self, spec, prefix):
"""Override this to preprocess source before building with luarocks"""
pass
@property
def lua(self):
return Executable(self.spec['lua-lang'].prefix.bin.lua)
@property
def luarocks(self):
lr = Executable(self.spec['lua-lang'].prefix.bin.luarocks)
return lr
def luarocks_args(self):
return []
def install(self, spec, prefix):
rock = '.'
specs = find('.', '*.rockspec', recursive=False)
if specs:
rock = specs[0]
rocks_args = self.luarocks_args()
rocks_args.append(rock)
self.luarocks('--tree=' + prefix, 'make', *rocks_args)

View File

@@ -30,6 +30,15 @@ class IntelOneApiPackage(Package):
# organization (e.g. University/Company).
redistribute_source = False
@staticmethod
def update_description(cls):
"""Updates oneapi package descriptions with common text."""
text = """ LICENSE INFORMATION: By downloading and using this software, you agree to the terms
and conditions of the software license agreements at https://intel.ly/393CijO."""
cls.__doc__ = cls.__doc__ + text
return cls
@property
def component_dir(self):
"""Subdirectory for this component in the install prefix."""

View File

@@ -90,8 +90,8 @@ def _create_buildgroup(opener, headers, url, project, group_name, group_type):
return build_group_id
def populate_buildgroup(job_names, group_name, project, site,
credentials, cdash_url):
def _populate_buildgroup(job_names, group_name, project, site,
credentials, cdash_url):
url = "{0}/api/v1/buildgroup.php".format(cdash_url)
headers = {
@@ -132,16 +132,30 @@ def populate_buildgroup(job_names, group_name, project, site,
response_code = response.getcode()
if response_code != 200:
msg = 'Error response code ({0}) in populate_buildgroup'.format(
msg = 'Error response code ({0}) in _populate_buildgroup'.format(
response_code)
tty.warn(msg)
def is_main_phase(phase_name):
def _is_main_phase(phase_name):
return True if phase_name == 'specs' else False
def get_job_name(phase, strip_compiler, spec, osarch, build_group):
""" Given the necessary parts, format the gitlab job name
Arguments:
phase (str): Either 'specs' for the main phase, or the name of a
bootstrapping phase
strip_compiler (bool): Should compiler be stripped from job name
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 = []
@@ -163,7 +177,7 @@ def get_job_name(phase, strip_compiler, spec, osarch, build_group):
format_args.append(spec.version)
item_idx += 1
if is_main_phase(phase) is True or strip_compiler is False:
if _is_main_phase(phase) is True or strip_compiler is False:
format_str += ' {{{0}}}'.format(item_idx)
format_args.append(spec.compiler)
item_idx += 1
@@ -180,12 +194,12 @@ def get_job_name(phase, strip_compiler, spec, osarch, build_group):
return format_str.format(*format_args)
def get_cdash_build_name(spec, build_group):
def _get_cdash_build_name(spec, build_group):
return '{0}@{1}%{2} arch={3} ({4})'.format(
spec.name, spec.version, spec.compiler, spec.architecture, build_group)
def get_spec_string(spec):
def _get_spec_string(spec):
format_elements = [
'{name}{@version}',
'{%compiler}',
@@ -197,15 +211,15 @@ def get_spec_string(spec):
return spec.format(''.join(format_elements))
def format_root_spec(spec, main_phase, strip_compiler):
def _format_root_spec(spec, main_phase, strip_compiler):
if main_phase is False and strip_compiler is True:
return '{0}@{1} arch={2}'.format(
spec.name, spec.version, spec.architecture)
else:
return spec.build_hash()
return spec.dag_hash()
def spec_deps_key(s):
def _spec_deps_key(s):
return '{0}/{1}'.format(s.name, s.dag_hash(7))
@@ -217,8 +231,8 @@ def _add_dependency(spec_label, dep_label, deps):
deps[spec_label].add(dep_label)
def get_spec_dependencies(specs, deps, spec_labels, check_index_only=False):
spec_deps_obj = compute_spec_deps(specs, check_index_only=check_index_only)
def _get_spec_dependencies(specs, deps, spec_labels, check_index_only=False):
spec_deps_obj = _compute_spec_deps(specs, check_index_only=check_index_only)
if spec_deps_obj:
dependencies = spec_deps_obj['dependencies']
@@ -266,11 +280,11 @@ def stage_spec_jobs(specs, check_index_only=False):
"""
# The convenience method below, "remove_satisfied_deps()", does not modify
# The convenience method below, "_remove_satisfied_deps()", does not modify
# the "deps" parameter. Instead, it returns a new dictionary where only
# dependencies which have not yet been satisfied are included in the
# return value.
def remove_satisfied_deps(deps, satisfied_list):
def _remove_satisfied_deps(deps, satisfied_list):
new_deps = {}
for key, value in iteritems(deps):
@@ -283,7 +297,7 @@ def remove_satisfied_deps(deps, satisfied_list):
deps = {}
spec_labels = {}
get_spec_dependencies(
_get_spec_dependencies(
specs, deps, spec_labels, check_index_only=check_index_only)
# Save the original deps, as we need to return them at the end of the
@@ -302,7 +316,7 @@ def remove_satisfied_deps(deps, satisfied_list):
# Note that "dependencies" is a dictionary mapping each dependent
# package to the set of not-yet-handled dependencies. The final step
# below removes all the dependencies that are handled by this stage.
dependencies = remove_satisfied_deps(dependencies, next_stage)
dependencies = _remove_satisfied_deps(dependencies, next_stage)
if unstaged:
stages.append(unstaged.copy())
@@ -310,13 +324,12 @@ def remove_satisfied_deps(deps, satisfied_list):
return spec_labels, deps, stages
def print_staging_summary(spec_labels, dependencies, stages):
def _print_staging_summary(spec_labels, dependencies, stages):
if not stages:
return
tty.msg(' Staging summary:')
stage_index = 0
for stage in stages:
tty.msg(' Staging summary ([x] means a job needs rebuilding):')
for stage_index, stage in enumerate(stages):
tty.msg(' stage {0} ({1} jobs):'.format(stage_index, len(stage)))
for job in sorted(stage):
@@ -324,12 +337,10 @@ def print_staging_summary(spec_labels, dependencies, stages):
tty.msg(' [{1}] {0} -> {2}'.format(
job,
'x' if spec_labels[job]['needs_rebuild'] else ' ',
get_spec_string(s)))
stage_index += 1
_get_spec_string(s)))
def compute_spec_deps(spec_list, check_index_only=False):
def _compute_spec_deps(spec_list, check_index_only=False):
"""
Computes all the dependencies for the spec(s) and generates a JSON
object which provides both a list of unique spec names as well as a
@@ -402,17 +413,17 @@ def append_dep(s, d):
continue
up_to_date_mirrors = bindist.get_mirrors_for_spec(
spec=s, full_hash_match=True, index_only=check_index_only)
spec=s, index_only=check_index_only)
skey = spec_deps_key(s)
skey = _spec_deps_key(s)
spec_labels[skey] = {
'spec': get_spec_string(s),
'spec': _get_spec_string(s),
'root': root_spec,
'needs_rebuild': not up_to_date_mirrors,
}
for d in s.dependencies(deptype=all):
dkey = spec_deps_key(d)
dkey = _spec_deps_key(d)
if d.external:
tty.msg('Will not stage external dep: {0}'.format(d))
continue
@@ -435,11 +446,11 @@ def append_dep(s, d):
return deps_json_obj
def spec_matches(spec, match_string):
def _spec_matches(spec, match_string):
return spec.satisfies(match_string)
def copy_attributes(attrs_list, src_dict, dest_dict):
def _copy_attributes(attrs_list, src_dict, dest_dict):
for runner_attr in attrs_list:
if runner_attr in src_dict:
if runner_attr in dest_dict and runner_attr == 'tags':
@@ -460,7 +471,7 @@ def copy_attributes(attrs_list, src_dict, dest_dict):
dest_dict[runner_attr] = copy.deepcopy(src_dict[runner_attr])
def find_matching_config(spec, gitlab_ci):
def _find_matching_config(spec, gitlab_ci):
runner_attributes = {}
overridable_attrs = [
'image',
@@ -471,16 +482,16 @@ def find_matching_config(spec, gitlab_ci):
'after_script',
]
copy_attributes(overridable_attrs, gitlab_ci, runner_attributes)
_copy_attributes(overridable_attrs, gitlab_ci, runner_attributes)
ci_mappings = gitlab_ci['mappings']
for ci_mapping in ci_mappings:
for match_string in ci_mapping['match']:
if spec_matches(spec, match_string):
if _spec_matches(spec, match_string):
if 'runner-attributes' in ci_mapping:
copy_attributes(overridable_attrs,
ci_mapping['runner-attributes'],
runner_attributes)
_copy_attributes(overridable_attrs,
ci_mapping['runner-attributes'],
runner_attributes)
return runner_attributes
else:
return None
@@ -488,16 +499,16 @@ def find_matching_config(spec, gitlab_ci):
return runner_attributes
def pkg_name_from_spec_label(spec_label):
def _pkg_name_from_spec_label(spec_label):
return spec_label[:spec_label.index('/')]
def format_job_needs(phase_name, strip_compilers, dep_jobs,
osname, build_group, prune_dag, stage_spec_dict,
enable_artifacts_buildcache):
def _format_job_needs(phase_name, strip_compilers, dep_jobs,
osname, build_group, prune_dag, stage_spec_dict,
enable_artifacts_buildcache):
needs_list = []
for dep_job in dep_jobs:
dep_spec_key = spec_deps_key(dep_job)
dep_spec_key = _spec_deps_key(dep_job)
dep_spec_info = stage_spec_dict[dep_spec_key]
if not prune_dag or dep_spec_info['needs_rebuild']:
@@ -592,6 +603,33 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
prune_dag=False, check_index_only=False,
run_optimizer=False, use_dependencies=False,
artifacts_root=None):
""" Generate a gitlab yaml file to run a dynamic chile pipeline from
the spec matrix in the active environment.
Arguments:
env (spack.environment.Environment): Activated environment object
which must contain a gitlab-ci section describing how to map
specs to runners
print_summary (bool): Should we print a summary of all the jobs in
the stages in which they were placed.
output_file (str): File path where generated file should be written
prune_dag (bool): If True, do not generate jobs for specs already
exist built on the mirror.
check_index_only (bool): If True, attempt to fetch the mirror index
and only use that to determine whether built specs on the mirror
this mode results in faster yaml generation time). Otherwise, also
check each spec directly by url (useful if there is no index or it
might be out of date).
run_optimizer (bool): If True, post-process the generated yaml to try
try to reduce the size (attempts to collect repeated configuration
and replace with definitions).)
use_dependencies (bool): If true, use "dependencies" rather than "needs"
("needs" allows DAG scheduling). Useful if gitlab instance cannot
be configured to handle more than a few "needs" per job.
artifacts_root (str): Path where artifacts like logs, environment
files (spack.yaml, spack.lock), etc should be written. GitLab
requires this to be within the project directory.
"""
with spack.concretize.disable_compiler_existence_check():
with env.write_transaction():
env.concretize()
@@ -804,7 +842,7 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
max_needs_job = ''
# If this is configured, spack will fail "spack ci generate" if it
# generates any full hash which exists under the broken specs url.
# generates any hash which exists under the broken specs url.
broken_spec_urls = None
if broken_specs_url:
if broken_specs_url.startswith('http'):
@@ -819,7 +857,7 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
phase_name = phase['name']
strip_compilers = phase['strip-compilers']
main_phase = is_main_phase(phase_name)
main_phase = _is_main_phase(phase_name)
spec_labels, dependencies, stages = staged_phases[phase_name]
for stage_jobs in stages:
@@ -830,11 +868,9 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
for spec_label in stage_jobs:
spec_record = spec_labels[spec_label]
root_spec = spec_record['rootSpec']
pkg_name = pkg_name_from_spec_label(spec_label)
pkg_name = _pkg_name_from_spec_label(spec_label)
release_spec = root_spec[pkg_name]
release_spec_full_hash = release_spec.full_hash()
release_spec_dag_hash = release_spec.dag_hash()
release_spec_build_hash = release_spec.build_hash()
if prune_untouched_packages:
if release_spec not in affected_specs:
@@ -843,7 +879,7 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
spec_record['needs_rebuild'] = False
continue
runner_attribs = find_matching_config(
runner_attribs = _find_matching_config(
release_spec, gitlab_ci)
if not runner_attribs:
@@ -897,15 +933,13 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
compiler_action = 'NONE'
if len(phases) > 1:
compiler_action = 'FIND_ANY'
if is_main_phase(phase_name):
if _is_main_phase(phase_name):
compiler_action = 'INSTALL_MISSING'
job_vars = {
'SPACK_ROOT_SPEC': format_root_spec(
'SPACK_ROOT_SPEC': _format_root_spec(
root_spec, main_phase, strip_compilers),
'SPACK_JOB_SPEC_DAG_HASH': release_spec_dag_hash,
'SPACK_JOB_SPEC_BUILD_HASH': release_spec_build_hash,
'SPACK_JOB_SPEC_FULL_HASH': release_spec_full_hash,
'SPACK_JOB_SPEC_PKG_NAME': release_spec.name,
'SPACK_COMPILER_ACTION': compiler_action
}
@@ -924,15 +958,15 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
# purposes, so we only get the direct dependencies.
dep_jobs = []
for dep_label in dependencies[spec_label]:
dep_pkg = pkg_name_from_spec_label(dep_label)
dep_pkg = _pkg_name_from_spec_label(dep_label)
dep_root = spec_labels[dep_label]['rootSpec']
dep_jobs.append(dep_root[dep_pkg])
job_dependencies.extend(
format_job_needs(phase_name, strip_compilers,
dep_jobs, osname, build_group,
prune_dag, spec_labels,
enable_artifacts_buildcache))
_format_job_needs(phase_name, strip_compilers,
dep_jobs, osname, build_group,
prune_dag, spec_labels,
enable_artifacts_buildcache))
rebuild_spec = spec_record['needs_rebuild']
@@ -943,7 +977,7 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
# compiler we are supposed to use is listed in any of the
# bootstrap spec lists, then we will add more dependencies to
# the job (that compiler and maybe it's dependencies as well).
if is_main_phase(phase_name):
if _is_main_phase(phase_name):
spec_arch_family = (release_spec.architecture
.target
.microarchitecture
@@ -971,7 +1005,7 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
# be rebuilt if the compiler targeted to build it
# needs to be rebuilt.
bs_specs, _, _ = staged_phases[bs['phase-name']]
c_spec_key = spec_deps_key(c_spec)
c_spec_key = _spec_deps_key(c_spec)
rbld_comp = bs_specs[c_spec_key]['needs_rebuild']
rebuild_spec = rebuild_spec or rbld_comp
# Also update record so dependents do not fail to
@@ -985,14 +1019,14 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
]
job_dependencies.extend(
format_job_needs(bs['phase-name'],
bs['strip-compilers'],
dep_jobs,
str(bs_arch),
build_group,
prune_dag,
bs_specs,
enable_artifacts_buildcache))
_format_job_needs(bs['phase-name'],
bs['strip-compilers'],
dep_jobs,
str(bs_arch),
build_group,
prune_dag,
bs_specs,
enable_artifacts_buildcache))
else:
debug_msg = ''.join([
'Considered compiler {0} for spec ',
@@ -1009,9 +1043,9 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
continue
if (broken_spec_urls is not None and
release_spec_full_hash in broken_spec_urls):
release_spec_dag_hash in broken_spec_urls):
known_broken_specs_encountered.append('{0} ({1})'.format(
release_spec, release_spec_full_hash))
release_spec, release_spec_dag_hash))
if artifacts_root:
job_dependencies.append({
@@ -1022,7 +1056,7 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
job_vars['SPACK_SPEC_NEEDS_REBUILD'] = str(rebuild_spec)
if enable_cdash_reporting:
cdash_build_name = get_cdash_build_name(
cdash_build_name = _get_cdash_build_name(
release_spec, build_group)
all_job_names.append(cdash_build_name)
job_vars['SPACK_CDASH_BUILD_NAME'] = cdash_build_name
@@ -1087,7 +1121,7 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
phase_name = phase['name']
tty.msg('Stages for phase "{0}"'.format(phase_name))
phase_stages = staged_phases[phase_name]
print_staging_summary(*phase_stages)
_print_staging_summary(*phase_stages)
tty.debug('{0} build jobs generated in {1} stages'.format(
job_id, stage_id))
@@ -1099,8 +1133,8 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
# Use "all_job_names" to populate the build group for this set
if enable_cdash_reporting and cdash_auth_token:
try:
populate_buildgroup(all_job_names, build_group, cdash_project,
cdash_site, cdash_auth_token, cdash_url)
_populate_buildgroup(all_job_names, build_group, cdash_project,
cdash_site, cdash_auth_token, cdash_url)
except (SpackError, HTTPError, URLError) as err:
tty.warn('Problem populating buildgroup: {0}'.format(err))
else:
@@ -1136,9 +1170,9 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
cleanup_job = {}
if service_job_config:
copy_attributes(default_attrs,
service_job_config,
cleanup_job)
_copy_attributes(default_attrs,
service_job_config,
cleanup_job)
cleanup_job['stage'] = 'cleanup-temp-storage'
cleanup_job['script'] = [
@@ -1156,9 +1190,9 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
final_job = {}
if service_job_config:
copy_attributes(default_attrs,
service_job_config,
final_job)
_copy_attributes(default_attrs,
service_job_config,
final_job)
index_target_mirror = mirror_urls[0]
if is_pr_pipeline:
@@ -1229,9 +1263,9 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
noop_job = {}
if service_job_config:
copy_attributes(default_attrs,
service_job_config,
noop_job)
_copy_attributes(default_attrs,
service_job_config,
noop_job)
if 'script' not in noop_job:
noop_job['script'] = [
@@ -1254,7 +1288,7 @@ def generate_gitlab_ci_yaml(env, print_summary, output_file,
outf.write(syaml.dump_config(sorted_output, default_flow_style=True))
def url_encode_string(input_string):
def _url_encode_string(input_string):
encoded_keyval = urlencode({'donotcare': input_string})
eq_idx = encoded_keyval.find('=') + 1
encoded_value = encoded_keyval[eq_idx:]
@@ -1262,6 +1296,17 @@ def url_encode_string(input_string):
def import_signing_key(base64_signing_key):
""" Given Base64-encoded gpg key, decode and import it to use for
signing packages.
Arguments:
base64_signing_key (str): A gpg key including the secret key,
armor-exported and base64 encoded, so it can be stored in a
gitlab CI variable. For an example of how to generate such
a key, see:
https://github.com/spack/spack-infrastructure/blob/main/gitlab-docker/files/gen-key
"""
if not base64_signing_key:
tty.warn('No key found for signing/verifying packages')
return
@@ -1299,14 +1344,34 @@ def import_signing_key(base64_signing_key):
def can_sign_binaries():
""" Utility method to determine if this spack instance is capable of
signing binary packages. This is currently only possible if the
spack gpg keystore contains exactly one secret key."""
return len(gpg_util.signing_keys()) == 1
def can_verify_binaries():
""" Utility method to determin if this spack instance is capable (at
least in theory) of verifying signed binaries."""
return len(gpg_util.public_keys()) >= 1
def configure_compilers(compiler_action, scope=None):
""" Depending on the compiler_action parameter, either turn on the
install_missing_compilers config option, or find spack compilers,
or do nothing. This is used from rebuild jobs in bootstrapping
pipelines, where in the bootsrapping phase we would pass
FIND_ANY in case of compiler-agnostic bootstrapping, while in the
spec building phase we would pass INSTALL_MISSING in order to get
spack to use the compiler which was built in the previous phase and
is now sitting in the binary mirror.
Arguments:
compiler_action (str): 'FIND_ANY', 'INSTALL_MISSING' have meanings
described above. Any other value essentially results in a no-op.
scope (spack.config.ConfigScope): Optional. The scope in which to look for
compilers, in case 'FIND_ANY' was provided.
"""
if compiler_action == 'INSTALL_MISSING':
tty.debug('Make sure bootstrapped compiler will be installed')
config = cfg.get('config')
@@ -1330,6 +1395,35 @@ def configure_compilers(compiler_action, scope=None):
def get_concrete_specs(env, root_spec, job_name, compiler_action):
""" Build a dictionary of concrete specs relevant to a particular
rebuild job. This includes the root spec and the spec to be
rebuilt (which could be the same).
Arguments:
env (spack.environment.Environment): Activated spack environment
used to get concrete root spec by hash in case compiler_action
is anthing other than FIND_ANY.
root_spec (str): If compiler_action is FIND_ANY root_spec is
a string representation which can be turned directly into
a spec, otherwise, it's a hash used to index the activated
spack environment.
job_name (str): Name of package to be built, used to index the
concrete root spec and produce the concrete spec to be
built.
compiler_action (str): Determines how to interpret the root_spec
parameter, either as a string representation as a hash.
Returns:
.. code-block:: JSON
{
"root": "<spec>",
"<job-pkg-name>": "<spec>",
}
"""
spec_map = {
'root': None,
}
@@ -1376,6 +1470,19 @@ def _push_mirror_contents(env, specfile_path, sign_binaries, mirror_url):
def push_mirror_contents(env, specfile_path, mirror_url, sign_binaries):
""" Push one or more binary packages to the mirror.
Arguments:
env (spack.environment.Environment): Optional environment. If
provided, it is used to make sure binary package to push
exists in the environment.
specfile_path (str): Path to spec.json corresponding to built pkg
to push.
mirror_url (str): Base url of target mirror
sign_binaries (bool): If True, spack will attempt to sign binary
package before pushing.
"""
try:
_push_mirror_contents(env, specfile_path, sign_binaries, mirror_url)
except Exception as inst:
@@ -1400,6 +1507,15 @@ def push_mirror_contents(env, specfile_path, mirror_url, sign_binaries):
def copy_stage_logs_to_artifacts(job_spec, job_log_dir):
""" Looks for spack-build-out.txt in the stage directory of the given
job_spec, and attempts to copy the file into the directory given
by job_log_dir.
Arguments:
job_spec (spack.spec.Spec): Spec associated with spack install log
job_log_dir (str): Path into which build log should be copied
"""
try:
job_pkg = spack.repo.get(job_spec)
tty.debug('job package: {0}'.format(job_pkg))
@@ -1418,6 +1534,14 @@ def copy_stage_logs_to_artifacts(job_spec, job_log_dir):
def download_and_extract_artifacts(url, work_dir):
""" Look for gitlab artifacts.zip at the given url, and attempt to download
and extract the contents into the given work_dir
Arguments:
url (str): Complete url to artifacts.zip file
work_dir (str): Path to destination where artifacts should be extracted
"""
tty.msg('Fetching artifacts from: {0}\n'.format(url))
headers = {
@@ -1457,6 +1581,8 @@ def download_and_extract_artifacts(url, work_dir):
def get_spack_info():
""" If spack is running from a git repo, return the most recent git log
entry, otherwise, return a string containing the spack version. """
git_path = os.path.join(spack.paths.prefix, ".git")
if os.path.exists(git_path):
git = exe.which("git")
@@ -1472,6 +1598,23 @@ def get_spack_info():
def setup_spack_repro_version(repro_dir, checkout_commit, merge_commit=None):
""" Look in the local spack clone to find the checkout_commit, and if
provided, the merge_commit given as arguments. If those commits can
be found locally, then clone spack and attempt to recreate a merge
commit with the same parent commits as tested in gitlab. This looks
something like 1) git clone repo && cd repo 2) git checkout
<checkout_commit> 3) git merge <merge_commit>. If there is no
merge_commit provided, then skip step (3).
Arguments:
repro_dir (str): Location where spack should be cloned
checkout_commit (str): SHA of PR branch commit
merge_commit (str): SHA of target branch parent
Returns: True if git repo state was successfully recreated, or False
otherwise.
"""
# figure out the path to the spack git version being used for the
# reproduction
print('checkout_commit: {0}'.format(checkout_commit))
@@ -1513,7 +1656,7 @@ def setup_spack_repro_version(repro_dir, checkout_commit, merge_commit=None):
fail_on_error=False)
if git.returncode != 0:
tty.error('Unable to clone your local spac repo:')
tty.error('Unable to clone your local spack repo:')
tty.msg(clone_out)
return False
@@ -1546,6 +1689,18 @@ def setup_spack_repro_version(repro_dir, checkout_commit, merge_commit=None):
def reproduce_ci_job(url, work_dir):
""" Given a url to gitlab artifacts.zip from a failed 'spack ci rebuild' job,
attempt to setup an environment in which the failure can be reproduced
locally. This entails the following:
First download and extract artifacts. Then look through those artifacts
to glean some information needed for the reproduer (e.g. one of the
artifacts contains information about the version of spack tested by
gitlab, another is the generated pipeline yaml containing details
of the job like the docker image used to run it). The output of this
function is a set of printed instructions for running docker and then
commands to run to reproduce the build once inside the container.
"""
download_and_extract_artifacts(url, work_dir)
lock_file = fs.find(work_dir, 'spack.lock')[0]

View File

@@ -155,31 +155,17 @@ def parse_specs(args, **kwargs):
normalize = kwargs.get('normalize', False)
tests = kwargs.get('tests', False)
try:
sargs = args
if not isinstance(args, six.string_types):
sargs = ' '.join(spack.util.string.quote(args))
specs = spack.spec.parse(sargs)
for spec in specs:
if concretize:
spec.concretize(tests=tests) # implies normalize
elif normalize:
spec.normalize(tests=tests)
sargs = args
if not isinstance(args, six.string_types):
sargs = ' '.join(spack.util.string.quote(args))
specs = spack.spec.parse(sargs)
for spec in specs:
if concretize:
spec.concretize(tests=tests) # implies normalize
elif normalize:
spec.normalize(tests=tests)
return specs
except spack.spec.SpecParseError as e:
msg = e.message + "\n" + str(e.string) + "\n"
msg += (e.pos + 2) * " " + "^"
raise spack.error.SpackError(msg)
except spack.error.SpecError as e:
msg = e.message
if e.long_message:
msg += e.long_message
raise spack.error.SpackError(msg)
return specs
def matching_spec_from_env(spec):

View File

@@ -161,11 +161,6 @@ def setup_parser(subparser):
help=('Check single spec from json or yaml file instead of release ' +
'specs file'))
check.add_argument(
'--rebuild-on-error', default=False, action='store_true',
help="Default to rebuilding packages if errors are encountered " +
"during the process of checking whether rebuilding is needed")
check.set_defaults(func=check_fn)
# Download tarball and specfile
@@ -361,7 +356,7 @@ def list_fn(args):
try:
specs = bindist.update_cache_and_get_specs()
except bindist.FetchCacheError as e:
tty.error(e)
tty.die(e)
if not args.allarch:
arch = spack.spec.Spec.default_arch()
@@ -430,7 +425,7 @@ def check_fn(args):
sys.exit(0)
sys.exit(bindist.check_specs_against_mirrors(
configured_mirrors, specs, args.output_file, args.rebuild_on_error))
configured_mirrors, specs, args.output_file))
def download_fn(args):
@@ -483,11 +478,12 @@ def save_specfile_fn(args):
if args.root_specfile:
with open(args.root_specfile) as fd:
root_spec_as_json = fd.read()
spec_format = 'yaml' if args.root_specfile.endswith('yaml') else 'json'
else:
root_spec = Spec(args.root_spec)
root_spec.concretize()
root_spec_as_json = root_spec.to_json(hash=ht.build_hash)
spec_format = 'yaml' if args.root_specfile.endswith('yaml') else 'json'
root_spec_as_json = root_spec.to_json(hash=ht.dag_hash)
spec_format = 'json'
save_dependency_specfiles(
root_spec_as_json, args.specfile_dir, args.specs.split(), spec_format)
@@ -701,7 +697,7 @@ def update_index(mirror_url, update_keys=False):
def update_index_fn(args):
"""Update a buildcache index."""
outdir = '.'
outdir = 'file://.'
if args.mirror_url:
outdir = args.mirror_url

View File

@@ -167,8 +167,7 @@ def ci_reindex(args):
def ci_rebuild(args):
"""Check a single spec against the remote mirror, and rebuild it from
source if the mirror does not contain the full hash match of the spec
as computed locally. """
source if the mirror does not contain the hash. """
env = spack.cmd.require_active_env(cmd_name='ci rebuild')
# Make sure the environment is "gitlab-enabled", or else there's nothing
@@ -280,8 +279,8 @@ def ci_rebuild(args):
env, root_spec, job_spec_pkg_name, compiler_action)
job_spec = spec_map[job_spec_pkg_name]
job_spec_yaml_file = '{0}.yaml'.format(job_spec_pkg_name)
job_spec_yaml_path = os.path.join(repro_dir, job_spec_yaml_file)
job_spec_json_file = '{0}.json'.format(job_spec_pkg_name)
job_spec_json_path = os.path.join(repro_dir, job_spec_json_file)
# To provide logs, cdash reports, etc for developer download/perusal,
# these things have to be put into artifacts. This means downstream
@@ -335,23 +334,23 @@ def ci_rebuild(args):
# using a compiler already installed on the target system).
spack_ci.configure_compilers(compiler_action)
# Write this job's spec yaml into the reproduction directory, and it will
# Write this job's spec json into the reproduction directory, and it will
# also be used in the generated "spack install" command to install the spec
tty.debug('job concrete spec path: {0}'.format(job_spec_yaml_path))
with open(job_spec_yaml_path, 'w') as fd:
fd.write(job_spec.to_yaml(hash=ht.build_hash))
tty.debug('job concrete spec path: {0}'.format(job_spec_json_path))
with open(job_spec_json_path, 'w') as fd:
fd.write(job_spec.to_json(hash=ht.dag_hash))
# Write the concrete root spec yaml into the reproduction directory
root_spec_yaml_path = os.path.join(repro_dir, 'root.yaml')
with open(root_spec_yaml_path, 'w') as fd:
fd.write(spec_map['root'].to_yaml(hash=ht.build_hash))
# Write the concrete root spec json into the reproduction directory
root_spec_json_path = os.path.join(repro_dir, 'root.json')
with open(root_spec_json_path, 'w') as fd:
fd.write(spec_map['root'].to_json(hash=ht.dag_hash))
# Write some other details to aid in reproduction into an artifact
repro_file = os.path.join(repro_dir, 'repro.json')
repro_details = {
'job_name': ci_job_name,
'job_spec_yaml': job_spec_yaml_file,
'root_spec_yaml': 'root.yaml',
'job_spec_json': job_spec_json_file,
'root_spec_json': 'root.json',
'ci_project_dir': ci_project_dir
}
with open(repro_file, 'w') as fd:
@@ -366,25 +365,24 @@ def ci_rebuild(args):
fd.write(b'\n')
# If we decided there should be a temporary storage mechanism, add that
# mirror now so it's used when we check for a full hash match already
# mirror now so it's used when we check for a hash match already
# built for this spec.
if pipeline_mirror_url:
spack.mirror.add(spack_ci.TEMP_STORAGE_MIRROR_NAME,
pipeline_mirror_url,
cfg.default_modify_scope())
# Check configured mirrors for a built spec with a matching full hash
matches = bindist.get_mirrors_for_spec(
job_spec, full_hash_match=True, index_only=False)
# Check configured mirrors for a built spec with a matching hash
matches = bindist.get_mirrors_for_spec(job_spec, index_only=False)
if matches:
# Got a full hash match on at least one configured mirror. All
# Got a hash match on at least one configured mirror. All
# matches represent the fully up-to-date spec, so should all be
# equivalent. If artifacts mirror is enabled, we just pick one
# of the matches and download the buildcache files from there to
# the artifacts, so they're available to be used by dependent
# jobs in subsequent stages.
tty.msg('No need to rebuild {0}, found full hash match at: '.format(
tty.msg('No need to rebuild {0}, found hash match at: '.format(
job_spec_pkg_name))
for match in matches:
tty.msg(' {0}'.format(match['mirror_url']))
@@ -403,7 +401,7 @@ def ci_rebuild(args):
# Now we are done and successful
sys.exit(0)
# No full hash match anywhere means we need to rebuild spec
# No hash match anywhere means we need to rebuild spec
# Start with spack arguments
install_args = [base_arg for base_arg in CI_REBUILD_INSTALL_BASE_ARGS]
@@ -415,7 +413,6 @@ def ci_rebuild(args):
install_args.extend([
'install',
'--keep-stage',
'--require-full-hash-match',
])
can_verify = spack_ci.can_verify_binaries()
@@ -443,8 +440,8 @@ def ci_rebuild(args):
# TODO: once we have the concrete spec registry, use the DAG hash
# to identify the spec to install, rather than the concrete spec
# yaml file.
install_args.extend(['-f', job_spec_yaml_path])
# json file.
install_args.extend(['-f', job_spec_json_path])
tty.debug('Installing {0} from source'.format(job_spec.name))
tty.debug('spack install arguments: {0}'.format(
@@ -477,13 +474,13 @@ def ci_rebuild(args):
tty.debug('spack install exited {0}'.format(install_exit_code))
# If a spec fails to build in a spack develop pipeline, we add it to a
# list of known broken full hashes. This allows spack PR pipelines to
# list of known broken hashes. This allows spack PR pipelines to
# avoid wasting compute cycles attempting to build those hashes.
if install_exit_code == INSTALL_FAIL_CODE and spack_is_develop_pipeline:
tty.debug('Install failed on develop')
if 'broken-specs-url' in gitlab_ci:
broken_specs_url = gitlab_ci['broken-specs-url']
dev_fail_hash = job_spec.full_hash()
dev_fail_hash = job_spec.dag_hash()
broken_spec_path = url_util.join(broken_specs_url, dev_fail_hash)
tty.msg('Reporting broken develop build as: {0}'.format(
broken_spec_path))
@@ -494,7 +491,7 @@ def ci_rebuild(args):
'broken-spec': {
'job-url': get_env_var('CI_JOB_URL'),
'pipeline-url': get_env_var('CI_PIPELINE_URL'),
'concrete-spec-yaml': job_spec.to_dict(hash=ht.full_hash)
'concrete-spec-dict': job_spec.to_dict(hash=ht.dag_hash)
}
}
@@ -539,7 +536,7 @@ def ci_rebuild(args):
# per-PR mirror, if this is a PR pipeline
if buildcache_mirror_url:
spack_ci.push_mirror_contents(
env, job_spec_yaml_path, buildcache_mirror_url, sign_binaries
env, job_spec_json_path, buildcache_mirror_url, sign_binaries
)
# Create another copy of that buildcache in the per-pipeline
@@ -548,14 +545,14 @@ def ci_rebuild(args):
# prefix is set)
if pipeline_mirror_url:
spack_ci.push_mirror_contents(
env, job_spec_yaml_path, pipeline_mirror_url, sign_binaries
env, job_spec_json_path, pipeline_mirror_url, sign_binaries
)
# If this is a develop pipeline, check if the spec that we just built is
# on the broken-specs list. If so, remove it.
if spack_is_develop_pipeline and 'broken-specs-url' in gitlab_ci:
broken_specs_url = gitlab_ci['broken-specs-url']
just_built_hash = job_spec.full_hash()
just_built_hash = job_spec.dag_hash()
broken_spec_path = url_util.join(broken_specs_url, just_built_hash)
if web_util.url_exists(broken_spec_path):
tty.msg('Removing {0} from the list of broken specs'.format(

View File

@@ -380,6 +380,11 @@ def add_concretizer_args(subparser):
const=False, default=None,
help='do not reuse installed deps; build newest configuration'
)
subgroup.add_argument(
'--minimal', action=ConfigSetAction, dest="concretizer:minimal",
const=True, default=None,
help='minimize builds (disables default variants, may choose older versions)'
)
subgroup.add_argument(
'--reuse', action=ConfigSetAction, dest="concretizer:reuse",
const=True, default=None,

View File

@@ -18,6 +18,8 @@
def setup_parser(subparser):
arguments.add_common_arguments(subparser, ['clean', 'dirty'])
arguments.add_concretizer_args(subparser)
subparser.add_argument(
'--dump', metavar="FILE",
help="dump a source-able environment to FILE"

View File

@@ -22,6 +22,9 @@ def setup_parser(subparser):
help="""Concretize with test dependencies. When 'root' is chosen, test
dependencies are only added for the environment's root specs. When 'all' is
chosen, test dependencies are enabled for all packages in the environment.""")
subparser.add_argument(
'-q', '--quiet', action='store_true',
help="Don't print concretized specs")
spack.cmd.common.arguments.add_concretizer_args(subparser)
@@ -38,5 +41,6 @@ def concretize(parser, args):
with env.write_transaction():
concretized_specs = env.concretize(force=args.force, tests=tests)
ev.display_specs(concretized_specs)
if not args.quiet:
ev.display_specs(concretized_specs)
env.write()

View File

@@ -187,6 +187,27 @@ def cmake_args(self):
return args"""
class LuaPackageTemplate(PackageTemplate):
"""Provides appropriate overrides for LuaRocks-based packages"""
base_class_name = 'LuaPackage'
body_def = """\
def luarocks_args(self):
# FIXME: Add arguments to `luarocks make` other than rockspec path
# FIXME: If not needed delete this function
args = []
return args"""
def __init__(self, name, url, *args, **kwargs):
# If the user provided `--name lua-lpeg`, don't rename it lua-lua-lpeg
if not name.startswith('lua-'):
# Make it more obvious that we are renaming the package
tty.msg("Changing package name from {0} to lua-{0}".format(name))
name = 'lua-{0}'.format(name)
super(LuaPackageTemplate, self).__init__(name, url, *args, **kwargs)
class MesonPackageTemplate(PackageTemplate):
"""Provides appropriate overrides for meson-based packages"""
@@ -580,6 +601,7 @@ def __init__(self, name, *args, **kwargs):
'makefile': MakefilePackageTemplate,
'intel': IntelPackageTemplate,
'meson': MesonPackageTemplate,
'lua': LuaPackageTemplate,
'sip': SIPPackageTemplate,
'generic': PackageTemplate,
}
@@ -644,6 +666,9 @@ def __call__(self, stage, url):
if url.endswith('.whl') or '.whl#' in url:
self.build_system = 'python'
return
if url.endswith('.rock'):
self.build_system = 'lua'
return
# A list of clues that give us an idea of the build system a package
# uses. If the regular expression matches a file contained in the
@@ -668,6 +693,7 @@ def __call__(self, stage, url):
(r'/Rakefile$', 'ruby'),
(r'/setup\.rb$', 'ruby'),
(r'/.*\.pro$', 'qmake'),
(r'/.*\.rockspec$', 'lua'),
(r'/(GNU)?[Mm]akefile$', 'makefile'),
(r'/DESCRIPTION$', 'octave'),
(r'/meson\.build$', 'meson'),

View File

@@ -91,8 +91,8 @@ def dev_build(self, args):
spec.concretize()
package = spack.repo.get(spec)
if package.installed:
tty.error("Already installed in %s" % package.prefix)
if spec.installed:
tty.error("Already installed in %s" % spec.prefix)
tty.msg("Uninstall or try adding a version suffix for this dev build.")
sys.exit(1)

View File

@@ -68,8 +68,14 @@ def compare_specs(a, b, to_string=False, color=None):
# Prepare a solver setup to parse differences
setup = asp.SpackSolverSetup()
a_facts = set(t for t in setup.spec_clauses(a, body=True, expand_hashes=True))
b_facts = set(t for t in setup.spec_clauses(b, body=True, expand_hashes=True))
# get facts for specs, making sure to include build dependencies of concrete
# specs and to descend into dependency hashes so we include all facts.
a_facts = set(t for t in setup.spec_clauses(
a, body=True, expand_hashes=True, concrete_build_deps=True,
))
b_facts = set(t for t in setup.spec_clauses(
b, body=True, expand_hashes=True, concrete_build_deps=True,
))
# We want to present them to the user as simple key: values
intersect = sorted(a_facts.intersection(b_facts))

View File

@@ -8,6 +8,8 @@
import sys
import tempfile
import six
import llnl.util.filesystem as fs
import llnl.util.tty as tty
from llnl.util.tty.colify import colify
@@ -41,7 +43,8 @@
'loads',
'view',
'update',
'revert'
'revert',
'depfile'
]
@@ -523,6 +526,154 @@ def env_revert(args):
tty.msg(msg.format(manifest_file))
def env_depfile_setup_parser(subparser):
"""generate a depfile from the concrete environment specs"""
subparser.add_argument(
'--make-target-prefix', default=None, metavar='TARGET',
help='prefix Makefile targets with <TARGET>/<name>. By default the absolute '
'path to the directory makedeps under the environment metadata dir is '
'used. Can be set to an empty string --make-target-prefix \'\'.')
subparser.add_argument(
'--make-disable-jobserver', default=True, action='store_false',
dest='jobserver', help='disable POSIX jobserver support.')
subparser.add_argument(
'-o', '--output', default=None, metavar='FILE',
help='write the depfile to FILE rather than to stdout')
subparser.add_argument(
'-G', '--generator', default='make', choices=('make',),
help='specify the depfile type. Currently only make is supported.')
def env_depfile(args):
# Currently only make is supported.
spack.cmd.require_active_env(cmd_name='env depfile')
env = ev.active_environment()
# Maps each hash in the environment to a string of install prereqs
hash_to_prereqs = {}
hash_to_spec = {}
if args.make_target_prefix is None:
target_prefix = os.path.join(env.env_subdir_path, 'makedeps')
else:
target_prefix = args.make_target_prefix
def get_target(name):
# The `all`, `fetch` and `clean` targets are phony. It doesn't make sense to
# have /abs/path/to/env/metadir/{all,clean} targets. But it *does* make
# sense to have a prefix like `env/all`, `env/fetch`, `env/clean` when they are
# supposed to be included
if name in ('all', 'fetch-all', 'clean') and os.path.isabs(target_prefix):
return name
else:
return os.path.join(target_prefix, name)
def get_install_target(name):
return os.path.join(target_prefix, '.install', name)
def get_fetch_target(name):
return os.path.join(target_prefix, '.fetch', name)
for _, spec in env.concretized_specs():
for s in spec.traverse(root=True):
hash_to_spec[s.dag_hash()] = s
hash_to_prereqs[s.dag_hash()] = [
get_install_target(dep.dag_hash()) for dep in s.dependencies()]
root_dags = [s.dag_hash() for _, s in env.concretized_specs()]
# Root specs without deps are the prereqs for the environment target
root_install_targets = [get_install_target(h) for h in root_dags]
# All package install targets, not just roots.
all_install_targets = [get_install_target(h) for h in hash_to_spec.keys()]
# Fetch targets for all packages in the environment, not just roots.
all_fetch_targets = [get_fetch_target(h) for h in hash_to_spec.keys()]
buf = six.StringIO()
buf.write("""SPACK ?= spack
.PHONY: {} {} {}
{}: {}
{}: {}
{}: {}
\t@touch $@
{}: {}
\t@touch $@
{}:
\t@mkdir -p {} {}
{}: | {}
\t$(info Fetching $(SPEC))
\t$(SPACK) -e '{}' fetch $(SPACK_FETCH_FLAGS) /$(notdir $@) && touch $@
{}: {}
\t$(info Installing $(SPEC))
\t{}$(SPACK) -e '{}' install $(SPACK_INSTALL_FLAGS) --only-concrete --only=package \
--no-add /$(notdir $@) && touch $@
""".format(get_target('all'), get_target('fetch-all'), get_target('clean'),
get_target('all'), get_target('env'),
get_target('fetch-all'), get_target('fetch'),
get_target('env'), ' '.join(root_install_targets),
get_target('fetch'), ' '.join(all_fetch_targets),
get_target('dirs'), get_target('.fetch'), get_target('.install'),
get_target('.fetch/%'), get_target('dirs'),
env.path,
get_target('.install/%'), get_target('.fetch/%'),
'+' if args.jobserver else '', env.path))
# Targets are of the form <prefix>/<name>: [<prefix>/<depname>]...,
# The prefix can be an empty string, in that case we don't add the `/`.
# The name is currently the dag hash of the spec. In principle it
# could be the package name in case of `concretization: together` so
# it can be more easily referred to, but for now we don't special case
# this.
fmt = '{name}{@version}{%compiler}{variants}{arch=architecture}'
# Set SPEC for each hash
buf.write('# Set the human-readable spec for each target\n')
for dag_hash in hash_to_prereqs.keys():
formatted_spec = hash_to_spec[dag_hash].format(fmt)
buf.write("{}: SPEC = {}\n".format(get_target('%/' + dag_hash), formatted_spec))
buf.write('\n')
# Set install dependencies
buf.write('# Install dependencies\n')
for parent, children in hash_to_prereqs.items():
if not children:
continue
buf.write('{}: {}\n'.format(get_install_target(parent), ' '.join(children)))
buf.write('\n')
# Clean target: remove target files but not their folders, cause
# --make-target-prefix can be any existing directory we do not control,
# including empty string (which means deleting the containing folder
# would delete the folder with the Makefile)
buf.write("{}:\n\trm -f -- {} {} {} {}\n".format(
get_target('clean'),
get_target('env'),
get_target('fetch'),
' '.join(all_fetch_targets),
' '.join(all_install_targets)))
makefile = buf.getvalue()
# Finally write to stdout/file.
if args.output:
with open(args.output, 'w') as f:
f.write(makefile)
else:
sys.stdout.write(makefile)
#: Dictionary mapping subcommand names and aliases to functions
subcommand_functions = {}

View File

@@ -5,6 +5,7 @@
from __future__ import print_function
import argparse
import os
import sys
import llnl.util.tty as tty
@@ -13,6 +14,7 @@
import spack
import spack.cmd
import spack.cmd.common.arguments
import spack.cray_manifest as cray_manifest
import spack.detection
import spack.error
import spack.util.environment
@@ -35,6 +37,9 @@ def setup_parser(subparser):
find_parser.add_argument(
'--not-buildable', action='store_true', default=False,
help="packages with detected externals won't be built with Spack")
find_parser.add_argument(
'-p', '--path', default=None, action='append',
help="Alternative search paths for finding externals. May be repeated")
find_parser.add_argument(
'--scope', choices=scopes, metavar=scopes_metavar,
default=spack.config.default_modify_scope('packages'),
@@ -55,8 +60,40 @@ def setup_parser(subparser):
'list', help='list detectable packages, by repository and name'
)
read_cray_manifest = sp.add_parser(
'read-cray-manifest', help=(
"consume a Spack-compatible description of externally-installed "
"packages, including dependency relationships"
)
)
read_cray_manifest.add_argument(
'--file', default=None,
help="specify a location other than the default")
read_cray_manifest.add_argument(
'--directory', default=None,
help="specify a directory storing a group of manifest files")
read_cray_manifest.add_argument(
'--dry-run', action='store_true', default=False,
help="don't modify DB with files that are read")
read_cray_manifest.add_argument(
'--fail-on-error', action='store_true',
help=("if a manifest file cannot be parsed, fail and report the "
"full stack trace")
)
def external_find(args):
if args.all or not (args.tags or args.packages):
# If the user calls 'spack external find' with no arguments, and
# this system has a description of installed packages, then we should
# consume it automatically.
try:
_collect_and_consume_cray_manifest_files()
except NoManifestFileError:
# It's fine to not find any manifest file if we are doing the
# search implicitly (i.e. as part of 'spack external find')
pass
# If the user didn't specify anything, search for build tools by default
if not args.tags and not args.all and not args.packages:
args.tags = ['core-packages', 'build-tools']
@@ -90,8 +127,10 @@ def external_find(args):
if not args.tags and not packages_to_check:
packages_to_check = spack.repo.path.all_packages()
detected_packages = spack.detection.by_executable(packages_to_check)
detected_packages.update(spack.detection.by_library(packages_to_check))
detected_packages = spack.detection.by_executable(
packages_to_check, path_hints=args.path)
detected_packages.update(spack.detection.by_library(
packages_to_check, path_hints=args.path))
new_entries = spack.detection.update_configuration(
detected_packages, scope=args.scope, buildable=not args.not_buildable
@@ -106,6 +145,56 @@ def external_find(args):
tty.msg('No new external packages detected')
def external_read_cray_manifest(args):
_collect_and_consume_cray_manifest_files(
manifest_file=args.file,
manifest_directory=args.directory,
dry_run=args.dry_run,
fail_on_error=args.fail_on_error
)
def _collect_and_consume_cray_manifest_files(
manifest_file=None, manifest_directory=None, dry_run=False,
fail_on_error=False):
manifest_files = []
if manifest_file:
manifest_files.append(manifest_file)
manifest_dirs = []
if manifest_directory:
manifest_dirs.append(manifest_directory)
if os.path.isdir(cray_manifest.default_path):
tty.debug(
"Cray manifest path {0} exists: collecting all files to read."
.format(cray_manifest.default_path))
manifest_dirs.append(cray_manifest.default_path)
else:
tty.debug("Default Cray manifest directory {0} does not exist."
.format(cray_manifest.default_path))
for directory in manifest_dirs:
for fname in os.listdir(directory):
manifest_files.append(os.path.join(directory, fname))
if not manifest_files:
raise NoManifestFileError(
"--file/--directory not specified, and no manifest found at {0}"
.format(cray_manifest.default_path))
for path in manifest_files:
try:
cray_manifest.read(path, not dry_run)
except (spack.compilers.UnknownCompilerError, spack.error.SpackError) as e:
if fail_on_error:
raise
else:
tty.warn("Failure reading manifest file: {0}"
"\n\t{1}".format(path, str(e)))
def external_list(args):
# Trigger a read of all packages, might take a long time.
list(spack.repo.path.all_packages())
@@ -117,5 +206,10 @@ def external_list(args):
def external(parser, args):
action = {'find': external_find, 'list': external_list}
action = {'find': external_find, 'list': external_list,
'read-cray-manifest': external_read_cray_manifest}
action[args.external_command](args)
class NoManifestFileError(spack.error.SpackError):
pass

View File

@@ -69,14 +69,10 @@ def fetch(parser, args):
for spec in specs:
if args.missing or args.dependencies:
for s in spec.traverse():
package = spack.repo.get(s)
for s in spec.traverse(root=False):
# Skip already-installed packages with --missing
if args.missing and package.installed:
if args.missing and s.installed:
continue
package.do_fetch()
package = spack.repo.get(spec)
package.do_fetch()
s.package.do_fetch()
spec.package.do_fetch()

View File

@@ -184,8 +184,9 @@ def print_detectable(pkg):
color.cprint('')
color.cprint(section_title('Externally Detectable: '))
# If the package has an 'executables' field, it can detect an installation
if hasattr(pkg, 'executables'):
# If the package has an 'executables' of 'libraries' field, it
# can detect an installation
if hasattr(pkg, 'executables') or hasattr(pkg, 'libraries'):
find_attributes = []
if hasattr(pkg, 'determine_version'):
find_attributes.append('version')

View File

@@ -47,7 +47,6 @@ def update_kwargs_from_args(args, kwargs):
'explicit': True, # Always true for install command
'stop_at': args.until,
'unsigned': args.unsigned,
'full_hash_match': args.full_hash_match,
})
kwargs.update({
@@ -117,11 +116,6 @@ def setup_parser(subparser):
'--no-check-signature', action='store_true',
dest='unsigned', default=False,
help="do not check signatures of binary packages")
subparser.add_argument(
'--require-full-hash-match', action='store_true',
dest='full_hash_match', default=False, help="""when installing from
binary mirrors, do not install binary package unless the full hash of the
remote spec matches that of the local spec""")
subparser.add_argument(
'--show-log-on-error', action='store_true',
help="print full build log to stderr if build fails")
@@ -159,10 +153,6 @@ def setup_parser(subparser):
if 'all' is chosen, run package tests during installation for all
packages. If neither are chosen, don't run tests for any packages."""
)
testing.add_argument(
'--run-tests', action='store_true',
help='run package tests during installation (same as --test=all)'
)
subparser.add_argument(
'--log-format',
default=None,
@@ -316,11 +306,8 @@ def install(parser, args, **kwargs):
if args.log_file:
reporter.filename = args.log_file
if args.run_tests:
tty.warn("Deprecated option: --run-tests: use --test=all instead")
def get_tests(specs):
if args.test == 'all' or args.run_tests:
if args.test == 'all':
return True
elif args.test == 'root':
return [spec.name for spec in specs]
@@ -477,7 +464,7 @@ def get_tests(specs):
})
# If we are using the monitor, we send configs. and create build
# The full_hash is the main package id, the build_hash for others
# The dag_hash is the main package id
if args.use_monitor and specs:
monitor.new_configuration(specs)
install_specs(args, kwargs, zip(abstract_specs, specs))

View File

@@ -273,7 +273,7 @@ def refresh(module_type, specs, args):
return
if not args.upstream_modules:
specs = list(s for s in specs if not s.package.installed_upstream)
specs = list(s for s in specs if not s.installed_upstream)
if not args.yes_to_all:
msg = 'You are about to regenerate {types} module files for:\n'

View File

@@ -136,13 +136,13 @@ def solve(parser, args):
)
fmt = " @K{%%-8d} %%-%ds%%9s %%7s" % maxlen
for i, (idx, build_idx, name) in enumerate(result.criteria, 1):
for i, (installed_cost, build_cost, name) in enumerate(result.criteria, 1):
color.cprint(
fmt % (
i,
name,
"-" if build_idx is None else opt[idx],
opt[idx] if build_idx is None else opt[build_idx],
"-" if build_cost is None else installed_cost,
installed_cost if build_cost is None else build_cost,
)
)
print()
@@ -151,9 +151,9 @@ def solve(parser, args):
# With -y, just print YAML to output.
if args.format == 'yaml':
# use write because to_yaml already has a newline.
sys.stdout.write(spec.to_yaml(hash=ht.build_hash))
sys.stdout.write(spec.to_yaml(hash=ht.dag_hash))
elif args.format == 'json':
sys.stdout.write(spec.to_json(hash=ht.build_hash))
sys.stdout.write(spec.to_json(hash=ht.dag_hash))
else:
sys.stdout.write(
spec.tree(color=sys.stdout.isatty(), **kwargs))

View File

@@ -34,12 +34,16 @@ def setup_parser(subparser):
arguments.add_common_arguments(
subparser, ['long', 'very_long', 'install_status']
)
subparser.add_argument(
format_group = subparser.add_mutually_exclusive_group()
format_group.add_argument(
'-y', '--yaml', action='store_const', dest='format', default=None,
const='yaml', help='print concrete spec as YAML')
subparser.add_argument(
format_group.add_argument(
'-j', '--json', action='store_const', dest='format', default=None,
const='json', help='print concrete spec as JSON')
format_group.add_argument(
'--format', action='store', default=None,
help='print concrete spec with the specified format string')
subparser.add_argument(
'-c', '--cover', action='store',
default='nodes', choices=['nodes', 'edges', 'paths'],
@@ -47,10 +51,6 @@ def setup_parser(subparser):
subparser.add_argument(
'-N', '--namespaces', action='store_true', default=False,
help='show fully qualified package names')
subparser.add_argument(
'--hash-type', default="build_hash",
choices=['build_hash', 'full_hash', 'dag_hash'],
help='generate spec with a particular hash type.')
subparser.add_argument(
'-t', '--types', action='store_true', default=False,
help='show dependency types')
@@ -92,14 +92,13 @@ def spec(parser, args):
for (input, output) in specs:
# With -y, just print YAML to output.
if args.format:
# The user can specify the hash type to use
hash_type = getattr(ht, args.hash_type)
if args.format == 'yaml':
# use write because to_yaml already has a newline.
sys.stdout.write(output.to_yaml(hash=hash_type))
sys.stdout.write(output.to_yaml(hash=ht.dag_hash))
elif args.format == 'json':
print(output.to_json(hash=ht.dag_hash))
else:
print(output.to_json(hash=hash_type))
print(output.format(args.format))
continue
with tree_context():

View File

@@ -27,12 +27,6 @@ def setup_parser(subparser):
def stage(parser, args):
# We temporarily modify the working directory when setting up a stage, so we need to
# convert this to an absolute path here in order for it to remain valid later.
custom_path = os.path.abspath(args.path) if args.path else None
if custom_path:
spack.stage.create_stage_root(custom_path)
if not args.specs:
env = ev.active_environment()
if env:
@@ -54,6 +48,10 @@ def stage(parser, args):
specs = spack.cmd.parse_specs(args.specs, concretize=False)
# We temporarily modify the working directory when setting up a stage, so we need to
# convert this to an absolute path here in order for it to remain valid later.
custom_path = os.path.abspath(args.path) if args.path else None
# prevent multiple specs from extracting in the same folder
if len(specs) > 1 and custom_path:
tty.die("`--path` requires a single spec, but multiple were provided")

View File

@@ -337,6 +337,8 @@ def _report_suite_results(test_suite, args, constraints):
pkg_id, status = line.split()
results[pkg_id] = status
tty.msg('test specs:')
failed, skipped, untested = 0, 0, 0
for pkg_id in test_specs:
if pkg_id in results:

View File

@@ -24,7 +24,7 @@
# tutorial configuration parameters
tutorial_branch = "releases/v%d.%d" % spack.spack_version_info[:2]
tutorial_branch = "releases/v0.17"
tutorial_mirror = "file:///mirror"
tutorial_key = os.path.join(spack.paths.share_path, "keys", "tutorial.pub")

View File

@@ -62,9 +62,14 @@ def setup_parser(subparser):
'-a', '--all', action='store_true', dest='all',
help="remove ALL installed packages that match each supplied spec"
)
subparser.add_argument(
'--origin', dest='origin',
help="only remove DB records with the specified origin"
)
def find_matching_specs(env, specs, allow_multiple_matches=False, force=False):
def find_matching_specs(env, specs, allow_multiple_matches=False, force=False,
origin=None):
"""Returns a list of specs matching the not necessarily
concretized specs given from cli
@@ -85,8 +90,8 @@ def find_matching_specs(env, specs, allow_multiple_matches=False, force=False):
has_errors = False
for spec in specs:
install_query = [InstallStatuses.INSTALLED, InstallStatuses.DEPRECATED]
matching = spack.store.db.query_local(spec, hashes=hashes,
installed=install_query)
matching = spack.store.db.query_local(
spec, hashes=hashes, installed=install_query, origin=origin)
# For each spec provided, make sure it refers to only one package.
# Fail and ask user to be unambiguous if it doesn't
if not allow_multiple_matches and len(matching) > 1:
@@ -220,15 +225,25 @@ def do_uninstall(env, specs, force):
# A package is ready to be uninstalled when nothing else references it,
# unless we are requested to force uninstall it.
is_ready = lambda x: not spack.store.db.query_by_spec_hash(x)[1].ref_count
if force:
is_ready = lambda x: True
def is_ready(dag_hash):
if force:
return True
_, record = spack.store.db.query_by_spec_hash(dag_hash)
if not record.ref_count:
return True
# If this spec is only used as a build dependency, we can uninstall
return all(
dspec.deptypes == ("build",) or not dspec.parent.installed
for dspec in record.spec.edges_from_dependents()
)
while packages:
ready = [x for x in packages if is_ready(x.spec.dag_hash())]
if not ready:
msg = 'unexpected error [cannot proceed uninstalling specs with' \
' remaining dependents {0}]'
' remaining link or run dependents {0}]'
msg = msg.format(', '.join(x.name for x in packages))
raise spack.error.SpackError(msg)
@@ -240,7 +255,8 @@ def do_uninstall(env, specs, force):
def get_uninstall_list(args, specs, env):
# Gets the list of installed specs that match the ones give via cli
# args.all takes care of the case where '-a' is given in the cli
uninstall_list = find_matching_specs(env, specs, args.all, args.force)
uninstall_list = find_matching_specs(env, specs, args.all, args.force,
args.origin)
# Takes care of '-R'
active_dpts, inactive_dpts = installed_dependents(uninstall_list, env)

View File

@@ -495,7 +495,8 @@ def get_compiler_duplicates(compiler_spec, arch_spec):
@llnl.util.lang.memoized
def class_for_compiler_name(compiler_name):
"""Given a compiler module name, get the corresponding Compiler class."""
assert supported(compiler_name)
if not supported(compiler_name):
raise UnknownCompilerError(compiler_name)
# Hack to be able to call the compiler `apple-clang` while still
# using a valid python name for the module
@@ -765,7 +766,8 @@ def name_matches(name, name_list):
toolchains.add(compiler_cls.__name__)
if len(toolchains) > 1:
if toolchains == set(['Clang', 'AppleClang', 'Aocc']):
if toolchains == set(['Clang', 'AppleClang', 'Aocc']) or \
toolchains == set(['Dpcpp', 'Oneapi']):
return False
tty.debug("[TOOLCHAINS] {0}".format(toolchains))
return True
@@ -788,6 +790,13 @@ def __init__(self):
"Spack could not find any compilers!")
class UnknownCompilerError(spack.error.SpackError):
def __init__(self, compiler_name):
super(UnknownCompilerError, self).__init__(
"Spack doesn't support the requested compiler: {0}"
.format(compiler_name))
class NoCompilerForSpecError(spack.error.SpackError):
def __init__(self, compiler_spec, target):
super(NoCompilerForSpecError, self).__init__(

View File

@@ -78,10 +78,8 @@ def cxx14_flag(self):
self, "the C++14 standard", "cxx14_flag", "< 4.8")
elif self.real_version < ver('4.9'):
return "-std=c++1y"
elif self.real_version < ver('6.0'):
return "-std=c++14"
else:
return ""
return "-std=c++14"
@property
def cxx17_flag(self):

View File

@@ -88,7 +88,7 @@
#: Path to the default configuration
configuration_defaults_path = (
'defaults', os.path.join(spack.paths.etc_path, 'spack', 'defaults')
'defaults', os.path.join(spack.paths.etc_path, 'defaults')
)
#: Hard-coded default values for some key configuration options.
@@ -104,6 +104,10 @@
'build_jobs': min(16, cpus_available()),
'build_stage': '$tempdir/spack-stage',
'concretizer': 'clingo',
'license_dir': spack.paths.default_license_dir,
'flags': {
'keep_werror': 'none',
},
}
}
@@ -815,7 +819,7 @@ def _config():
# Site configuration is per spack instance, for sites or projects
# No site-level configs should be checked into spack by default.
configuration_paths.append(
('site', os.path.join(spack.paths.etc_path, 'spack')),
('site', os.path.join(spack.paths.etc_path)),
)
# User configuration can override both spack defaults and site config

View File

@@ -0,0 +1,193 @@
# Copyright 2013-2021 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)
import json
import jsonschema
import six
import llnl.util.tty as tty
import spack.cmd
import spack.hash_types as hash_types
from spack.schema.cray_manifest import schema as manifest_schema
#: Cray systems can store a Spack-compatible description of system
#: packages here.
default_path = '/opt/cray/pe/cpe-descriptive-manifest/'
compiler_name_translation = {
'nvidia': 'nvhpc',
}
def translated_compiler_name(manifest_compiler_name):
"""
When creating a Compiler object, Spack expects a name matching
one of the classes in `spack.compilers`. Names in the Cray manifest
may differ; for cases where we know the name refers to a compiler in
Spack, this function translates it automatically.
This function will raise an error if there is no recorded translation
and the name doesn't match a known compiler name.
"""
if manifest_compiler_name in compiler_name_translation:
return compiler_name_translation[manifest_compiler_name]
elif manifest_compiler_name in spack.compilers.supported_compilers():
return manifest_compiler_name
else:
# Try to fail quickly. This can occur in two cases: (1) the compiler
# definition (2) a spec can specify a compiler that doesn't exist; the
# first will be caught when creating compiler definition. The second
# will result in Specs with associated undefined compilers.
raise spack.compilers.UnknownCompilerError(
"Manifest parsing - unknown compiler: {0}"
.format(manifest_compiler_name))
def compiler_from_entry(entry):
compiler_name = translated_compiler_name(entry['name'])
paths = entry['executables']
version = entry['version']
arch = entry['arch']
operating_system = arch['os']
target = arch['target']
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
)
def spec_from_entry(entry):
arch_str = ""
if 'arch' in entry:
arch_format = "arch={platform}-{os}-{target}"
arch_str = arch_format.format(
platform=entry['arch']['platform'],
os=entry['arch']['platform_os'],
target=entry['arch']['target']['name']
)
compiler_str = ""
if 'compiler' in entry:
compiler_format = "%{name}@{version}"
compiler_str = compiler_format.format(
name=translated_compiler_name(entry['compiler']['name']),
version=entry['compiler']['version']
)
spec_format = "{name}@{version} {compiler} {arch}"
spec_str = spec_format.format(
name=entry['name'],
version=entry['version'],
compiler=compiler_str,
arch=arch_str
)
package = spack.repo.get(entry['name'])
if 'parameters' in entry:
variant_strs = list()
for name, value in entry['parameters'].items():
# TODO: also ensure that the variant value is valid?
if not (name in package.variants):
tty.debug("Omitting variant {0} for entry {1}/{2}"
.format(name, entry['name'], entry['hash'][:7]))
continue
# Value could be a list (of strings), boolean, or string
if isinstance(value, six.string_types):
variant_strs.append('{0}={1}'.format(name, value))
else:
try:
iter(value)
variant_strs.append(
'{0}={1}'.format(name, ','.join(value)))
continue
except TypeError:
# Not an iterable
pass
# At this point not a string or collection, check for boolean
if value in [True, False]:
bool_symbol = '+' if value else '~'
variant_strs.append('{0}{1}'.format(bool_symbol, name))
else:
raise ValueError(
"Unexpected value for {0} ({1}): {2}".format(
name, str(type(value)), str(value)
)
)
spec_str += ' ' + ' '.join(variant_strs)
spec, = spack.cmd.parse_specs(spec_str.split())
for ht in [hash_types.dag_hash, hash_types.build_hash,
hash_types.full_hash]:
setattr(spec, ht.attr, entry['hash'])
spec._concrete = True
spec._hashes_final = True
spec.external_path = entry['prefix']
spec.origin = 'external-db'
spack.spec.Spec.ensure_valid_variants(spec)
return spec
def entries_to_specs(entries):
spec_dict = {}
for entry in entries:
try:
spec = spec_from_entry(entry)
spec_dict[spec._hash] = spec
except spack.repo.UnknownPackageError:
tty.debug("Omitting package {0}: no corresponding repo package"
.format(entry['name']))
except spack.error.SpackError:
raise
except Exception:
tty.warn("Could not parse entry: " + str(entry))
for entry in filter(lambda x: 'dependencies' in x, entries):
dependencies = entry['dependencies']
for name, properties in dependencies.items():
dep_hash = properties['hash']
deptypes = properties['type']
if dep_hash in spec_dict:
if entry['hash'] not in spec_dict:
continue
parent_spec = spec_dict[entry['hash']]
dep_spec = spec_dict[dep_hash]
parent_spec._add_dependency(dep_spec, deptypes)
return spec_dict
def read(path, apply_updates):
with open(path, 'r') as json_file:
json_data = json.load(json_file)
jsonschema.validate(json_data, manifest_schema)
specs = entries_to_specs(json_data['specs'])
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'])
tty.debug("{0}: {1} compilers read from manifest".format(
path,
str(len(compilers))))
if apply_updates and compilers:
spack.compilers.add_compilers_to_config(
compilers, init_config=False)
if apply_updates:
for spec in specs.values():
spack.store.db.add(spec, directory_layout=None)

View File

@@ -91,7 +91,8 @@
_pkg_lock_timeout = None
# Types of dependencies tracked by the database
_tracked_deps = ('link', 'run')
# We store by DAG hash, so we track the dependencies that the DAG hash includes.
_tracked_deps = ht.dag_hash.deptype
# Default list of fields written for each install record
default_install_record_fields = [
@@ -187,6 +188,7 @@ def __init__(
installation_time=None,
deprecated_for=None,
in_buildcache=False,
origin=None
):
self.spec = spec
self.path = str(path) if path else None
@@ -196,6 +198,7 @@ def __init__(
self.installation_time = installation_time or _now()
self.deprecated_for = deprecated_for
self.in_buildcache = in_buildcache
self.origin = origin
def install_type_matches(self, installed):
installed = InstallStatuses.canonicalize(installed)
@@ -217,6 +220,9 @@ def to_dict(self, include_fields=default_install_record_fields):
else:
rec_dict.update({field_name: getattr(self, field_name)})
if self.origin:
rec_dict['origin'] = self.origin
return rec_dict
@classmethod
@@ -350,10 +356,10 @@ def __init__(self, root, db_dir=None, upstream_dbs=None,
self.prefix_fail_path = os.path.join(self._db_dir, 'prefix_failures')
# Create needed directories and files
if not os.path.exists(self._db_dir):
if not is_upstream and not os.path.exists(self._db_dir):
fs.mkdirp(self._db_dir)
if not os.path.exists(self._failure_dir) and not is_upstream:
if not is_upstream and not os.path.exists(self._failure_dir):
fs.mkdirp(self._failure_dir)
self.is_upstream = is_upstream
@@ -428,7 +434,7 @@ def _failed_spec_path(self, spec):
.format(spec.name))
return os.path.join(self._failure_dir,
'{0}-{1}'.format(spec.name, spec.full_hash()))
'{0}-{1}'.format(spec.name, spec.dag_hash()))
def clear_all_failures(self):
"""Force remove install failure tracking files."""
@@ -640,8 +646,12 @@ def _write_to_file(self, stream):
# TODO: fix this before we support multiple install locations.
database = {
'database': {
# TODO: move this to a top-level _meta section if we ever
# TODO: bump the DB version to 7
'version': str(_db_version),
# dictionary of installation records, keyed by DAG hash
'installs': installs,
'version': str(_db_version)
}
}
@@ -681,6 +691,13 @@ def db_for_spec_hash(self, hash_key):
return db
def query_by_spec_hash(self, hash_key, data=None):
"""Get a spec for hash, and whether it's installed upstream.
Return:
(tuple): (bool, optional InstallRecord): bool tells us whether
the spec is installed upstream. Its InstallRecord is also
returned if it's installed at all; otherwise None.
"""
if data and hash_key in data:
return False, data[hash_key]
if not data:
@@ -1047,9 +1064,7 @@ def _read(self):
self._state_is_inconsistent = False
return
elif self.is_upstream:
raise UpstreamDatabaseLockingError(
"No database index file is present, and upstream"
" databases cannot generate an index file")
tty.warn('upstream not found: {0}'.format(self._index_path))
def _add(
self,
@@ -1087,6 +1102,7 @@ def _add(
"Specs added to DB must be concrete.")
key = spec.dag_hash()
spec_pkg_hash = spec._package_hash
upstream, record = self.query_by_spec_hash(key)
if upstream:
return
@@ -1131,6 +1147,10 @@ def _add(
'explicit': explicit,
'installation_time': installation_time
}
# Commands other than 'spack install' may add specs to the DB,
# we can record the source of an installed Spec with 'origin'
if hasattr(spec, 'origin'):
extra_args['origin'] = spec.origin
self._data[key] = InstallRecord(
new_spec, path, installed, ref_count=0, **extra_args
)
@@ -1144,10 +1164,10 @@ def _add(
record.ref_count += 1
# Mark concrete once everything is built, and preserve
# the original hash of concrete specs.
# the original hashes of concrete specs.
new_spec._mark_concrete()
new_spec._hash = key
new_spec._full_hash = spec._full_hash
new_spec._package_hash = spec_pkg_hash
else:
# It is already in the database
@@ -1462,6 +1482,7 @@ def _query(
end_date=None,
hashes=None,
in_buildcache=any,
origin=None
):
"""Run a query on the database."""
@@ -1490,6 +1511,9 @@ def _query(
if hashes is not None and rec.spec.dag_hash() not in hashes:
continue
if origin and not (origin == rec.origin):
continue
if not rec.install_type_matches(installed):
continue
@@ -1583,11 +1607,12 @@ def unused_specs(self):
needed, visited = set(), set()
with self.read_transaction():
for key, rec in self._data.items():
if rec.explicit:
# recycle `visited` across calls to avoid
# redundantly traversing
for spec in rec.spec.traverse(visited=visited):
needed.add(spec.dag_hash())
if not rec.explicit:
continue
# recycle `visited` across calls to avoid redundantly traversing
for spec in rec.spec.traverse(visited=visited, deptype=("link", "run")):
needed.add(spec.dag_hash())
unused = [rec.spec for key, rec in self._data.items()
if key not in needed and rec.installed]

View File

@@ -74,7 +74,8 @@ def executables_in_path(path_hints=None):
def libraries_in_ld_library_path(path_hints=None):
"""Get the paths of all libraries available from LD_LIBRARY_PATH.
"""Get the paths of all libraries available from LD_LIBRARY_PATH,
LIBRARY_PATH, DYLD_LIBRARY_PATH, and DYLD_FALLBACK_LIBRARY_PATH.
For convenience, this is constructed as a dictionary where the keys are
the library paths and the values are the names of the libraries
@@ -85,9 +86,15 @@ def libraries_in_ld_library_path(path_hints=None):
Args:
path_hints (list): list of paths to be searched. If None the list will be
constructed based on the LD_LIBRARY_PATH environment variable.
constructed based on the set of LD_LIBRARY_PATH, LIBRARY_PATH,
DYLD_LIBRARY_PATH, and DYLD_FALLBACK_LIBRARY_PATH environment
variables.
"""
path_hints = path_hints or spack.util.environment.get_path('LD_LIBRARY_PATH')
path_hints = path_hints or \
spack.util.environment.get_path('LIBRARY_PATH') + \
spack.util.environment.get_path('LD_LIBRARY_PATH') + \
spack.util.environment.get_path('DYLD_LIBRARY_PATH') + \
spack.util.environment.get_path('DYLD_FALLBACK_LIBRARY_PATH')
search_paths = llnl.util.filesystem.search_paths_for_libraries(*path_hints)
path_to_lib = {}

View File

@@ -48,13 +48,13 @@ class OpenMpi(Package):
from spack.resource import Resource
from spack.version import Version, VersionChecksumError
__all__ = ['DirectiveError', 'DirectiveMeta']
__all__ = ['DirectiveError', 'DirectiveMeta', 'version', 'conflicts', 'depends_on',
'extends', 'provides', 'patch', 'variant', 'resource']
#: These are variant names used by Spack internally; packages can't use them
reserved_names = ['patches', 'dev_path']
#: Names of possible directives. This list is populated elsewhere in the file and then
#: added to `__all__` at the bottom.
#: Names of possible directives. This list is populated elsewhere in the file.
directive_names = []
_patch_order_index = 0
@@ -731,7 +731,3 @@ class DependencyPatchError(DirectiveError):
class UnsupportedPackageDirective(DirectiveError):
"""Raised when an invalid or unsupported package directive is specified."""
#: add all directive names to __all__
__all__.extend(directive_names)

View File

@@ -9,6 +9,7 @@
import posixpath
import re
import shutil
import sys
import tempfile
from contextlib import contextmanager
@@ -24,6 +25,7 @@
import spack.util.spack_json as sjson
from spack.error import SpackError
is_windows = sys.platform == 'win32'
# Note: Posixpath is used here as opposed to
# os.path.join due to spack.spec.Spec.format
# requiring forward slash path seperators at this stage
@@ -108,13 +110,9 @@ def write_spec(self, spec, path):
"""Write a spec out to a file."""
_check_concrete(spec)
with open(path, 'w') as f:
# The hash the the projection is the DAG hash but we write out the
# full provenance by full hash so it's availabe if we want it later
# extension = os.path.splitext(path)[-1].lower()
# if 'json' in extension:
spec.to_json(f, hash=ht.full_hash)
# elif 'yaml' in extension:
# spec.to_yaml(f, hash=ht.full_hash)
# The hash of the projection is the DAG hash which contains
# the full provenance, so it's availabe if we want it later
spec.to_json(f, hash=ht.dag_hash)
def write_host_environment(self, spec):
"""The host environment is a json file with os, kernel, and spack
@@ -240,10 +238,10 @@ def create_install_directory(self, spec):
def ensure_installed(self, spec):
"""
Throws DirectoryLayoutError if:
Throws InconsistentInstallDirectoryError if:
1. spec prefix does not exist
2. spec prefix does not contain a spec file
3. the spec file does not correspond to the spec
2. spec prefix does not contain a spec file, or
3. We read a spec with the wrong DAG hash out of an existing install directory.
"""
_check_concrete(spec)
path = self.path_for_spec(spec)
@@ -259,25 +257,7 @@ def ensure_installed(self, spec):
" " + path)
installed_spec = self.read_spec(spec_file_path)
if installed_spec == spec:
return
# DAG hashes currently do not include build dependencies.
#
# TODO: remove this when we do better concretization and don't
# ignore build-only deps in hashes.
elif (installed_spec.copy(deps=('link', 'run')) ==
spec.copy(deps=('link', 'run'))):
# The directory layout prefix is based on the dag hash, so among
# specs with differing full-hash but matching dag-hash, only one
# may be installed. This means for example that for two instances
# that differ only in CMake version used to build, only one will
# be installed.
return
if spec.dag_hash() == installed_spec.dag_hash():
raise SpecHashCollisionError(spec, installed_spec)
else:
if installed_spec.dag_hash() != spec.dag_hash():
raise InconsistentInstallDirectoryError(
'Spec file in %s does not match hash!' % spec_file_path)
@@ -349,6 +329,14 @@ def remove_install_directory(self, spec, deprecated=False):
path = self.path_for_spec(spec)
assert(path.startswith(self.root))
# Windows readonly files cannot be removed by Python
# directly, change permissions before attempting to remove
if is_windows:
kwargs = {'ignore_errors': False,
'onerror': fs.readonly_file_handler(ignore_errors=False)}
else:
kwargs = {} # the default value for ignore_errors is false
if deprecated:
if os.path.exists(path):
try:
@@ -357,10 +345,9 @@ def remove_install_directory(self, spec, deprecated=False):
os.remove(metapath)
except OSError as e:
raise six.raise_from(RemoveFailedError(spec, path, e), e)
elif os.path.exists(path):
try:
shutil.rmtree(path)
shutil.rmtree(path, **kwargs)
except OSError as e:
raise six.raise_from(RemoveFailedError(spec, path, e), e)
@@ -458,8 +445,8 @@ def add_extension(self, spec, ext_spec):
def check_extension_conflict(self, spec, ext_spec):
exts = self._extension_map(spec)
if ext_spec.name in exts:
installed_spec = exts[ext_spec.name].copy(deps=('link', 'run'))
if ext_spec.copy(deps=('link', 'run')) == installed_spec:
installed_spec = exts[ext_spec.name]
if ext_spec.dag_hash() == installed_spec.dag_hash():
raise ExtensionAlreadyInstalledError(spec, ext_spec)
else:
raise ExtensionConflictError(spec, ext_spec, installed_spec)
@@ -579,15 +566,6 @@ def __init__(self, message, long_msg=None):
super(DirectoryLayoutError, self).__init__(message, long_msg)
class SpecHashCollisionError(DirectoryLayoutError):
"""Raised when there is a hash collision in an install layout."""
def __init__(self, installed_spec, new_spec):
super(SpecHashCollisionError, self).__init__(
'Specs %s and %s have the same SHA-1 prefix!'
% (installed_spec, new_spec))
class RemoveFailedError(DirectoryLayoutError):
"""Raised when a DirectoryLayout cannot remove an install prefix."""

View File

@@ -1,7 +1,334 @@
# -*- coding: utf-8 -*-
# Copyright 2013-2022 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)
"""This package implements Spack environments.
.. _lockfile-format:
`spack.lock` format
===================
Spack environments have existed since Spack ``v0.12.0``, and there have been 4 different
``spack.lock`` formats since then. The formats are documented here.
The high-level format of a Spack lockfile hasn't changed much between versions, but the
contents have. Lockfiles are JSON-formatted and their top-level sections are:
1. ``_meta`` (object): this contains deatails about the file format, including:
* ``file-type``: always ``"spack-lockfile"``
* ``lockfile-version``: an integer representing the lockfile format version
* ``specfile-version``: an integer representing the spec format version (since
``v0.17``)
2. ``roots`` (list): an ordered list of records representing the roots of the Spack
environment. Each has two fields:
* ``hash``: a Spack spec hash uniquely identifying the concrete root spec
* ``spec``: a string representation of the abstract spec that was concretized
3. ``concrete_specs``: a dictionary containing the specs in the environment.
Compatibility
-------------
New versions of Spack can (so far) read all old lockfile formats -- they are
backward-compatible. Old versions cannot read new lockfile formats, and you'll need to
upgrade Spack to use them.
.. list-table:: Lockfile version compatibility across Spack versions
:header-rows: 1
* - Spack version
- ``v1``
- ``v2``
- ``v3``
- ``v4``
* - ``v0.12:0.14``
-
-
-
-
* - ``v0.15:0.16``
-
-
-
-
* - ``v0.17``
-
-
-
-
* - ``v0.18:``
-
-
-
-
Version 1
---------
When lockfiles were first created, there was only one hash in Spack: the DAG hash. This
DAG hash (we'll call it the old DAG hash) did *not* include build dependencies -- it
only included transitive link and run dependencies.
The spec format at this time was keyed by name. Each spec started with a key for its
name, whose value was a dictionary of other spec attributes. The lockfile put these
name-keyed specs into dictionaries keyed by their DAG hash, and the spec records did not
actually have a "hash" field in the lockfile -- you have to associate the hash from the
key with the spec record after the fact.
Dependencies in original lockfiles were keyed by ``"hash"``, i.e. the old DAG hash.
.. code-block:: json
{
"_meta": {
"file-type": "spack-lockfile",
"lockfile-version": 1
},
"roots": [
{
"hash": "<old_dag_hash 1>",
"spec": "<abstract spec 1>"
},
{
"hash": "<old_dag_hash 2>",
"spec": "<abstract spec 2>"
}
],
"concrete_specs": {
"<old_dag_hash 1>": {
"... <spec dict attributes> ...": { },
"dependencies": {
"depname_1": {
"hash": "<old_dag_hash for depname_1>",
"type": ["build", "link"]
},
"depname_2": {
"hash": "<old_dag_hash for depname_3>",
"type": ["build", "link"]
}
},
"hash": "<old_dag_hash 1>"
},
"<old_dag_hash 2>": {
"... <spec dict attributes> ...": { },
"dependencies": {
"depname_3": {
"hash": "<old_dag_hash for depname_3>",
"type": ["build", "link"]
},
"depname_4": {
"hash": "<old_dag_hash for depname_4>",
"type": ["build", "link"]
},
},
"hash": "<old_dag_hash 2>"
},
}
}
Version 2
---------
Version 2 changes one thing: specs in the lockfile are now keyed by ``build_hash``
instead of the old ``dag_hash``. Specs have a ``hash`` attribute with their real DAG
hash, so you can't go by the dictionary key anymore to identify a spec -- you have to
read it in and look at ``"hash"``. Dependencies are still keyed by old DAG hash.
Even though we key lockfiles by ``build_hash``, specs in Spack were still deployed with
the old, coarser DAG hash. This means that in v2 and v3 lockfiles (which are keyed by
build hash), there may be multiple versions of the same spec with different build
dependencies, which means they will have different build hashes but the same DAG hash.
Spack would only have been able to actually install one of these.
.. code-block:: json
{
"_meta": {
"file-type": "spack-lockfile",
"lockfile-version": 2
},
"roots": [
{
"hash": "<build_hash 1>",
"spec": "<abstract spec 1>"
},
{
"hash": "<build_hash 2>",
"spec": "<abstract spec 2>"
}
],
"concrete_specs": {
"<build_hash 1>": {
"... <spec dict attributes> ...": { },
"dependencies": {
"depname_1": {
"hash": "<old_dag_hash for depname_1>",
"type": ["build", "link"]
},
"depname_2": {
"hash": "<old_dag_hash for depname_3>",
"type": ["build", "link"]
}
},
"hash": "<old_dag_hash 1>",
},
"<build_hash 2>": {
"... <spec dict attributes> ...": { },
"dependencies": {
"depname_3": {
"hash": "<old_dag_hash for depname_3>",
"type": ["build", "link"]
},
"depname_4": {
"hash": "<old_dag_hash for depname_4>",
"type": ["build", "link"]
}
},
"hash": "<old_dag_hash 2>"
}
}
}
Version 3
---------
Version 3 doesn't change the top-level lockfile format, but this was when we changed the
specfile format. Specs in ``concrete_specs`` are now keyed by the build hash, with no
inner dictionary keyed by their package name. The package name is in a ``name`` field
inside each spec dictionary. The ``dependencies`` field in the specs is a list instead
of a dictionary, and each element of the list is a record with the name, dependency
types, and hash of the dependency. Instead of a key called ``hash``, dependencies are
keyed by ``build_hash``. Each spec still has a ``hash`` attribute.
Version 3 adds the ``specfile_version`` field to ``_meta`` and uses the new JSON spec
format.
.. code-block:: json
{
"_meta": {
"file-type": "spack-lockfile",
"lockfile-version": 3,
"specfile-version": 2
},
"roots": [
{
"hash": "<build_hash 1>",
"spec": "<abstract spec 1>"
},
{
"hash": "<build_hash 2>",
"spec": "<abstract spec 2>"
},
],
"concrete_specs": {
"<build_hash 1>": {
"... <spec dict attributes> ...": { },
"dependencies": [
{
"name": "depname_1",
"build_hash": "<build_hash for depname_1>",
"type": ["build", "link"]
},
{
"name": "depname_2",
"build_hash": "<build_hash for depname_2>",
"type": ["build", "link"]
},
],
"hash": "<old_dag_hash 1>",
},
"<build_hash 2>": {
"... <spec dict attributes> ...": { },
"dependencies": [
{
"name": "depname_3",
"build_hash": "<build_hash for depname_3>",
"type": ["build", "link"]
},
{
"name": "depname_4",
"build_hash": "<build_hash for depname_4>",
"type": ["build", "link"]
},
],
"hash": "<old_dag_hash 2>"
}
}
}
Version 4
---------
Version 4 removes build hashes and is keyed by the new DAG hash (``hash``). The ``hash``
now includes build dependencies and a canonical hash of the ``package.py`` file.
Dependencies are keyed by ``hash`` (DAG hash) as well. There are no more ``build_hash``
fields in the specs, and there are no more issues with lockfiles being able to store
multiple specs with the same DAG hash (because the DAG hash is now finer-grained).
.. code-block:: json
{
"_meta": {
"file-type": "spack-lockfile",
"lockfile-version": 3,
"specfile-version": 2
},
"roots": [
{
"hash": "<dag_hash 1>",
"spec": "<abstract spec 1>"
},
{
"hash": "<dag_hash 2>",
"spec": "<abstract spec 2>"
}
],
"concrete_specs": {
"<dag_hash 1>": {
"... <spec dict attributes> ...": { },
"dependencies": [
{
"name": "depname_1",
"hash": "<dag_hash for depname_1>",
"type": ["build", "link"]
},
{
"name": "depname_2",
"hash": "<dag_hash for depname_2>",
"type": ["build", "link"]
}
],
"hash": "<dag_hash 1>",
},
"<daghash 2>": {
"... <spec dict attributes> ...": { },
"dependencies": [
{
"name": "depname_3",
"hash": "<dag_hash for depname_3>",
"type": ["build", "link"]
},
{
"name": "depname_4",
"hash": "<dag_hash for depname_4>",
"type": ["build", "link"]
}
],
"hash": "<dag_hash 2>"
}
}
}
"""
from .environment import (
Environment,
SpackEnvironmentError,

View File

@@ -79,8 +79,9 @@
env_subdir_name = '.spack-env'
#: default spack.yaml file to put in new environments
default_manifest_yaml = """\
def default_manifest_yaml():
"""default spack.yaml file to put in new environments"""
return """\
# This is a Spack Environment file.
#
# It describes a set of packages to be installed, along with
@@ -89,12 +90,16 @@
# add package specs to the `specs` list
specs: []
view: true
"""
concretizer:
unify: {}
""".format('true' if spack.config.get('concretizer:unify') else 'false')
#: regex for validating enviroment names
valid_environment_name_re = r'^\w[\w-]*$'
#: version of the lockfile format. Must increase monotonically.
lockfile_format_version = 3
lockfile_format_version = 4
# Magic names
# The name of the standalone spec list in the manifest yaml
@@ -302,7 +307,7 @@ def _is_dev_spec_and_has_changed(spec):
return False
# Now we can check whether the code changed since the last installation
if not spec.package.installed:
if not spec.installed:
# Not installed -> nothing to compare against
return False
@@ -315,7 +320,7 @@ def _spec_needs_overwrite(spec, changed_dev_specs):
"""Check whether the current spec needs to be overwritten because either it has
changed itself or one of its dependencies have changed"""
# if it's not installed, we don't need to overwrite it
if not spec.package.installed:
if not spec.installed:
return False
# If the spec itself has changed this is a trivial decision
@@ -330,7 +335,7 @@ def _spec_needs_overwrite(spec, changed_dev_specs):
# If any dep needs overwrite, or any dep is missing and is a dev build then
# overwrite this package
if any(
((not dep.package.installed) and dep.satisfies('dev_path=*')) or
((not dep.installed) and dep.satisfies('dev_path=*')) or
_spec_needs_overwrite(dep, changed_dev_specs)
for dep in spec.traverse(root=False)
):
@@ -439,7 +444,7 @@ def _next_root(self, specs):
def content_hash(self, specs):
d = syaml.syaml_dict([
('descriptor', self.to_dict()),
('specs', [(spec.full_hash(), spec.prefix) for spec in sorted(specs)])
('specs', [(spec.dag_hash(), spec.prefix) for spec in sorted(specs)])
])
contents = sjson.dump(d)
return spack.util.hash.b32_hash(contents)
@@ -518,7 +523,7 @@ def specs_for_view(self, concretized_root_specs):
# Filter selected, installed specs
with spack.store.db.read_transaction():
specs = [s for s in specs if s in self and s.package.installed]
specs = [s for s in specs if s in self and s.installed]
return specs
@@ -632,11 +637,11 @@ def __init__(self, path, init_file=None, with_view=None, keep_relative=False):
# the init file.
with fs.open_if_filename(init_file) as f:
if hasattr(f, 'name') and f.name.endswith('.lock'):
self._read_manifest(default_manifest_yaml)
self._read_manifest(default_manifest_yaml())
self._read_lockfile(f)
self._set_user_specs_from_lockfile()
else:
self._read_manifest(f, raw_yaml=default_manifest_yaml)
self._read_manifest(f, raw_yaml=default_manifest_yaml())
# Rewrite relative develop paths when initializing a new
# environment in a different location from the spack.yaml file.
@@ -700,7 +705,7 @@ def _read(self):
default_manifest = not os.path.exists(self.manifest_path)
if default_manifest:
# No manifest, use default yaml
self._read_manifest(default_manifest_yaml)
self._read_manifest(default_manifest_yaml())
else:
with open(self.manifest_path) as f:
self._read_manifest(f)
@@ -766,8 +771,11 @@ def _read_manifest(self, f, raw_yaml=None):
self.views = {}
# Retrieve the current concretization strategy
configuration = config_dict(self.yaml)
# default concretization to separately
self.concretization = configuration.get('concretization', 'separately')
# Let `concretization` overrule `concretize:unify` config for now.
unify = spack.config.get('concretizer:unify')
self.concretization = configuration.get(
'concretization', 'together' if unify else 'separately')
# Retrieve dev-build packages:
self.dev_specs = configuration.get('develop', {})
@@ -1010,14 +1018,9 @@ def remove(self, query_spec, list_name=user_speclist_name, force=False):
if not matches:
# concrete specs match against concrete specs in the env
# by *dag hash*, not build hash.
dag_hashes_in_order = [
self.specs_by_hash[build_hash].dag_hash()
for build_hash in self.concretized_order
]
# by dag hash.
specs_hashes = zip(
self.concretized_user_specs, dag_hashes_in_order
self.concretized_user_specs, self.concretized_order
)
matches = [
@@ -1274,7 +1277,7 @@ def _concretize_separately(self, tests=False):
by_hash = {}
for abstract, concrete in zip(root_specs, concretized_root_specs):
self._add_concrete_spec(abstract, concrete)
by_hash[concrete.build_hash()] = concrete
by_hash[concrete.dag_hash()] = concrete
# Unify the specs objects, so we get correct references to all parents
self._read_lockfile_dict(self._to_lockfile_dict())
@@ -1331,7 +1334,7 @@ def concretize_and_add(self, user_spec, concrete_spec=None, tests=False):
spec = next(
s for s in self.user_specs if s.satisfies(user_spec)
)
concrete = self.specs_by_hash.get(spec.build_hash())
concrete = self.specs_by_hash.get(spec.dag_hash())
if not concrete:
concrete = spec.concretized(tests=tests)
self._add_concrete_spec(spec, concrete)
@@ -1380,9 +1383,10 @@ def check_views(self):
# default view if they are installed.
for view_name, view in self.views.items():
for _, spec in self.concretized_specs():
if spec in view and spec.package.installed:
tty.debug(
'Spec %s in view %s' % (spec.name, view_name))
if spec in view and spec.package and spec.installed:
msg = '{0} in view "{1}"'
tty.debug(msg.format(spec.name, view_name))
except (spack.repo.UnknownPackageError,
spack.repo.UnknownNamespaceError) as e:
tty.warn(e)
@@ -1398,7 +1402,8 @@ def _env_modifications_for_default_view(self, reverse=False):
errors = []
for _, root_spec in self.concretized_specs():
if root_spec in self.default_view and root_spec.package.installed:
if (root_spec in self.default_view and
root_spec.installed and root_spec.package):
for spec in root_spec.traverse(deptype='run', root=True):
if spec.name in visited:
# It is expected that only one instance of the package
@@ -1497,7 +1502,7 @@ def _add_concrete_spec(self, spec, concrete, new=True):
# update internal lists of specs
self.concretized_user_specs.append(spec)
h = concrete.build_hash()
h = concrete.dag_hash()
self.concretized_order.append(h)
self.specs_by_hash[h] = concrete
@@ -1537,7 +1542,7 @@ def uninstalled_specs(self):
with spack.store.db.read_transaction():
for concretized_hash in self.concretized_order:
spec = self.specs_by_hash[concretized_hash]
if not spec.package.installed or (
if not spec.installed or (
spec.satisfies('dev_path=*') or
spec.satisfies('^dev_path=*')
):
@@ -1572,7 +1577,7 @@ def install_specs(self, specs=None, **install_args):
# ensure specs already installed are marked explicit
all_specs = specs or [cs for _, cs in self.concretized_specs()]
specs_installed = [s for s in all_specs if s.package.installed]
specs_installed = [s for s in all_specs if s.installed]
with spack.store.db.write_transaction(): # do all in one transaction
for spec in specs_installed:
spack.store.db.update_explicit(spec, True)
@@ -1599,7 +1604,7 @@ def install_specs(self, specs=None, **install_args):
finally:
# Ensure links are set appropriately
for spec in specs_to_install:
if spec.package.installed:
if spec.installed:
self.new_installs.append(spec)
try:
self._install_log_links(spec)
@@ -1614,14 +1619,19 @@ def all_specs(self):
"""Return all specs, even those a user spec would shadow."""
all_specs = set()
for h in self.concretized_order:
all_specs.update(self.specs_by_hash[h].traverse())
try:
spec = self.specs_by_hash[h]
except KeyError:
tty.warn(
'Environment %s appears to be corrupt: missing spec '
'"%s"' % (self.name, h))
continue
all_specs.update(spec.traverse())
return sorted(all_specs)
def all_hashes(self):
"""Return hashes of all specs.
Note these hashes exclude build dependencies."""
"""Return hashes of all specs."""
return list(set(s.dag_hash() for s in self.all_specs()))
def roots(self):
@@ -1649,7 +1659,7 @@ def added_specs(self):
concrete = concretized.get(spec)
if not concrete:
yield spec
elif not concrete.package.installed:
elif not concrete.installed:
yield concrete
def concretized_specs(self):
@@ -1657,6 +1667,15 @@ def concretized_specs(self):
for s, h in zip(self.concretized_user_specs, self.concretized_order):
yield (s, self.specs_by_hash[h])
def get_by_hash(self, dag_hash):
matches = {}
for _, root in self.concretized_specs():
for spec in root.traverse(root=True):
dep_hash = spec.dag_hash()
if dep_hash.startswith(dag_hash):
matches[dep_hash] = spec
return list(matches.values())
def matching_spec(self, spec):
"""
Given a spec (likely not concretized), find a matching concretized
@@ -1684,13 +1703,7 @@ def matching_spec(self, spec):
for user_spec, concretized_user_spec in self.concretized_specs():
# Deal with concrete specs differently
if spec.concrete:
# Matching a concrete spec is more restrictive
# than just matching the dag hash
is_match = (
spec in concretized_user_spec and
concretized_user_spec[spec.name].build_hash() == spec.build_hash()
)
if is_match:
if spec in concretized_user_spec:
matches[spec] = spec
continue
@@ -1770,12 +1783,12 @@ def _to_lockfile_dict(self):
concrete_specs = {}
for spec in self.specs_by_hash.values():
for s in spec.traverse():
build_hash = s.build_hash()
if build_hash not in concrete_specs:
spec_dict = s.to_node_dict(hash=ht.build_hash)
dag_hash = s.dag_hash()
if dag_hash not in concrete_specs:
spec_dict = s.node_dict_with_hashes(hash=ht.dag_hash)
# Assumes no legacy formats, since this was just created.
spec_dict[ht.dag_hash.name] = s.dag_hash()
concrete_specs[build_hash] = spec_dict
concrete_specs[dag_hash] = spec_dict
hash_spec_list = zip(
self.concretized_order, self.concretized_user_specs)
@@ -1809,47 +1822,56 @@ def _read_lockfile(self, file_or_json):
def _read_lockfile_dict(self, d):
"""Read a lockfile dictionary into this environment."""
self.specs_by_hash = {}
roots = d['roots']
self.concretized_user_specs = [Spec(r['spec']) for r in roots]
self.concretized_order = [r['hash'] for r in roots]
json_specs_by_hash = d['concrete_specs']
root_hashes = set(self.concretized_order)
# Track specs by their lockfile key. Currently spack uses the finest
# grained hash as the lockfile key, while older formats used the build
# hash or a previous incarnation of the DAG hash (one that did not
# include build deps or package hash).
specs_by_hash = {}
for build_hash, node_dict in json_specs_by_hash.items():
spec = Spec.from_node_dict(node_dict)
if d['_meta']['lockfile-version'] > 1:
# Build hash is stored as a key, but not as part of the node dict
# To ensure build hashes are not recomputed, we reattach here
setattr(spec, ht.build_hash.attr, build_hash)
specs_by_hash[build_hash] = spec
for build_hash, node_dict in json_specs_by_hash.items():
# Track specs by their DAG hash, allows handling DAG hash collisions
first_seen = {}
# First pass: Put each spec in the map ignoring dependencies
for lockfile_key, node_dict in json_specs_by_hash.items():
spec = Spec.from_node_dict(node_dict)
if not spec._hash:
# in v1 lockfiles, the hash only occurs as a key
spec._hash = lockfile_key
specs_by_hash[lockfile_key] = spec
# Second pass: For each spec, get its dependencies from the node dict
# and add them to the spec
for lockfile_key, node_dict in json_specs_by_hash.items():
for _, dep_hash, deptypes, _ in (
Spec.dependencies_from_node_dict(node_dict)):
specs_by_hash[build_hash]._add_dependency(
specs_by_hash[lockfile_key]._add_dependency(
specs_by_hash[dep_hash], deptypes)
# If we are reading an older lockfile format (which uses dag hashes
# that exclude build deps), we use this to convert the old
# concretized_order to the full hashes (preserving the order)
old_hash_to_new = {}
self.specs_by_hash = {}
for _, spec in specs_by_hash.items():
dag_hash = spec.dag_hash()
build_hash = spec.build_hash()
if dag_hash in root_hashes:
old_hash_to_new[dag_hash] = build_hash
# Traverse the root specs one at a time in the order they appear.
# The first time we see each DAG hash, that's the one we want to
# keep. This is only required as long as we support older lockfile
# formats where the mapping from DAG hash to lockfile key is possibly
# one-to-many.
for lockfile_key in self.concretized_order:
for s in specs_by_hash[lockfile_key].traverse():
if s.dag_hash() not in first_seen:
first_seen[s.dag_hash()] = s
if (dag_hash in root_hashes or build_hash in root_hashes):
self.specs_by_hash[build_hash] = spec
# Now make sure concretized_order and our internal specs dict
# contains the keys used by modern spack (i.e. the dag_hash
# that includes build deps and package hash).
self.concretized_order = [specs_by_hash[h_key].dag_hash()
for h_key in self.concretized_order]
if old_hash_to_new:
# Replace any older hashes in concretized_order with hashes
# that include build deps
self.concretized_order = [
old_hash_to_new.get(h, h) for h in self.concretized_order]
for spec_dag_hash in self.concretized_order:
self.specs_by_hash[spec_dag_hash] = first_seen[spec_dag_hash]
def write(self, regenerate=True):
"""Writes an in-memory environment to its location on disk.
@@ -1862,17 +1884,15 @@ def write(self, regenerate=True):
regenerate (bool): regenerate views and run post-write hooks as
well as writing if True.
"""
# Intercept environment not using the latest schema format and prevent
# them from being modified
manifest_exists = os.path.exists(self.manifest_path)
if manifest_exists and not is_latest_format(self.manifest_path):
msg = ('The environment "{0}" needs to be written to disk, but '
'is currently using a deprecated format. Please update it '
'using:\n\n'
'\tspack env update {0}\n\n'
'Note that previous versions of Spack will not be able to '
# Warn that environments are not in the latest format.
if not is_latest_format(self.manifest_path):
ver = '.'.join(str(s) for s in spack.spack_version_info[:2])
msg = ('The environment "{}" is written to disk in a deprecated format. '
'Please update it using:\n\n'
'\tspack env update {}\n\n'
'Note that versions of Spack older than {} may not be able to '
'use the updated configuration.')
raise RuntimeError(msg.format(self.name))
tty.warn(msg.format(self.name, self.name, ver))
# ensure path in var/spack/environments
fs.mkdirp(self.path)
@@ -2224,14 +2244,16 @@ def _top_level_key(data):
def is_latest_format(manifest):
"""Return True if the manifest file is at the latest schema format,
False otherwise.
"""Return False if the manifest file exists and is not in the latest schema format.
Args:
manifest (str): manifest file to be analyzed
"""
with open(manifest) as f:
data = syaml.load(f)
try:
with open(manifest) as f:
data = syaml.load(f)
except (OSError, IOError):
return True
top_level_key = _top_level_key(data)
changed = spack.schema.env.update(data[top_level_key])
return not changed

View File

@@ -10,9 +10,9 @@
import llnl.util.tty as tty
#: whether we should write stack traces or short error messages
#: at what level we should write stack traces or short error messages
#: this is module-scoped because it needs to be set very early
debug = False
debug = 0
class SpackError(Exception):

View File

@@ -406,12 +406,12 @@ def write(self, spec, color=None, out=None):
# Colors associated with each node in the DAG.
# Edges are colored by the node they point to.
self._name_to_color = {
spec.full_hash(): self.colors[i % len(self.colors)]
spec.dag_hash(): self.colors[i % len(self.colors)]
for i, spec in enumerate(nodes_in_topological_order)
}
# Frontier tracks open edges of the graph as it's written out.
self._frontier = [[spec.full_hash()]]
self._frontier = [[spec.dag_hash()]]
while self._frontier:
# Find an unexpanded part of frontier
i = find(self._frontier, lambda f: len(f) > 1)
@@ -488,14 +488,16 @@ def write(self, spec, color=None, out=None):
node = nodes_in_topological_order.pop()
# Find the named node in the frontier and draw it.
i = find(self._frontier, lambda f: node.full_hash() in f)
i = find(self._frontier, lambda f: node.dag_hash() in f)
self._node_line(i, node)
# Replace node with its dependencies
self._frontier.pop(i)
deps = node.dependencies(deptype=self.deptype)
if deps:
deps = sorted((d.full_hash() for d in deps), reverse=True)
edges = sorted(
node.edges_to_dependencies(deptype=self.deptype), reverse=True
)
if edges:
deps = [e.spec.dag_hash() for e in edges]
self._connect_deps(i, deps, "new-deps") # anywhere.
elif self._frontier:

View File

@@ -33,15 +33,14 @@ def attr(self):
"""Private attribute stored on spec"""
return '_' + self.name
def __call__(self, spec):
"""Run this hash on the provided spec."""
return spec.spec_hash(self)
#: Default Hash descriptor, used by Spec.dag_hash() and stored in the DB.
#: Spack's deployment hash. Includes all inputs that can affect how a package is built.
dag_hash = SpecHashDescriptor(
deptype=('link', 'run'), package_hash=False, name='hash')
#: Hash descriptor that includes build dependencies.
build_hash = SpecHashDescriptor(
deptype=('build', 'link', 'run'), package_hash=False, name='build_hash')
deptype=('build', 'link', 'run'), package_hash=True, name='hash')
#: Hash descriptor used only to transfer a DAG, as is, across processes
@@ -51,12 +50,19 @@ def attr(self):
name='process_hash'
)
#: Full hash used in build pipelines to determine when to rebuild packages.
#: Package hash used as part of dag hash
package_hash = SpecHashDescriptor(
deptype=(), package_hash=True, name='package_hash',
override=lambda s: s.package.content_hash())
# Deprecated hash types, no longer used, but needed to understand old serialized
# spec formats
full_hash = SpecHashDescriptor(
deptype=('build', 'link', 'run'), package_hash=True, name='full_hash')
#: Package hash used as part of full hash
package_hash = SpecHashDescriptor(
deptype=(), package_hash=True, name='package_hash',
override=lambda s: s.package.content_hash())
build_hash = SpecHashDescriptor(
deptype=('build', 'link', 'run'), package_hash=False, name='build_hash')

View File

@@ -140,7 +140,7 @@ def _handle_external_and_upstream(pkg, explicit):
.format(pkg.prefix, package_id(pkg)))
return True
if pkg.installed_upstream:
if pkg.spec.installed_upstream:
tty.verbose('{0} is installed in an upstream Spack instance at {1}'
.format(package_id(pkg), pkg.spec.prefix))
_print_installed_pkg(pkg.prefix)
@@ -260,8 +260,7 @@ def _hms(seconds):
return ' '.join(parts)
def _install_from_cache(pkg, cache_only, explicit, unsigned=False,
full_hash_match=False):
def _install_from_cache(pkg, cache_only, explicit, unsigned=False):
"""
Extract the package from binary cache
@@ -278,7 +277,7 @@ def _install_from_cache(pkg, cache_only, explicit, unsigned=False,
``False`` otherwise
"""
installed_from_cache = _try_install_from_binary_cache(
pkg, explicit, unsigned=unsigned, full_hash_match=full_hash_match)
pkg, explicit, unsigned=unsigned)
pkg_id = package_id(pkg)
if not installed_from_cache:
pre = 'No binary for {0} found'.format(pkg_id)
@@ -390,8 +389,7 @@ def _process_binary_cache_tarball(pkg, binary_spec, explicit, unsigned,
return True
def _try_install_from_binary_cache(pkg, explicit, unsigned=False,
full_hash_match=False):
def _try_install_from_binary_cache(pkg, explicit, unsigned=False):
"""
Try to extract the package from binary cache.
@@ -403,8 +401,7 @@ def _try_install_from_binary_cache(pkg, explicit, unsigned=False,
"""
pkg_id = package_id(pkg)
tty.debug('Searching for binary cache of {0}'.format(pkg_id))
matches = binary_distribution.get_mirrors_for_spec(
pkg.spec, full_hash_match=full_hash_match)
matches = binary_distribution.get_mirrors_for_spec(pkg.spec)
if not matches:
return False
@@ -561,6 +558,10 @@ def log(pkg):
# Archive the environment modifications for the build.
fs.install(pkg.env_mods_path, pkg.install_env_path)
# Archive the install-phase test log, if present
if pkg.test_install_log_path and os.path.exists(pkg.test_install_log_path):
fs.install(pkg.test_install_log_path, pkg.install_test_install_log_path)
if os.path.exists(pkg.configure_args_path):
# Archive the args used for the build
fs.install(pkg.configure_args_path, pkg.install_configure_args_path)
@@ -853,7 +854,7 @@ def _check_deps_status(self, request):
raise InstallError(err.format(request.pkg_id, msg))
# Flag external and upstream packages as being installed
if dep_pkg.spec.external or dep_pkg.installed_upstream:
if dep_pkg.spec.external or dep_pkg.spec.installed_upstream:
self._flag_installed(dep_pkg)
continue
@@ -995,7 +996,7 @@ def _ensure_install_ready(self, pkg):
raise ExternalPackageError('{0} {1}'.format(pre, 'is external'))
# Upstream packages cannot be installed locally.
if pkg.installed_upstream:
if pkg.spec.installed_upstream:
raise UpstreamPackageError('{0} {1}'.format(pre, 'is upstream'))
# The package must have a prefix lock at this stage.
@@ -1200,7 +1201,6 @@ def _install_task(self, task):
install_args = task.request.install_args
cache_only = install_args.get('cache_only')
explicit = task.explicit
full_hash_match = install_args.get('full_hash_match')
tests = install_args.get('tests')
unsigned = install_args.get('unsigned')
use_cache = install_args.get('use_cache')
@@ -1213,8 +1213,7 @@ def _install_task(self, task):
# Use the binary cache if requested
if use_cache and \
_install_from_cache(pkg, cache_only, explicit, unsigned,
full_hash_match):
_install_from_cache(pkg, cache_only, explicit, unsigned):
self._update_installed(task)
if task.compiler:
spack.compilers.add_compilers_to_config(
@@ -2018,11 +2017,10 @@ def build_process(pkg, install_args):
class OverwriteInstall(object):
def __init__(self, installer, database, task, tmp_root=None):
def __init__(self, installer, database, task):
self.installer = installer
self.database = database
self.task = task
self.tmp_root = tmp_root
def install(self):
"""
@@ -2032,7 +2030,7 @@ def install(self):
install error if installation fails.
"""
try:
with fs.replace_directory_transaction(self.task.pkg.prefix, self.tmp_root):
with fs.replace_directory_transaction(self.task.pkg.prefix):
self.installer._install_task(self.task)
except fs.CouldNotRestoreDirectoryBackup as e:
self.database.remove(self.task.pkg.spec)
@@ -2303,7 +2301,6 @@ def _add_default_args(self):
('dirty', False),
('fail_fast', False),
('fake', False),
('full_hash_match', False),
('install_deps', True),
('install_package', True),
('install_source', False),

View File

@@ -30,7 +30,7 @@
import llnl.util.tty as tty
import llnl.util.tty.colify
import llnl.util.tty.color as color
from llnl.util.tty.log import log_output, winlog
from llnl.util.tty.log import log_output
import spack
import spack.cmd
@@ -375,13 +375,6 @@ def make_argument_parser(**kwargs):
# stat names in groups of 7, for nice wrapping.
stat_lines = list(zip(*(iter(stat_names),) * 7))
# help message for --show-cores
show_cores_help = 'provide additional information on concretization failures\n'
show_cores_help += 'off (default): show only the violated rule\n'
show_cores_help += 'full: show raw unsat cores from clingo\n'
show_cores_help += 'minimized: show subset-minimal unsat cores '
show_cores_help += '(Warning: this may take hours for some specs)'
parser.add_argument(
'-h', '--help',
dest='help', action='store_const', const='short', default=None,
@@ -405,9 +398,6 @@ def make_argument_parser(**kwargs):
'-d', '--debug', action='count', default=0,
help="write out debug messages "
"(more d's for more verbosity: -d, -dd, -ddd, etc.)")
parser.add_argument(
'--show-cores', choices=["off", "full", "minimized"], default="off",
help=show_cores_help)
parser.add_argument(
'--timestamp', action='store_true',
help="Add a timestamp to tty output")
@@ -490,18 +480,11 @@ def setup_main_options(args):
# errors raised by spack.config.
if args.debug:
spack.error.debug = True
spack.error.debug = args.debug
spack.util.debug.register_interrupt_handler()
spack.config.set('config:debug', True, scope='command_line')
spack.util.environment.tracing_enabled = True
if args.show_cores != "off":
# minimize_cores defaults to true, turn it off if we're showing full core
# but don't want to wait to minimize it.
spack.solver.asp.full_cores = True
if args.show_cores == 'full':
spack.solver.asp.minimize_cores = False
if args.timestamp:
tty.set_timestamp(True)
@@ -605,14 +588,9 @@ def __call__(self, *argv, **kwargs):
out = StringIO()
try:
if sys.platform == 'win32':
with winlog(out):
self.returncode = _invoke_command(
self.command, self.parser, args, unknown)
else:
with log_output(out):
self.returncode = _invoke_command(
self.command, self.parser, args, unknown)
with log_output(out):
self.returncode = _invoke_command(
self.command, self.parser, args, unknown)
except SystemExit as e:
self.returncode = e.code

View File

@@ -184,19 +184,38 @@ def _filter_compiler_wrappers_impl(self):
x = llnl.util.filesystem.FileFilter(*abs_files)
replacements = [
compiler_vars = [
('CC', self.compiler.cc),
('CXX', self.compiler.cxx),
('F77', self.compiler.f77),
('FC', self.compiler.fc)
]
for env_var, compiler_path in replacements:
# Some paths to the compiler wrappers might be substrings of the others.
# For example:
# CC=/path/to/spack/lib/spack/env/cc (realpath to the wrapper)
# FC=/path/to/spack/lib/spack/env/cce/ftn
# Therefore, we perform the filtering in the reversed sorted order of
# the substituted strings. If, however, the strings are identical (e.g.
# both CC and FC are set using realpath), the filtering is done
# according to the order in compiler_vars. To achieve that, we populate
# the following array with tuples of three elements: path to the
# wrapper, negated index of the variable in compiler_vars, path to the
# real compiler. This way, the reversed sorted order of the resulting
# array is the order of replacements that we need.
replacements = []
for idx, (env_var, compiler_path) in enumerate(compiler_vars):
if env_var in os.environ:
# filter spack wrapper and links to spack wrapper in case
# build system runs realpath
wrapper = os.environ[env_var]
for wrapper_path in (wrapper, os.path.realpath(wrapper)):
x.filter(wrapper_path, compiler_path, **filter_kwargs)
replacements.append((wrapper_path, -idx, compiler_path))
for wrapper_path, _, compiler_path in sorted(replacements,
reverse=True):
x.filter(wrapper_path, compiler_path, **filter_kwargs)
# Remove this linking flag if present (it turns RPATH into RUNPATH)
x.filter('{0}--enable-new-dtags'.format(self.compiler.linker_arg), '',

View File

@@ -370,7 +370,7 @@ def get_module(
available.
"""
try:
upstream = spec.package.installed_upstream
upstream = spec.installed_upstream
except spack.repo.UnknownPackageError:
upstream, record = spack.store.db.query_by_spec_hash(spec.dag_hash())
if upstream:

View File

@@ -132,7 +132,7 @@ def __init__(self, host=None, prefix="ms1", allow_fail=False, tags=None,
self.tags = tags
self.save_local = save_local
# We keey lookup of build_id by full_hash
# We key lookup of build_id by dag_hash
self.build_ids = {}
self.setup_save()
@@ -412,6 +412,8 @@ def new_configuration(self, specs):
spec.concretize()
# Remove extra level of nesting
# This is the only place in Spack we still use full_hash, as `spack monitor`
# requires specs with full_hash-keyed dependencies.
as_dict = {"spec": spec.to_dict(hash=ht.full_hash)['spec'],
"spack_version": self.spack_version}
@@ -437,8 +439,7 @@ def failed_concretization(self, specs):
meta = spec.to_dict()['spec']
nodes = []
for node in meta.get("nodes", []):
for hashtype in ["build_hash", "full_hash"]:
node[hashtype] = "FAILED_CONCRETIZATION"
node["full_hash"] = "FAILED_CONCRETIZATION"
nodes.append(node)
meta['nodes'] = nodes
@@ -470,13 +471,13 @@ def get_build_id(self, spec, return_response=False, spec_exists=True):
"""
Retrieve a build id, either in the local cache, or query the server.
"""
full_hash = spec.full_hash()
if full_hash in self.build_ids:
return self.build_ids[full_hash]
dag_hash = spec.dag_hash()
if dag_hash in self.build_ids:
return self.build_ids[dag_hash]
# Prepare build environment data (including spack version)
data = self.build_environment.copy()
data['full_hash'] = full_hash
data['full_hash'] = dag_hash
# If the build should be tagged, add it
if self.tags:
@@ -494,10 +495,10 @@ def get_build_id(self, spec, return_response=False, spec_exists=True):
data['spec'] = syaml.load(read_file(spec_file))
if self.save_local:
return self.get_local_build_id(data, full_hash, return_response)
return self.get_server_build_id(data, full_hash, return_response)
return self.get_local_build_id(data, dag_hash, return_response)
return self.get_server_build_id(data, dag_hash, return_response)
def get_local_build_id(self, data, full_hash, return_response):
def get_local_build_id(self, data, dag_hash, return_response):
"""
Generate a local build id based on hashing the expected data
"""
@@ -510,15 +511,15 @@ def get_local_build_id(self, data, full_hash, return_response):
return response
return bid
def get_server_build_id(self, data, full_hash, return_response=False):
def get_server_build_id(self, data, dag_hash, return_response=False):
"""
Retrieve a build id from the spack monitor server
"""
response = self.do_request("builds/new/", data=sjson.dump(data))
# Add the build id to the lookup
bid = self.build_ids[full_hash] = response['data']['build']['build_id']
self.build_ids[full_hash] = bid
bid = self.build_ids[dag_hash] = response['data']['build']['build_id']
self.build_ids[dag_hash] = bid
# If the function is called directly, the user might want output
if return_response:

View File

@@ -26,13 +26,14 @@
import time
import traceback
import types
import warnings
from typing import Any, Callable, Dict, List, Optional # novm
import six
import llnl.util.filesystem as fsys
import llnl.util.tty as tty
from llnl.util.lang import memoized
from llnl.util.lang import memoized, nullcontext
from llnl.util.link_tree import LinkTree
import spack.compilers
@@ -52,6 +53,7 @@
import spack.store
import spack.url
import spack.util.environment
import spack.util.path
import spack.util.web
from spack.filesystem_view import YamlFilesystemView
from spack.install_test import TestFailure, TestSuite
@@ -59,7 +61,6 @@
from spack.stage import ResourceStage, Stage, StageComposite, stage_prefix
from spack.util.executable import ProcessError, which
from spack.util.package_hash import package_hash
from spack.util.path import win_exe_ext
from spack.util.prefix import Prefix
from spack.version import Version
@@ -76,6 +77,9 @@
# Filename for the Spack build/install environment modifications file.
_spack_build_envmodsfile = 'spack-build-env-mods.txt'
# Filename for the Spack install phase-time test log.
_spack_install_test_log = 'install-time-test-log.txt'
# Filename of json with total build and phase times (seconds)
_spack_times_log = 'install_times.json'
@@ -196,9 +200,9 @@ def __init__(cls, name, bases, attr_dict):
def platform_executables(self):
def to_windows_exe(exe):
if exe.endswith('$'):
exe = exe.replace('$', '%s$' % win_exe_ext())
exe = exe.replace('$', '%s$' % spack.util.path.win_exe_ext())
else:
exe += win_exe_ext()
exe += spack.util.path.win_exe_ext()
return exe
plat_exe = []
if hasattr(self, 'executables'):
@@ -434,6 +438,11 @@ def name(self):
self._name = self._name[self._name.rindex('.') + 1:]
return self._name
@property
def global_license_dir(self):
"""Returns the directory where license files for all packages are stored."""
return spack.util.path.canonicalize_path(spack.config.get('config:license_dir'))
def run_before(*phases):
"""Registers a method of a package to be run before a given phase"""
@@ -790,15 +799,6 @@ def __init__(self, spec):
super(PackageBase, self).__init__()
@property
def installed_upstream(self):
if not hasattr(self, '_installed_upstream'):
upstream, record = spack.store.db.query_by_spec_hash(
self.spec.dag_hash())
self._installed_upstream = upstream
return self._installed_upstream
@classmethod
def possible_dependencies(
cls, transitive=True, expand_virtuals=True, deptype='all',
@@ -943,9 +943,8 @@ def name(self):
@property
def global_license_dir(self):
"""Returns the directory where global license files for all
packages are stored."""
return os.path.join(spack.paths.prefix, 'etc', 'spack', 'licenses')
"""Returns the directory where global license files are stored."""
return type(self).global_license_dir
@property
def global_license_file(self):
@@ -1252,6 +1251,16 @@ def configure_args_path(self):
"""Return the configure args file path associated with staging."""
return os.path.join(self.stage.path, _spack_configure_argsfile)
@property
def test_install_log_path(self):
"""Return the install phase-time test log file path, if set."""
return getattr(self, 'test_log_file', None)
@property
def install_test_install_log_path(self):
"""Return the install location for the install phase-time test log."""
return fsys.join_path(self.metadata_dir, _spack_install_test_log)
@property
def times_log_path(self):
"""Return the times log json file."""
@@ -1267,6 +1276,20 @@ def install_test_root(self):
"""Return the install test root directory."""
return os.path.join(self.metadata_dir, 'test')
@property
def installed(self):
msg = ('the "PackageBase.installed" property is deprecated and will be '
'removed in Spack v0.19, use "Spec.installed" instead')
warnings.warn(msg)
return self.spec.installed
@property
def installed_upstream(self):
msg = ('the "PackageBase.installed_upstream" property is deprecated and will '
'be removed in Spack v0.19, use "Spec.installed_upstream" instead')
warnings.warn(msg)
return self.spec.installed_upstream
def _make_fetcher(self):
# Construct a composite fetcher that always contains at least
# one element (the root package). In case there are resources
@@ -1380,7 +1403,7 @@ def is_activated(self, view):
if not self.is_extension:
raise ValueError(
"is_activated called on package that is not an extension.")
if self.extendee_spec.package.installed_upstream:
if self.extendee_spec.installed_upstream:
# If this extends an upstream package, it cannot be activated for
# it. This bypasses construction of the extension map, which can
# can fail when run in the context of a downstream Spack instance
@@ -1406,22 +1429,6 @@ def virtuals_provided(self):
return [vspec for vspec, constraints in self.provided.items()
if any(self.spec.satisfies(c) for c in constraints)]
@property
def installed(self):
"""Installation status of a package.
Returns:
True if the package has been installed, False otherwise.
"""
try:
# If the spec is in the DB, check the installed
# attribute of the record
return spack.store.db.get_record(self.spec).installed
except KeyError:
# If the spec is not in the DB, the method
# above raises a Key error
return False
@property
def prefix(self):
"""Get the prefix into which this package should be installed."""
@@ -1670,39 +1677,65 @@ def all_patches(cls):
return patches
def content_hash(self, content=None):
"""Create a hash based on the sources and logic used to build the
package. This includes the contents of all applied patches and the
contents of applicable functions in the package subclass."""
if not self.spec.concrete:
err_msg = ("Cannot invoke content_hash on a package"
" if the associated spec is not concrete")
raise spack.error.SpackError(err_msg)
"""Create a hash based on the artifacts and patches used to build this package.
hash_content = list()
try:
source_id = fs.for_package_version(self, self.version).source_id()
except fs.ExtrapolationError:
source_id = None
if not source_id:
# TODO? in cases where a digest or source_id isn't available,
# should this attempt to download the source and set one? This
# probably only happens for source repositories which are
# referenced by branch name rather than tag or commit ID.
env = spack.environment.active_environment()
from_local_sources = env and env.is_develop(self.spec)
if not self.spec.external and not from_local_sources:
message = 'Missing a source id for {s.name}@{s.version}'
tty.warn(message.format(s=self))
hash_content.append(''.encode('utf-8'))
else:
hash_content.append(source_id.encode('utf-8'))
hash_content.extend(':'.join((p.sha256, str(p.level))).encode('utf-8')
for p in self.spec.patches)
This includes:
* source artifacts (tarballs, repositories) used to build;
* content hashes (``sha256``'s) of all patches applied by Spack; and
* canonicalized contents the ``package.py`` recipe used to build.
This hash is only included in Spack's DAG hash for concrete specs, but if it
happens to be called on a package with an abstract spec, only applicable (i.e.,
determinable) portions of the hash will be included.
"""
# list of components to make up the hash
hash_content = []
# source artifacts/repositories
# TODO: resources
if self.spec.versions.concrete:
try:
source_id = fs.for_package_version(self, self.version).source_id()
except (fs.ExtrapolationError, fs.InvalidArgsError):
# ExtrapolationError happens if the package has no fetchers defined.
# InvalidArgsError happens when there are version directives with args,
# but none of them identifies an actual fetcher.
source_id = None
if not source_id:
# TODO? in cases where a digest or source_id isn't available,
# should this attempt to download the source and set one? This
# probably only happens for source repositories which are
# referenced by branch name rather than tag or commit ID.
env = spack.environment.active_environment()
from_local_sources = env and env.is_develop(self.spec)
if not self.spec.external and not from_local_sources:
message = 'Missing a source id for {s.name}@{s.version}'
tty.warn(message.format(s=self))
hash_content.append(''.encode('utf-8'))
else:
hash_content.append(source_id.encode('utf-8'))
# patch sha256's
# Only include these if they've been assigned by the concretizer.
# We check spec._patches_assigned instead of spec.concrete because
# we have to call package_hash *before* marking specs concrete
if self.spec._patches_assigned():
hash_content.extend(
':'.join((p.sha256, str(p.level))).encode('utf-8')
for p in self.spec.patches
)
# package.py contents
hash_content.append(package_hash(self.spec, source=content).encode('utf-8'))
# put it all together and encode as base32
b32_hash = base64.b32encode(
hashlib.sha256(bytes().join(
sorted(hash_content))).digest()).lower()
hashlib.sha256(
bytes().join(sorted(hash_content))
).digest()
).lower()
# convert from bytes if running python 3
if sys.version_info[0] >= 3:
@@ -1926,6 +1959,33 @@ def cache_extra_test_sources(self, srcs):
fsys.mkdirp(os.path.dirname(dest_path))
fsys.copy(src_path, dest_path)
@contextlib.contextmanager
def _setup_test(self, verbose, externals):
self.test_failures = []
if self.test_suite:
self.test_log_file = self.test_suite.log_file_for_spec(self.spec)
self.tested_file = self.test_suite.tested_file_for_spec(self.spec)
pkg_id = self.test_suite.test_pkg_id(self.spec)
else:
self.test_log_file = fsys.join_path(
self.stage.path, _spack_install_test_log)
pkg_id = self.spec.format('{name}-{version}-{hash:7}')
fsys.touch(self.test_log_file) # Otherwise log_parse complains
with tty.log.log_output(self.test_log_file, verbose) as logger:
with logger.force_echo():
tty.msg('Testing package {0}'.format(pkg_id))
# use debug print levels for log file to record commands
old_debug = tty.is_debug()
tty.set_debug(True)
try:
yield logger
finally:
# reset debug level
tty.set_debug(old_debug)
def do_test(self, dirty=False, externals=False):
if self.test_requires_compiler:
compilers = spack.compilers.compilers_for_spec(
@@ -1937,19 +1997,14 @@ def do_test(self, dirty=False, externals=False):
self.spec.compiler)
return
# Clear test failures
self.test_failures = []
self.test_log_file = self.test_suite.log_file_for_spec(self.spec)
self.tested_file = self.test_suite.tested_file_for_spec(self.spec)
fsys.touch(self.test_log_file) # Otherwise log_parse complains
kwargs = {
'dirty': dirty, 'fake': False, 'context': 'test',
'externals': externals
}
if tty.is_verbose():
kwargs['verbose'] = True
spack.build_environment.start_build_process(self, test_process, kwargs)
spack.build_environment.start_build_process(
self, test_process, kwargs)
def test(self):
# Defer tests to virtual and concrete packages
@@ -2143,21 +2198,21 @@ def build_log_path(self):
to the staging build file until the software is successfully installed,
when it points to the file in the installation directory.
"""
return self.install_log_path if self.installed else self.log_path
return self.install_log_path if self.spec.installed else self.log_path
@classmethod
def inject_flags(cls, name, flags):
"""
flag_handler that injects all flags through the compiler wrapper.
"""
return (flags, None, None)
return flags, None, None
@classmethod
def env_flags(cls, name, flags):
"""
flag_handler that adds all flags to canonical environment variables.
"""
return (None, flags, None)
return None, flags, None
@classmethod
def build_system_flags(cls, name, flags):
@@ -2168,7 +2223,7 @@ def build_system_flags(cls, name, flags):
implements it. Currently, AutotoolsPackage and CMakePackage
implement it.
"""
return (None, None, flags)
return None, None, flags
def setup_build_environment(self, env):
"""Sets up the build environment for a package.
@@ -2323,7 +2378,11 @@ def uninstall_by_spec(spec, force=False, deprecator=None):
if not force:
dependents = spack.store.db.installed_relatives(
spec, 'parents', True)
spec,
direction='parents',
transitive=True,
deptype=("link", "run"),
)
if dependents:
raise PackageStillNeededError(spec, dependents)
@@ -2465,10 +2524,10 @@ def _sanity_check_extension(self):
extendee_package = self.extendee_spec.package
extendee_package._check_extendable()
if not extendee_package.installed:
if not self.extendee_spec.installed:
raise ActivationError(
"Can only (de)activate extensions for installed packages.")
if not self.installed:
if not self.spec.installed:
raise ActivationError("Extensions must first be installed.")
if self.extendee_spec.name not in self.extendees:
raise ActivationError("%s does not extend %s!" %
@@ -2694,45 +2753,54 @@ def rpath_args(self):
"""
return " ".join("-Wl,-rpath,%s" % p for p in self.rpath)
def _run_test_callbacks(self, method_names, callback_type='install'):
"""Tries to call all of the listed methods, returning immediately
if the list is None."""
if method_names is None:
return
fail_fast = spack.config.get('config:fail_fast', False)
with self._setup_test(verbose=False, externals=False) as logger:
# Report running each of the methods in the build log
print_test_message(
logger, 'Running {0}-time tests'.format(callback_type), True)
for name in method_names:
try:
fn = getattr(self, name)
msg = 'RUN-TESTS: {0}-time tests [{1}]' \
.format(callback_type, name),
print_test_message(logger, msg, True)
fn()
except AttributeError as e:
msg = 'RUN-TESTS: method not implemented [{0}]' \
.format(name),
print_test_message(logger, msg, True)
self.test_failures.append((e, msg))
if fail_fast:
break
# Raise any collected failures here
if self.test_failures:
raise TestFailure(self.test_failures)
@on_package_attributes(run_tests=True)
def _run_default_build_time_test_callbacks(self):
"""Tries to call all the methods that are listed in the attribute
``build_time_test_callbacks`` if ``self.run_tests is True``.
If ``build_time_test_callbacks is None`` returns immediately.
"""
if self.build_time_test_callbacks is None:
return
for name in self.build_time_test_callbacks:
try:
fn = getattr(self, name)
except AttributeError:
msg = 'RUN-TESTS: method not implemented [{0}]'
tty.warn(msg.format(name))
else:
tty.msg('RUN-TESTS: build-time tests [{0}]'.format(name))
fn()
self._run_test_callbacks(self.build_time_test_callbacks, 'build')
@on_package_attributes(run_tests=True)
def _run_default_install_time_test_callbacks(self):
"""Tries to call all the methods that are listed in the attribute
``install_time_test_callbacks`` if ``self.run_tests is True``.
If ``install_time_test_callbacks is None`` returns immediately.
"""
if self.install_time_test_callbacks is None:
return
for name in self.install_time_test_callbacks:
try:
fn = getattr(self, name)
except AttributeError:
msg = 'RUN-TESTS: method not implemented [{0}]'
tty.warn(msg.format(name))
else:
tty.msg('RUN-TESTS: install-time tests [{0}]'.format(name))
fn()
self._run_test_callbacks(self.install_time_test_callbacks, 'install')
def has_test_method(pkg):
@@ -2757,27 +2825,21 @@ def has_test_method(pkg):
def print_test_message(logger, msg, verbose):
if verbose:
with logger.force_echo():
print(msg)
tty.msg(msg)
else:
print(msg)
tty.msg(msg)
def test_process(pkg, kwargs):
verbose = kwargs.get('verbose', False)
externals = kwargs.get('externals', False)
with tty.log.log_output(pkg.test_log_file, verbose) as logger:
with logger.force_echo():
tty.msg('Testing package {0}'
.format(pkg.test_suite.test_pkg_id(pkg.spec)))
with pkg._setup_test(verbose, externals) as logger:
if pkg.spec.external and not externals:
print_test_message(logger, 'Skipped external package', verbose)
print_test_message(
logger, 'Skipped tests for external package', verbose)
return
# use debug print levels for log file to record commands
old_debug = tty.is_debug()
tty.set_debug(True)
# run test methods from the package and all virtuals it
# provides virtuals have to be deduped by name
v_names = list(set([vspec.name
@@ -2796,8 +2858,7 @@ def test_process(pkg, kwargs):
ran_actual_test_function = False
try:
with fsys.working_dir(
pkg.test_suite.test_dir_for_spec(pkg.spec)):
with fsys.working_dir(pkg.test_suite.test_dir_for_spec(pkg.spec)):
for spec in test_specs:
pkg.test_suite.current_test_spec = spec
# Fail gracefully if a virtual has no package/tests
@@ -2839,7 +2900,9 @@ def test_process(pkg, kwargs):
# Run the tests
ran_actual_test_function = True
test_fn(pkg)
context = logger.force_echo if verbose else nullcontext
with context():
test_fn(pkg)
# If fail-fast was on, we error out above
# If we collect errors, raise them in batch here
@@ -2847,15 +2910,12 @@ def test_process(pkg, kwargs):
raise TestFailure(pkg.test_failures)
finally:
# reset debug level
tty.set_debug(old_debug)
# flag the package as having been tested (i.e., ran one or more
# non-pass-only methods
if ran_actual_test_function:
fsys.touch(pkg.tested_file)
else:
print_test_message(logger, 'No tests to run', verbose)
print_test_message(logger, 'No tests to run', verbose)
inject_flags = PackageBase.inject_flags

View File

@@ -123,11 +123,11 @@ def accept(self, id):
def next_token_error(self, message):
"""Raise an error about the next token in the stream."""
raise ParseError(message, self.text, self.token.end)
raise ParseError(message, self.text[0], self.token.end)
def last_token_error(self, message):
"""Raise an error about the previous token in the stream."""
raise ParseError(message, self.text, self.token.start)
raise ParseError(message, self.text[0], self.token.start)
def unexpected_token(self):
self.next_token_error("Unexpected token: '%s'" % self.next.value)

View File

@@ -43,8 +43,12 @@
hooks_path = os.path.join(module_path, "hooks")
opt_path = os.path.join(prefix, "opt")
share_path = os.path.join(prefix, "share", "spack")
etc_path = os.path.join(prefix, "etc")
etc_path = os.path.join(prefix, "etc", "spack")
#
# Things in $spack/etc/spack
#
default_license_dir = os.path.join(etc_path, "licenses")
#
# Things in $spack/var/spack

View File

@@ -25,6 +25,7 @@
from spack.build_systems.cuda import CudaPackage
from spack.build_systems.gnu import GNUMirrorPackage
from spack.build_systems.intel import IntelPackage
from spack.build_systems.lua import LuaPackage
from spack.build_systems.makefile import MakefilePackage
from spack.build_systems.maven import MavenPackage
from spack.build_systems.meson import MesonPackage

View File

@@ -355,9 +355,17 @@ def list_packages(rev):
ref = rev.replace('...', '')
rev = git('merge-base', ref, 'HEAD', output=str).strip()
output = git('ls-tree', '--name-only', rev, output=str)
return sorted(line for line in output.split('\n')
if line and not line.startswith('.'))
output = git('ls-tree', '-r', '--name-only', rev, output=str)
# recursively list the packages directory
package_paths = [
line.split(os.sep) for line in output.split("\n") if line.endswith("package.py")
]
# take the directory names with one-level-deep package files
package_names = sorted(set([line[0] for line in package_paths if len(line) == 2]))
return package_names
def diff_packages(rev1, rev2):

View File

@@ -112,8 +112,7 @@ def __enter__(self):
# Check which specs are already installed and mark them as skipped
# only for install_task
if self.do_fn == '_install_task':
for dep in filter(lambda x: x.package.installed,
input_spec.traverse()):
for dep in filter(lambda x: x.installed, input_spec.traverse()):
package = {
'name': dep.name,
'id': dep.dag_hash(),
@@ -140,7 +139,7 @@ def wrapper(instance, *args, **kwargs):
raise Exception
# We accounted before for what is already installed
installed_already = pkg.installed
installed_already = pkg.spec.installed
package = {
'name': pkg.name,

View File

@@ -38,13 +38,13 @@ def rewire(spliced_spec):
nodes in the DAG of that spec."""
assert spliced_spec.spliced
for spec in spliced_spec.traverse(order='post', root=True):
if not spec.build_spec.package.installed:
if not spec.build_spec.installed:
# TODO: May want to change this at least for the root spec...
# spec.build_spec.package.do_install(force=True)
raise PackageNotInstalledError(spliced_spec,
spec.build_spec,
spec)
if spec.build_spec is not spec and not spec.package.installed:
if spec.build_spec is not spec and not spec.installed:
explicit = spec is spliced_spec
rewire_node(spec, explicit)
@@ -95,7 +95,8 @@ def rewire_node(spec, explicit):
spec.prefix)
relocate.relocate_text_bin(binaries=bins_to_relocate,
prefixes=prefix_to_prefix)
# copy package into place (shutil.copytree)
# Copy package into place, except for spec.json (because spec.json
# describes the old spec and not the new spliced spec).
shutil.copytree(os.path.join(tempdir, spec.dag_hash()), spec.prefix,
ignore=shutil.ignore_patterns('spec.json',
'install_manifest.json'))
@@ -104,7 +105,10 @@ def rewire_node(spec, explicit):
spec.build_spec.prefix,
spec.prefix)
shutil.rmtree(tempdir)
# handle all metadata changes; don't copy over spec.json file in .spack/
# Above, we did not copy spec.json: instead, here we write the new
# (spliced) spec into spec.json, without this, Database.add would fail on
# the next line (because it checks the spec.json in the prefix against the
# spec being added to look for mismatches)
spack.store.layout.write_spec(spec, spack.store.layout.spec_file_path(spec))
# add to database, not sure about explicit
spack.store.db.add(spec, spack.store.layout, explicit=explicit)

View File

@@ -4,6 +4,8 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""This module contains jsonschema files for all of Spack's YAML formats."""
import warnings
import six
import llnl.util.lang
@@ -49,10 +51,12 @@ def _deprecated_properties(validator, deprecated, instance, schema):
msg = msg_str_or_func.format(properties=deprecated_properties)
else:
msg = msg_str_or_func(instance, deprecated_properties)
if msg is None:
return
is_error = deprecated['error']
if not is_error:
llnl.util.tty.warn(msg)
warnings.warn(msg)
else:
import jsonschema
yield jsonschema.ValidationError(msg)

View File

@@ -15,6 +15,25 @@
'additionalProperties': False,
'properties': {
'reuse': {'type': 'boolean'},
'minimal': {'type': 'boolean'},
'targets': {
'type': 'object',
'properties': {
'host_compatible': {'type': 'boolean'},
'granularity': {
'type': 'string',
'enum': ['generic', 'microarchitectures']
}
}
},
'unify': {
'type': 'boolean'
# Todo: add when_possible.
# 'oneOf': [
# {'type': 'boolean'},
# {'type': 'string', 'enum': ['when_possible']}
# ]
}
}
}
}

View File

@@ -56,6 +56,7 @@
'type': 'array',
'items': {'type': 'string'}
},
'license_dir': {'type': 'string'},
'source_cache': {'type': 'string'},
'misc_cache': {'type': 'string'},
'connect_timeout': {'type': 'integer', 'minimum': 0},
@@ -90,7 +91,16 @@
'additional_external_search_paths': {
'type': 'array',
'items': {'type': 'string'}
}
},
'flags': {
'type': 'object',
'properties': {
'keep_werror': {
'type': 'string',
'enum': ['all', 'specific', 'none'],
},
},
},
},
'deprecatedProperties': {
'properties': ['module_roots'],

View File

@@ -0,0 +1,131 @@
# Copyright 2013-2022 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)
"""Schema for Cray descriptive manifest: this describes a set of
installed packages on the system and also specifies dependency
relationships between them (so this provides more information than
external entries in packages configuration).
This does not specify a configuration - it is an input format
that is consumed and transformed into Spack DB records.
"""
schema = {
"$schema": "http://json-schema.org/schema#",
"title": "CPE manifest schema",
"type": "object",
"additionalProperties": False,
"properties": {
"_meta": {
"type": "object",
"additionalProperties": False,
"properties": {
"file-type": {"type": "string", "minLength": 1},
"cpe-version": {"type": "string", "minLength": 1},
"system-type": {"type": "string", "minLength": 1},
"schema-version": {"type": "string", "minLength": 1},
}
},
"compilers": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": False,
"properties": {
"name": {"type": "string", "minLength": 1},
"version": {"type": "string", "minLength": 1},
"prefix": {"type": "string", "minLength": 1},
"executables": {
"type": "object",
"additionalProperties": False,
"properties": {
"cc": {"type": "string", "minLength": 1},
"cxx": {"type": "string", "minLength": 1},
"fc": {"type": "string", "minLength": 1}
}
},
"arch": {
"type": "object",
"required": ["os", "target"],
"additionalProperties": False,
"properties": {
"os": {"type": "string", "minLength": 1},
"target": {"type": "string", "minLength": 1}
}
}
}
}
},
"specs": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"version",
"arch",
"compiler",
"prefix",
"hash"],
"additionalProperties": False,
"properties": {
"name": {"type": "string", "minLength": 1},
"version": {"type": "string", "minLength": 1},
"arch": {
"type": "object",
"required": ["platform", "platform_os", "target"],
"additioanlProperties": False,
"properties": {
"platform": {"type": "string", "minLength": 1},
"platform_os": {"type": "string", "minLength": 1},
"target": {
"type": "object",
"additionalProperties": False,
"required": ["name"],
"properties": {
"name": {"type": "string", "minLength": 1}
}
}
}
},
"compiler": {
"type": "object",
"required": ["name", "version"],
"additionalProperties": False,
"properties": {
"name": {"type": "string", "minLength": 1},
"version": {"type": "string", "minLength": 1}
}
},
"dependencies": {
"type": "object",
"patternProperties": {
"\\w[\\w-]*": {
"type": "object",
"required": ["hash"],
"additionalProperties": False,
"properties": {
"hash": {"type": "string", "minLength": 1},
"type": {
"type": "array",
"items": {
"type": "string", "minLength": 1}
}
}
}
}
},
"prefix": {
"type": "string", "minLength": 1},
"rpm": {"type": "string", "minLength": 1},
"hash": {"type": "string", "minLength": 1},
"parameters": {
"type": "object",
}
}
}
}
}
}

View File

@@ -16,6 +16,24 @@
import spack.schema.packages
import spack.schema.projections
warned_about_concretization = False
def deprecate_concretization(instance, props):
global warned_about_concretization
if warned_about_concretization:
return None
# Deprecate `spack:concretization` in favor of `spack:concretizer:unify`.
concretization_to_unify = {'together': 'true', 'separately': 'false'}
concretization = instance['concretization']
unify = concretization_to_unify[concretization]
return (
'concretization:{} is deprecated and will be removed in Spack 0.19 in favor of '
'the new concretizer:unify:{} config option.'.format(concretization, unify)
)
#: legal first keys in the schema
keys = ('spack', 'env')
@@ -61,6 +79,11 @@
'type': 'object',
'default': {},
'additionalProperties': False,
'deprecatedProperties': {
'properties': ['concretization'],
'message': deprecate_concretization,
'error': False
},
'properties': union_dicts(
# merged configuration scope schemas
spack.schema.merged.properties,
@@ -169,11 +192,33 @@ def update(data):
Returns:
True if data was changed, False otherwise
"""
updated = False
if 'include' in data:
msg = ("included configuration files should be updated manually"
" [files={0}]")
warnings.warn(msg.format(', '.join(data['include'])))
if 'packages' in data:
return spack.schema.packages.update(data['packages'])
return False
updated |= spack.schema.packages.update(data['packages'])
# Spack 0.19 drops support for `spack:concretization` in favor of
# `spack:concretizer:unify`. Here we provide an upgrade path that changes the former
# into the latter, or warns when there's an ambiguity. Note that Spack 0.17 is not
# forward compatible with `spack:concretizer:unify`.
if 'concretization' in data:
has_unify = 'unify' in data.get('concretizer', {})
to_unify = {'together': True, 'separately': False}
unify = to_unify[data['concretization']]
if has_unify and data['concretizer']['unify'] != unify:
warnings.warn(
'The following configuration conflicts: '
'`spack:concretization:{}` and `spack:concretizer:unify:{}`'
'. Please update manually.'.format(
data['concretization'], data['concretizer']['unify']))
else:
data.update({'concretizer': {'unify': unify}})
data.pop('concretization')
updated = True
return updated

View File

@@ -13,6 +13,7 @@
import spack.schema.bootstrap
import spack.schema.cdash
import spack.schema.compilers
import spack.schema.concretizer
import spack.schema.config
import spack.schema.container
import spack.schema.gitlab_ci
@@ -27,6 +28,7 @@
spack.schema.bootstrap.properties,
spack.schema.cdash.properties,
spack.schema.compilers.properties,
spack.schema.concretizer.properties,
spack.schema.config.properties,
spack.schema.container.properties,
spack.schema.gitlab_ci.properties,

View File

@@ -110,9 +110,12 @@
'properties': {
'name': {'type': 'string'},
'hash': {'type': 'string'},
'package_hash': {'type': 'string'},
# these hashes were used on some specs prior to 0.18
'full_hash': {'type': 'string'},
'build_hash': {'type': 'string'},
'package_hash': {'type': 'string'},
'version': {
'oneOf': [
{'type': 'string'},

View File

@@ -9,6 +9,7 @@
import itertools
import os
import pprint
import re
import types
import warnings
@@ -55,14 +56,6 @@
parse_files = None
#: whether we should write ASP unsat cores quickly in debug mode when the cores
#: may be very large or take the time (sometimes hours) to minimize them
minimize_cores = True
#: whether we should include all facts in the unsat cores or only error messages
full_cores = False
# backward compatibility functions for clingo ASTs
def ast_getter(*names):
def getter(node):
@@ -77,20 +70,25 @@ def getter(node):
ast_type = ast_getter("ast_type", "type")
ast_sym = ast_getter("symbol", "term")
#: Order of precedence for version origins. Topmost types are preferred.
version_origin_fields = [
'spec',
'external',
'packages_yaml',
'package_py',
'installed',
]
#: Look up version precedence strings by enum id
version_origin_str = {
i: name for i, name in enumerate(version_origin_fields)
}
#: Enumeration like object to mark version provenance
version_provenance = collections.namedtuple( # type: ignore
'VersionProvenance', ['external', 'packages_yaml', 'package_py', 'spec']
)(spec=0, external=1, packages_yaml=2, package_py=3)
#: String representation of version origins, to emit legible
# facts for the ASP solver
version_origin_str = {
0: 'spec',
1: 'external',
2: 'packages_yaml',
3: 'package_py'
}
'VersionProvenance',
version_origin_fields,
)(**{name: i for i, name in enumerate(version_origin_fields)})
#: Named tuple to contain information on declared versions
DeclaredVersion = collections.namedtuple(
@@ -109,7 +107,7 @@ def getter(node):
def build_criteria_names(costs, tuples):
"""Construct an ordered mapping from criteria names to indices in the cost list."""
"""Construct an ordered mapping from criteria names to costs."""
# pull optimization criteria names out of the solution
priorities_names = []
@@ -136,7 +134,10 @@ def build_criteria_names(costs, tuples):
# sort the criteria by priority
priorities_names = sorted(priorities_names, reverse=True)
assert len(priorities_names) == len(costs), "Wrong number of optimization criteria!"
# We only have opt-criterion values for non-error types
# error type criteria are excluded (they come first)
error_criteria = len(costs) - len(priorities_names)
costs = costs[error_criteria:]
# split list into three parts: build criteria, fixed criteria, non-build criteria
num_criteria = len(priorities_names)
@@ -149,12 +150,12 @@ def build_criteria_names(costs, tuples):
# mapping from priority to index in cost list
indices = dict((p, i) for i, (p, n) in enumerate(priorities_names))
# make a list that has each name with its build and non-build priority
# make a list that has each name with its build and non-build costs
criteria = [
(p - fixed_priority_offset + num_build, None, name) for p, name in fixed
(costs[p - fixed_priority_offset + num_build], None, name) for p, name in fixed
]
for (i, name), (b, _) in zip(installed, build):
criteria.append((indices[i], indices[b], name))
criteria.append((costs[indices[i]], costs[indices[b]], name))
return criteria
@@ -326,9 +327,6 @@ def format_core(self, core):
core_symbols = []
for atom in core:
sym = symbols[atom]
if sym.name in ("rule", "error"):
# these are special symbols we use to get messages in the core
sym = sym.arguments[0].string
core_symbols.append(sym)
return sorted(str(symbol) for symbol in core_symbols)
@@ -387,7 +385,7 @@ def raise_if_unsat(self):
"""
Raise an appropriate error if the result is unsatisfiable.
The error is a UnsatisfiableSpecError, and includes the minimized cores
The error is an InternalConcretizerError, and includes the minimized cores
resulting from the solve, formatted to be human readable.
"""
if self.satisfiable:
@@ -397,12 +395,8 @@ def raise_if_unsat(self):
if len(constraints) == 1:
constraints = constraints[0]
if minimize_cores:
conflicts = self.format_minimal_cores()
else:
conflicts = self.format_cores()
raise UnsatisfiableSpecError(constraints, conflicts=conflicts)
conflicts = self.format_minimal_cores()
raise InternalConcretizerError(constraints, conflicts=conflicts)
@property
def specs(self):
@@ -502,13 +496,11 @@ def h2(self, name):
def newline(self):
self.out.write('\n')
def fact(self, head, assumption=False):
def fact(self, head):
"""ASP fact (a rule without a body).
Arguments:
head (AspFunction): ASP function to generate as fact
assumption (bool): If True and using cores, use this fact as a
choice point in ASP and include it in unsatisfiable cores
"""
symbol = head.symbol() if hasattr(head, 'symbol') else head
@@ -516,10 +508,9 @@ def fact(self, head, assumption=False):
atom = self.backend.add_atom(symbol)
# with `--show-cores=full or --show-cores=minimized, make all facts
# choices/assumptions, otherwise only if assumption=True
choice = self.cores and (full_cores or assumption)
# Only functions relevant for constructing bug reports for bad error messages
# are assumptions, and only when using cores.
choice = self.cores and symbol.name == 'internal_error'
self.backend.add_rule([atom], [], choice=choice)
if choice:
self.assumptions.append(atom)
@@ -577,9 +568,10 @@ def visit(node):
for term in node.body:
if ast_type(term) == ASTType.Literal:
if ast_type(term.atom) == ASTType.SymbolicAtom:
if ast_sym(term.atom).name == "error":
name = ast_sym(term.atom).name
if name == 'internal_error':
arg = ast_sym(ast_sym(term.atom).arguments[0])
self.fact(fn.error(arg.string), assumption=True)
self.fact(AspFunction(name)(arg.string))
path = os.path.join(parent_dir, 'concretize.lp')
parse_files([path], visit)
@@ -662,7 +654,7 @@ def stringify(x):
class SpackSolverSetup(object):
"""Class to set up and run a Spack concretization solve."""
def __init__(self, reuse=False, tests=False):
def __init__(self, reuse=None, minimal=None, tests=False):
self.gen = None # set by setup()
self.declared_versions = {}
@@ -687,24 +679,22 @@ def __init__(self, reuse=False, tests=False):
# Caches to optimize the setup phase of the solver
self.target_specs_cache = None
# whether to add installed/binary hashes to the solve
self.reuse = reuse
# whether to add installed/binary hashes to the solve
# Solver paramters that affect setup -- see Solver documentation
self.reuse = spack.config.get(
"concretizer:reuse", False) if reuse is None else reuse
self.minimal = spack.config.get(
"concretizer:minimal", False) if minimal is None else minimal
self.tests = tests
def pkg_version_rules(self, pkg):
"""Output declared versions of a package.
This uses self.possible_versions so that we include any versions
This uses self.declared_versions so that we include any versions
that arise from a spec.
"""
def key_fn(version):
# Origins are sorted by order of importance:
# 1. Spec from command line
# 2. Externals
# 3. Package preferences
# 4. Directives in package.py
# Origins are sorted by precedence defined in `version_origin_str`,
# then by order added.
return version.origin, version.idx
pkg = packagize(pkg)
@@ -735,7 +725,7 @@ def spec_versions(self, spec):
# record all version constraints for later
self.version_constraints.add((spec.name, spec.versions))
return [fn.version_satisfies(spec.name, spec.versions)]
return [fn.node_version_satisfies(spec.name, spec.versions)]
def target_ranges(self, spec, single_target_fn):
target = spec.architecture.target
@@ -748,13 +738,24 @@ def target_ranges(self, spec, single_target_fn):
return [fn.node_target_satisfies(spec.name, target)]
def conflict_rules(self, pkg):
default_msg = "{0} '{1}' conflicts with '{2}'"
no_constraint_msg = "{0} conflicts with '{1}'"
for trigger, constraints in pkg.conflicts.items():
trigger_id = self.condition(spack.spec.Spec(trigger), name=pkg.name)
self.gen.fact(fn.conflict_trigger(trigger_id))
trigger_msg = "conflict trigger %s" % str(trigger)
trigger_id = self.condition(
spack.spec.Spec(trigger), name=pkg.name, msg=trigger_msg)
for constraint, _ in constraints:
constraint_id = self.condition(constraint, name=pkg.name)
self.gen.fact(fn.conflict(pkg.name, trigger_id, constraint_id))
for constraint, conflict_msg in constraints:
if conflict_msg is None:
if constraint == spack.spec.Spec():
conflict_msg = no_constraint_msg.format(pkg.name, trigger)
else:
conflict_msg = default_msg.format(pkg.name, trigger, constraint)
constraint_msg = "conflict constraint %s" % str(constraint)
constraint_id = self.condition(
constraint, name=pkg.name, msg=constraint_msg)
self.gen.fact(
fn.conflict(pkg.name, trigger_id, constraint_id, conflict_msg))
self.gen.newline()
def available_compilers(self):
@@ -827,7 +828,7 @@ def package_compiler_defaults(self, pkg):
pkg.name, cspec.name, cspec.version, -i * 100
))
def pkg_rules(self, pkg, tests):
def pkg_rules(self, pkg):
pkg = packagize(pkg)
# versions
@@ -838,9 +839,18 @@ def pkg_rules(self, pkg, tests):
for name, entry in sorted(pkg.variants.items()):
variant, when = entry
for w in when:
cond_id = self.condition(w, name=pkg.name)
self.gen.fact(fn.variant_condition(cond_id, pkg.name, name))
if spack.spec.Spec() in when:
# unconditional variant
self.gen.fact(fn.variant(pkg.name, name))
else:
# conditional variant
for w in when:
msg = "%s has variant %s" % (pkg.name, name)
if str(w):
msg += " when %s" % w
cond_id = self.condition(w, name=pkg.name, msg=msg)
self.gen.fact(fn.variant_condition(cond_id, pkg.name, name))
single_value = not variant.multi
if single_value:
@@ -883,7 +893,9 @@ def pkg_rules(self, pkg, tests):
imposed = spack.spec.Spec(value.when)
imposed.name = pkg.name
self.condition(
required_spec=required, imposed_spec=imposed, name=pkg.name
required_spec=required, imposed_spec=imposed, name=pkg.name,
msg="%s variant %s value %s when %s" % (
pkg.name, name, value, when)
)
if variant.sticky:
@@ -911,7 +923,7 @@ def pkg_rules(self, pkg, tests):
)
)
def condition(self, required_spec, imposed_spec=None, name=None):
def condition(self, required_spec, imposed_spec=None, name=None, msg=None):
"""Generate facts for a dependency or virtual provider condition.
Arguments:
@@ -920,7 +932,7 @@ def condition(self, required_spec, imposed_spec=None, name=None):
are imposed when this condition is triggered
name (str or None): name for `required_spec` (required if
required_spec is anonymous, ignored if not)
msg (str or None): description of the condition
Returns:
int: id of the condition created by this function
"""
@@ -929,7 +941,7 @@ def condition(self, required_spec, imposed_spec=None, name=None):
assert named_cond.name, "must provide name for anonymous condtions!"
condition_id = next(self._condition_id_counter)
self.gen.fact(fn.condition(condition_id))
self.gen.fact(fn.condition(condition_id, msg))
# requirements trigger the condition
requirements = self.spec_clauses(
@@ -961,7 +973,8 @@ def package_provider_rules(self, pkg):
for provided, whens in pkg.provided.items():
for when in whens:
condition_id = self.condition(when, provided, pkg.name)
msg = '%s provides %s when %s' % (pkg.name, provided, when)
condition_id = self.condition(when, provided, pkg.name, msg)
self.gen.fact(fn.provider_condition(
condition_id, when.name, provided.name
))
@@ -985,7 +998,11 @@ def package_dependencies_rules(self, pkg):
if not deptypes:
continue
condition_id = self.condition(cond, dep.spec, pkg.name)
msg = '%s depends on %s' % (pkg.name, dep.spec.name)
if cond != spack.spec.Spec():
msg += ' when %s' % cond
condition_id = self.condition(cond, dep.spec, pkg.name, msg)
self.gen.fact(fn.dependency_condition(
condition_id, pkg.name, dep.spec.name
))
@@ -1065,7 +1082,8 @@ def external_packages(self):
# Declare external conditions with a local index into packages.yaml
for local_idx, spec in enumerate(external_specs):
condition_id = self.condition(spec)
msg = '%s available as external when satisfying %s' % (spec.name, spec)
condition_id = self.condition(spec, msg=msg)
self.gen.fact(
fn.possible_external(condition_id, pkg_name, local_idx)
)
@@ -1147,7 +1165,14 @@ def spec_clauses(self, *args, **kwargs):
raise RuntimeError(msg)
return clauses
def _spec_clauses(self, spec, body=False, transitive=True, expand_hashes=False):
def _spec_clauses(
self,
spec,
body=False,
transitive=True,
expand_hashes=False,
concrete_build_deps=False,
):
"""Return a list of clauses for a spec mandates are true.
Arguments:
@@ -1158,6 +1183,8 @@ def _spec_clauses(self, spec, body=False, transitive=True, expand_hashes=False):
dependencies (default True)
expand_hashes (bool): if True, descend into hashes of concrete specs
(default False)
concrete_build_deps (bool): if False, do not include pure build deps
of concrete specs (as they have no effect on runtime constraints)
Normally, if called with ``transitive=True``, ``spec_clauses()`` just generates
hashes for the dependency requirements of concrete specs. If ``expand_hashes``
@@ -1265,18 +1292,34 @@ class Body(object):
# add all clauses from dependencies
if transitive:
if spec.concrete:
# TODO: We need to distinguish 2 specs from the same package later
for edge in spec.edges_to_dependencies():
for dtype in edge.deptypes:
clauses.append(fn.depends_on(spec.name, edge.spec.name, dtype))
# TODO: Eventually distinguish 2 deps on the same pkg (build and link)
for dspec in spec.edges_to_dependencies():
dep = dspec.spec
for dep in spec.traverse(root=False):
if spec.concrete:
clauses.append(fn.hash(dep.name, dep.dag_hash()))
# We know dependencies are real for concrete specs. For abstract
# specs they just mean the dep is somehow in the DAG.
for dtype in dspec.deptypes:
# skip build dependencies of already-installed specs
if concrete_build_deps or dtype != "build":
clauses.append(fn.depends_on(spec.name, dep.name, dtype))
# imposing hash constraints for all but pure build deps of
# already-installed concrete specs.
if concrete_build_deps or dspec.deptypes != ("build",):
clauses.append(fn.hash(dep.name, dep.dag_hash()))
# if the spec is abstract, descend into dependencies.
# if it's concrete, then the hashes above take care of dependency
# constraints, but expand the hashes if asked for.
if not spec.concrete or expand_hashes:
clauses.extend(
self._spec_clauses(dep, body, transitive=False)
self._spec_clauses(
dep,
body=body,
expand_hashes=expand_hashes,
concrete_build_deps=concrete_build_deps,
)
)
return clauses
@@ -1411,23 +1454,48 @@ def target_defaults(self, specs):
self.gen.h2('Target compatibility')
compatible_targets = [uarch] + uarch.ancestors
additional_targets_in_family = sorted([
t for t in archspec.cpu.TARGETS.values()
if (t.family.name == uarch.family.name and
t not in compatible_targets)
], key=lambda x: len(x.ancestors), reverse=True)
compatible_targets += additional_targets_in_family
# Construct the list of targets which are compatible with the host
candidate_targets = [uarch] + uarch.ancestors
# Get configuration options
granularity = spack.config.get('concretizer:targets:granularity')
host_compatible = spack.config.get('concretizer:targets:host_compatible')
# Add targets which are not compatible with the current host
if not host_compatible:
additional_targets_in_family = sorted([
t for t in archspec.cpu.TARGETS.values()
if (t.family.name == uarch.family.name and
t not in candidate_targets)
], key=lambda x: len(x.ancestors), reverse=True)
candidate_targets += additional_targets_in_family
# Check if we want only generic architecture
if granularity == 'generic':
candidate_targets = [t for t in candidate_targets if t.vendor == 'generic']
compilers = self.possible_compilers
# this loop can be used to limit the number of targets
# considered. Right now we consider them all, but it seems that
# many targets can make things slow.
# TODO: investigate this.
# Add targets explicitly requested from specs
for spec in specs:
if not spec.architecture or not spec.architecture.target:
continue
target = archspec.cpu.TARGETS.get(spec.target.name)
if not target:
self.target_ranges(spec, None)
continue
if target not in candidate_targets and not host_compatible:
candidate_targets.append(target)
for ancestor in target.ancestors:
if ancestor not in candidate_targets:
candidate_targets.append(ancestor)
best_targets = set([uarch.family.name])
for compiler in sorted(compilers):
supported = self._supported_targets(
compiler.name, compiler.version, compatible_targets
compiler.name, compiler.version, candidate_targets
)
# If we can't find supported targets it may be due to custom
@@ -1440,7 +1508,7 @@ def target_defaults(self, specs):
supported = self._supported_targets(
compiler.name,
compiler_obj.real_version,
compatible_targets
candidate_targets
)
if not supported:
@@ -1456,21 +1524,8 @@ def target_defaults(self, specs):
compiler.name, compiler.version, uarch.family.name
))
# add any targets explicitly mentioned in specs
for spec in specs:
if not spec.architecture or not spec.architecture.target:
continue
target = archspec.cpu.TARGETS.get(spec.target.name)
if not target:
self.target_ranges(spec, None)
continue
if target not in compatible_targets:
compatible_targets.append(target)
i = 0
for target in compatible_targets:
for target in candidate_targets:
self.gen.fact(fn.target(target.name))
self.gen.fact(fn.target_family(target.name, target.family.name))
for parent in sorted(target.parents):
@@ -1512,9 +1567,12 @@ def generate_possible_compilers(self, specs):
continue
if strict and s.compiler not in cspecs:
raise spack.concretize.UnavailableCompilerVersionError(
s.compiler
)
if not s.concrete:
raise spack.concretize.UnavailableCompilerVersionError(
s.compiler
)
# Allow unknown compilers to exist if the associated spec
# is already built
else:
cspecs.add(s.compiler)
self.gen.fact(fn.allow_compiler(
@@ -1645,6 +1703,12 @@ def _facts_from_concrete_spec(self, spec, possible):
# be dependencies (don't tell it about the others)
h = spec.dag_hash()
if spec.name in possible and h not in self.seen_hashes:
try:
# Only consider installed packages for repo we know
spack.repo.path.get(spec)
except (spack.repo.UnknownNamespaceError, spack.repo.UnknownPackageError):
return
# this indicates that there is a spec like this installed
self.gen.fact(fn.installed_hash(spec.name, h))
@@ -1652,8 +1716,16 @@ def _facts_from_concrete_spec(self, spec, possible):
self.impose(h, spec, body=True)
self.gen.newline()
# add OS to possible OS's
# Declare as possible parts of specs that are not in package.py
# - Add versions to possible versions
# - Add OS to possible OS's
for dep in spec.traverse():
self.possible_versions[dep.name].add(dep.version)
self.declared_versions[dep.name].append(DeclaredVersion(
version=dep.version,
idx=0,
origin=version_provenance.installed
))
self.possible_oses.add(dep.os)
# add the hash to the one seen so far
@@ -1718,7 +1790,7 @@ def setup(self, driver, specs):
# Fail if we already know an unreachable node is requested
for spec in specs:
missing_deps = [d for d in spec.traverse()
missing_deps = [str(d) for d in spec.traverse()
if d.name not in possible and not d.virtual]
if missing_deps:
raise spack.spec.InvalidDependencyError(spec.name, missing_deps)
@@ -1738,10 +1810,14 @@ def setup(self, driver, specs):
self.gen.h1("Concrete input spec definitions")
self.define_concrete_input_specs(specs, possible)
self.gen.h1("Concretizer options")
if self.reuse:
self.gen.fact(fn.optimize_for_reuse())
if self.minimal:
self.gen.fact(fn.minimal_installs())
if self.reuse:
self.gen.h1("Installed packages")
self.gen.fact(fn.optimize_for_reuse())
self.gen.newline()
self.define_installed_packages(specs, possible)
self.gen.h1('General Constraints')
@@ -1762,7 +1838,7 @@ def setup(self, driver, specs):
self.gen.h1('Package Constraints')
for pkg in sorted(pkgs):
self.gen.h2('Package rules: %s' % pkg)
self.pkg_rules(pkg, tests=self.tests)
self.pkg_rules(pkg)
self.gen.h2('Package preferences: %s' % pkg)
self.preferred_variants(pkg)
self.preferred_targets(pkg)
@@ -1781,12 +1857,14 @@ def setup(self, driver, specs):
fn.virtual_root(spec.name) if spec.virtual
else fn.root(spec.name)
)
for clause in self.spec_clauses(spec):
self.gen.fact(clause)
if clause.name == 'variant_set':
self.gen.fact(fn.variant_default_value_from_cli(
*clause.args
))
self.gen.fact(
fn.variant_default_value_from_cli(*clause.args)
)
self.gen.h1("Variant Values defined in specs")
self.define_variant_values()
@@ -1809,6 +1887,7 @@ class SpecBuilder(object):
ignored_attributes = ["opt_criterion"]
def __init__(self, specs):
self._specs = {}
self._result = None
self._command_line_specs = specs
self._flag_sources = collections.defaultdict(lambda: set())
@@ -1861,6 +1940,17 @@ def node_os(self, pkg, os):
def node_target(self, pkg, target):
self._arch(pkg).target = target
def error(self, priority, msg, *args):
msg = msg.format(*args)
# For variant formatting, we sometimes have to construct specs
# to format values properly. Find/replace all occurances of
# Spec(...) with the string representation of the spec mentioned
specs_to_construct = re.findall(r'Spec\(([^)]*)\)', msg)
for spec_str in specs_to_construct:
msg = msg.replace('Spec(%s)' % spec_str, str(spack.spec.Spec(spec_str)))
raise UnsatisfiableSpecError(msg)
def variant_value(self, pkg, name, value):
# FIXME: is there a way not to special case 'dev_path' everywhere?
if name == 'dev_path':
@@ -1983,15 +2073,27 @@ def deprecated(self, pkg, version):
msg = 'using "{0}@{1}" which is a deprecated version'
tty.warn(msg.format(pkg, version))
@staticmethod
def sort_fn(function_tuple):
name = function_tuple[0]
if name == 'error':
priority = function_tuple[1][0]
return (-4, priority)
elif name == 'hash':
return (-3, 0)
elif name == 'node':
return (-2, 0)
elif name == 'node_compiler':
return (-1, 0)
else:
return (0, 0)
def build_specs(self, function_tuples):
# Functions don't seem to be in particular order in output. Sort
# them here so that directives that build objects (like node and
# node_compiler) are called in the right order.
function_tuples.sort(key=lambda f: {
"hash": -3,
"node": -2,
"node_compiler": -1,
}.get(f[0], 0))
self.function_tuples = function_tuples
self.function_tuples.sort(key=self.sort_fn)
self._specs = {}
for name, args in function_tuples:
@@ -1999,7 +2101,6 @@ def build_specs(self, function_tuples):
continue
action = getattr(self, name, None)
# print out unknown actions so we can display them for debugging
if not action:
msg = "%s(%s)" % (name, ", ".join(str(a) for a in args))
@@ -2009,22 +2110,26 @@ def build_specs(self, function_tuples):
assert action and callable(action)
# ignore predicates on virtual packages, as they're used for
# solving but don't construct anything
pkg = args[0]
if spack.repo.path.is_virtual(pkg):
continue
# solving but don't construct anything. Do not ignore error
# predicates on virtual packages.
if name != 'error':
pkg = args[0]
if spack.repo.path.is_virtual(pkg):
continue
# if we've already gotten a concrete spec for this pkg,
# do not bother calling actions on it.
spec = self._specs.get(pkg)
if spec and spec.concrete:
continue
# if we've already gotten a concrete spec for this pkg,
# do not bother calling actions on it.
spec = self._specs.get(pkg)
if spec and spec.concrete:
continue
action(*args)
# namespace assignment is done after the fact, as it is not
# currently part of the solve
for spec in self._specs.values():
if spec.namespace:
continue
repo = spack.repo.path.repo_for_pkg(spec)
spec.namespace = repo.namespace
@@ -2034,7 +2139,7 @@ def build_specs(self, function_tuples):
# inject patches -- note that we' can't use set() to unique the
# roots here, because the specs aren't complete, and the hash
# function will loop forever.
roots = [spec.root for spec in self._specs.values()]
roots = [spec.root for spec in self._specs.values() if not spec.root.installed]
roots = dict((id(r), r) for r in roots)
for root in roots.values():
spack.spec.Spec.inject_patches_variant(root)
@@ -2046,8 +2151,9 @@ def build_specs(self, function_tuples):
for s in self._specs.values():
_develop_specs_from_env(s, ev.active_environment())
for s in self._specs.values():
s._mark_concrete()
# mark concrete and assign hashes to all specs in the solve
for root in roots.values():
root._finalize_concretization()
for s in self._specs.values():
spack.spec.Spec.ensure_no_deprecated(s)
@@ -2090,6 +2196,10 @@ class Solver(object):
``reuse (bool)``
Whether to try to reuse existing installs/binaries
``minimal (bool)``
If ``True`` make minimizing nodes the top priority, even higher
than defaults from packages and preferences.
"""
def __init__(self):
self.driver = PyclingoDriver()
@@ -2097,6 +2207,7 @@ def __init__(self):
# These properties are settable via spack configuration, and overridable
# by setting them directly as properties.
self.reuse = spack.config.get("concretizer:reuse", False)
self.minimal = spack.config.get("concretizer:minimal", False)
def solve(
self,
@@ -2127,7 +2238,7 @@ def solve(
continue
spack.spec.Spec.ensure_valid_variants(s)
setup = SpackSolverSetup(reuse=self.reuse, tests=tests)
setup = SpackSolverSetup(reuse=self.reuse, minimal=self.minimal, tests=tests)
return self.driver.solve(
setup,
specs,
@@ -2140,25 +2251,27 @@ def solve(
class UnsatisfiableSpecError(spack.error.UnsatisfiableSpecError):
"""
Subclass for new constructor signature for new concretizer
"""
def __init__(self, msg):
super(spack.error.UnsatisfiableSpecError, self).__init__(msg)
self.provided = None
self.required = None
self.constraint_type = None
class InternalConcretizerError(spack.error.UnsatisfiableSpecError):
"""
Subclass for new constructor signature for new concretizer
"""
def __init__(self, provided, conflicts):
indented = [' %s\n' % conflict for conflict in conflicts]
conflict_msg = ''.join(indented)
issue = 'conflicts' if full_cores else 'errors'
msg = '%s is unsatisfiable, %s are:\n%s' % (provided, issue, conflict_msg)
newline_indent = '\n '
if not full_cores:
msg += newline_indent + 'To see full clingo unsat cores, '
msg += 're-run with `spack --show-cores=full`'
if not minimize_cores or not full_cores:
# not solver.minimalize_cores and not solver.full_cores impossible
msg += newline_indent + 'For full, subset-minimal unsat cores, '
msg += 're-run with `spack --show-cores=minimized'
msg += newline_indent
msg += 'Warning: This may take (up to) hours for some specs'
error_msg = ''.join(indented)
msg = 'Spack concretizer internal error. Please submit a bug report'
msg += '\n Please include the command, environment if applicable,'
msg += '\n and the following error message.'
msg = '\n %s is unsatisfiable, errors are:\n%s' % (provided, error_msg)
super(spack.error.UnsatisfiableSpecError, self).__init__(msg)

View File

@@ -7,22 +7,6 @@
% This logic program implements Spack's concretizer
%=============================================================================
%-----------------------------------------------------------------------------
% Generic constraints on nodes
%-----------------------------------------------------------------------------
% each node must have a single version
:- not 1 { version(Package, _) } 1, node(Package).
% each node must have a single platform, os and target
:- not 1 { node_platform(Package, _) } 1, node(Package), error("A node must have exactly one platform").
:- not 1 { node_os(Package, _) } 1, node(Package).
:- not 1 { node_target(Package, _) } 1, node(Package).
% each node has a single compiler associated with it
:- not 1 { node_compiler(Package, _) } 1, node(Package).
:- not 1 { node_compiler_version(Package, _, _) } 1, node(Package).
%-----------------------------------------------------------------------------
% Version semantics
%-----------------------------------------------------------------------------
@@ -35,18 +19,40 @@ version_declared(Package, Version, Weight) :- version_declared(Package, Version,
:- version_declared(Package, Version, Weight, Origin1),
version_declared(Package, Version, Weight, Origin2),
Origin1 < Origin2,
error("Internal error: two versions with identical weights").
internal_error("Two versions with identical weights").
% We cannot use a version declared for an installed package if we end up building it
:- version_declared(Package, Version, Weight, "installed"),
version(Package, Version),
version_weight(Package, Weight),
not hash(Package, _).
% versions are declared w/priority -- declared with priority implies declared
version_declared(Package, Version) :- version_declared(Package, Version, _).
% If something is a package, it has only one version and that must be a
% declared version.
1 { version(Package, Version) : version_declared(Package, Version) } 1
:- node(Package), error("Each node must have exactly one version").
% We allow clingo to choose any version(s), and infer an error if there
% is not precisely one version chosen. Error facts are heavily optimized
% against to ensure they cannot be inferred when a non-error solution is
% possible
{ version(Package, Version) : version_declared(Package, Version) }
:- node(Package).
error(2, "No version for '{0}' satisfies '@{1}' and '@{2}'", Package, Version1, Version2)
:- node(Package),
version(Package, Version1),
version(Package, Version2),
Version1 < Version2. % see[1]
% A virtual package may have or not a version, but never has more than one
:- virtual_node(Package), 2 { version(Package, _) }.
error(2, "No versions available for package '{0}'", Package)
:- node(Package), not version(Package, _).
% A virtual package may or may not have a version, but never has more than one
error(2, "No version for '{0}' satisfies '@{1}' and '@{2}'", Virtual, Version1, Version2)
:- virtual_node(Virtual),
version(Virtual, Version1),
version(Virtual, Version2),
Version1 < Version2. % see[1]
% If we select a deprecated version, mark the package as deprecated
deprecated(Package, Version) :- version(Package, Version), deprecated_version(Package, Version).
@@ -55,14 +61,27 @@ possible_version_weight(Package, Weight)
:- version(Package, Version),
version_declared(Package, Version, Weight).
1 { version_weight(Package, Weight) : possible_version_weight(Package, Weight) } 1 :- node(Package), error("Internal error: Package version must have a unique weight").
version_weight(Package, Weight)
:- version(Package, Version),
node(Package),
Weight = #min{W : version_declared(Package, Version, W)}.
% version_satisfies implies that exactly one of the satisfying versions
% node_version_satisfies implies that exactly one of the satisfying versions
% is the package's version, and vice versa.
1 { version(Package, Version) : version_satisfies(Package, Constraint, Version) } 1
:- version_satisfies(Package, Constraint),
error("no version satisfies the given constraints").
version_satisfies(Package, Constraint)
% While this choice rule appears redundant with the initial choice rule for
% versions, virtual nodes with version constraints require this rule to be
% able to choose versions
{ version(Package, Version) : version_satisfies(Package, Constraint, Version) }
:- node_version_satisfies(Package, Constraint).
% More specific error message if the version cannot satisfy some constraint
% Otherwise covered by `no_version_error` and `versions_conflict_error`.
error(1, "No valid version for '{0}' satisfies '@{1}'", Package, Constraint)
:- node_version_satisfies(Package, Constraint),
C = #count{ Version : version(Package, Version), version_satisfies(Package, Constraint, Version)},
C < 1.
node_version_satisfies(Package, Constraint)
:- version(Package, Version), version_satisfies(Package, Constraint, Version).
#defined version_satisfies/3.
@@ -81,7 +100,7 @@ version_satisfies(Package, Constraint)
% conditions are specified with `condition_requirement` and hold when
% corresponding spec attributes hold.
condition_holds(ID) :-
condition(ID);
condition(ID, _);
attr(Name, A1) : condition_requirement(ID, Name, A1);
attr(Name, A1, A2) : condition_requirement(ID, Name, A1, A2);
attr(Name, A1, A2, A3) : condition_requirement(ID, Name, A1, A2, A3).
@@ -100,7 +119,12 @@ attr(Name, A1, A2, A3) :- impose(ID), imposed_constraint(ID, Name, A1, A2, A3).
variant_value(Package, Variant, Value),
not imposed_constraint(Hash, "variant_value", Package, Variant, Value).
#defined condition/1.
% we cannot have additional flag values when we are working with concrete specs
:- node(Package), hash(Package, Hash),
node_flag(Package, FlagType, Flag),
not imposed_constraint(Hash, "node_flag", Package, FlagType, Flag).
#defined condition/2.
#defined condition_requirement/3.
#defined condition_requirement/4.
#defined condition_requirement/5.
@@ -127,9 +151,9 @@ depends_on(Package, Dependency) :- depends_on(Package, Dependency, _).
dependency_holds(Package, Dependency, Type) :-
dependency_condition(ID, Package, Dependency),
dependency_type(ID, Type),
condition_holds(ID),
build(Package),
not external(Package).
not external(Package),
condition_holds(ID).
% We cut off dependencies of externals (as we don't really know them).
% Don't impose constraints on dependencies that don't exist.
@@ -155,17 +179,18 @@ node(Dependency) :- node(Package), depends_on(Package, Dependency).
% dependencies) and get a two-node unconnected graph
needed(Package) :- root(Package).
needed(Dependency) :- needed(Package), depends_on(Package, Dependency).
:- node(Package), not needed(Package),
error("All dependencies must be reachable from root").
error(1, "'{0}' is not a valid dependency for any package in the DAG", Package)
:- node(Package),
not needed(Package).
% Avoid cycles in the DAG
% some combinations of conditional dependencies can result in cycles;
% this ensures that we solve around them
path(Parent, Child) :- depends_on(Parent, Child).
path(Parent, Descendant) :- path(Parent, A), depends_on(A, Descendant).
:- path(A, B), path(B, A), error("Cyclic dependencies are not allowed").
#defined error/1.
error(2, "Cyclic dependency detected between '{0}' and '{1}'\n Consider changing variants to avoid the cycle", A, B)
:- path(A, B),
path(B, A).
#defined dependency_type/2.
#defined dependency_condition/3.
@@ -173,14 +198,13 @@ path(Parent, Descendant) :- path(Parent, A), depends_on(A, Descendant).
%-----------------------------------------------------------------------------
% Conflicts
%-----------------------------------------------------------------------------
:- node(Package),
conflict(Package, TriggerID, ConstraintID),
error(0, Msg) :- node(Package),
conflict(Package, TriggerID, ConstraintID, Msg),
condition_holds(TriggerID),
condition_holds(ConstraintID),
not external(Package), % ignore conflicts for externals
error("A conflict was triggered").
not external(Package). % ignore conflicts for externals
#defined conflict/3.
#defined conflict/4.
%-----------------------------------------------------------------------------
% Virtual dependencies
@@ -200,8 +224,17 @@ virtual_node(Virtual)
% If there's a virtual node, we must select one and only one provider.
% The provider must be selected among the possible providers.
1 { provider(Package, Virtual) : possible_provider(Package, Virtual) } 1
:- virtual_node(Virtual), error("Virtual packages must be satisfied by a unique provider").
{ provider(Package, Virtual) : possible_provider(Package, Virtual) }
:- virtual_node(Virtual).
error(2, "Cannot find valid provider for virtual {0}", Virtual)
:- virtual_node(Virtual),
P = #count{ Package : provider(Package, Virtual)},
P < 1.
error(2, "Spec cannot include multiple providers for virtual '{0}'\n Requested '{1}' and '{2}'", Virtual, P1, P2)
:- virtual_node(Virtual),
provider(P1, Virtual),
provider(P2, Virtual),
P1 < P2.
% virtual roots imply virtual nodes, and that one provider is a root
virtual_node(Virtual) :- virtual_root(Virtual).
@@ -226,7 +259,7 @@ virtual_condition_holds(Provider, Virtual) :-
% A package cannot be the actual provider for a virtual if it does not
% fulfill the conditions to provide that virtual
:- provider(Package, Virtual), not virtual_condition_holds(Package, Virtual),
error("Internal error: virtual when provides not respected").
internal_error("Virtual when provides not respected").
#defined possible_provider/2.
@@ -239,7 +272,7 @@ virtual_condition_holds(Provider, Virtual) :-
% we select the weight, among the possible ones, that minimizes the overall objective function.
1 { provider_weight(Dependency, Virtual, Weight, Reason) :
possible_provider_weight(Dependency, Virtual, Weight, Reason) } 1
:- provider(Dependency, Virtual), error("Internal error: package provider weights must be unique").
:- provider(Dependency, Virtual), internal_error("Package provider weights must be unique").
% Get rid or the reason for enabling the possible weight (useful for debugging)
provider_weight(Dependency, Virtual, Weight) :- provider_weight(Dependency, Virtual, Weight, _).
@@ -282,9 +315,10 @@ possible_provider_weight(Dependency, Virtual, 100, "fallback") :- provider(Depen
% These allow us to easily define conditional dependency and conflict rules
% without enumerating all spec attributes every time.
node(Package) :- attr("node", Package).
virtual_node(Virtual) :- attr("virtual_node", Virtual).
hash(Package, Hash) :- attr("hash", Package, Hash).
version(Package, Version) :- attr("version", Package, Version).
version_satisfies(Package, Constraint) :- attr("version_satisfies", Package, Constraint).
node_version_satisfies(Package, Constraint) :- attr("node_version_satisfies", Package, Constraint).
node_platform(Package, Platform) :- attr("node_platform", Package, Platform).
node_os(Package, OS) :- attr("node_os", Package, OS).
node_target(Package, Target) :- attr("node_target", Package, Target).
@@ -300,9 +334,10 @@ node_compiler_version_satisfies(Package, Compiler, Version)
:- attr("node_compiler_version_satisfies", Package, Compiler, Version).
attr("node", Package) :- node(Package).
attr("virtual_node", Virtual) :- virtual_node(Virtual).
attr("hash", Package, Hash) :- hash(Package, Hash).
attr("version", Package, Version) :- version(Package, Version).
attr("version_satisfies", Package, Constraint) :- version_satisfies(Package, Constraint).
attr("node_version_satisfies", Package, Constraint) :- node_version_satisfies(Package, Constraint).
attr("node_platform", Package, Platform) :- node_platform(Package, Platform).
attr("node_os", Package, OS) :- node_os(Package, OS).
attr("node_target", Package, Target) :- node_target(Package, Target).
@@ -330,7 +365,7 @@ attr("node_compiler_version_satisfies", Package, Compiler, Version)
#defined external_only/1.
#defined pkg_provider_preference/4.
#defined default_provider_preference/3.
#defined version_satisfies/2.
#defined node_version_satisfies/2.
#defined node_compiler_version_satisfies/3.
#defined root/1.
@@ -339,9 +374,17 @@ attr("node_compiler_version_satisfies", Package, Compiler, Version)
%-----------------------------------------------------------------------------
% if a package is external its version must be one of the external versions
1 { external_version(Package, Version, Weight):
version_declared(Package, Version, Weight, "external") } 1
:- external(Package), error("External package version does not satisfy external spec").
{ external_version(Package, Version, Weight):
version_declared(Package, Version, Weight, "external") }
:- external(Package).
error(2, "Attempted to use external for '{0}' which does not satisfy any configured external spec", Package)
:- external(Package),
not external_version(Package, _, _).
error(2, "Attempted to use external for '{0}' which does not satisfy any configured external spec", Package)
:- external(Package),
external_version(Package, Version1, Weight1),
external_version(Package, Version2, Weight2),
(Version1, Weight1) < (Version2, Weight2). % see[1]
version_weight(Package, Weight) :- external_version(Package, Version, Weight).
version(Package, Version) :- external_version(Package, Version, Weight).
@@ -361,7 +404,7 @@ external(Package) :- external_spec_selected(Package, _).
version_weight(Package, Weight),
version_declared(Package, Version, Weight, "external"),
not external(Package),
error("Internal error: external weight used for internal spec").
internal_error("External weight used for internal spec").
% determine if an external spec has been selected
external_spec_selected(Package, LocalIndex) :-
@@ -373,8 +416,9 @@ external_conditions_hold(Package, LocalIndex) :-
% it cannot happen that a spec is external, but none of the external specs
% conditions hold.
:- external(Package), not external_conditions_hold(Package, _),
error("External package does not satisfy external spec").
error(2, "Attempted to use external for '{0}' which does not satisfy any configured external spec", Package)
:- external(Package),
not external_conditions_hold(Package, _).
#defined possible_external/3.
#defined external_spec_index/3.
@@ -391,16 +435,16 @@ variant(Package, Variant) :- variant_condition(ID, Package, Variant),
condition_holds(ID).
% a variant cannot be set if it is not a variant on the package
:- variant_set(Package, Variant),
not variant(Package, Variant),
build(Package),
error("Unsatisfied conditional variants cannot be set").
error(2, "Cannot set variant '{0}' for package '{1}' because the variant condition cannot be satisfied for the given spec", Package, Variant)
:- variant_set(Package, Variant),
not variant(Package, Variant),
build(Package).
% a variant cannot take on a value if it is not a variant of the package
:- variant_value(Package, Variant, _),
not variant(Package, Variant),
build(Package),
error("Unsatisfied conditional variants cannot take on a variant value").
error(2, "Cannot set variant '{0}' for package '{1}' because the variant condition cannot be satisfied for the given spec", Package, Variant)
:- variant_value(Package, Variant, _),
not variant(Package, Variant),
build(Package).
% if a variant is sticky and not set its value is the default value
variant_value(Package, Variant, Value) :-
@@ -410,27 +454,30 @@ variant_value(Package, Variant, Value) :-
variant_default_value(Package, Variant, Value),
build(Package).
% one variant value for single-valued variants.
1 {
% at most one variant value for single-valued variants.
{
variant_value(Package, Variant, Value)
: variant_possible_value(Package, Variant, Value)
} 1
:- node(Package),
variant(Package, Variant),
variant_single_value(Package, Variant),
build(Package),
error("Single valued variants must have a single value").
% at least one variant value for multi-valued variants.
1 {
variant_value(Package, Variant, Value)
: variant_possible_value(Package, Variant, Value)
}
:- node(Package),
variant(Package, Variant),
not variant_single_value(Package, Variant),
build(Package),
error("Internal error: All variants must have a value").
build(Package).
error(2, "'{0}' required multiple values for single-valued variant '{1}'\n Requested 'Spec({1}={2})' and 'Spec({1}={3})'", Package, Variant, Value1, Value2)
:- node(Package),
variant(Package, Variant),
variant_single_value(Package, Variant),
build(Package),
variant_value(Package, Variant, Value1),
variant_value(Package, Variant, Value2),
Value1 < Value2. % see[1]
error(2, "No valid value for variant '{1}' of package '{0}'", Package, Variant)
:- node(Package),
variant(Package, Variant),
build(Package),
C = #count{ Value : variant_value(Package, Variant, Value) },
C < 1.
% if a variant is set to anything, it is considered 'set'.
variant_set(Package, Variant) :- variant_set(Package, Variant, _).
@@ -438,21 +485,21 @@ variant_set(Package, Variant) :- variant_set(Package, Variant, _).
% A variant cannot have a value that is not also a possible value
% This only applies to packages we need to build -- concrete packages may
% have been built w/different variants from older/different package versions.
:- variant_value(Package, Variant, Value),
not variant_possible_value(Package, Variant, Value),
build(Package),
error("Variant set to invalid value").
error(1, "'Spec({1}={2})' is not a valid value for '{0}' variant '{1}'", Package, Variant, Value)
:- variant_value(Package, Variant, Value),
not variant_possible_value(Package, Variant, Value),
build(Package).
% Some multi valued variants accept multiple values from disjoint sets.
% Ensure that we respect that constraint and we don't pick values from more
% than one set at once
:- variant_value(Package, Variant, Value1),
variant_value(Package, Variant, Value2),
variant_value_from_disjoint_sets(Package, Variant, Value1, Set1),
variant_value_from_disjoint_sets(Package, Variant, Value2, Set2),
Set1 < Set2,
build(Package),
error("Variant values selected from multiple disjoint sets").
error(2, "{0} variant '{1}' cannot have values '{2}' and '{3}' as they come from disjoing value sets", Package, Variant, Value1, Value2)
:- variant_value(Package, Variant, Value1),
variant_value(Package, Variant, Value2),
variant_value_from_disjoint_sets(Package, Variant, Value1, Set1),
variant_value_from_disjoint_sets(Package, Variant, Value2, Set2),
Set1 < Set2, % see[1]
build(Package).
% variant_set is an explicitly set variant value. If it's not 'set',
% we revert to the default value. If it is set, we force the set value
@@ -510,12 +557,11 @@ variant_default_value(Package, Variant, Value) :- variant_default_value_from_cli
% Treat 'none' in a special way - it cannot be combined with other
% values even if the variant is multi-valued
:- 2 {
variant_value(Package, Variant, Value) : variant_possible_value(Package, Variant, Value)
},
variant_value(Package, Variant, "none"),
build(Package),
error("Variant value 'none' cannot be combined with any other value").
error(2, "{0} variant '{1}' cannot have values '{2}' and 'none'", Package, Variant, Value)
:- variant_value(Package, Variant, Value),
variant_value(Package, Variant, "none"),
Value != "none",
build(Package).
% patches and dev_path are special variants -- they don't have to be
% declared in the package, so we just allow them to spring into existence
@@ -559,6 +605,18 @@ node_platform(Package, Platform)
% platform is set if set to anything
node_platform_set(Package) :- node_platform_set(Package, _).
% each node must have a single platform
error(2, "No valid platform found for {0}", Package)
:- node(Package),
C = #count{ Platform : node_platform(Package, Platform)},
C < 1.
error(2, "Cannot concretize {0} with multiple platforms\n Requested 'platform={1}' and 'platform={2}'", Package, Platform1, Platform2)
:- node(Package),
node_platform(Package, Platform1),
node_platform(Package, Platform2),
Platform1 < Platform2. % see[1]
#defined node_platform_set/2. % avoid warnings
%-----------------------------------------------------------------------------
@@ -568,20 +626,32 @@ node_platform_set(Package) :- node_platform_set(Package, _).
os(OS) :- os(OS, _).
% one os per node
1 { node_os(Package, OS) : os(OS) } 1 :-
node(Package), error("Each node must have exactly one OS").
{ node_os(Package, OS) : os(OS) } :- node(Package).
error(2, "Cannot find valid operating system for '{0}'", Package)
:- node(Package),
C = #count{ OS : node_os(Package, OS)},
C < 1.
error(2, "Cannot concretize {0} with multiple operating systems\n Requested 'os={1}' and 'os={2}'", Package, OS1, OS2)
:- node(Package),
node_os(Package, OS1),
node_os(Package, OS2),
OS1 < OS2. %see [1]
% can't have a non-buildable OS on a node we need to build
:- build(Package), node_os(Package, OS), not buildable_os(OS),
error("No available OS can be built for").
error(2, "Cannot concretize '{0} os={1}'. Operating system '{1}' is not buildable", Package, OS)
:- build(Package),
node_os(Package, OS),
not buildable_os(OS).
% can't have dependencies on incompatible OS's
:- depends_on(Package, Dependency),
node_os(Package, PackageOS),
node_os(Dependency, DependencyOS),
not os_compatible(PackageOS, DependencyOS),
build(Package),
error("Dependencies must have compatible OS's with their dependents").
error(2, "{0} and dependency {1} have incompatible operating systems 'os={2}' and 'os={3}'", Package, Dependency, PackageOS, DependencyOS)
:- depends_on(Package, Dependency),
node_os(Package, PackageOS),
node_os(Dependency, DependencyOS),
not os_compatible(PackageOS, DependencyOS),
build(Package).
% give OS choice weights according to os declarations
node_os_weight(Package, Weight)
@@ -613,14 +683,24 @@ node_os(Package, OS) :- node_os_set(Package, OS), node(Package).
%-----------------------------------------------------------------------------
% Each node has only one target chosen among the known targets
1 { node_target(Package, Target) : target(Target) } 1 :- node(Package), error("Each node must have exactly one target").
{ node_target(Package, Target) : target(Target) } :- node(Package).
error(2, "Cannot find valid target for '{0}'", Package)
:- node(Package),
C = #count{Target : node_target(Package, Target)},
C < 1.
error(2, "Cannot concretize '{0}' with multiple targets\n Requested 'target={1}' and 'target={2}'", Package, Target1, Target2)
:- node(Package),
node_target(Package, Target1),
node_target(Package, Target2),
Target1 < Target2. % see[1]
% If a node must satisfy a target constraint, enforce it
:- node_target(Package, Target),
node_target_satisfies(Package, Constraint),
not target_satisfies(Constraint, Target),
error("Node targets must satisfy node target constraints").
error(1, "'{0} target={1}' cannot satisfy constraint 'target={2}'", Package, Target, Constraint)
:- node_target(Package, Target),
node_target_satisfies(Package, Constraint),
not target_satisfies(Constraint, Target).
% If a node has a target and the target satisfies a constraint, then the target
% associated with the node satisfies the same constraint
@@ -628,10 +708,10 @@ node_target_satisfies(Package, Constraint)
:- node_target(Package, Target), target_satisfies(Constraint, Target).
% If a node has a target, all of its dependencies must be compatible with that target
:- depends_on(Package, Dependency),
node_target(Package, Target),
not node_target_compatible(Dependency, Target),
error("Dependency node targets must be compatible with dependent targets").
error(2, "Cannot find compatible targets for {0} and {1}", Package, Dependency)
:- depends_on(Package, Dependency),
node_target(Package, Target),
not node_target_compatible(Dependency, Target).
% Intermediate step for performance reasons
% When the integrity constraint above was formulated including this logic
@@ -672,12 +752,12 @@ target_weight(Target, Package, Weight)
:- package_target_weight(Target, Package, Weight).
% can't use targets on node if the compiler for the node doesn't support them
:- node_target(Package, Target),
not compiler_supports_target(Compiler, Version, Target),
node_compiler(Package, Compiler),
node_compiler_version(Package, Compiler, Version),
build(Package),
error("No satisfying compiler available is compatible with a satisfying target").
error(2, "{0} compiler '{2}@{3}' incompatible with 'target={1}'", Package, Target, Compiler, Version)
:- node_target(Package, Target),
not compiler_supports_target(Compiler, Version, Target),
node_compiler(Package, Compiler),
node_compiler_version(Package, Compiler, Version),
build(Package).
% if a target is set explicitly, respect it
node_target(Package, Target)
@@ -704,8 +784,10 @@ node_target_mismatch(Parent, Dependency)
not node_target_match(Parent, Dependency).
% disallow reusing concrete specs that don't have a compatible target
:- node(Package), node_target(Package, Target), not target(Target),
error("No satisfying package's target is compatible with this machine").
error(2, "'{0} target={1}' is not compatible with this machine", Package, Target)
:- node(Package),
node_target(Package, Target),
not target(Target).
#defined node_target_set/2.
#defined package_target_weight/3.
@@ -717,10 +799,19 @@ compiler(Compiler) :- compiler_version(Compiler, _).
% There must be only one compiler set per built node. The compiler
% is chosen among available versions.
1 { node_compiler_version(Package, Compiler, Version) : compiler_version(Compiler, Version) } 1 :-
{ node_compiler_version(Package, Compiler, Version) : compiler_version(Compiler, Version) } :-
node(Package),
build(Package),
error("Each node must have exactly one compiler").
build(Package).
error(2, "No valid compiler version found for '{0}'", Package)
:- node(Package),
C = #count{ Version : node_compiler_version(Package, _, Version)},
C < 1.
error(2, "'{0}' compiler constraints '%{1}@{2}' and '%{3}@{4}' are incompatible", Package, Compiler1, Version1, Compiler2, Version2)
:- node(Package),
node_compiler_version(Package, Compiler1, Version1),
node_compiler_version(Package, Compiler2, Version2),
(Compiler1, Version1) < (Compiler2, Version2). % see[1]
% Sometimes we just need to know the compiler and not the version
node_compiler(Package, Compiler) :- node_compiler_version(Package, Compiler, _).
@@ -729,14 +820,22 @@ node_compiler(Package, Compiler) :- node_compiler_version(Package, Compiler, _).
:- node_compiler(Package, Compiler1),
node_compiler_version(Package, Compiler2, _),
Compiler1 != Compiler2,
error("Internal error: mismatch between selected compiler and compiler version").
internal_error("Mismatch between selected compiler and compiler version").
% If the compiler of a node cannot be satisfied, raise
error(1, "No valid compiler for {0} satisfies '%{1}'", Package, Compiler)
:- node(Package),
node_compiler_version_satisfies(Package, Compiler, ":"),
C = #count{ Version : node_compiler_version(Package, Compiler, Version), compiler_version_satisfies(Compiler, ":", Version) },
C < 1.
% If the compiler of a node must satisfy a constraint, then its version
% must be chosen among the ones that satisfy said constraint
1 { node_compiler_version(Package, Compiler, Version)
: compiler_version_satisfies(Compiler, Constraint, Version) } 1 :-
node_compiler_version_satisfies(Package, Compiler, Constraint),
error("Internal error: node compiler version mismatch").
error(2, "No valid version for '{0}' compiler '{1}' satisfies '@{2}'", Package, Compiler, Constraint)
:- node(Package),
node_compiler_version_satisfies(Package, Compiler, Constraint),
C = #count{ Version : node_compiler_version(Package, Compiler, Version), compiler_version_satisfies(Compiler, Constraint, Version) },
C < 1.
% If the node is associated with a compiler and the compiler satisfy a constraint, then
% the compiler associated with the node satisfy the same constraint
@@ -754,11 +853,12 @@ node_compiler_version(Package, Compiler, Version) :- node_compiler_version_set(P
% Cannot select a compiler if it is not supported on the OS
% Compilers that are explicitly marked as allowed
% are excluded from this check
:- node_compiler_version(Package, Compiler, Version), node_os(Package, OS),
not compiler_supports_os(Compiler, Version, OS),
not allow_compiler(Compiler, Version),
build(Package),
error("No satisfying compiler available is compatible with a satisfying os").
error(2, "{0} compiler '%{1}@{2}' incompatible with 'os={3}'", Package, Compiler, Version, OS)
:- node_compiler_version(Package, Compiler, Version),
node_os(Package, OS),
not compiler_supports_os(Compiler, Version, OS),
not allow_compiler(Compiler, Version),
build(Package).
% If a package and one of its dependencies don't have the
% same compiler there's a mismatch.
@@ -851,7 +951,7 @@ no_flags(Package, FlagType)
%-----------------------------------------------------------------------------
% the solver is free to choose at most one installed hash for each package
{ hash(Package, Hash) : installed_hash(Package, Hash) } 1
:- node(Package), error("Internal error: package must resolve to at most one hash").
:- node(Package), internal_error("Package must resolve to at most one hash").
% you can't choose an installed hash for a dev spec
:- hash(Package, Hash), variant_value(Package, "dev_path", _).
@@ -862,25 +962,72 @@ impose(Hash) :- hash(Package, Hash).
% if we haven't selected a hash for a package, we'll be building it
build(Package) :- not hash(Package, _), node(Package).
% Minimizing builds is tricky. We want a minimizing criterion
% because we want to reuse what is avaialble, but
% we also want things that are built to stick to *default preferences* from
% the package and from the user. We therefore treat built specs differently and apply
% a different set of optimization criteria to them. Spack's *first* priority is to
% reuse what it *can*, but if it builds something, the built specs will respect
% defaults and preferences. This is implemented by bumping the priority of optimization
% criteria for built specs -- so that they take precedence over the otherwise
% topmost-priority criterion to reuse what is installed.
% Minimizing builds is tricky. We want a minimizing criterion because we want to reuse
% what is avaialble, but we also want things that are built to stick to *default
% preferences* from the package and from the user. We therefore treat built specs
% differently and apply a different set of optimization criteria to them. Spack's first
% priority is to reuse what it can, but if it builds something, the built specs will
% respect defaults and preferences.
%
% This is implemented by bumping the priority of optimization criteria for built specs
% -- so that they take precedence over the otherwise topmost-priority criterion to reuse
% what is installed.
%
% If the user explicitly asks for *minimal* installs, we don't differentiate between
% built and reused specs - the top priority is just minimizing builds.
%
% The priority ranges are:
% 200+ Shifted priorities for build nodes; correspond to priorities 0 - 99.
% 100 - 199 Unshifted priorities. Currently only includes minimizing #builds.
% 0 - 99 Priorities for non-built nodes.
build_priority(Package, 200) :- build(Package), node(Package).
build_priority(Package, 0) :- not build(Package), node(Package).
build_priority(Package, 200) :- node(Package), build(Package), optimize_for_reuse(),
not minimal_installs().
build_priority(Package, 0) :- node(Package), not build(Package), optimize_for_reuse().
% Don't adjust build priorities if reusing, or if doing minimal installs
% With minimal, minimizing builds is the TOP priority
build_priority(Package, 0) :- node(Package), not optimize_for_reuse().
build_priority(Package, 0) :- node(Package), minimal_installs().
% Minimize builds with both --reuse and with --minimal
minimize_builds() :- optimize_for_reuse().
minimize_builds() :- minimal_installs().
% don't assign versions from installed packages unless reuse is enabled
% NOTE: that "installed" means the declared version was only included because
% that package happens to be installed, NOT because it was asked for on the
% command line. If the user specifies a hash, the origin will be "spec".
%
% TODO: There's a slight inconsistency with this: if the user concretizes
% and installs `foo ^bar`, for some build dependency `bar`, and then later
% does a `spack install --fresh foo ^bar/abcde` (i.e.,the hash of `bar`, it
% currently *won't* force versions for `bar`'s build dependencies -- `--fresh`
% will instead build the latest bar. When we actually include transitive
% build deps in the solve, consider using them as a preference to resolve this.
:- version(Package, Version),
version_weight(Package, Weight),
version_declared(Package, Version, Weight, "installed"),
not optimize_for_reuse().
#defined installed_hash/2.
#defined minimal_installs/0.
%-----------------------------------------------------------------
% Optimization to avoid errors
%-----------------------------------------------------------------
% Some errors are handled as rules instead of constraints because
% it allows us to explain why something failed. Here we optimize
% HEAVILY against the facts generated by those rules.
#minimize{ 0@1000: #true}.
#minimize{ 0@1001: #true}.
#minimize{ 0@1002: #true}.
#minimize{ 1000@1000+Priority,Msg: error(Priority, Msg) }.
#minimize{ 1000@1000+Priority,Msg,Arg1: error(Priority, Msg, Arg1) }.
#minimize{ 1000@1000+Priority,Msg,Arg1,Arg2: error(Priority, Msg, Arg1, Arg2) }.
#minimize{ 1000@1000+Priority,Msg,Arg1,Arg2,Arg3: error(Priority, Msg, Arg1, Arg2, Arg3) }.
#minimize{ 1000@1000+Priority,Msg,Arg1,Arg2,Arg3,Arg4: error(Priority, Msg, Arg1, Arg2, Arg3, Arg4) }.
#minimize{ 1000@1000+Priority,Msg,Arg1,Arg2,Arg3,Arg4,Arg5: error(Priority, Msg, Arg1, Arg2, Arg3, Arg4, Arg5) }.
%-----------------------------------------------------------------------------
% How to optimize the spec (high to low priority)
@@ -893,7 +1040,7 @@ build_priority(Package, 0) :- not build(Package), node(Package).
% Try hard to reuse installed packages (i.e., minimize the number built)
opt_criterion(100, "number of packages to build (vs. reuse)").
#minimize { 0@100: #true }.
#minimize { 1@100,Package : build(Package), optimize_for_reuse() }.
#minimize { 1@100,Package : build(Package), minimize_builds() }.
#defined optimize_for_reuse/0.
% Minimize the number of deprecated versions being used
@@ -1061,3 +1208,11 @@ opt_criterion(1, "non-preferred targets").
#heuristic variant_value(Package, Variant, Value) : variant_default_value(Package, Variant, Value), node(Package). [10, true]
#heuristic provider(Package, Virtual) : possible_provider_weight(Package, Virtual, 0, _), virtual_node(Virtual). [10, true]
#heuristic node(Package) : possible_provider_weight(Package, Virtual, 0, _), virtual_node(Virtual). [10, true]
%-----------
% Notes
%-----------
% [1] Clingo ensures a total ordering among all atoms. We rely on that total ordering
% to reduce symmetry in the solution by checking `<` instead of `!=` in symmetric
% cases. These choices are made without loss of generality.

View File

@@ -34,3 +34,13 @@
% deprecated packages
#show deprecated/2.
% error types
#show error/2.
#show error/3.
#show error/4.
#show error/5.
#show error/6.
#show error/7.
% debug

View File

@@ -184,7 +184,7 @@
default_format += '{variants}{arch=architecture}'
#: specfile format version. Must increase monotonically
specfile_format_version = 2
specfile_format_version = 3
def colorize_spec(spec):
@@ -1191,11 +1191,14 @@ def __init__(self, spec_like=None, normal=False,
self._dependencies = _EdgeMap(store_by=EdgeDirection.child)
self.namespace = None
self._hash = None
self._build_hash = None
self._full_hash = None
self._package_hash = None
# initial values for all spec hash types
for h in ht.hashes:
setattr(self, h.attr, None)
# Python __hash__ is handled separately from the cached spec hashes
self._dunder_hash = None
# cache of package for this spec
self._package = None
# Most of these are internal implementation details that can be
@@ -1210,14 +1213,6 @@ def __init__(self, spec_like=None, normal=False,
self.external_path = external_path
self.external_modules = Spec._format_module_list(external_modules)
# Older spack versions did not compute full_hash or build_hash,
# and we may not have the necessary information to recompute them
# if we read in old specs. Old concrete specs are marked "final"
# when read in to indicate that we shouldn't recompute full_hash
# or build_hash. New specs are not final; we can lazily compute
# their hashes.
self._hashes_final = False
# This attribute is used to store custom information for
# external specs. None signal that it was not set yet.
self.extra_attributes = None
@@ -1554,6 +1549,38 @@ def spliced(self):
"""
return any(s.build_spec is not s for s in self.traverse(root=True))
@property
def installed(self):
"""Installation status of a package.
Returns:
True if the package has been installed, False otherwise.
"""
if not self.concrete:
return False
try:
# If the spec is in the DB, check the installed
# attribute of the record
return spack.store.db.get_record(self).installed
except KeyError:
# If the spec is not in the DB, the method
# above raises a Key error
return False
@property
def installed_upstream(self):
"""Whether the spec is installed in an upstream repository.
Returns:
True if the package is installed in an upstream, False otherwise.
"""
if not self.concrete:
return False
upstream, _ = spack.store.db.query_by_spec_hash(self.dag_hash())
return upstream
def traverse(self, **kwargs):
direction = kwargs.get('direction', 'children')
depth = kwargs.get('depth', False)
@@ -1572,7 +1599,15 @@ def traverse(self, **kwargs):
def traverse_edges(self, visited=None, d=0, deptype='all',
dep_spec=None, **kwargs):
"""Generic traversal of the DAG represented by this spec.
This will yield each node in the spec. Options:
This yields ``DependencySpec`` objects as they are traversed.
When traversing top-down, an imaginary incoming edge to the root
is yielded first as ``DependencySpec(None, root, ())``. When
traversing bottom-up, imaginary edges to leaves are yielded first
as ``DependencySpec(left, None, ())`` objects.
Options:
order [=pre|post]
Order to traverse spec nodes. Defaults to preorder traversal.
@@ -1727,7 +1762,7 @@ def prefix(self):
def prefix(self, value):
self._prefix = spack.util.prefix.Prefix(pth.convert_to_platform_path(value))
def _spec_hash(self, hash):
def spec_hash(self, hash):
"""Utility method for computing different types of Spec hashes.
Arguments:
@@ -1741,71 +1776,69 @@ def _spec_hash(self, hash):
json_text = sjson.dump(node_dict)
return spack.util.hash.b32_hash(json_text)
def _cached_hash(self, hash, length=None):
def _cached_hash(self, hash, length=None, force=False):
"""Helper function for storing a cached hash on the spec.
This will run _spec_hash() with the deptype and package_hash
This will run spec_hash() with the deptype and package_hash
parameters, and if this spec is concrete, it will store the value
in the supplied attribute on this spec.
Arguments:
hash (spack.hash_types.SpecHashDescriptor): type of hash to generate.
length (int): length of hash prefix to return (default is full hash string)
force (bool): cache the hash even if spec is not concrete (default False)
"""
if not hash.attr:
return self._spec_hash(hash)[:length]
return self.spec_hash(hash)[:length]
hash_string = getattr(self, hash.attr, None)
if hash_string:
return hash_string[:length]
else:
hash_string = self._spec_hash(hash)
if self.concrete:
hash_string = self.spec_hash(hash)
if force or self.concrete:
setattr(self, hash.attr, hash_string)
return hash_string[:length]
def package_hash(self):
"""Compute the hash of the contents of the package for this node"""
# Concrete specs with the old DAG hash did not have the package hash, so we do
# not know what the package looked like at concretization time
if self.concrete and not self._package_hash:
raise ValueError(
"Cannot call package_hash() on concrete specs with the old dag_hash()"
)
return self._cached_hash(ht.package_hash)
def dag_hash(self, length=None):
"""This is Spack's default hash, used to identify installations.
At the moment, it excludes build dependencies to avoid rebuilding
packages whenever build dependency versions change. We will
revise this to include more detailed provenance when the
concretizer can more aggressievly reuse installed dependencies.
Same as the full hash (includes package hash and build/link/run deps).
Tells us when package files and any dependencies have changes.
NOTE: Versions of Spack prior to 0.18 only included link and run deps.
"""
return self._cached_hash(ht.dag_hash, length)
def build_hash(self, length=None):
"""Hash used to store specs in environments.
This hash includes build dependencies, and we need to preserve
them to be able to rebuild an entire environment for a user.
"""
return self._cached_hash(ht.build_hash, length)
def process_hash(self, length=None):
"""Hash used to store specs in environments.
"""Hash used to transfer specs among processes.
This hash includes build and test dependencies and is only used to
serialize a spec and pass it around among processes.
"""
return self._cached_hash(ht.process_hash, length)
def full_hash(self, length=None):
"""Hash to determine when to rebuild packages in the build pipeline.
This hash includes the package hash, so that we know when package
files has changed between builds.
"""
return self._cached_hash(ht.full_hash, length)
def dag_hash_bit_prefix(self, bits):
"""Get the first <bits> bits of the DAG hash as an integer type."""
return spack.util.hash.base32_prefix_bits(self.dag_hash(), bits)
def process_hash_bit_prefix(self, bits):
"""Get the first <bits> bits of the DAG hash as an integer type."""
return spack.util.hash.base32_prefix_bits(self.process_hash(), bits)
def to_node_dict(self, hash=ht.dag_hash):
"""Create a dictionary representing the state of this Spec.
@@ -1899,8 +1932,13 @@ def to_node_dict(self, hash=ht.dag_hash):
if hasattr(variant, '_patches_in_order_of_appearance'):
d['patches'] = variant._patches_in_order_of_appearance
if hash.package_hash:
package_hash = self.package_hash()
if self._concrete and hash.package_hash and self._package_hash:
# We use the attribute here instead of `self.package_hash()` because this
# should *always* be assignhed at concretization time. We don't want to try
# to compute a package hash for concrete spec where a) the package might not
# exist, or b) the `dag_hash` didn't include the package hash when the spec
# was concretized.
package_hash = self._package_hash
# Full hashes are in bytes
if (not isinstance(package_hash, six.text_type)
@@ -1971,7 +2009,7 @@ def to_dict(self, hash=ht.dag_hash):
"dependencies": [
{
"name": "readline",
"build_hash": "4f47cggum7p4qmp3xna4hi547o66unva",
"hash": "4f47cggum7p4qmp3xna4hi547o66unva",
"type": [
"build",
"link"
@@ -1979,16 +2017,14 @@ def to_dict(self, hash=ht.dag_hash):
},
{
"name": "zlib",
"build_hash": "uvgh6p7rhll4kexqnr47bvqxb3t33jtq",
"hash": "uvgh6p7rhll4kexqnr47bvqxb3t33jtq",
"type": [
"build",
"link"
]
}
],
"hash": "d2yzqp2highd7sn4nr5ndkw3ydcrlhtk",
"full_hash": "tve45xfqkfgmzwcyfetze2z6syrg7eaf",
"build_hash": "tsjnz7lgob7bu2wd4sqzzjenxewc2zha"
"hash": "tve45xfqkfgmzwcyfetze2z6syrg7eaf",
},
# ... more node dicts for readline and its dependencies ...
]
@@ -2017,10 +2053,12 @@ def to_dict(self, hash=ht.dag_hash):
node_list = [] # Using a list to preserve preorder traversal for hash.
hash_set = set()
for s in self.traverse(order='pre', deptype=hash.deptype):
spec_hash = s.node_dict_with_hashes(hash)[hash.name]
spec_hash = s._cached_hash(hash)
if spec_hash not in hash_set:
node_list.append(s.node_dict_with_hashes(hash))
hash_set.add(spec_hash)
if s.build_spec is not s:
build_spec_list = s.build_spec.to_dict(hash)['spec']['nodes']
for node in build_spec_list:
@@ -2028,6 +2066,7 @@ def to_dict(self, hash=ht.dag_hash):
if node_hash not in hash_set:
node_list.append(node)
hash_set.add(node_hash)
meta_dict = syaml.syaml_dict([('version', specfile_format_version)])
inner_dict = syaml.syaml_dict([('_meta', meta_dict), ('nodes', node_list)])
spec_dict = syaml.syaml_dict([('spec', inner_dict)])
@@ -2040,38 +2079,19 @@ def node_dict_with_hashes(self, hash=ht.dag_hash):
node = self.to_node_dict(hash)
node[ht.dag_hash.name] = self.dag_hash()
# full_hash and build_hash are lazily computed -- but if we write
# a spec out, we want them to be included. This is effectively
# the last chance we get to compute them accurately.
# dag_hash is lazily computed -- but if we write a spec out, we want it
# to be included. This is effectively the last chance we get to compute
# it accurately.
if self.concrete:
# build and full hashes can be written out if:
# 1. they're precomputed (i.e. we read them from somewhere
# and they were already on the spec
# 2. we can still compute them lazily (i.e. we just made them and
# have the full dependency graph on-hand)
#
# we want to avoid recomputing either hash for specs we read
# in from the DB or elsewhere, as we may not have the info
# (like patches, package versions, etc.) that we need to
# compute them. Unknown hashes are better than wrong hashes.
write_full_hash = (
self._hashes_final and self._full_hash or # cached and final
not self._hashes_final) # lazily compute
if write_full_hash:
node[ht.full_hash.name] = self.full_hash()
# all specs have at least a DAG hash
node[ht.dag_hash.name] = self.dag_hash()
write_build_hash = 'build' in hash.deptype and (
self._hashes_final and self._build_hash or # cached and final
not self._hashes_final) # lazily compute
if write_build_hash:
node[ht.build_hash.name] = self.build_hash()
else:
node['concrete'] = False
if hash.name == 'build_hash':
node[hash.name] = self.build_hash()
elif hash.name == 'process_hash':
node[hash.name] = self.process_hash()
# we can also give them other hash types if we want
if hash.name != ht.dag_hash.name:
node[hash.name] = self._cached_hash(hash)
return node
@@ -2152,11 +2172,6 @@ def from_node_dict(node):
# specs read in are concrete unless marked abstract
spec._concrete = node.get('concrete', True)
# this spec may have been built with older packages than we have
# on-hand, and we may not have the build dependencies, so mark it
# so we don't recompute full_hash and build_hash.
spec._hashes_final = spec._concrete
if 'patches' in node:
patches = node['patches']
if len(patches) > 0:
@@ -2167,7 +2182,7 @@ def from_node_dict(node):
# FIXME: Monkey patches mvar to store patches order
mvar._patches_in_order_of_appearance = patches
# Don't read dependencies here; from_node_dict() is used by
# Don't read dependencies here; from_dict() is used by
# from_yaml() and from_json() to read the root *and* each dependency
# spec.
@@ -2194,7 +2209,6 @@ def dependencies_from_node_dict(node):
@staticmethod
def read_yaml_dep_specs(deps, hash_type=ht.dag_hash.name):
"""Read the DependencySpec portion of a YAML-formatted Spec.
This needs to be backward-compatible with older spack spec
formats so that reindex will work on old specs/databases.
"""
@@ -2213,17 +2227,13 @@ def read_yaml_dep_specs(deps, hash_type=ht.dag_hash.name):
dep_hash, deptypes = elt
elif isinstance(elt, dict):
# new format: elements of dependency spec are keyed.
for key in (ht.full_hash.name,
ht.build_hash.name,
ht.dag_hash.name,
ht.process_hash.name):
if key in elt:
dep_hash, deptypes = elt[key], elt['type']
hash_type = key
for h in ht.hashes:
if h.name in elt:
dep_hash, deptypes = elt[h.name], elt['type']
hash_type = h.name
break
else: # We never determined a hash type...
raise spack.error.SpecError(
"Couldn't parse dependency spec.")
raise spack.error.SpecError("Couldn't parse dependency spec.")
else:
raise spack.error.SpecError(
"Couldn't parse dependency types in spec.")
@@ -2655,11 +2665,11 @@ def _old_concretize(self, tests=False, deprecation_warning=True):
import spack.concretize
# Add a warning message to inform users that the original concretizer
# will be removed in v0.18.0
# will be removed
if deprecation_warning:
msg = ('the original concretizer is currently being used.\n\tUpgrade to '
'"clingo" at your earliest convenience. The original concretizer '
'will be removed from Spack starting at v0.18.0')
'will be removed from Spack in a future version.')
warnings.warn(msg)
if not self.name:
@@ -2698,8 +2708,8 @@ def _old_concretize(self, tests=False, deprecation_warning=True):
# TODO: or turn external_path into a lazy property
Spec.ensure_external_path_if_external(s)
# Mark everything in the spec as concrete, as well.
self._mark_concrete()
# assign hashes and mark concrete
self._finalize_concretization()
# If any spec in the DAG is deprecated, throw an error
Spec.ensure_no_deprecated(self)
@@ -2729,6 +2739,21 @@ def _old_concretize(self, tests=False, deprecation_warning=True):
# there are declared inconsistencies)
self.architecture.target.optimization_flags(self.compiler)
def _patches_assigned(self):
"""Whether patches have been assigned to this spec by the concretizer."""
# FIXME: _patches_in_order_of_appearance is attached after concretization
# FIXME: to store the order of patches.
# FIXME: Probably needs to be refactored in a cleaner way.
if "patches" not in self.variants:
return False
# ensure that patch state is consistent
patch_variant = self.variants["patches"]
assert hasattr(patch_variant, "_patches_in_order_of_appearance"), \
"patches should always be assigned with a patch variant."
return True
@staticmethod
def inject_patches_variant(root):
# This dictionary will store object IDs rather than Specs as keys
@@ -2813,13 +2838,13 @@ def ensure_external_path_if_external(external_spec):
@staticmethod
def ensure_no_deprecated(root):
"""Raise is a deprecated spec is in the dag.
"""Raise if a deprecated spec is in the dag.
Args:
root (Spec): root spec to be analyzed
Raises:
SpecDeprecatedError: is any deprecated spec is found
SpecDeprecatedError: if any deprecated spec is found
"""
deprecated = []
with spack.store.db.read_transaction():
@@ -2863,7 +2888,6 @@ def _new_concretize(self, tests=False):
concretized = answer[name]
self._dup(concretized)
self._mark_concrete()
def concretize(self, tests=False):
"""Concretize the current spec.
@@ -2880,7 +2904,7 @@ def concretize(self, tests=False):
def _mark_root_concrete(self, value=True):
"""Mark just this spec (not dependencies) concrete."""
if (not value) and self.concrete and self.package.installed:
if (not value) and self.concrete and self.installed:
return
self._normal = value
self._concrete = value
@@ -2894,12 +2918,70 @@ def _mark_concrete(self, value=True):
# if set to false, clear out all hashes (set to None or remove attr)
# may need to change references to respect None
for s in self.traverse():
if (not value) and s.concrete and s.package.installed:
if (not value) and s.concrete and s.installed:
continue
elif not value:
s.clear_cached_hashes()
s._mark_root_concrete(value)
def _assign_hash(self, hash):
"""Compute and cache the provided hash type for this spec and its dependencies.
Arguments:
hash (spack.hash_types.SpecHashDescriptor): the hash to assign to nodes
in the spec.
There are special semantics to consider for `package_hash`.
This should be called:
1. for `package_hash`, immediately after concretization, but *before* marking
concrete, and
2. for `dag_hash`, immediately after marking concrete.
`package_hash` is tricky, because we can't call it on *already* concrete specs,
but we need to assign it *at concretization time* to just-concretized specs. So,
the concretizer must assign the package hash *before* marking their specs
concrete (so that the only concrete specs are the ones already marked concrete).
`dag_hash` is also tricky, since it cannot compute `package_hash()` lazily for
the same reason. `package_hash` needs to be assigned *at concretization time*,
so, `to_node_dict()` can't just assume that it can compute `package_hash` itself
-- it needs to either see or not see a `_package_hash` attribute.
Rules of thumb for `package_hash`:
1. Old-style concrete specs from *before* `dag_hash` included `package_hash`
will not have a `_package_hash` attribute at all.
2. New-style concrete specs will have a `_package_hash` assigned at
concretization time.
3. Abstract specs will not have a `_package_hash` attribute at all.
"""
for spec in self.traverse():
# Already concrete specs either already have a package hash (new dag_hash())
# or they never will b/c we can't know it (old dag_hash()). Skip them.
if hash is ht.package_hash and not spec.concrete:
spec._cached_hash(hash, force=True)
# keep this check here to ensure package hash is saved
assert getattr(spec, hash.attr)
else:
spec._cached_hash(hash)
def _finalize_concretization(self):
"""Assign hashes to this spec, and mark it concrete.
This is called at the end of concretization.
"""
# See docs for in _assign_hash for why package_hash needs to happen here.
self._assign_hash(ht.package_hash)
# Mark everything in the spec as concrete
self._mark_concrete()
# Assign dag_hash (this *could* be done lazily, but it's assigned anyway in
# ensure_no_deprecated, and it's clearer to see explicitly where it happens)
self._assign_hash(ht.dag_hash)
def concretized(self, tests=False):
"""This is a non-destructive version of concretize().
@@ -2911,7 +2993,7 @@ def concretized(self, tests=False):
if a list of names activate them for the packages in the list,
if True activate 'test' dependencies for all packages.
"""
clone = self.copy(caches=True)
clone = self.copy()
clone.concretize(tests=tests)
return clone
@@ -3159,7 +3241,7 @@ def _normalize_helper(self, visited, spec_deps, provider_index, tests):
# Avoid recursively adding constraints for already-installed packages:
# these may include build dependencies which are not needed for this
# install (since this package is already installed).
if self.concrete and self.package.installed:
if self.concrete and self.installed:
return False
# Combine constraints from package deps with constraints from
@@ -3210,8 +3292,8 @@ def normalize(self, force=False, tests=False, user_spec_deps=None):
"Attempting to normalize anonymous spec")
# Set _normal and _concrete to False when forced
if force:
self._mark_concrete(False)
if force and not self._concrete:
self._normal = False
if self._normal:
return False
@@ -3651,7 +3733,6 @@ def virtual_dependencies(self):
return [spec for spec in self.traverse() if spec.virtual]
@property # type: ignore[misc] # decorated prop not supported in mypy
@lang.memoized
def patches(self):
"""Return patch objects for any patch sha256 sums on this Spec.
@@ -3661,26 +3742,19 @@ def patches(self):
TODO: this only checks in the package; it doesn't resurrect old
patches from install directories, but it probably should.
"""
if not self.concrete:
raise spack.error.SpecError("Spec is not concrete: " + str(self))
if not hasattr(self, "_patches"):
self._patches = []
if 'patches' not in self.variants:
return []
# translate patch sha256sums to patch objects by consulting the index
if self._patches_assigned():
for sha256 in self.variants["patches"]._patches_in_order_of_appearance:
index = spack.repo.path.patch_index
patch = index.patch_for_package(sha256, self.package)
self._patches.append(patch)
# FIXME: _patches_in_order_of_appearance is attached after
# FIXME: concretization to store the order of patches somewhere.
# FIXME: Needs to be refactored in a cleaner way.
return self._patches
# translate patch sha256sums to patch objects by consulting the index
patches = []
for sha256 in self.variants['patches']._patches_in_order_of_appearance:
index = spack.repo.path.patch_index
patch = index.patch_for_package(sha256, self.package)
patches.append(patch)
return patches
def _dup(self, other, deps=True, cleardeps=True, caches=None):
def _dup(self, other, deps=True, cleardeps=True):
"""Copy the spec other into self. This is an overwriting
copy. It does not copy any dependents (parents), but by default
copies dependencies.
@@ -3695,10 +3769,6 @@ def _dup(self, other, deps=True, cleardeps=True, caches=None):
cleardeps (bool): if True clears the dependencies of ``self``,
before possibly copying the dependencies of ``other`` onto
``self``
caches (bool or None): preserve cached fields such as
``_normal``, ``_hash``, and ``_dunder_hash``. By
default this is ``False`` if DAG structure would be
changed by the copy, ``True`` if it's an exact copy.
Returns:
True if ``self`` changed because of the copy operation,
@@ -3749,12 +3819,6 @@ def _dup(self, other, deps=True, cleardeps=True, caches=None):
self.extra_attributes = other.extra_attributes
self.namespace = other.namespace
# Cached fields are results of expensive operations.
# If we preserved the original structure, we can copy them
# safely. If not, they need to be recomputed.
if caches is None:
caches = (deps is True or deps == dp.all_deptypes)
# If we copy dependencies, preserve DAG structure in the new spec
if deps:
# If caller restricted deptypes to be copied, adjust that here.
@@ -3762,29 +3826,26 @@ def _dup(self, other, deps=True, cleardeps=True, caches=None):
deptypes = dp.all_deptypes
if isinstance(deps, (tuple, list)):
deptypes = deps
self._dup_deps(other, deptypes, caches)
self._dup_deps(other, deptypes)
self._concrete = other._concrete
self._hashes_final = other._hashes_final
if caches:
self._hash = other._hash
self._build_hash = other._build_hash
if self._concrete:
self._dunder_hash = other._dunder_hash
self._normal = other._normal
self._full_hash = other._full_hash
self._package_hash = other._package_hash
for h in ht.hashes:
setattr(self, h.attr, getattr(other, h.attr, None))
else:
self._hash = None
self._build_hash = None
self._dunder_hash = None
# Note, we could use other._normal if we are copying all deps, but
# always set it False here to avoid the complexity of checking
self._normal = False
self._full_hash = None
self._package_hash = None
for h in ht.hashes:
setattr(self, h.attr, None)
return changed
def _dup_deps(self, other, deptypes, caches):
def _dup_deps(self, other, deptypes):
def spid(spec):
return id(spec)
@@ -3795,11 +3856,11 @@ def spid(spec):
if spid(edge.parent) not in new_specs:
new_specs[spid(edge.parent)] = edge.parent.copy(
deps=False, caches=caches
deps=False
)
if spid(edge.spec) not in new_specs:
new_specs[spid(edge.spec)] = edge.spec.copy(deps=False, caches=caches)
new_specs[spid(edge.spec)] = edge.spec.copy(deps=False)
new_specs[spid(edge.parent)].add_dependency_edge(
new_specs[spid(edge.spec)], edge.deptypes
@@ -4529,7 +4590,7 @@ def tree(self, **kwargs):
if status_fn:
status = status_fn(node)
if node.package.installed_upstream:
if node.installed_upstream:
out += clr.colorize("@g{[^]} ", color=color)
elif status is None:
out += clr.colorize("@K{ - } ", color=color) # !installed
@@ -4677,16 +4738,16 @@ def from_self(name, transitive):
return False
return True
self_nodes = dict((s.name, s.copy(deps=False, caches=True))
self_nodes = dict((s.name, s.copy(deps=False))
for s in self.traverse(root=True)
if from_self(s.name, transitive))
if transitive:
other_nodes = dict((s.name, s.copy(deps=False, caches=True))
other_nodes = dict((s.name, s.copy(deps=False))
for s in other.traverse(root=True))
else:
# NOTE: Does not fully validate providers; loader races possible
other_nodes = dict((s.name, s.copy(deps=False, caches=True))
other_nodes = dict((s.name, s.copy(deps=False))
for s in other.traverse(root=True)
if s is other or s.name not in self)
@@ -4719,23 +4780,10 @@ def from_self(name, transitive):
for dep in ret.traverse(root=True, order='post'):
opposite = other_nodes if dep.name in self_nodes else self_nodes
if any(name in dep for name in opposite.keys()):
# Record whether hashes are already cached
# So we don't try to compute a hash from insufficient
# provenance later
has_build_hash = getattr(dep, ht.build_hash.name, None)
has_full_hash = getattr(dep, ht.full_hash.name, None)
# package hash cannot be affected by splice
dep.clear_cached_hashes(ignore=['package_hash'])
# Since this is a concrete spec, we want to make sure hashes
# are cached writing specs only writes cached hashes in case
# the spec is too old to have full provenance for these hashes,
# so we can't rely on doing it at write time.
if has_build_hash:
_ = dep.build_hash()
if has_full_hash:
_ = dep.full_hash()
dep.dag_hash()
return nodes[self.name]
@@ -4747,16 +4795,21 @@ def clear_cached_hashes(self, ignore=()):
if h.attr not in ignore:
if hasattr(self, h.attr):
setattr(self, h.attr, None)
self._dunder_hash = None
def __hash__(self):
# If the spec is concrete, we leverage the DAG hash and just use
# a 64-bit prefix of it. The DAG hash has the advantage that it's
# computed once per concrete spec, and it's saved -- so if we
# read concrete specs we don't need to recompute the whole hash.
# This is good for large, unchanging specs.
# If the spec is concrete, we leverage the process hash and just use
# a 64-bit prefix of it. The process hash has the advantage that it's
# computed once per concrete spec, and it's saved -- so if we read
# concrete specs we don't need to recompute the whole hash. This is
# good for large, unchanging specs.
#
# We use the process hash instead of the DAG hash here because the DAG
# hash includes the package hash, which can cause infinite recursion,
# and which isn't defined unless the spec has a known package.
if self.concrete:
if not self._dunder_hash:
self._dunder_hash = self.dag_hash_bit_prefix(64)
self._dunder_hash = self.process_hash_bit_prefix(64)
return self._dunder_hash
# This is the normal hash for lazy_lexicographic_ordering. It's
@@ -4821,7 +4874,7 @@ def _spec_from_old_dict(data):
if 'dependencies' not in node[name]:
continue
for dname, dhash, dtypes, _ in Spec.dependencies_from_node_dict(node):
for dname, _, dtypes, _ in Spec.dependencies_from_node_dict(node):
deps[name]._add_dependency(deps[dname], dtypes)
return spec
@@ -4855,7 +4908,7 @@ def _spec_from_dict(data):
break
if not any_deps: # If we never see a dependency...
hash_type = ht.dag_hash.name # use the full_hash provenance
hash_type = ht.dag_hash.name
elif not hash_type: # Seen a dependency, still don't know hash_type
raise spack.error.SpecError("Spec dictionary contains malformed "
"dependencies. Old format?")
@@ -4865,10 +4918,7 @@ def _spec_from_dict(data):
# Pass 1: Create a single lookup dictionary by hash
for i, node in enumerate(nodes):
if 'build_spec' in node.keys():
node_hash = node[hash_type]
else:
node_hash = node[hash_type]
node_hash = node[hash_type]
node_spec = Spec.from_node_dict(node)
hash_dict[node_hash] = node
hash_dict[node_hash]['node_spec'] = node_spec
@@ -5053,7 +5103,7 @@ def do_parse(self):
# Raise an error if the previous spec is already
# concrete (assigned by hash)
if specs[-1]._hash:
if specs[-1].concrete:
raise RedundantSpecError(specs[-1], 'dependency')
# command line deps get empty deptypes now.
# Real deptypes are assigned later per packages.
@@ -5063,9 +5113,8 @@ def do_parse(self):
# If the next token can be part of a valid anonymous spec,
# create the anonymous spec
if self.next.type in (AT, ON, OFF, PCT):
# Raise an error if the previous spec is already
# concrete (assigned by hash)
if specs and specs[-1]._hash:
# Raise an error if the previous spec is already concrete
if specs and specs[-1].concrete:
raise RedundantSpecError(specs[-1],
'compiler, version, '
'or variant')
@@ -5135,10 +5184,15 @@ def parse_compiler(self, text):
return self.compiler()
def spec_by_hash(self):
# TODO: Remove parser dependency on active environment and database.
import spack.environment
self.expect(ID)
dag_hash = self.token.value
matches = spack.store.db.get_by_hash(dag_hash)
matches = []
if spack.environment.active_environment():
matches = spack.environment.active_environment().get_by_hash(dag_hash)
if not matches:
matches = spack.store.db.get_by_hash(dag_hash)
if not matches:
raise NoSuchHashError(dag_hash)
@@ -5322,7 +5376,7 @@ def save_dependency_specfiles(
json_path = os.path.join(output_directory, '{0}.json'.format(dep_name))
with open(json_path, 'w') as fd:
fd.write(dep_spec.to_json(hash=ht.build_hash))
fd.write(dep_spec.to_json(hash=ht.dag_hash))
class SpecParseError(spack.error.SpecError):
@@ -5332,6 +5386,16 @@ def __init__(self, parse_error):
self.string = parse_error.string
self.pos = parse_error.pos
@property
def long_message(self):
return "\n".join(
[
" Encountered when parsing spec:",
" %s" % self.string,
" %s^" % (" " * self.pos),
]
)
class DuplicateDependencyError(spack.error.SpecError):
"""Raised when the same dependency occurs in a spec twice."""

View File

@@ -17,6 +17,8 @@
(['wrong-variant-in-depends-on'], 'PKG-DIRECTIVES'),
# This package has a GitHub patch URL without full_index=1
(['invalid-github-patch-url'], 'PKG-DIRECTIVES'),
# This package has a stand-alone 'test' method in build-time callbacks
(['test-build-callbacks'], 'PKG-DIRECTIVES'),
# This package has no issues
(['mpileaks'], None),
# This package has a conflict with a trigger which cannot constrain the constraint

View File

@@ -11,15 +11,12 @@
import py
import pytest
import llnl.util.filesystem as fs
import spack.binary_distribution as bindist
import spack.config
import spack.hooks.sbang as sbang
import spack.main
import spack.mirror
import spack.repo
import spack.spec as spec
import spack.store
import spack.util.gpg
import spack.util.web as web_util
@@ -81,13 +78,13 @@ def config_directory(tmpdir_factory):
tmpdir = tmpdir_factory.mktemp('test_configs')
# restore some sane defaults for packages and config
config_path = py.path.local(spack.paths.etc_path)
modules_yaml = config_path.join('spack', 'defaults', 'modules.yaml')
os_modules_yaml = config_path.join('spack', 'defaults', '%s' %
modules_yaml = config_path.join('defaults', 'modules.yaml')
os_modules_yaml = config_path.join('defaults', '%s' %
platform.system().lower(),
'modules.yaml')
packages_yaml = config_path.join('spack', 'defaults', 'packages.yaml')
config_yaml = config_path.join('spack', 'defaults', 'config.yaml')
repos_yaml = config_path.join('spack', 'defaults', 'repos.yaml')
packages_yaml = config_path.join('defaults', 'packages.yaml')
config_yaml = config_path.join('defaults', 'config.yaml')
repos_yaml = config_path.join('defaults', 'repos.yaml')
tmpdir.ensure('site', dir=True)
tmpdir.ensure('user', dir=True)
tmpdir.ensure('site/%s' % platform.system().lower(), dir=True)
@@ -394,31 +391,12 @@ def test_built_spec_cache(mirror_dir):
gspec, cspec = Spec('garply').concretized(), Spec('corge').concretized()
full_hash_map = {
'garply': gspec.full_hash(),
'corge': cspec.full_hash(),
}
gspec_results = bindist.get_mirrors_for_spec(gspec)
gspec_mirrors = {}
for result in gspec_results:
s = result['spec']
assert(s._full_hash == full_hash_map[s.name])
assert(result['mirror_url'] not in gspec_mirrors)
gspec_mirrors[result['mirror_url']] = True
cspec_results = bindist.get_mirrors_for_spec(cspec, full_hash_match=True)
cspec_mirrors = {}
for result in cspec_results:
s = result['spec']
assert(s._full_hash == full_hash_map[s.name])
assert(result['mirror_url'] not in cspec_mirrors)
cspec_mirrors[result['mirror_url']] = True
for s in [gspec, cspec]:
results = bindist.get_mirrors_for_spec(s)
assert(any([r['spec'] == s for r in results]))
def fake_full_hash(spec):
def fake_dag_hash(spec):
# Generate an arbitrary hash that is intended to be different than
# whatever a Spec reported before (to test actions that trigger when
# the hash changes)
@@ -430,7 +408,7 @@ def fake_full_hash(spec):
'test_mirror'
)
def test_spec_needs_rebuild(monkeypatch, tmpdir):
"""Make sure needs_rebuild properly compares remote full_hash
"""Make sure needs_rebuild properly compares remote hash
against locally computed one, avoiding unnecessary rebuilds"""
# Create a temp mirror directory for buildcache usage
@@ -445,14 +423,14 @@ def test_spec_needs_rebuild(monkeypatch, tmpdir):
# Put installed package in the buildcache
buildcache_cmd('create', '-u', '-a', '-d', mirror_dir.strpath, s.name)
rebuild = bindist.needs_rebuild(s, mirror_url, rebuild_on_errors=True)
rebuild = bindist.needs_rebuild(s, mirror_url)
assert not rebuild
# Now monkey patch Spec to change the full hash on the package
monkeypatch.setattr(spack.spec.Spec, 'full_hash', fake_full_hash)
# Now monkey patch Spec to change the hash on the package
monkeypatch.setattr(spack.spec.Spec, 'dag_hash', fake_dag_hash)
rebuild = bindist.needs_rebuild(s, mirror_url, rebuild_on_errors=True)
rebuild = bindist.needs_rebuild(s, mirror_url)
assert rebuild
@@ -624,57 +602,6 @@ def test_install_legacy_yaml(test_legacy_mirror, install_mockery_mutable_config,
uninstall_cmd('-y', '/t5mczux3tfqpxwmg7egp7axy2jvyulqk')
@pytest.mark.usefixtures(
'install_mockery_mutable_config', 'mock_packages', 'mock_fetch',
)
def test_update_index_fix_deps(monkeypatch, tmpdir, mutable_config):
"""Ensure spack buildcache update-index properly fixes up spec descriptor
files on the mirror when updating the buildcache index."""
# Create a temp mirror directory for buildcache usage
mirror_dir = tmpdir.join('mirror_dir')
mirror_url = 'file://{0}'.format(mirror_dir.strpath)
spack.config.set('mirrors', {'test': mirror_url})
a = Spec('a').concretized()
b = Spec('b').concretized()
new_b_full_hash = 'abcdef'
# Install package a with dep b
install_cmd('--no-cache', a.name)
# Create a buildcache for a and its dep b, and update index
buildcache_cmd('create', '-uad', mirror_dir.strpath, a.name)
buildcache_cmd('update-index', '-d', mirror_dir.strpath)
# Simulate an update to b that only affects full hash by simply overwriting
# the full hash in the spec.json file on the mirror
b_spec_json_name = bindist.tarball_name(b, '.spec.json')
b_spec_json_path = os.path.join(mirror_dir.strpath,
bindist.build_cache_relative_path(),
b_spec_json_name)
fs.filter_file(r'"full_hash":\s"\S+"',
'"full_hash": "{0}"'.format(new_b_full_hash),
b_spec_json_path)
# When we update the index, spack should notice that a's notion of the
# full hash of b doesn't match b's notion of it's own full hash, and as
# a result, spack should fix the spec.json for a
buildcache_cmd('update-index', '-d', mirror_dir.strpath)
# Read in the concrete spec json of a
a_spec_json_name = bindist.tarball_name(a, '.spec.json')
a_spec_json_path = os.path.join(mirror_dir.strpath,
bindist.build_cache_relative_path(),
a_spec_json_name)
# Turn concrete spec json into a concrete spec (a)
with open(a_spec_json_path) as fd:
a_prime = spec.Spec.from_json(fd.read())
# Make sure the full hash of b in a's spec json matches the new value
assert(a_prime[b.name].full_hash() == new_b_full_hash)
def test_FetchCacheError_only_accepts_lists_of_errors():
with pytest.raises(TypeError, match="list"):
bindist.FetchCacheError("error")

View File

@@ -62,6 +62,22 @@ def test_raising_exception_if_bootstrap_disabled(mutable_config):
spack.bootstrap.store_path()
def test_raising_exception_module_importable():
with pytest.raises(
ImportError,
match='cannot bootstrap the "asdf" Python module',
):
spack.bootstrap.ensure_module_importable_or_raise("asdf")
def test_raising_exception_executables_in_path():
with pytest.raises(
RuntimeError,
match="cannot bootstrap any of the asdf, fdsa executables",
):
spack.bootstrap.ensure_executables_in_path_or_raise(["asdf", "fdsa"], "python")
@pytest.mark.regression('25603')
def test_bootstrap_deactivates_environments(active_mock_environment):
assert spack.environment.active_environment() == active_mock_environment

View File

@@ -95,6 +95,25 @@ def _ensure(env_mods):
return _ensure
@pytest.fixture
def mock_module_cmd(monkeypatch):
class Logger(object):
def __init__(self, fn=None):
self.fn = fn
self.calls = []
def __call__(self, *args, **kwargs):
self.calls.append((args, kwargs))
if self.fn:
return self.fn(*args, **kwargs)
mock_module_cmd = Logger()
monkeypatch.setattr(spack.build_environment, 'module', mock_module_cmd)
monkeypatch.setattr(spack.build_environment, '_on_cray', lambda: (True, None))
return mock_module_cmd
@pytest.mark.skipif(sys.platform == 'win32',
reason="Static to Shared not supported on Win (yet)")
def test_static_to_shared_library(build_environment):
@@ -433,3 +452,23 @@ def test_build_jobs_defaults():
parallel=True, command_line=None, config_default=1, max_cpus=10) == 1
assert determine_number_of_jobs(
parallel=True, command_line=None, config_default=100, max_cpus=10) == 10
def test_dirty_disable_module_unload(
config, mock_packages, working_env, mock_module_cmd
):
"""Test that on CRAY platform 'module unload' is not called if the 'dirty'
option is on.
"""
s = spack.spec.Spec('a').concretized()
# If called with "dirty" we don't unload modules, so no calls to the
# `module` function on Cray
spack.build_environment.setup_package(s.package, dirty=True)
assert not mock_module_cmd.calls
# If called without "dirty" we unload modules on Cray
spack.build_environment.setup_package(s.package, dirty=False)
assert mock_module_cmd.calls
assert any(('unload', 'cray-libsci') == item[0] for item in mock_module_cmd.calls)
assert any(('unload', 'cray-mpich') == item[0] for item in mock_module_cmd.calls)

View File

@@ -18,26 +18,27 @@
@pytest.fixture(
scope='function',
params=[
('configure', 'autotools'),
('CMakeLists.txt', 'cmake'),
('project.pro', 'qmake'),
('pom.xml', 'maven'),
('SConstruct', 'scons'),
('waf', 'waf'),
('setup.py', 'python'),
('NAMESPACE', 'r'),
('WORKSPACE', 'bazel'),
('Makefile.PL', 'perlmake'),
('Build.PL', 'perlbuild'),
('foo.gemspec', 'ruby'),
('Rakefile', 'ruby'),
('setup.rb', 'ruby'),
('GNUmakefile', 'makefile'),
('makefile', 'makefile'),
('Makefile', 'makefile'),
('meson.build', 'meson'),
('configure.py', 'sip'),
('foobar', 'generic')
('configure', 'autotools'),
('CMakeLists.txt', 'cmake'),
('project.pro', 'qmake'),
('pom.xml', 'maven'),
('SConstruct', 'scons'),
('waf', 'waf'),
('argbah.rockspec', 'lua'),
('setup.py', 'python'),
('NAMESPACE', 'r'),
('WORKSPACE', 'bazel'),
('Makefile.PL', 'perlmake'),
('Build.PL', 'perlbuild'),
('foo.gemspec', 'ruby'),
('Rakefile', 'ruby'),
('setup.rb', 'ruby'),
('GNUmakefile', 'makefile'),
('makefile', 'makefile'),
('Makefile', 'makefile'),
('meson.build', 'meson'),
('configure.py', 'sip'),
('foobar', 'generic')
]
)
def url_and_build_system(request, tmpdir):

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