Compare commits
343 Commits
v1.0.0-alp
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ceba90bde2 | ||
|
|
c0bdc37226 | ||
|
|
8bad9fb804 | ||
|
|
2df7cc0087 | ||
|
|
40d40ccc52 | ||
|
|
afe7d6c39e | ||
|
|
113733d9fb | ||
|
|
a8e2da5bb8 | ||
|
|
97750189b6 | ||
|
|
bcd40835a0 | ||
|
|
2c3f2c5733 | ||
|
|
302d74394b | ||
|
|
cf94dc7823 | ||
|
|
4411ee3382 | ||
|
|
f790ce0f72 | ||
|
|
64d53037db | ||
|
|
4aef50739b | ||
|
|
a6e966f6f2 | ||
|
|
1f428c4188 | ||
|
|
731e48b1bd | ||
|
|
74ff9ad821 | ||
|
|
16a4eff689 | ||
|
|
d0b0d8db50 | ||
|
|
54f591cce5 | ||
|
|
8677bb4d43 | ||
|
|
b66b80a96a | ||
|
|
10e21f399c | ||
|
|
56892f6140 | ||
|
|
7eddc4b1f8 | ||
|
|
3c7392bbcc | ||
|
|
bb0517f4d9 | ||
|
|
c8994ee50f | ||
|
|
4b2f5638f2 | ||
|
|
31312a379f | ||
|
|
b0d5f272b0 | ||
|
|
1c93fef160 | ||
|
|
8bb5f4faf4 | ||
|
|
f76ab5f72f | ||
|
|
49c831edc3 | ||
|
|
c943c8c1d2 | ||
|
|
e0e6f29584 | ||
|
|
72bc3bb803 | ||
|
|
dba8fe2b96 | ||
|
|
4487598d60 | ||
|
|
495537cf56 | ||
|
|
22c3b4099f | ||
|
|
13978d11a0 | ||
|
|
a22114b20b | ||
|
|
c10624390f | ||
|
|
fb3d9de80b | ||
|
|
fbb688af07 | ||
|
|
d34b709425 | ||
|
|
cb0b188cf6 | ||
|
|
9a2b0aca66 | ||
|
|
89a8ab3233 | ||
|
|
5d87166c07 | ||
|
|
15c989b3fe | ||
|
|
b7f556e4b4 | ||
|
|
36f32ceda3 | ||
|
|
01d77ed915 | ||
|
|
0049f8332d | ||
|
|
39c10c3116 | ||
|
|
71d1901831 | ||
|
|
41e0863b86 | ||
|
|
a75d83f65c | ||
|
|
f2f13964fb | ||
|
|
9b032018d6 | ||
|
|
7d470c05be | ||
|
|
664fe9e9e6 | ||
|
|
2745a519e2 | ||
|
|
4348ee1c75 | ||
|
|
8e39fb1e54 | ||
|
|
09458312a3 | ||
|
|
5fd0693df4 | ||
|
|
f58684429d | ||
|
|
409611a479 | ||
|
|
dd98cfb839 | ||
|
|
5c91667dab | ||
|
|
9efd6f3f11 | ||
|
|
a8f5289801 | ||
|
|
ac635aa777 | ||
|
|
45dcddf9c3 | ||
|
|
f1660722e7 | ||
|
|
04b44d841c | ||
|
|
7f30502297 | ||
|
|
61b1586c51 | ||
|
|
8579efcadf | ||
|
|
1c3e2b5425 | ||
|
|
011ef0aaaf | ||
|
|
9642f3f49a | ||
|
|
a6c9b55fad | ||
|
|
608ed967e1 | ||
|
|
742eaa32b7 | ||
|
|
763b35a2e0 | ||
|
|
12280f864c | ||
|
|
253ba05732 | ||
|
|
195b869e1c | ||
|
|
393961ffd6 | ||
|
|
392a58e9be | ||
|
|
0e8e97a811 | ||
|
|
43a0cbe7a2 | ||
|
|
bb35a98079 | ||
|
|
fa7e0e8230 | ||
|
|
2c128751f5 | ||
|
|
fb0493a366 | ||
|
|
6d1b6e7087 | ||
|
|
759518182c | ||
|
|
7ebabfcf0e | ||
|
|
6203ae31d2 | ||
|
|
6b13017ded | ||
|
|
2c51b5853f | ||
|
|
d0cbd056a8 | ||
|
|
e1b579a8b4 | ||
|
|
b02dcf697d | ||
|
|
6e046b04c7 | ||
|
|
d196795437 | ||
|
|
0d444fb4e7 | ||
|
|
467e631260 | ||
|
|
f21de698f7 | ||
|
|
59532986be | ||
|
|
36fd547b40 | ||
|
|
b5f9dea6d0 | ||
|
|
5904834295 | ||
|
|
2da8a1d1e3 | ||
|
|
d50eba40d9 | ||
|
|
8d3a733b77 | ||
|
|
dfa86dce08 | ||
|
|
3d82e5c573 | ||
|
|
a77f903f4d | ||
|
|
92260b179d | ||
|
|
196c912b8a | ||
|
|
0f54995e53 | ||
|
|
9d1332f1a1 | ||
|
|
40a1da4a73 | ||
|
|
82e091e2c2 | ||
|
|
c86112b0e8 | ||
|
|
bb25c04845 | ||
|
|
d69d26d9ce | ||
|
|
06d660b9ba | ||
|
|
40b3196412 | ||
|
|
7e893da4a6 | ||
|
|
13aa8b6867 | ||
|
|
b0afb619de | ||
|
|
7a82c703c7 | ||
|
|
0d3667175a | ||
|
|
a754341f6c | ||
|
|
a50c45f00c | ||
|
|
87e65e5377 | ||
|
|
50fe96aaf6 | ||
|
|
56495a8cd8 | ||
|
|
c054cb818d | ||
|
|
bc28ec35d1 | ||
|
|
e47a6059a7 | ||
|
|
0d170b9ef3 | ||
|
|
5174cb9180 | ||
|
|
22ba366e85 | ||
|
|
13558269b5 | ||
|
|
615b7a6ddb | ||
|
|
0415b21d3d | ||
|
|
053c9d2846 | ||
|
|
1e763629f6 | ||
|
|
7568687f1e | ||
|
|
3b81c0e6b7 | ||
|
|
c764400338 | ||
|
|
4e8a6eec1a | ||
|
|
ebc9f03dda | ||
|
|
8ac0bd2825 | ||
|
|
cc9e0137df | ||
|
|
b8e448afa0 | ||
|
|
209d670bf3 | ||
|
|
c6202842ed | ||
|
|
b2a75db030 | ||
|
|
0ec00a9c9a | ||
|
|
5e3020ad02 | ||
|
|
a0d0e6321f | ||
|
|
0afac0beaa | ||
|
|
6155be8548 | ||
|
|
611cb98b02 | ||
|
|
ea5742853f | ||
|
|
25a3e8ba59 | ||
|
|
7fbb3df6b0 | ||
|
|
a728db95de | ||
|
|
7bc4069b9e | ||
|
|
51fc195d14 | ||
|
|
27a0593104 | ||
|
|
f95e27a159 | ||
|
|
effe433c96 | ||
|
|
21988fbb18 | ||
|
|
2db654bf5a | ||
|
|
9992b563db | ||
|
|
daba1a805e | ||
|
|
832bf95aa4 | ||
|
|
81e6dcd95c | ||
|
|
518572e710 | ||
|
|
6f4ac31a67 | ||
|
|
e291daaa17 | ||
|
|
58f1e791a0 | ||
|
|
aba0a740c2 | ||
|
|
0fe8e763c3 | ||
|
|
0e2d261b7e | ||
|
|
85cb234861 | ||
|
|
87a83db623 | ||
|
|
e1e17786c5 | ||
|
|
68af5cc4c0 | ||
|
|
70df460fa7 | ||
|
|
31a1b2fd6c | ||
|
|
f8fd51e12f | ||
|
|
12784594aa | ||
|
|
e0eb0aba37 | ||
|
|
f47bf5f6b8 | ||
|
|
9296527775 | ||
|
|
08c53fa405 | ||
|
|
0c6f0c090d | ||
|
|
c623448f81 | ||
|
|
df71341972 | ||
|
|
75862c456d | ||
|
|
e680a0c153 | ||
|
|
9ad36080ca | ||
|
|
ecd14f0ad9 | ||
|
|
c44edf1e8d | ||
|
|
1eacdca5aa | ||
|
|
4a8f5efb38 | ||
|
|
2e753571bd | ||
|
|
da16336550 | ||
|
|
1818e70e74 | ||
|
|
1dde785e9a | ||
|
|
a7af32c23b | ||
|
|
6c92ad439b | ||
|
|
93f555eb14 | ||
|
|
fa3725e9de | ||
|
|
870dd6206f | ||
|
|
b1d411ab06 | ||
|
|
783eccfbd5 | ||
|
|
a842332b1b | ||
|
|
7e41288ca6 | ||
|
|
3bb375a47f | ||
|
|
478855728f | ||
|
|
5e3baeabfa | ||
|
|
58b9b54066 | ||
|
|
3918deab74 | ||
|
|
ceb2ce352f | ||
|
|
7dc6bff7b1 | ||
|
|
05fbbd7164 | ||
|
|
58421866c2 | ||
|
|
962498095d | ||
|
|
d0217cf04e | ||
|
|
65745fa0df | ||
|
|
9f7cff1780 | ||
|
|
bb43fa5444 | ||
|
|
847f560a6e | ||
|
|
623ff835fc | ||
|
|
ca19790ff2 | ||
|
|
f23366e4f8 | ||
|
|
42fb689501 | ||
|
|
c33bbdb77d | ||
|
|
1af6aa22c1 | ||
|
|
03d9373e5c | ||
|
|
f469a3d6ab | ||
|
|
25f24d947a | ||
|
|
af25a84a56 | ||
|
|
59a71959e7 | ||
|
|
00e804a94b | ||
|
|
db997229f2 | ||
|
|
6fac041d40 | ||
|
|
f8b2c65ddf | ||
|
|
c504304d39 | ||
|
|
976f1c2198 | ||
|
|
e7c591a8b8 | ||
|
|
f3522cba74 | ||
|
|
0bd9c235a0 | ||
|
|
335fca7049 | ||
|
|
ce5ef14fdb | ||
|
|
2447d16e55 | ||
|
|
8196c68ff3 | ||
|
|
308f74fe8b | ||
|
|
864f09fef0 | ||
|
|
29b53581e2 | ||
|
|
e441e780b9 | ||
|
|
4c642df5ae | ||
|
|
217774c972 | ||
|
|
8ec89fc54c | ||
|
|
66ce93a2e3 | ||
|
|
116ffe5809 | ||
|
|
6b0ea2db1d | ||
|
|
d72b371c8a | ||
|
|
aa88ced154 | ||
|
|
d89ae7bcde | ||
|
|
53d1665a8b | ||
|
|
9fa1654102 | ||
|
|
2c692a5755 | ||
|
|
c0df012b18 | ||
|
|
66e8523e14 | ||
|
|
3932299768 | ||
|
|
3eba6b8379 | ||
|
|
369928200a | ||
|
|
81ed0f8d87 | ||
|
|
194b6311e9 | ||
|
|
8420898f79 | ||
|
|
f556ba46d9 | ||
|
|
ddaa9d5d81 | ||
|
|
b878fe5555 | ||
|
|
b600bfc779 | ||
|
|
612c289c41 | ||
|
|
e42c76cccf | ||
|
|
25013bacf2 | ||
|
|
3d554db198 | ||
|
|
b6def50dcb | ||
|
|
bf591c96bd | ||
|
|
edf1d2ec40 | ||
|
|
07f607ec9f | ||
|
|
93747c5e24 | ||
|
|
b746d4596a | ||
|
|
8814705936 | ||
|
|
c989541ebc | ||
|
|
1759ce05dd | ||
|
|
c0c1a4aea1 | ||
|
|
53353ae64e | ||
|
|
62f7a4c9b1 | ||
|
|
39679d0882 | ||
|
|
50e6bf9979 | ||
|
|
b874c31cc8 | ||
|
|
04baad90f5 | ||
|
|
1022527923 | ||
|
|
7ef19ec1d8 | ||
|
|
6e45b51f27 | ||
|
|
5f9cd0991b | ||
|
|
98c44fc351 | ||
|
|
b99f850c8e | ||
|
|
cbbd68d16b | ||
|
|
e4fbf99497 | ||
|
|
6a225d5405 | ||
|
|
af9fd82476 | ||
|
|
29c1152484 | ||
|
|
d6a8af6a1d | ||
|
|
3c3dad0a7a | ||
|
|
109efdff88 | ||
|
|
fa318e2c92 | ||
|
|
064e70990d | ||
|
|
c40139b7d6 | ||
|
|
c302e1a768 | ||
|
|
7171015f1c | ||
|
|
8ab6f33eb6 | ||
|
|
a66ab9cc6c |
18
.github/workflows/build-containers.yml
vendored
18
.github/workflows/build-containers.yml
vendored
@@ -40,17 +40,17 @@ jobs:
|
|||||||
# 1: Platforms to build for
|
# 1: Platforms to build for
|
||||||
# 2: Base image (e.g. ubuntu:22.04)
|
# 2: Base image (e.g. ubuntu:22.04)
|
||||||
dockerfile: [[amazon-linux, 'linux/amd64,linux/arm64', 'amazonlinux:2'],
|
dockerfile: [[amazon-linux, 'linux/amd64,linux/arm64', 'amazonlinux:2'],
|
||||||
[centos-stream9, 'linux/amd64,linux/arm64,linux/ppc64le', 'centos:stream9'],
|
[centos-stream9, 'linux/amd64,linux/arm64', 'centos:stream9'],
|
||||||
[leap15, 'linux/amd64,linux/arm64,linux/ppc64le', 'opensuse/leap:15'],
|
[leap15, 'linux/amd64,linux/arm64', 'opensuse/leap:15'],
|
||||||
[ubuntu-focal, 'linux/amd64,linux/arm64,linux/ppc64le', 'ubuntu:20.04'],
|
[ubuntu-focal, 'linux/amd64,linux/arm64', 'ubuntu:20.04'],
|
||||||
[ubuntu-jammy, 'linux/amd64,linux/arm64,linux/ppc64le', 'ubuntu:22.04'],
|
[ubuntu-jammy, 'linux/amd64,linux/arm64', 'ubuntu:22.04'],
|
||||||
[ubuntu-noble, 'linux/amd64,linux/arm64,linux/ppc64le', 'ubuntu:24.04'],
|
[ubuntu-noble, 'linux/amd64,linux/arm64', 'ubuntu:24.04'],
|
||||||
[almalinux8, 'linux/amd64,linux/arm64,linux/ppc64le', 'almalinux:8'],
|
[almalinux8, 'linux/amd64,linux/arm64', 'almalinux:8'],
|
||||||
[almalinux9, 'linux/amd64,linux/arm64,linux/ppc64le', 'almalinux:9'],
|
[almalinux9, 'linux/amd64,linux/arm64', 'almalinux:9'],
|
||||||
[rockylinux8, 'linux/amd64,linux/arm64', 'rockylinux:8'],
|
[rockylinux8, 'linux/amd64,linux/arm64', 'rockylinux:8'],
|
||||||
[rockylinux9, 'linux/amd64,linux/arm64', 'rockylinux:9'],
|
[rockylinux9, 'linux/amd64,linux/arm64', 'rockylinux:9'],
|
||||||
[fedora39, 'linux/amd64,linux/arm64,linux/ppc64le', 'fedora:39'],
|
[fedora39, 'linux/amd64,linux/arm64', 'fedora:39'],
|
||||||
[fedora40, 'linux/amd64,linux/arm64,linux/ppc64le', 'fedora:40']]
|
[fedora40, 'linux/amd64,linux/arm64', 'fedora:40']]
|
||||||
name: Build ${{ matrix.dockerfile[0] }}
|
name: Build ${{ matrix.dockerfile[0] }}
|
||||||
if: github.repository == 'spack/spack'
|
if: github.repository == 'spack/spack'
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
4
.github/workflows/ci.yaml
vendored
4
.github/workflows/ci.yaml
vendored
@@ -81,6 +81,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
with_coverage: ${{ needs.changes.outputs.core }}
|
with_coverage: ${{ needs.changes.outputs.core }}
|
||||||
|
|
||||||
|
import-check:
|
||||||
|
needs: [ changes ]
|
||||||
|
uses: ./.github/workflows/import-check.yaml
|
||||||
|
|
||||||
all-prechecks:
|
all-prechecks:
|
||||||
needs: [ prechecks ]
|
needs: [ prechecks ]
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
|
|||||||
1
.github/workflows/coverage.yml
vendored
1
.github/workflows/coverage.yml
vendored
@@ -33,3 +33,4 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
verbose: true
|
verbose: true
|
||||||
fail_ci_if_error: false
|
fail_ci_if_error: false
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
|||||||
49
.github/workflows/import-check.yaml
vendored
Normal file
49
.github/workflows/import-check.yaml
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
name: import-check
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Check we don't make the situation with circular imports worse
|
||||||
|
import-check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: julia-actions/setup-julia@v2
|
||||||
|
with:
|
||||||
|
version: '1.10'
|
||||||
|
- uses: julia-actions/cache@v2
|
||||||
|
|
||||||
|
# PR: use the base of the PR as the old commit
|
||||||
|
- name: Checkout PR base commit
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.base.sha }}
|
||||||
|
path: old
|
||||||
|
# not a PR: use the previous commit as the old commit
|
||||||
|
- name: Checkout previous commit
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
|
with:
|
||||||
|
fetch-depth: 2
|
||||||
|
path: old
|
||||||
|
- name: Checkout previous commit
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
run: git -C old reset --hard HEAD^
|
||||||
|
|
||||||
|
- name: Checkout new commit
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
|
with:
|
||||||
|
path: new
|
||||||
|
- name: Install circular import checker
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
|
with:
|
||||||
|
repository: haampie/circular-import-fighter
|
||||||
|
ref: e38bcd0aa46368e30648b61b7f0d8c1ca68aadff
|
||||||
|
path: circular-import-fighter
|
||||||
|
- name: Install dependencies
|
||||||
|
working-directory: circular-import-fighter
|
||||||
|
run: make -j dependencies
|
||||||
|
- name: Circular import check
|
||||||
|
working-directory: circular-import-fighter
|
||||||
|
run: make -j compare "SPACK_ROOT=../old ../new"
|
||||||
7
.github/workflows/unit_tests.yaml
vendored
7
.github/workflows/unit_tests.yaml
vendored
@@ -61,7 +61,7 @@ jobs:
|
|||||||
run: "brew install kcov"
|
run: "brew install kcov"
|
||||||
- name: Install Python packages
|
- name: Install Python packages
|
||||||
run: |
|
run: |
|
||||||
pip install --upgrade pip setuptools pytest pytest-xdist pytest-cov clingo
|
pip install --upgrade pip setuptools pytest pytest-xdist pytest-cov
|
||||||
pip install --upgrade flake8 "isort>=4.3.5" "mypy>=0.900" "click" "black"
|
pip install --upgrade flake8 "isort>=4.3.5" "mypy>=0.900" "click" "black"
|
||||||
- name: Setup git configuration
|
- name: Setup git configuration
|
||||||
run: |
|
run: |
|
||||||
@@ -185,6 +185,7 @@ jobs:
|
|||||||
spack bootstrap disable github-actions-v0.5
|
spack bootstrap disable github-actions-v0.5
|
||||||
spack bootstrap disable github-actions-v0.6
|
spack bootstrap disable github-actions-v0.6
|
||||||
spack bootstrap status
|
spack bootstrap status
|
||||||
|
spack solve zlib
|
||||||
spack unit-test --verbose --cov --cov-config=pyproject.toml --cov-report=xml:coverage.xml lib/spack/spack/test/concretization/core.py
|
spack unit-test --verbose --cov --cov-config=pyproject.toml --cov-report=xml:coverage.xml lib/spack/spack/test/concretization/core.py
|
||||||
- uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b
|
- uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b
|
||||||
with:
|
with:
|
||||||
@@ -222,7 +223,7 @@ jobs:
|
|||||||
. share/spack/setup-env.sh
|
. share/spack/setup-env.sh
|
||||||
$(which spack) bootstrap disable spack-install
|
$(which spack) bootstrap disable spack-install
|
||||||
$(which spack) solve zlib
|
$(which spack) solve zlib
|
||||||
common_args=(--dist loadfile --tx '4*popen//python=./bin/spack-tmpconfig python -u ./bin/spack python')
|
common_args=(--dist loadfile --tx '4*popen//python=./bin/spack-tmpconfig python -u ./bin/spack python' -x)
|
||||||
$(which spack) unit-test --verbose --cov --cov-config=pyproject.toml --cov-report=xml:coverage.xml "${common_args[@]}"
|
$(which spack) unit-test --verbose --cov --cov-config=pyproject.toml --cov-report=xml:coverage.xml "${common_args[@]}"
|
||||||
- uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b
|
- uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b
|
||||||
with:
|
with:
|
||||||
@@ -253,7 +254,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
COVERAGE_FILE: coverage/.coverage-windows
|
COVERAGE_FILE: coverage/.coverage-windows
|
||||||
run: |
|
run: |
|
||||||
spack unit-test --verbose --cov --cov-config=pyproject.toml
|
spack unit-test -x --verbose --cov --cov-config=pyproject.toml
|
||||||
./share/spack/qa/validate_last_exit.ps1
|
./share/spack/qa/validate_last_exit.ps1
|
||||||
- uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b
|
- uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b
|
||||||
with:
|
with:
|
||||||
|
|||||||
60
.github/workflows/valid-style.yml
vendored
60
.github/workflows/valid-style.yml
vendored
@@ -86,66 +86,6 @@ jobs:
|
|||||||
spack -d bootstrap now --dev
|
spack -d bootstrap now --dev
|
||||||
spack -d style -t black
|
spack -d style -t black
|
||||||
spack unit-test -V
|
spack unit-test -V
|
||||||
# Check we don't make the situation with circular imports worse
|
|
||||||
import-check:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: julia-actions/setup-julia@v2
|
|
||||||
with:
|
|
||||||
version: '1.10'
|
|
||||||
- uses: julia-actions/cache@v2
|
|
||||||
|
|
||||||
# PR: use the base of the PR as the old commit
|
|
||||||
- name: Checkout PR base commit
|
|
||||||
if: github.event_name == 'pull_request'
|
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.base.sha }}
|
|
||||||
path: old
|
|
||||||
# not a PR: use the previous commit as the old commit
|
|
||||||
- name: Checkout previous commit
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
|
||||||
with:
|
|
||||||
fetch-depth: 2
|
|
||||||
path: old
|
|
||||||
- name: Checkout previous commit
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
run: git -C old reset --hard HEAD^
|
|
||||||
|
|
||||||
- name: Checkout new commit
|
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
|
||||||
with:
|
|
||||||
path: new
|
|
||||||
- name: Install circular import checker
|
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
|
||||||
with:
|
|
||||||
repository: haampie/circular-import-fighter
|
|
||||||
ref: b5d6ce9be35f602cca7d5a6aa0259fca10639cca
|
|
||||||
path: circular-import-fighter
|
|
||||||
- name: Install dependencies
|
|
||||||
working-directory: circular-import-fighter
|
|
||||||
run: make -j dependencies
|
|
||||||
- name: Problematic imports before
|
|
||||||
working-directory: circular-import-fighter
|
|
||||||
run: make SPACK_ROOT=../old SUFFIX=.old
|
|
||||||
- name: Problematic imports after
|
|
||||||
working-directory: circular-import-fighter
|
|
||||||
run: make SPACK_ROOT=../new SUFFIX=.new
|
|
||||||
- name: Compare import cycles
|
|
||||||
working-directory: circular-import-fighter
|
|
||||||
run: |
|
|
||||||
edges_before="$(head -n1 solution.old)"
|
|
||||||
edges_after="$(head -n1 solution.new)"
|
|
||||||
if [ "$edges_after" -gt "$edges_before" ]; then
|
|
||||||
printf '\033[1;31mImport check failed: %s imports need to be deleted, ' "$edges_after"
|
|
||||||
printf 'previously this was %s\033[0m\n' "$edges_before"
|
|
||||||
printf 'Compare \033[1;97m"Problematic imports before"\033[0m and '
|
|
||||||
printf '\033[1;97m"Problematic imports after"\033[0m.\n'
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
printf '\033[1;32mImport check passed: %s <= %s\033[0m\n' "$edges_after" "$edges_before"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Further style checks from pylint
|
# Further style checks from pylint
|
||||||
pylint:
|
pylint:
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ exit 1
|
|||||||
# The code above runs this file with our preferred python interpreter.
|
# The code above runs this file with our preferred python interpreter.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
min_python3 = (3, 6)
|
min_python3 = (3, 6)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ config:
|
|||||||
install_tree:
|
install_tree:
|
||||||
root: $spack/opt/spack
|
root: $spack/opt/spack
|
||||||
projections:
|
projections:
|
||||||
all: "{architecture.platform}-{architecture.target}/{name}-{version}-{hash}"
|
all: "{architecture}/{compiler.name}-{compiler.version}/{name}-{version}-{hash}"
|
||||||
# install_tree can include an optional padded length (int or boolean)
|
# install_tree can include an optional padded length (int or boolean)
|
||||||
# default is False (do not pad)
|
# default is False (do not pad)
|
||||||
# if padded_length is True, Spack will pad as close to the system max path
|
# if padded_length is True, Spack will pad as close to the system max path
|
||||||
|
|||||||
@@ -15,11 +15,12 @@
|
|||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
packages:
|
packages:
|
||||||
all:
|
all:
|
||||||
|
compiler:
|
||||||
|
- apple-clang
|
||||||
|
- clang
|
||||||
|
- gcc
|
||||||
providers:
|
providers:
|
||||||
c: [apple-clang, llvm, gcc]
|
|
||||||
cxx: [apple-clang, llvm, gcc]
|
|
||||||
elf: [libelf]
|
elf: [libelf]
|
||||||
fortran: [gcc]
|
|
||||||
fuse: [macfuse]
|
fuse: [macfuse]
|
||||||
gl: [apple-gl]
|
gl: [apple-gl]
|
||||||
glu: [apple-glu]
|
glu: [apple-glu]
|
||||||
|
|||||||
@@ -15,18 +15,19 @@
|
|||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
packages:
|
packages:
|
||||||
all:
|
all:
|
||||||
|
compiler: [gcc, clang, oneapi, xl, nag, fj, aocc]
|
||||||
providers:
|
providers:
|
||||||
awk: [gawk]
|
awk: [gawk]
|
||||||
armci: [armcimpi]
|
armci: [armcimpi]
|
||||||
blas: [openblas, amdblis]
|
blas: [openblas, amdblis]
|
||||||
c: [gcc, llvm, intel-oneapi-compilers, xl, aocc]
|
c: [gcc]
|
||||||
cxx: [gcc, llvm, intel-oneapi-compilers, xl, aocc]
|
cxx: [gcc]
|
||||||
D: [ldc]
|
D: [ldc]
|
||||||
daal: [intel-oneapi-daal]
|
daal: [intel-oneapi-daal]
|
||||||
elf: [elfutils]
|
elf: [elfutils]
|
||||||
fftw-api: [fftw, amdfftw]
|
fftw-api: [fftw, amdfftw]
|
||||||
flame: [libflame, amdlibflame]
|
flame: [libflame, amdlibflame]
|
||||||
fortran: [gcc, llvm]
|
fortran: [gcc]
|
||||||
fortran-rt: [gcc-runtime, intel-oneapi-runtime]
|
fortran-rt: [gcc-runtime, intel-oneapi-runtime]
|
||||||
fuse: [libfuse]
|
fuse: [libfuse]
|
||||||
gl: [glx, osmesa]
|
gl: [glx, osmesa]
|
||||||
@@ -35,7 +36,7 @@ packages:
|
|||||||
go-or-gccgo-bootstrap: [go-bootstrap, gcc]
|
go-or-gccgo-bootstrap: [go-bootstrap, gcc]
|
||||||
iconv: [libiconv]
|
iconv: [libiconv]
|
||||||
ipp: [intel-oneapi-ipp]
|
ipp: [intel-oneapi-ipp]
|
||||||
java: [openjdk, jdk, ibm-java]
|
java: [openjdk, jdk]
|
||||||
jpeg: [libjpeg-turbo, libjpeg]
|
jpeg: [libjpeg-turbo, libjpeg]
|
||||||
lapack: [openblas, amdlibflame]
|
lapack: [openblas, amdlibflame]
|
||||||
libc: [glibc, musl]
|
libc: [glibc, musl]
|
||||||
@@ -72,15 +73,27 @@ packages:
|
|||||||
permissions:
|
permissions:
|
||||||
read: world
|
read: world
|
||||||
write: user
|
write: user
|
||||||
|
cray-fftw:
|
||||||
|
buildable: false
|
||||||
|
cray-libsci:
|
||||||
|
buildable: false
|
||||||
cray-mpich:
|
cray-mpich:
|
||||||
buildable: false
|
buildable: false
|
||||||
cray-mvapich2:
|
cray-mvapich2:
|
||||||
buildable: false
|
buildable: false
|
||||||
|
cray-pmi:
|
||||||
|
buildable: false
|
||||||
egl:
|
egl:
|
||||||
buildable: false
|
buildable: false
|
||||||
|
essl:
|
||||||
|
buildable: false
|
||||||
fujitsu-mpi:
|
fujitsu-mpi:
|
||||||
buildable: false
|
buildable: false
|
||||||
|
fujitsu-ssl2:
|
||||||
|
buildable: false
|
||||||
hpcx-mpi:
|
hpcx-mpi:
|
||||||
buildable: false
|
buildable: false
|
||||||
|
mpt:
|
||||||
|
buildable: false
|
||||||
spectrum-mpi:
|
spectrum-mpi:
|
||||||
buildable: false
|
buildable: false
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
config:
|
config:
|
||||||
locks: false
|
locks: false
|
||||||
build_stage::
|
build_stage::
|
||||||
- '$spack/.staging'
|
- '$user_cache_path/stage'
|
||||||
stage_name: '{name}-{version}-{hash:7}'
|
stage_name: '{name}-{version}-{hash:7}'
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
packages:
|
packages:
|
||||||
all:
|
all:
|
||||||
|
compiler:
|
||||||
|
- msvc
|
||||||
providers:
|
providers:
|
||||||
c : [msvc]
|
|
||||||
cxx: [msvc]
|
|
||||||
mpi: [msmpi]
|
mpi: [msmpi]
|
||||||
gl: [wgl]
|
gl: [wgl]
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ bootstrapping.
|
|||||||
To register the mirror on the platform where it's supposed to be used run the following command(s):
|
To register the mirror on the platform where it's supposed to be used run the following command(s):
|
||||||
% spack bootstrap add --trust local-sources /opt/bootstrap/metadata/sources
|
% spack bootstrap add --trust local-sources /opt/bootstrap/metadata/sources
|
||||||
% spack bootstrap add --trust local-binaries /opt/bootstrap/metadata/binaries
|
% spack bootstrap add --trust local-binaries /opt/bootstrap/metadata/binaries
|
||||||
|
% spack buildcache update-index /opt/bootstrap/bootstrap_cache
|
||||||
|
|
||||||
This command needs to be run on a machine with internet access and the resulting folder
|
This command needs to be run on a machine with internet access and the resulting folder
|
||||||
has to be moved over to the air-gapped system. Once the local sources are added using the
|
has to be moved over to the air-gapped system. Once the local sources are added using the
|
||||||
|
|||||||
@@ -272,9 +272,9 @@ often lists dependencies and the flags needed to locate them. The
|
|||||||
"environment variables" section lists environment variables that the
|
"environment variables" section lists environment variables that the
|
||||||
build system uses to pass flags to the compiler and linker.
|
build system uses to pass flags to the compiler and linker.
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
Addings flags to configure
|
Adding flags to configure
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
For most of the flags you encounter, you will want a variant to
|
For most of the flags you encounter, you will want a variant to
|
||||||
optionally enable/disable them. You can then optionally pass these
|
optionally enable/disable them. You can then optionally pass these
|
||||||
@@ -285,7 +285,7 @@ function like so:
|
|||||||
|
|
||||||
def configure_args(self):
|
def configure_args(self):
|
||||||
args = []
|
args = []
|
||||||
|
...
|
||||||
if self.spec.satisfies("+mpi"):
|
if self.spec.satisfies("+mpi"):
|
||||||
args.append("--enable-mpi")
|
args.append("--enable-mpi")
|
||||||
else:
|
else:
|
||||||
@@ -299,7 +299,10 @@ Alternatively, you can use the :ref:`enable_or_disable <autotools_enable_or_dis
|
|||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def configure_args(self):
|
def configure_args(self):
|
||||||
return [self.enable_or_disable("mpi")]
|
args = []
|
||||||
|
...
|
||||||
|
args.extend(self.enable_or_disable("mpi"))
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
Note that we are explicitly disabling MPI support if it is not
|
Note that we are explicitly disabling MPI support if it is not
|
||||||
@@ -344,7 +347,14 @@ typically used to enable or disable some feature within the package.
|
|||||||
default=False,
|
default=False,
|
||||||
description="Memchecker support for debugging [degrades performance]"
|
description="Memchecker support for debugging [degrades performance]"
|
||||||
)
|
)
|
||||||
config_args.extend(self.enable_or_disable("memchecker"))
|
...
|
||||||
|
|
||||||
|
def configure_args(self):
|
||||||
|
args = []
|
||||||
|
...
|
||||||
|
args.extend(self.enable_or_disable("memchecker"))
|
||||||
|
|
||||||
|
return args
|
||||||
|
|
||||||
In this example, specifying the variant ``+memchecker`` will generate
|
In this example, specifying the variant ``+memchecker`` will generate
|
||||||
the following configuration options:
|
the following configuration options:
|
||||||
|
|||||||
@@ -56,13 +56,13 @@ If you look at the ``perl`` package, you'll see:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
phases = ["configure", "build", "install"]
|
phases = ("configure", "build", "install")
|
||||||
|
|
||||||
Similarly, ``cmake`` defines:
|
Similarly, ``cmake`` defines:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
phases = ["bootstrap", "build", "install"]
|
phases = ("bootstrap", "build", "install")
|
||||||
|
|
||||||
If we look at the ``cmake`` example, this tells Spack's ``PackageBase``
|
If we look at the ``cmake`` example, this tells Spack's ``PackageBase``
|
||||||
class to run the ``bootstrap``, ``build``, and ``install`` functions
|
class to run the ``bootstrap``, ``build``, and ``install`` functions
|
||||||
|
|||||||
@@ -361,7 +361,6 @@ and the tags associated with the class of runners to build on.
|
|||||||
* ``.linux_neoverse_n1``
|
* ``.linux_neoverse_n1``
|
||||||
* ``.linux_neoverse_v1``
|
* ``.linux_neoverse_v1``
|
||||||
* ``.linux_neoverse_v2``
|
* ``.linux_neoverse_v2``
|
||||||
* ``.linux_power``
|
|
||||||
* ``.linux_skylake``
|
* ``.linux_skylake``
|
||||||
* ``.linux_x86_64``
|
* ``.linux_x86_64``
|
||||||
* ``.linux_x86_64_v4``
|
* ``.linux_x86_64_v4``
|
||||||
|
|||||||
@@ -543,10 +543,10 @@ With either interpreter you can run a single command:
|
|||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ spack python -c 'from spack.spec import Spec; Spec("python").concretized()'
|
$ spack python -c 'from spack.concretize import concretize_one; concretize_one("python")'
|
||||||
...
|
...
|
||||||
|
|
||||||
$ spack python -i ipython -c 'from spack.spec import Spec; Spec("python").concretized()'
|
$ spack python -i ipython -c 'from spack.concretize import concretize_one; concretize_one("python")'
|
||||||
Out[1]: ...
|
Out[1]: ...
|
||||||
|
|
||||||
or a file:
|
or a file:
|
||||||
|
|||||||
@@ -112,6 +112,19 @@ the original but may concretize differently in the presence of different
|
|||||||
explicit or default configuration settings (e.g., a different version of
|
explicit or default configuration settings (e.g., a different version of
|
||||||
Spack or for a different user account).
|
Spack or for a different user account).
|
||||||
|
|
||||||
|
Environments created from a manifest will copy any included configs
|
||||||
|
from relative paths inside the environment. Relative paths from
|
||||||
|
outside the environment will cause errors, and absolute paths will be
|
||||||
|
kept absolute. For example, if ``spack.yaml`` includes:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
spack:
|
||||||
|
include: [./config.yaml]
|
||||||
|
|
||||||
|
then the created environment will have its own copy of the file
|
||||||
|
``config.yaml`` copied from the location in the original environment.
|
||||||
|
|
||||||
Create an environment from a ``spack.lock`` file using:
|
Create an environment from a ``spack.lock`` file using:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|||||||
@@ -456,14 +456,13 @@ For instance, the following config options,
|
|||||||
tcl:
|
tcl:
|
||||||
all:
|
all:
|
||||||
suffixes:
|
suffixes:
|
||||||
^python@3: 'python{^python.version}'
|
^python@3: 'python{^python.version.up_to_2}'
|
||||||
^openblas: 'openblas'
|
^openblas: 'openblas'
|
||||||
|
|
||||||
will add a ``python-3.12.1`` version string to any packages compiled with
|
will add a ``python3.12`` to module names of packages compiled with Python 3.12, and similarly for
|
||||||
Python matching the spec, ``python@3``. This is useful to know which
|
all specs depending on ``python@3``. This is useful to know which version of Python a set of Python
|
||||||
version of Python a set of Python extensions is associated with. Likewise, the
|
extensions is associated with. Likewise, the ``openblas`` string is attached to any program that
|
||||||
``openblas`` string is attached to any program that has openblas in the spec,
|
has openblas in the spec, most likely via the ``+blas`` variant specification.
|
||||||
most likely via the ``+blas`` variant specification.
|
|
||||||
|
|
||||||
The most heavyweight solution to module naming is to change the entire
|
The most heavyweight solution to module naming is to change the entire
|
||||||
naming convention for module files. This uses the projections format
|
naming convention for module files. This uses the projections format
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ that ``--tests`` is passed to ``spack ci rebuild`` as part of the
|
|||||||
- spack --version
|
- spack --version
|
||||||
- cd ${SPACK_CONCRETE_ENV_DIR}
|
- cd ${SPACK_CONCRETE_ENV_DIR}
|
||||||
- spack env activate --without-view .
|
- spack env activate --without-view .
|
||||||
- spack config add "config:install_tree:projections:${SPACK_JOB_SPEC_PKG_NAME}:'morepadding/{architecture.platform}-{architecture.target}/{name}-{version}-{hash}'"
|
- spack config add "config:install_tree:projections:${SPACK_JOB_SPEC_PKG_NAME}:'morepadding/{architecture}/{compiler.name}-{compiler.version}/{name}-{version}-{hash}'"
|
||||||
- mkdir -p ${SPACK_ARTIFACTS_ROOT}/user_data
|
- mkdir -p ${SPACK_ARTIFACTS_ROOT}/user_data
|
||||||
- if [[ -r /mnt/key/intermediate_ci_signing_key.gpg ]]; then spack gpg trust /mnt/key/intermediate_ci_signing_key.gpg; fi
|
- if [[ -r /mnt/key/intermediate_ci_signing_key.gpg ]]; then spack gpg trust /mnt/key/intermediate_ci_signing_key.gpg; fi
|
||||||
- if [[ -r /mnt/key/spack_public_key.gpg ]]; then spack gpg trust /mnt/key/spack_public_key.gpg; fi
|
- if [[ -r /mnt/key/spack_public_key.gpg ]]; then spack gpg trust /mnt/key/spack_public_key.gpg; fi
|
||||||
|
|||||||
1
lib/spack/env/aocc/clang
vendored
Symbolic link
1
lib/spack/env/aocc/clang
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/aocc/clang++
vendored
Symbolic link
1
lib/spack/env/aocc/clang++
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cpp
|
||||||
1
lib/spack/env/aocc/flang
vendored
Symbolic link
1
lib/spack/env/aocc/flang
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../fc
|
||||||
1
lib/spack/env/arm/armclang
vendored
Symbolic link
1
lib/spack/env/arm/armclang
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/arm/armclang++
vendored
Symbolic link
1
lib/spack/env/arm/armclang++
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/arm/armflang
vendored
Symbolic link
1
lib/spack/env/arm/armflang
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/c++
vendored
Symbolic link
1
lib/spack/env/c++
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
cc
|
||||||
1
lib/spack/env/c89
vendored
Symbolic link
1
lib/spack/env/c89
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
cc
|
||||||
1
lib/spack/env/c99
vendored
Symbolic link
1
lib/spack/env/c99
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
cc
|
||||||
1
lib/spack/env/case-insensitive/CC
vendored
Symbolic link
1
lib/spack/env/case-insensitive/CC
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
@@ -39,6 +39,12 @@ readonly params="\
|
|||||||
SPACK_ENV_PATH
|
SPACK_ENV_PATH
|
||||||
SPACK_DEBUG_LOG_DIR
|
SPACK_DEBUG_LOG_DIR
|
||||||
SPACK_DEBUG_LOG_ID
|
SPACK_DEBUG_LOG_ID
|
||||||
|
SPACK_COMPILER_SPEC
|
||||||
|
SPACK_CC_RPATH_ARG
|
||||||
|
SPACK_CXX_RPATH_ARG
|
||||||
|
SPACK_F77_RPATH_ARG
|
||||||
|
SPACK_FC_RPATH_ARG
|
||||||
|
SPACK_LINKER_ARG
|
||||||
SPACK_SHORT_SPEC
|
SPACK_SHORT_SPEC
|
||||||
SPACK_SYSTEM_DIRS
|
SPACK_SYSTEM_DIRS
|
||||||
SPACK_MANAGED_DIRS"
|
SPACK_MANAGED_DIRS"
|
||||||
@@ -339,9 +345,6 @@ case "$command" in
|
|||||||
;;
|
;;
|
||||||
ld|ld.gold|ld.lld)
|
ld|ld.gold|ld.lld)
|
||||||
mode=ld
|
mode=ld
|
||||||
if [ -z "$SPACK_CC_RPATH_ARG" ]; then
|
|
||||||
comp="CXX"
|
|
||||||
fi
|
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
die "Unknown compiler: $command"
|
die "Unknown compiler: $command"
|
||||||
@@ -396,12 +399,10 @@ fi
|
|||||||
#
|
#
|
||||||
dtags_to_add="${SPACK_DTAGS_TO_ADD}"
|
dtags_to_add="${SPACK_DTAGS_TO_ADD}"
|
||||||
dtags_to_strip="${SPACK_DTAGS_TO_STRIP}"
|
dtags_to_strip="${SPACK_DTAGS_TO_STRIP}"
|
||||||
|
linker_arg="${SPACK_LINKER_ARG}"
|
||||||
linker_arg="ERROR: LINKER ARG WAS NOT SET, MAYBE THE PACKAGE DOES NOT DEPEND ON ${comp}?"
|
|
||||||
eval "linker_arg=\${SPACK_${comp}_LINKER_ARG:?${linker_arg}}"
|
|
||||||
|
|
||||||
# Set up rpath variable according to language.
|
# Set up rpath variable according to language.
|
||||||
rpath="ERROR: RPATH ARG WAS NOT SET, MAYBE THE PACKAGE DOES NOT DEPEND ON ${comp}?"
|
rpath="ERROR: RPATH ARG WAS NOT SET"
|
||||||
eval "rpath=\${SPACK_${comp}_RPATH_ARG:?${rpath}}"
|
eval "rpath=\${SPACK_${comp}_RPATH_ARG:?${rpath}}"
|
||||||
|
|
||||||
# Dump the mode and exit if the command is dump-mode.
|
# Dump the mode and exit if the command is dump-mode.
|
||||||
@@ -410,6 +411,13 @@ if [ "$SPACK_TEST_COMMAND" = "dump-mode" ]; then
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# If, say, SPACK_CC is set but SPACK_FC is not, we want to know. Compilers do not
|
||||||
|
# *have* to set up Fortran executables, so we need to tell the user when a build is
|
||||||
|
# about to attempt to use them unsuccessfully.
|
||||||
|
if [ -z "$command" ]; then
|
||||||
|
die "Compiler '$SPACK_COMPILER_SPEC' does not have a $language compiler configured."
|
||||||
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# Filter '.' and Spack environment directories out of PATH so that
|
# Filter '.' and Spack environment directories out of PATH so that
|
||||||
# this script doesn't just call itself
|
# this script doesn't just call itself
|
||||||
@@ -779,17 +787,15 @@ case "$mode" in
|
|||||||
C)
|
C)
|
||||||
extend spack_flags_list SPACK_ALWAYS_CFLAGS
|
extend spack_flags_list SPACK_ALWAYS_CFLAGS
|
||||||
extend spack_flags_list SPACK_CFLAGS
|
extend spack_flags_list SPACK_CFLAGS
|
||||||
preextend flags_list SPACK_TARGET_ARGS_CC
|
|
||||||
;;
|
;;
|
||||||
CXX)
|
CXX)
|
||||||
extend spack_flags_list SPACK_ALWAYS_CXXFLAGS
|
extend spack_flags_list SPACK_ALWAYS_CXXFLAGS
|
||||||
extend spack_flags_list SPACK_CXXFLAGS
|
extend spack_flags_list SPACK_CXXFLAGS
|
||||||
preextend flags_list SPACK_TARGET_ARGS_CXX
|
|
||||||
;;
|
|
||||||
F)
|
|
||||||
preextend flags_list SPACK_TARGET_ARGS_FORTRAN
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
# prepend target args
|
||||||
|
preextend flags_list SPACK_TARGET_ARGS
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
1
lib/spack/env/cce/case-insensitive/CC
vendored
Symbolic link
1
lib/spack/env/cce/case-insensitive/CC
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../cc
|
||||||
1
lib/spack/env/cce/case-insensitive/crayCC
vendored
Symbolic link
1
lib/spack/env/cce/case-insensitive/crayCC
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../cc
|
||||||
1
lib/spack/env/cce/cc
vendored
Symbolic link
1
lib/spack/env/cce/cc
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/cce/craycc
vendored
Symbolic link
1
lib/spack/env/cce/craycc
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/cce/crayftn
vendored
Symbolic link
1
lib/spack/env/cce/crayftn
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/cce/ftn
vendored
Symbolic link
1
lib/spack/env/cce/ftn
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/clang/clang
vendored
Symbolic link
1
lib/spack/env/clang/clang
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/clang/clang++
vendored
Symbolic link
1
lib/spack/env/clang/clang++
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/clang/flang
vendored
Symbolic link
1
lib/spack/env/clang/flang
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/clang/gfortran
vendored
Symbolic link
1
lib/spack/env/clang/gfortran
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/cpp
vendored
Symbolic link
1
lib/spack/env/cpp
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
cc
|
||||||
1
lib/spack/env/f77
vendored
Symbolic link
1
lib/spack/env/f77
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
cc
|
||||||
1
lib/spack/env/f90
vendored
Symbolic link
1
lib/spack/env/f90
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
cc
|
||||||
1
lib/spack/env/f95
vendored
Symbolic link
1
lib/spack/env/f95
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
cc
|
||||||
1
lib/spack/env/fc
vendored
Symbolic link
1
lib/spack/env/fc
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
cc
|
||||||
1
lib/spack/env/fj/case-insensitive/FCC
vendored
Symbolic link
1
lib/spack/env/fj/case-insensitive/FCC
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../cc
|
||||||
1
lib/spack/env/fj/fcc
vendored
Symbolic link
1
lib/spack/env/fj/fcc
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/fj/frt
vendored
Symbolic link
1
lib/spack/env/fj/frt
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/ftn
vendored
Symbolic link
1
lib/spack/env/ftn
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
cc
|
||||||
1
lib/spack/env/gcc/g++
vendored
Symbolic link
1
lib/spack/env/gcc/g++
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/gcc/gcc
vendored
Symbolic link
1
lib/spack/env/gcc/gcc
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/gcc/gfortran
vendored
Symbolic link
1
lib/spack/env/gcc/gfortran
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/intel/icc
vendored
Symbolic link
1
lib/spack/env/intel/icc
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/intel/icpc
vendored
Symbolic link
1
lib/spack/env/intel/icpc
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/intel/ifort
vendored
Symbolic link
1
lib/spack/env/intel/ifort
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/ld
vendored
Symbolic link
1
lib/spack/env/ld
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
cc
|
||||||
1
lib/spack/env/ld.gold
vendored
Symbolic link
1
lib/spack/env/ld.gold
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
cc
|
||||||
1
lib/spack/env/ld.lld
vendored
Symbolic link
1
lib/spack/env/ld.lld
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
cc
|
||||||
1
lib/spack/env/nag/nagfor
vendored
Symbolic link
1
lib/spack/env/nag/nagfor
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/nvhpc/nvc
vendored
Symbolic link
1
lib/spack/env/nvhpc/nvc
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/nvhpc/nvc++
vendored
Symbolic link
1
lib/spack/env/nvhpc/nvc++
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/nvhpc/nvfortran
vendored
Symbolic link
1
lib/spack/env/nvhpc/nvfortran
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/oneapi/dpcpp
vendored
Symbolic link
1
lib/spack/env/oneapi/dpcpp
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/oneapi/icpx
vendored
Symbolic link
1
lib/spack/env/oneapi/icpx
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/oneapi/icx
vendored
Symbolic link
1
lib/spack/env/oneapi/icx
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/oneapi/ifx
vendored
Symbolic link
1
lib/spack/env/oneapi/ifx
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/pgi/pgc++
vendored
Symbolic link
1
lib/spack/env/pgi/pgc++
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/pgi/pgcc
vendored
Symbolic link
1
lib/spack/env/pgi/pgcc
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/pgi/pgfortran
vendored
Symbolic link
1
lib/spack/env/pgi/pgfortran
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/rocmcc/amdclang
vendored
Symbolic link
1
lib/spack/env/rocmcc/amdclang
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/rocmcc/amdclang++
vendored
Symbolic link
1
lib/spack/env/rocmcc/amdclang++
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cpp
|
||||||
1
lib/spack/env/rocmcc/amdflang
vendored
Symbolic link
1
lib/spack/env/rocmcc/amdflang
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../fc
|
||||||
1
lib/spack/env/xl/xlc
vendored
Symbolic link
1
lib/spack/env/xl/xlc
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/xl/xlc++
vendored
Symbolic link
1
lib/spack/env/xl/xlc++
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/xl/xlf
vendored
Symbolic link
1
lib/spack/env/xl/xlf
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/xl/xlf90
vendored
Symbolic link
1
lib/spack/env/xl/xlf90
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/xl_r/xlc++_r
vendored
Symbolic link
1
lib/spack/env/xl_r/xlc++_r
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/xl_r/xlc_r
vendored
Symbolic link
1
lib/spack/env/xl_r/xlc_r
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/xl_r/xlf90_r
vendored
Symbolic link
1
lib/spack/env/xl_r/xlf90_r
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
1
lib/spack/env/xl_r/xlf_r
vendored
Symbolic link
1
lib/spack/env/xl_r/xlf_r
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cc
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
"""URL primitives that just require Python standard library."""
|
"""URL primitives that just require Python standard library."""
|
||||||
import itertools
|
import itertools
|
||||||
import os.path
|
import os
|
||||||
import re
|
import re
|
||||||
from typing import Optional, Set, Tuple
|
from typing import Optional, Set, Tuple
|
||||||
from urllib.parse import urlsplit, urlunsplit
|
from urllib.parse import urlsplit, urlunsplit
|
||||||
|
|||||||
@@ -75,7 +75,6 @@
|
|||||||
"install_tree",
|
"install_tree",
|
||||||
"is_exe",
|
"is_exe",
|
||||||
"join_path",
|
"join_path",
|
||||||
"last_modification_time_recursive",
|
|
||||||
"library_extensions",
|
"library_extensions",
|
||||||
"mkdirp",
|
"mkdirp",
|
||||||
"partition_path",
|
"partition_path",
|
||||||
@@ -669,7 +668,7 @@ def copy(src, dest, _permissions=False):
|
|||||||
_permissions (bool): for internal use only
|
_permissions (bool): for internal use only
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
IOError: if *src* does not match any files or directories
|
OSError: if *src* does not match any files or directories
|
||||||
ValueError: if *src* matches multiple files but *dest* is
|
ValueError: if *src* matches multiple files but *dest* is
|
||||||
not a directory
|
not a directory
|
||||||
"""
|
"""
|
||||||
@@ -680,7 +679,7 @@ def copy(src, dest, _permissions=False):
|
|||||||
|
|
||||||
files = glob.glob(src)
|
files = glob.glob(src)
|
||||||
if not files:
|
if not files:
|
||||||
raise IOError("No such file or directory: '{0}'".format(src))
|
raise OSError("No such file or directory: '{0}'".format(src))
|
||||||
if len(files) > 1 and not os.path.isdir(dest):
|
if len(files) > 1 and not os.path.isdir(dest):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"'{0}' matches multiple files but '{1}' is not a directory".format(src, dest)
|
"'{0}' matches multiple files but '{1}' is not a directory".format(src, dest)
|
||||||
@@ -711,7 +710,7 @@ def install(src, dest):
|
|||||||
dest (str): the destination file or directory
|
dest (str): the destination file or directory
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
IOError: if *src* does not match any files or directories
|
OSError: if *src* does not match any files or directories
|
||||||
ValueError: if *src* matches multiple files but *dest* is
|
ValueError: if *src* matches multiple files but *dest* is
|
||||||
not a directory
|
not a directory
|
||||||
"""
|
"""
|
||||||
@@ -749,7 +748,7 @@ def copy_tree(
|
|||||||
_permissions (bool): for internal use only
|
_permissions (bool): for internal use only
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
IOError: if *src* does not match any files or directories
|
OSError: if *src* does not match any files or directories
|
||||||
ValueError: if *src* is a parent directory of *dest*
|
ValueError: if *src* is a parent directory of *dest*
|
||||||
"""
|
"""
|
||||||
if _permissions:
|
if _permissions:
|
||||||
@@ -763,7 +762,7 @@ def copy_tree(
|
|||||||
|
|
||||||
files = glob.glob(src)
|
files = glob.glob(src)
|
||||||
if not files:
|
if not files:
|
||||||
raise IOError("No such file or directory: '{0}'".format(src))
|
raise OSError("No such file or directory: '{0}'".format(src))
|
||||||
|
|
||||||
# For Windows hard-links and junctions, the source path must exist to make a symlink. Add
|
# For Windows hard-links and junctions, the source path must exist to make a symlink. Add
|
||||||
# all symlinks to this list while traversing the tree, then when finished, make all
|
# all symlinks to this list while traversing the tree, then when finished, make all
|
||||||
@@ -844,7 +843,7 @@ def install_tree(src, dest, symlinks=True, ignore=None):
|
|||||||
ignore (typing.Callable): function indicating which files to ignore
|
ignore (typing.Callable): function indicating which files to ignore
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
IOError: if *src* does not match any files or directories
|
OSError: if *src* does not match any files or directories
|
||||||
ValueError: if *src* is a parent directory of *dest*
|
ValueError: if *src* is a parent directory of *dest*
|
||||||
"""
|
"""
|
||||||
copy_tree(src, dest, symlinks=symlinks, ignore=ignore, _permissions=True)
|
copy_tree(src, dest, symlinks=symlinks, ignore=ignore, _permissions=True)
|
||||||
@@ -1470,15 +1469,36 @@ def set_executable(path):
|
|||||||
|
|
||||||
|
|
||||||
@system_path_filter
|
@system_path_filter
|
||||||
def last_modification_time_recursive(path):
|
def recursive_mtime_greater_than(path: str, time: float) -> bool:
|
||||||
path = os.path.abspath(path)
|
"""Returns true if any file or dir recursively under `path` has mtime greater than `time`."""
|
||||||
times = [os.stat(path).st_mtime]
|
# use bfs order to increase likelihood of early return
|
||||||
times.extend(
|
queue: Deque[str] = collections.deque([path])
|
||||||
os.lstat(os.path.join(root, name)).st_mtime
|
|
||||||
for root, dirs, files in os.walk(path)
|
if os.stat(path).st_mtime > time:
|
||||||
for name in dirs + files
|
return True
|
||||||
)
|
|
||||||
return max(times)
|
while queue:
|
||||||
|
current = queue.popleft()
|
||||||
|
|
||||||
|
try:
|
||||||
|
entries = os.scandir(current)
|
||||||
|
except OSError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
with entries:
|
||||||
|
for entry in entries:
|
||||||
|
try:
|
||||||
|
st = entry.stat(follow_symlinks=False)
|
||||||
|
except OSError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if st.st_mtime > time:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if entry.is_dir(follow_symlinks=False):
|
||||||
|
queue.append(entry.path)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
@system_path_filter
|
@system_path_filter
|
||||||
@@ -1740,8 +1760,7 @@ def find(
|
|||||||
|
|
||||||
|
|
||||||
def _log_file_access_issue(e: OSError, path: str) -> None:
|
def _log_file_access_issue(e: OSError, path: str) -> None:
|
||||||
errno_name = errno.errorcode.get(e.errno, "UNKNOWN")
|
tty.debug(f"find must skip {path}: {e}")
|
||||||
tty.debug(f"find must skip {path}: {errno_name} {e}")
|
|
||||||
|
|
||||||
|
|
||||||
def _file_id(s: os.stat_result) -> Tuple[int, int]:
|
def _file_id(s: os.stat_result) -> Tuple[int, int]:
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ def index_by(objects, *funcs):
|
|||||||
if isinstance(f, str):
|
if isinstance(f, str):
|
||||||
f = lambda x: getattr(x, funcs[0])
|
f = lambda x: getattr(x, funcs[0])
|
||||||
elif isinstance(f, tuple):
|
elif isinstance(f, tuple):
|
||||||
f = lambda x: tuple(getattr(x, p, None) for p in funcs[0])
|
f = lambda x: tuple(getattr(x, p) for p in funcs[0])
|
||||||
|
|
||||||
result = {}
|
result = {}
|
||||||
for o in objects:
|
for o in objects:
|
||||||
@@ -996,8 +996,11 @@ def _receive_forwarded(self, context: str, exc: Exception, tb: List[str]):
|
|||||||
def grouped_message(self, with_tracebacks: bool = True) -> str:
|
def grouped_message(self, with_tracebacks: bool = True) -> str:
|
||||||
"""Print out an error message coalescing all the forwarded errors."""
|
"""Print out an error message coalescing all the forwarded errors."""
|
||||||
each_exception_message = [
|
each_exception_message = [
|
||||||
"\n\t{0} raised {1}: {2}\n{3}".format(
|
"{0} raised {1}: {2}{3}".format(
|
||||||
context, exc.__class__.__name__, exc, f"\n{''.join(tb)}" if with_tracebacks else ""
|
context,
|
||||||
|
exc.__class__.__name__,
|
||||||
|
exc,
|
||||||
|
"\n{0}".format("".join(tb)) if with_tracebacks else "",
|
||||||
)
|
)
|
||||||
for context, exc, tb in self.exceptions
|
for context, exc, tb in self.exceptions
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ class LinkTree:
|
|||||||
|
|
||||||
def __init__(self, source_root):
|
def __init__(self, source_root):
|
||||||
if not os.path.exists(source_root):
|
if not os.path.exists(source_root):
|
||||||
raise IOError("No such file or directory: '%s'", source_root)
|
raise OSError("No such file or directory: '%s'", source_root)
|
||||||
|
|
||||||
self._root = source_root
|
self._root = source_root
|
||||||
|
|
||||||
|
|||||||
@@ -391,7 +391,7 @@ def _poll_lock(self, op: int) -> bool:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except IOError as e:
|
except OSError as e:
|
||||||
# EAGAIN and EACCES == locked by another process (so try again)
|
# EAGAIN and EACCES == locked by another process (so try again)
|
||||||
if e.errno not in (errno.EAGAIN, errno.EACCES):
|
if e.errno not in (errno.EAGAIN, errno.EACCES):
|
||||||
raise
|
raise
|
||||||
|
|||||||
@@ -918,7 +918,7 @@ def _writer_daemon(
|
|||||||
try:
|
try:
|
||||||
if stdin_file.read(1) == "v":
|
if stdin_file.read(1) == "v":
|
||||||
echo = not echo
|
echo = not echo
|
||||||
except IOError as e:
|
except OSError as e:
|
||||||
# If SIGTTIN is ignored, the system gives EIO
|
# If SIGTTIN is ignored, the system gives EIO
|
||||||
# to let the caller know the read failed b/c it
|
# to let the caller know the read failed b/c it
|
||||||
# was in the bg. Ignore that too.
|
# was in the bg. Ignore that too.
|
||||||
@@ -1013,7 +1013,7 @@ def wrapped(*args, **kwargs):
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
return function(*args, **kwargs)
|
return function(*args, **kwargs)
|
||||||
except IOError as e:
|
except OSError as e:
|
||||||
if e.errno == errno.EINTR:
|
if e.errno == errno.EINTR:
|
||||||
continue
|
continue
|
||||||
raise
|
raise
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
import spack.util.git
|
import spack.util.git
|
||||||
|
|
||||||
#: PEP440 canonical <major>.<minor>.<micro>.<devN> string
|
#: PEP440 canonical <major>.<minor>.<micro>.<devN> string
|
||||||
__version__ = "1.0.0-alpha.3"
|
__version__ = "1.0.0.dev0"
|
||||||
spack_version = __version__
|
spack_version = __version__
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1356,14 +1356,8 @@ def _test_detection_by_executable(pkgs, debug_log, error_cls):
|
|||||||
|
|
||||||
def _compare_extra_attribute(_expected, _detected, *, _spec):
|
def _compare_extra_attribute(_expected, _detected, *, _spec):
|
||||||
result = []
|
result = []
|
||||||
# Check items are of the same type
|
|
||||||
if not isinstance(_detected, type(_expected)):
|
|
||||||
_summary = f'{pkg_name}: error when trying to detect "{_expected}"'
|
|
||||||
_details = [f"{_detected} was detected instead"]
|
|
||||||
return [error_cls(summary=_summary, details=_details)]
|
|
||||||
|
|
||||||
# If they are string expected is a regex
|
# If they are string expected is a regex
|
||||||
if isinstance(_expected, str):
|
if isinstance(_expected, str) and isinstance(_detected, str):
|
||||||
try:
|
try:
|
||||||
_regex = re.compile(_expected)
|
_regex = re.compile(_expected)
|
||||||
except re.error:
|
except re.error:
|
||||||
@@ -1379,7 +1373,7 @@ def _compare_extra_attribute(_expected, _detected, *, _spec):
|
|||||||
_details = [f"{_detected} does not match the regex"]
|
_details = [f"{_detected} does not match the regex"]
|
||||||
return [error_cls(summary=_summary, details=_details)]
|
return [error_cls(summary=_summary, details=_details)]
|
||||||
|
|
||||||
if isinstance(_expected, dict):
|
elif isinstance(_expected, dict) and isinstance(_detected, dict):
|
||||||
_not_detected = set(_expected.keys()) - set(_detected.keys())
|
_not_detected = set(_expected.keys()) - set(_detected.keys())
|
||||||
if _not_detected:
|
if _not_detected:
|
||||||
_summary = f"{pkg_name}: cannot detect some attributes for spec {_spec}"
|
_summary = f"{pkg_name}: cannot detect some attributes for spec {_spec}"
|
||||||
@@ -1394,6 +1388,10 @@ def _compare_extra_attribute(_expected, _detected, *, _spec):
|
|||||||
result.extend(
|
result.extend(
|
||||||
_compare_extra_attribute(_expected[_key], _detected[_key], _spec=_spec)
|
_compare_extra_attribute(_expected[_key], _detected[_key], _spec=_spec)
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
_summary = f'{pkg_name}: error when trying to detect "{_expected}"'
|
||||||
|
_details = [f"{_detected} was detected instead"]
|
||||||
|
return [error_cls(summary=_summary, details=_details)]
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
import codecs
|
import codecs
|
||||||
import collections
|
import collections
|
||||||
import concurrent.futures
|
import concurrent.futures
|
||||||
|
import contextlib
|
||||||
import copy
|
import copy
|
||||||
import hashlib
|
import hashlib
|
||||||
import io
|
import io
|
||||||
@@ -23,7 +24,7 @@
|
|||||||
import urllib.request
|
import urllib.request
|
||||||
import warnings
|
import warnings
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
from typing import IO, Dict, Iterable, List, NamedTuple, Optional, Set, Tuple, Union
|
from typing import IO, Callable, Dict, Iterable, List, NamedTuple, Optional, Set, Tuple, Union
|
||||||
|
|
||||||
import llnl.util.filesystem as fsys
|
import llnl.util.filesystem as fsys
|
||||||
import llnl.util.lang
|
import llnl.util.lang
|
||||||
@@ -91,6 +92,9 @@
|
|||||||
CURRENT_BUILD_CACHE_LAYOUT_VERSION = 2
|
CURRENT_BUILD_CACHE_LAYOUT_VERSION = 2
|
||||||
|
|
||||||
|
|
||||||
|
INDEX_HASH_FILE = "index.json.hash"
|
||||||
|
|
||||||
|
|
||||||
class BuildCacheDatabase(spack_db.Database):
|
class BuildCacheDatabase(spack_db.Database):
|
||||||
"""A database for binary buildcaches.
|
"""A database for binary buildcaches.
|
||||||
|
|
||||||
@@ -502,7 +506,7 @@ def _fetch_and_cache_index(self, mirror_url, cache_entry={}):
|
|||||||
scheme = urllib.parse.urlparse(mirror_url).scheme
|
scheme = urllib.parse.urlparse(mirror_url).scheme
|
||||||
|
|
||||||
if scheme != "oci" and not web_util.url_exists(
|
if scheme != "oci" and not web_util.url_exists(
|
||||||
url_util.join(mirror_url, BUILD_CACHE_RELATIVE_PATH, "index.json")
|
url_util.join(mirror_url, BUILD_CACHE_RELATIVE_PATH, spack_db.INDEX_JSON_FILE)
|
||||||
):
|
):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -625,14 +629,7 @@ def tarball_directory_name(spec):
|
|||||||
Return name of the tarball directory according to the convention
|
Return name of the tarball directory according to the convention
|
||||||
<os>-<architecture>/<compiler>/<package>-<version>/
|
<os>-<architecture>/<compiler>/<package>-<version>/
|
||||||
"""
|
"""
|
||||||
if spec.original_spec_format() < 5:
|
return spec.format_path("{architecture}/{compiler.name}-{compiler.version}/{name}-{version}")
|
||||||
compiler = spec.annotations.compiler_node_attribute
|
|
||||||
assert compiler is not None, "a compiler spec is expected"
|
|
||||||
return spec.format_path(
|
|
||||||
f"{spec.architecture}/{compiler.name}-{compiler.version}/{spec.name}-{spec.version}"
|
|
||||||
)
|
|
||||||
|
|
||||||
return spec.format_path(f"{spec.architecture.platform}/{spec.name}-{spec.version}")
|
|
||||||
|
|
||||||
|
|
||||||
def tarball_name(spec, ext):
|
def tarball_name(spec, ext):
|
||||||
@@ -640,16 +637,8 @@ def tarball_name(spec, ext):
|
|||||||
Return the name of the tarfile according to the convention
|
Return the name of the tarfile according to the convention
|
||||||
<os>-<architecture>-<package>-<dag_hash><ext>
|
<os>-<architecture>-<package>-<dag_hash><ext>
|
||||||
"""
|
"""
|
||||||
if spec.original_spec_format() < 5:
|
spec_formatted = spec.format_path(
|
||||||
compiler = spec.annotations.compiler_node_attribute
|
"{architecture}-{compiler.name}-{compiler.version}-{name}-{version}-{hash}"
|
||||||
assert compiler is not None, "a compiler spec is expected"
|
|
||||||
spec_formatted = (
|
|
||||||
f"{spec.architecture}-{compiler.name}-{compiler.version}-{spec.name}"
|
|
||||||
f"-{spec.version}-{spec.dag_hash()}"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
spec_formatted = (
|
|
||||||
f"{spec.architecture.platform}-{spec.name}-{spec.version}-{spec.dag_hash()}"
|
|
||||||
)
|
)
|
||||||
return f"{spec_formatted}{ext}"
|
return f"{spec_formatted}{ext}"
|
||||||
|
|
||||||
@@ -684,19 +673,24 @@ def sign_specfile(key: str, specfile_path: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _read_specs_and_push_index(
|
def _read_specs_and_push_index(
|
||||||
file_list, read_method, cache_prefix, db: BuildCacheDatabase, temp_dir, concurrency
|
file_list: List[str],
|
||||||
|
read_method: Callable,
|
||||||
|
cache_prefix: str,
|
||||||
|
db: BuildCacheDatabase,
|
||||||
|
temp_dir: str,
|
||||||
|
concurrency: int,
|
||||||
):
|
):
|
||||||
"""Read all the specs listed in the provided list, using thread given thread parallelism,
|
"""Read all the specs listed in the provided list, using thread given thread parallelism,
|
||||||
generate the index, and push it to the mirror.
|
generate the index, and push it to the mirror.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
file_list (list(str)): List of urls or file paths pointing at spec files to read
|
file_list: List of urls or file paths pointing at spec files to read
|
||||||
read_method: A function taking a single argument, either a url or a file path,
|
read_method: A function taking a single argument, either a url or a file path,
|
||||||
and which reads the spec file at that location, and returns the spec.
|
and which reads the spec file at that location, and returns the spec.
|
||||||
cache_prefix (str): prefix of the build cache on s3 where index should be pushed.
|
cache_prefix: prefix of the build cache on s3 where index should be pushed.
|
||||||
db: A spack database used for adding specs and then writing the index.
|
db: A spack database used for adding specs and then writing the index.
|
||||||
temp_dir (str): Location to write index.json and hash for pushing
|
temp_dir: Location to write index.json and hash for pushing
|
||||||
concurrency (int): Number of parallel processes to use when fetching
|
concurrency: Number of parallel processes to use when fetching
|
||||||
"""
|
"""
|
||||||
for file in file_list:
|
for file in file_list:
|
||||||
contents = read_method(file)
|
contents = read_method(file)
|
||||||
@@ -714,7 +708,7 @@ def _read_specs_and_push_index(
|
|||||||
|
|
||||||
# Now generate the index, compute its hash, and push the two files to
|
# Now generate the index, compute its hash, and push the two files to
|
||||||
# the mirror.
|
# the mirror.
|
||||||
index_json_path = os.path.join(temp_dir, "index.json")
|
index_json_path = os.path.join(temp_dir, spack_db.INDEX_JSON_FILE)
|
||||||
with open(index_json_path, "w", encoding="utf-8") as f:
|
with open(index_json_path, "w", encoding="utf-8") as f:
|
||||||
db._write_to_file(f)
|
db._write_to_file(f)
|
||||||
|
|
||||||
@@ -724,14 +718,14 @@ def _read_specs_and_push_index(
|
|||||||
index_hash = compute_hash(index_string)
|
index_hash = compute_hash(index_string)
|
||||||
|
|
||||||
# Write the hash out to a local file
|
# Write the hash out to a local file
|
||||||
index_hash_path = os.path.join(temp_dir, "index.json.hash")
|
index_hash_path = os.path.join(temp_dir, INDEX_HASH_FILE)
|
||||||
with open(index_hash_path, "w", encoding="utf-8") as f:
|
with open(index_hash_path, "w", encoding="utf-8") as f:
|
||||||
f.write(index_hash)
|
f.write(index_hash)
|
||||||
|
|
||||||
# Push the index itself
|
# Push the index itself
|
||||||
web_util.push_to_url(
|
web_util.push_to_url(
|
||||||
index_json_path,
|
index_json_path,
|
||||||
url_util.join(cache_prefix, "index.json"),
|
url_util.join(cache_prefix, spack_db.INDEX_JSON_FILE),
|
||||||
keep_original=False,
|
keep_original=False,
|
||||||
extra_args={"ContentType": "application/json", "CacheControl": "no-cache"},
|
extra_args={"ContentType": "application/json", "CacheControl": "no-cache"},
|
||||||
)
|
)
|
||||||
@@ -739,7 +733,7 @@ def _read_specs_and_push_index(
|
|||||||
# Push the hash
|
# Push the hash
|
||||||
web_util.push_to_url(
|
web_util.push_to_url(
|
||||||
index_hash_path,
|
index_hash_path,
|
||||||
url_util.join(cache_prefix, "index.json.hash"),
|
url_util.join(cache_prefix, INDEX_HASH_FILE),
|
||||||
keep_original=False,
|
keep_original=False,
|
||||||
extra_args={"ContentType": "text/plain", "CacheControl": "no-cache"},
|
extra_args={"ContentType": "text/plain", "CacheControl": "no-cache"},
|
||||||
)
|
)
|
||||||
@@ -808,7 +802,7 @@ def url_read_method(url):
|
|||||||
try:
|
try:
|
||||||
_, _, spec_file = web_util.read_from_url(url)
|
_, _, spec_file = web_util.read_from_url(url)
|
||||||
contents = codecs.getreader("utf-8")(spec_file).read()
|
contents = codecs.getreader("utf-8")(spec_file).read()
|
||||||
except web_util.SpackWebError as e:
|
except (web_util.SpackWebError, OSError) as e:
|
||||||
tty.error(f"Error reading specfile: {url}: {e}")
|
tty.error(f"Error reading specfile: {url}: {e}")
|
||||||
return contents
|
return contents
|
||||||
|
|
||||||
@@ -876,9 +870,12 @@ def _url_generate_package_index(url: str, tmpdir: str, concurrency: int = 32):
|
|||||||
tty.debug(f"Retrieving spec descriptor files from {url} to build index")
|
tty.debug(f"Retrieving spec descriptor files from {url} to build index")
|
||||||
|
|
||||||
db = BuildCacheDatabase(tmpdir)
|
db = BuildCacheDatabase(tmpdir)
|
||||||
|
db._write()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_read_specs_and_push_index(file_list, read_fn, url, db, db.database_directory, concurrency)
|
_read_specs_and_push_index(
|
||||||
|
file_list, read_fn, url, db, str(db.database_directory), concurrency
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise GenerateIndexError(f"Encountered problem pushing package index to {url}: {e}") from e
|
raise GenerateIndexError(f"Encountered problem pushing package index to {url}: {e}") from e
|
||||||
|
|
||||||
@@ -1792,7 +1789,7 @@ def _oci_update_index(
|
|||||||
db.mark(spec, "in_buildcache", True)
|
db.mark(spec, "in_buildcache", True)
|
||||||
|
|
||||||
# Create the index.json file
|
# Create the index.json file
|
||||||
index_json_path = os.path.join(tmpdir, "index.json")
|
index_json_path = os.path.join(tmpdir, spack_db.INDEX_JSON_FILE)
|
||||||
with open(index_json_path, "w", encoding="utf-8") as f:
|
with open(index_json_path, "w", encoding="utf-8") as f:
|
||||||
db._write_to_file(f)
|
db._write_to_file(f)
|
||||||
|
|
||||||
@@ -2013,7 +2010,7 @@ def fetch_url_to_mirror(url):
|
|||||||
|
|
||||||
# Download the config = spec.json and the relevant tarball
|
# Download the config = spec.json and the relevant tarball
|
||||||
try:
|
try:
|
||||||
manifest = json.loads(response.read())
|
manifest = json.load(response)
|
||||||
spec_digest = spack.oci.image.Digest.from_string(manifest["config"]["digest"])
|
spec_digest = spack.oci.image.Digest.from_string(manifest["config"]["digest"])
|
||||||
tarball_digest = spack.oci.image.Digest.from_string(
|
tarball_digest = spack.oci.image.Digest.from_string(
|
||||||
manifest["layers"][-1]["digest"]
|
manifest["layers"][-1]["digest"]
|
||||||
@@ -2140,10 +2137,9 @@ def fetch_url_to_mirror(url):
|
|||||||
|
|
||||||
|
|
||||||
def dedupe_hardlinks_if_necessary(root, buildinfo):
|
def dedupe_hardlinks_if_necessary(root, buildinfo):
|
||||||
"""Updates a buildinfo dict for old archives that did
|
"""Updates a buildinfo dict for old archives that did not dedupe hardlinks. De-duping hardlinks
|
||||||
not dedupe hardlinks. De-duping hardlinks is necessary
|
is necessary when relocating files in parallel and in-place. This means we must preserve inodes
|
||||||
when relocating files in parallel and in-place. This
|
when relocating."""
|
||||||
means we must preserve inodes when relocating."""
|
|
||||||
|
|
||||||
# New archives don't need this.
|
# New archives don't need this.
|
||||||
if buildinfo.get("hardlinks_deduped", False):
|
if buildinfo.get("hardlinks_deduped", False):
|
||||||
@@ -2172,69 +2168,47 @@ def dedupe_hardlinks_if_necessary(root, buildinfo):
|
|||||||
buildinfo[key] = new_list
|
buildinfo[key] = new_list
|
||||||
|
|
||||||
|
|
||||||
def relocate_package(spec):
|
def relocate_package(spec: spack.spec.Spec) -> None:
|
||||||
"""
|
"""Relocate binaries and text files in the given spec prefix, based on its buildinfo file."""
|
||||||
Relocate the given package
|
spec_prefix = str(spec.prefix)
|
||||||
"""
|
buildinfo = read_buildinfo_file(spec_prefix)
|
||||||
workdir = str(spec.prefix)
|
|
||||||
buildinfo = read_buildinfo_file(workdir)
|
|
||||||
new_layout_root = str(spack.store.STORE.layout.root)
|
|
||||||
new_prefix = str(spec.prefix)
|
|
||||||
new_rel_prefix = str(os.path.relpath(new_prefix, new_layout_root))
|
|
||||||
new_spack_prefix = str(spack.paths.prefix)
|
|
||||||
|
|
||||||
old_sbang_install_path = None
|
|
||||||
if "sbang_install_path" in buildinfo:
|
|
||||||
old_sbang_install_path = str(buildinfo["sbang_install_path"])
|
|
||||||
old_layout_root = str(buildinfo["buildpath"])
|
old_layout_root = str(buildinfo["buildpath"])
|
||||||
old_spack_prefix = str(buildinfo.get("spackprefix"))
|
|
||||||
old_rel_prefix = buildinfo.get("relative_prefix")
|
|
||||||
old_prefix = os.path.join(old_layout_root, old_rel_prefix)
|
|
||||||
|
|
||||||
# Warn about old style tarballs created with the now removed --rel flag.
|
# Warn about old style tarballs created with the --rel flag (removed in Spack v0.20)
|
||||||
if buildinfo.get("relative_rpaths", False):
|
if buildinfo.get("relative_rpaths", False):
|
||||||
tty.warn(
|
tty.warn(
|
||||||
f"Tarball for {spec} uses relative rpaths, " "which can cause library loading issues."
|
f"Tarball for {spec} uses relative rpaths, which can cause library loading issues."
|
||||||
)
|
)
|
||||||
|
|
||||||
# In the past prefix_to_hash was the default and externals were not dropped, so prefixes
|
# In Spack 0.19 and older prefix_to_hash was the default and externals were not dropped, so
|
||||||
# were not unique.
|
# prefixes were not unique.
|
||||||
if "hash_to_prefix" in buildinfo:
|
if "hash_to_prefix" in buildinfo:
|
||||||
hash_to_old_prefix = buildinfo["hash_to_prefix"]
|
hash_to_old_prefix = buildinfo["hash_to_prefix"]
|
||||||
elif "prefix_to_hash" in buildinfo:
|
elif "prefix_to_hash" in buildinfo:
|
||||||
hash_to_old_prefix = dict((v, k) for (k, v) in buildinfo["prefix_to_hash"].items())
|
hash_to_old_prefix = {v: k for (k, v) in buildinfo["prefix_to_hash"].items()}
|
||||||
else:
|
else:
|
||||||
hash_to_old_prefix = dict()
|
raise NewLayoutException(
|
||||||
|
"Package tarball was created from an install prefix with a different directory layout "
|
||||||
|
"and an older buildcache create implementation. It cannot be relocated."
|
||||||
|
)
|
||||||
|
|
||||||
if old_rel_prefix != new_rel_prefix and not hash_to_old_prefix:
|
prefix_to_prefix: Dict[str, str] = {}
|
||||||
msg = "Package tarball was created from an install "
|
|
||||||
msg += "prefix with a different directory layout and an older "
|
|
||||||
msg += "buildcache create implementation. It cannot be relocated."
|
|
||||||
raise NewLayoutException(msg)
|
|
||||||
|
|
||||||
# Spurious replacements (e.g. sbang) will cause issues with binaries
|
if "sbang_install_path" in buildinfo:
|
||||||
# For example, the new sbang can be longer than the old one.
|
old_sbang_install_path = str(buildinfo["sbang_install_path"])
|
||||||
# Hence 2 dictionaries are maintained here.
|
prefix_to_prefix[old_sbang_install_path] = spack.hooks.sbang.sbang_install_path()
|
||||||
prefix_to_prefix_text = collections.OrderedDict()
|
|
||||||
prefix_to_prefix_bin = collections.OrderedDict()
|
|
||||||
|
|
||||||
if old_sbang_install_path:
|
# First match specific prefix paths. Possibly the *local* install prefix of some dependency is
|
||||||
install_path = spack.hooks.sbang.sbang_install_path()
|
# in an upstream, so we cannot assume the original spack store root can be mapped uniformly to
|
||||||
prefix_to_prefix_text[old_sbang_install_path] = install_path
|
# the new spack store root.
|
||||||
|
|
||||||
# First match specific prefix paths. Possibly the *local* install prefix
|
# If the spec is spliced, we need to handle the simultaneous mapping from the old install_tree
|
||||||
# of some dependency is in an upstream, so we cannot assume the original
|
# to the new install_tree and from the build_spec to the spliced spec. Because foo.build_spec
|
||||||
# spack store root can be mapped uniformly to the new spack store root.
|
# is foo for any non-spliced spec, we can simplify by checking for spliced-in nodes by checking
|
||||||
#
|
# for nodes not in the build_spec without any explicit check for whether the spec is spliced.
|
||||||
# If the spec is spliced, we need to handle the simultaneous mapping
|
# An analog in this algorithm is any spec that shares a name or provides the same virtuals in
|
||||||
# from the old install_tree to the new install_tree and from the build_spec
|
# the context of the relevant root spec. This ensures that the analog for a spec s is the spec
|
||||||
# to the spliced spec.
|
# that s replaced when we spliced.
|
||||||
# Because foo.build_spec is foo for any non-spliced spec, we can simplify
|
|
||||||
# by checking for spliced-in nodes by checking for nodes not in the build_spec
|
|
||||||
# without any explicit check for whether the spec is spliced.
|
|
||||||
# An analog in this algorithm is any spec that shares a name or provides the same virtuals
|
|
||||||
# in the context of the relevant root spec. This ensures that the analog for a spec s
|
|
||||||
# is the spec that s replaced when we spliced.
|
|
||||||
relocation_specs = specs_to_relocate(spec)
|
relocation_specs = specs_to_relocate(spec)
|
||||||
build_spec_ids = set(id(s) for s in spec.build_spec.traverse(deptype=dt.ALL & ~dt.BUILD))
|
build_spec_ids = set(id(s) for s in spec.build_spec.traverse(deptype=dt.ALL & ~dt.BUILD))
|
||||||
for s in relocation_specs:
|
for s in relocation_specs:
|
||||||
@@ -2254,56 +2228,38 @@ def relocate_package(spec):
|
|||||||
lookup_dag_hash = analog.dag_hash()
|
lookup_dag_hash = analog.dag_hash()
|
||||||
if lookup_dag_hash in hash_to_old_prefix:
|
if lookup_dag_hash in hash_to_old_prefix:
|
||||||
old_dep_prefix = hash_to_old_prefix[lookup_dag_hash]
|
old_dep_prefix = hash_to_old_prefix[lookup_dag_hash]
|
||||||
prefix_to_prefix_bin[old_dep_prefix] = str(s.prefix)
|
prefix_to_prefix[old_dep_prefix] = str(s.prefix)
|
||||||
prefix_to_prefix_text[old_dep_prefix] = str(s.prefix)
|
|
||||||
|
|
||||||
# Only then add the generic fallback of install prefix -> install prefix.
|
# Only then add the generic fallback of install prefix -> install prefix.
|
||||||
prefix_to_prefix_text[old_prefix] = new_prefix
|
prefix_to_prefix[old_layout_root] = str(spack.store.STORE.layout.root)
|
||||||
prefix_to_prefix_bin[old_prefix] = new_prefix
|
|
||||||
prefix_to_prefix_text[old_layout_root] = new_layout_root
|
|
||||||
prefix_to_prefix_bin[old_layout_root] = new_layout_root
|
|
||||||
|
|
||||||
# This is vestigial code for the *old* location of sbang. Previously,
|
# Delete identity mappings from prefix_to_prefix
|
||||||
# sbang was a bash script, and it lived in the spack prefix. It is
|
prefix_to_prefix = {k: v for k, v in prefix_to_prefix.items() if k != v}
|
||||||
# now a POSIX script that lives in the install prefix. Old packages
|
|
||||||
# will have the old sbang location in their shebangs.
|
|
||||||
orig_sbang = "#!/bin/bash {0}/bin/sbang".format(old_spack_prefix)
|
|
||||||
new_sbang = spack.hooks.sbang.sbang_shebang_line()
|
|
||||||
prefix_to_prefix_text[orig_sbang] = new_sbang
|
|
||||||
|
|
||||||
tty.debug("Relocating package from", "%s to %s." % (old_layout_root, new_layout_root))
|
# If there's nothing to relocate, we're done.
|
||||||
|
if not prefix_to_prefix:
|
||||||
|
return
|
||||||
|
|
||||||
|
for old, new in prefix_to_prefix.items():
|
||||||
|
tty.debug(f"Relocating: {old} => {new}.")
|
||||||
|
|
||||||
# Old archives may have hardlinks repeated.
|
# Old archives may have hardlinks repeated.
|
||||||
dedupe_hardlinks_if_necessary(workdir, buildinfo)
|
dedupe_hardlinks_if_necessary(spec_prefix, buildinfo)
|
||||||
|
|
||||||
# Text files containing the prefix text
|
# Text files containing the prefix text
|
||||||
text_names = [os.path.join(workdir, f) for f in buildinfo["relocate_textfiles"]]
|
textfiles = [os.path.join(spec_prefix, f) for f in buildinfo["relocate_textfiles"]]
|
||||||
|
binaries = [os.path.join(spec_prefix, f) for f in buildinfo.get("relocate_binaries")]
|
||||||
|
links = [os.path.join(spec_prefix, f) for f in buildinfo.get("relocate_links", [])]
|
||||||
|
|
||||||
# If we are not installing back to the same install tree do the relocation
|
|
||||||
if old_prefix != new_prefix:
|
|
||||||
files_to_relocate = [
|
|
||||||
os.path.join(workdir, filename) for filename in buildinfo.get("relocate_binaries")
|
|
||||||
]
|
|
||||||
# If the buildcache was not created with relativized rpaths
|
|
||||||
# do the relocation of path in binaries
|
|
||||||
platform = spack.platforms.by_name(spec.platform)
|
platform = spack.platforms.by_name(spec.platform)
|
||||||
if "macho" in platform.binary_formats:
|
if "macho" in platform.binary_formats:
|
||||||
relocate.relocate_macho_binaries(files_to_relocate, prefix_to_prefix_bin)
|
relocate.relocate_macho_binaries(binaries, prefix_to_prefix)
|
||||||
elif "elf" in platform.binary_formats:
|
elif "elf" in platform.binary_formats:
|
||||||
# The new ELF dynamic section relocation logic only handles absolute to
|
relocate.relocate_elf_binaries(binaries, prefix_to_prefix)
|
||||||
# absolute relocation.
|
|
||||||
relocate.relocate_elf_binaries(files_to_relocate, prefix_to_prefix_bin)
|
|
||||||
|
|
||||||
# Relocate links to the new install prefix
|
relocate.relocate_links(links, prefix_to_prefix)
|
||||||
links = [os.path.join(workdir, f) for f in buildinfo.get("relocate_links", [])]
|
relocate.relocate_text(textfiles, prefix_to_prefix)
|
||||||
relocate.relocate_links(links, prefix_to_prefix_bin)
|
changed_files = relocate.relocate_text_bin(binaries, prefix_to_prefix)
|
||||||
|
|
||||||
# For all buildcaches
|
|
||||||
# relocate the install prefixes in text files including dependencies
|
|
||||||
relocate.relocate_text(text_names, prefix_to_prefix_text)
|
|
||||||
|
|
||||||
# relocate the install prefixes in binary files including dependencies
|
|
||||||
changed_files = relocate.relocate_text_bin(files_to_relocate, prefix_to_prefix_bin)
|
|
||||||
|
|
||||||
# Add ad-hoc signatures to patched macho files when on macOS.
|
# Add ad-hoc signatures to patched macho files when on macOS.
|
||||||
if "macho" in platform.binary_formats and sys.platform == "darwin":
|
if "macho" in platform.binary_formats and sys.platform == "darwin":
|
||||||
@@ -2315,11 +2271,23 @@ def relocate_package(spec):
|
|||||||
with fsys.edit_in_place_through_temporary_file(binary) as tmp_binary:
|
with fsys.edit_in_place_through_temporary_file(binary) as tmp_binary:
|
||||||
codesign("-fs-", tmp_binary)
|
codesign("-fs-", tmp_binary)
|
||||||
|
|
||||||
# If we are installing back to the same location
|
install_manifest = os.path.join(
|
||||||
# relocate the sbang location if the spack directory changed
|
spec.prefix,
|
||||||
else:
|
spack.store.STORE.layout.metadata_dir,
|
||||||
if old_spack_prefix != new_spack_prefix:
|
spack.store.STORE.layout.manifest_file_name,
|
||||||
relocate.relocate_text(text_names, prefix_to_prefix_text)
|
)
|
||||||
|
if not os.path.exists(install_manifest):
|
||||||
|
spec_id = spec.format("{name}/{hash:7}")
|
||||||
|
tty.warn("No manifest file in tarball for spec %s" % spec_id)
|
||||||
|
|
||||||
|
# overwrite old metadata with new
|
||||||
|
if spec.spliced:
|
||||||
|
# rewrite spec on disk
|
||||||
|
spack.store.STORE.layout.write_spec(spec, spack.store.STORE.layout.spec_file_path(spec))
|
||||||
|
|
||||||
|
# de-cache the install manifest
|
||||||
|
with contextlib.suppress(FileNotFoundError):
|
||||||
|
os.unlink(install_manifest)
|
||||||
|
|
||||||
|
|
||||||
def _extract_inner_tarball(spec, filename, extract_to, signature_required: bool, remote_checksum):
|
def _extract_inner_tarball(spec, filename, extract_to, signature_required: bool, remote_checksum):
|
||||||
@@ -2487,15 +2455,6 @@ def extract_tarball(spec, download_result, force=False, timer=timer.NULL_TIMER):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
shutil.rmtree(spec.prefix, ignore_errors=True)
|
shutil.rmtree(spec.prefix, ignore_errors=True)
|
||||||
raise e
|
raise e
|
||||||
else:
|
|
||||||
manifest_file = os.path.join(
|
|
||||||
spec.prefix,
|
|
||||||
spack.store.STORE.layout.metadata_dir,
|
|
||||||
spack.store.STORE.layout.manifest_file_name,
|
|
||||||
)
|
|
||||||
if not os.path.exists(manifest_file):
|
|
||||||
spec_id = spec.format("{name}/{hash:7}")
|
|
||||||
tty.warn("No manifest file in tarball for spec %s" % spec_id)
|
|
||||||
finally:
|
finally:
|
||||||
if tmpdir:
|
if tmpdir:
|
||||||
shutil.rmtree(tmpdir, ignore_errors=True)
|
shutil.rmtree(tmpdir, ignore_errors=True)
|
||||||
@@ -2600,10 +2559,6 @@ def install_root_node(
|
|||||||
tty.msg('Installing "{0}" from a buildcache'.format(spec.format()))
|
tty.msg('Installing "{0}" from a buildcache'.format(spec.format()))
|
||||||
extract_tarball(spec, download_result, force)
|
extract_tarball(spec, download_result, force)
|
||||||
spec.package.windows_establish_runtime_linkage()
|
spec.package.windows_establish_runtime_linkage()
|
||||||
if spec.spliced: # overwrite old metadata with new
|
|
||||||
spack.store.STORE.layout.write_spec(
|
|
||||||
spec, spack.store.STORE.layout.spec_file_path(spec)
|
|
||||||
)
|
|
||||||
spack.hooks.post_install(spec, False)
|
spack.hooks.post_install(spec, False)
|
||||||
spack.store.STORE.db.add(spec, allow_missing=allow_missing)
|
spack.store.STORE.db.add(spec, allow_missing=allow_missing)
|
||||||
|
|
||||||
@@ -2641,11 +2596,14 @@ def try_direct_fetch(spec, mirrors=None):
|
|||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
_, _, fs = web_util.read_from_url(buildcache_fetch_url_signed_json)
|
_, _, fs = web_util.read_from_url(buildcache_fetch_url_signed_json)
|
||||||
|
specfile_contents = codecs.getreader("utf-8")(fs).read()
|
||||||
specfile_is_signed = True
|
specfile_is_signed = True
|
||||||
except web_util.SpackWebError as e1:
|
except (web_util.SpackWebError, OSError) as e1:
|
||||||
try:
|
try:
|
||||||
_, _, fs = web_util.read_from_url(buildcache_fetch_url_json)
|
_, _, fs = web_util.read_from_url(buildcache_fetch_url_json)
|
||||||
except web_util.SpackWebError as e2:
|
specfile_contents = codecs.getreader("utf-8")(fs).read()
|
||||||
|
specfile_is_signed = False
|
||||||
|
except (web_util.SpackWebError, OSError) as e2:
|
||||||
tty.debug(
|
tty.debug(
|
||||||
f"Did not find {specfile_name} on {buildcache_fetch_url_signed_json}",
|
f"Did not find {specfile_name} on {buildcache_fetch_url_signed_json}",
|
||||||
e1,
|
e1,
|
||||||
@@ -2655,7 +2613,6 @@ def try_direct_fetch(spec, mirrors=None):
|
|||||||
f"Did not find {specfile_name} on {buildcache_fetch_url_json}", e2, level=2
|
f"Did not find {specfile_name} on {buildcache_fetch_url_json}", e2, level=2
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
specfile_contents = codecs.getreader("utf-8")(fs).read()
|
|
||||||
|
|
||||||
# read the spec from the build cache file. All specs in build caches
|
# read the spec from the build cache file. All specs in build caches
|
||||||
# are concrete (as they are built) so we need to mark this spec
|
# are concrete (as they are built) so we need to mark this spec
|
||||||
@@ -2749,8 +2706,9 @@ def get_keys(install=False, trust=False, force=False, mirrors=None):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
_, _, json_file = web_util.read_from_url(keys_index)
|
_, _, json_file = web_util.read_from_url(keys_index)
|
||||||
json_index = sjson.load(codecs.getreader("utf-8")(json_file))
|
json_index = sjson.load(json_file)
|
||||||
except web_util.SpackWebError as url_err:
|
except (web_util.SpackWebError, OSError, ValueError) as url_err:
|
||||||
|
# TODO: avoid repeated request
|
||||||
if web_util.url_exists(keys_index):
|
if web_util.url_exists(keys_index):
|
||||||
tty.error(
|
tty.error(
|
||||||
f"Unable to find public keys in {url_util.format(fetch_url)},"
|
f"Unable to find public keys in {url_util.format(fetch_url)},"
|
||||||
@@ -2997,14 +2955,14 @@ def __init__(self, url, local_hash, urlopen=web_util.urlopen):
|
|||||||
|
|
||||||
def get_remote_hash(self):
|
def get_remote_hash(self):
|
||||||
# Failure to fetch index.json.hash is not fatal
|
# Failure to fetch index.json.hash is not fatal
|
||||||
url_index_hash = url_util.join(self.url, BUILD_CACHE_RELATIVE_PATH, "index.json.hash")
|
url_index_hash = url_util.join(self.url, BUILD_CACHE_RELATIVE_PATH, INDEX_HASH_FILE)
|
||||||
try:
|
try:
|
||||||
response = self.urlopen(urllib.request.Request(url_index_hash, headers=self.headers))
|
response = self.urlopen(urllib.request.Request(url_index_hash, headers=self.headers))
|
||||||
except (TimeoutError, urllib.error.URLError):
|
remote_hash = response.read(64)
|
||||||
|
except OSError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Validate the hash
|
# Validate the hash
|
||||||
remote_hash = response.read(64)
|
|
||||||
if not re.match(rb"[a-f\d]{64}$", remote_hash):
|
if not re.match(rb"[a-f\d]{64}$", remote_hash):
|
||||||
return None
|
return None
|
||||||
return remote_hash.decode("utf-8")
|
return remote_hash.decode("utf-8")
|
||||||
@@ -3018,17 +2976,17 @@ def conditional_fetch(self) -> FetchIndexResult:
|
|||||||
return FetchIndexResult(etag=None, hash=None, data=None, fresh=True)
|
return FetchIndexResult(etag=None, hash=None, data=None, fresh=True)
|
||||||
|
|
||||||
# Otherwise, download index.json
|
# Otherwise, download index.json
|
||||||
url_index = url_util.join(self.url, BUILD_CACHE_RELATIVE_PATH, "index.json")
|
url_index = url_util.join(self.url, BUILD_CACHE_RELATIVE_PATH, spack_db.INDEX_JSON_FILE)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = self.urlopen(urllib.request.Request(url_index, headers=self.headers))
|
response = self.urlopen(urllib.request.Request(url_index, headers=self.headers))
|
||||||
except (TimeoutError, urllib.error.URLError) as e:
|
except OSError as e:
|
||||||
raise FetchIndexError("Could not fetch index from {}".format(url_index), e) from e
|
raise FetchIndexError(f"Could not fetch index from {url_index}", e) from e
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = codecs.getreader("utf-8")(response).read()
|
result = codecs.getreader("utf-8")(response).read()
|
||||||
except ValueError as e:
|
except (ValueError, OSError) as e:
|
||||||
raise FetchIndexError("Remote index {} is invalid".format(url_index), e) from e
|
raise FetchIndexError(f"Remote index {url_index} is invalid") from e
|
||||||
|
|
||||||
computed_hash = compute_hash(result)
|
computed_hash = compute_hash(result)
|
||||||
|
|
||||||
@@ -3062,7 +3020,7 @@ def __init__(self, url, etag, urlopen=web_util.urlopen):
|
|||||||
|
|
||||||
def conditional_fetch(self) -> FetchIndexResult:
|
def conditional_fetch(self) -> FetchIndexResult:
|
||||||
# Just do a conditional fetch immediately
|
# Just do a conditional fetch immediately
|
||||||
url = url_util.join(self.url, BUILD_CACHE_RELATIVE_PATH, "index.json")
|
url = url_util.join(self.url, BUILD_CACHE_RELATIVE_PATH, spack_db.INDEX_JSON_FILE)
|
||||||
headers = {"User-Agent": web_util.SPACK_USER_AGENT, "If-None-Match": f'"{self.etag}"'}
|
headers = {"User-Agent": web_util.SPACK_USER_AGENT, "If-None-Match": f'"{self.etag}"'}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -3072,12 +3030,12 @@ def conditional_fetch(self) -> FetchIndexResult:
|
|||||||
# Not modified; that means fresh.
|
# Not modified; that means fresh.
|
||||||
return FetchIndexResult(etag=None, hash=None, data=None, fresh=True)
|
return FetchIndexResult(etag=None, hash=None, data=None, fresh=True)
|
||||||
raise FetchIndexError(f"Could not fetch index {url}", e) from e
|
raise FetchIndexError(f"Could not fetch index {url}", e) from e
|
||||||
except (TimeoutError, urllib.error.URLError) as e:
|
except OSError as e: # URLError, socket.timeout, etc.
|
||||||
raise FetchIndexError(f"Could not fetch index {url}", e) from e
|
raise FetchIndexError(f"Could not fetch index {url}", e) from e
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = codecs.getreader("utf-8")(response).read()
|
result = codecs.getreader("utf-8")(response).read()
|
||||||
except ValueError as e:
|
except (ValueError, OSError) as e:
|
||||||
raise FetchIndexError(f"Remote index {url} is invalid", e) from e
|
raise FetchIndexError(f"Remote index {url} is invalid", e) from e
|
||||||
|
|
||||||
headers = response.headers
|
headers = response.headers
|
||||||
@@ -3109,11 +3067,11 @@ def conditional_fetch(self) -> FetchIndexResult:
|
|||||||
headers={"Accept": "application/vnd.oci.image.manifest.v1+json"},
|
headers={"Accept": "application/vnd.oci.image.manifest.v1+json"},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except (TimeoutError, urllib.error.URLError) as e:
|
except OSError as e:
|
||||||
raise FetchIndexError(f"Could not fetch manifest from {url_manifest}", e) from e
|
raise FetchIndexError(f"Could not fetch manifest from {url_manifest}", e) from e
|
||||||
|
|
||||||
try:
|
try:
|
||||||
manifest = json.loads(response.read())
|
manifest = json.load(response)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise FetchIndexError(f"Remote index {url_manifest} is invalid", e) from e
|
raise FetchIndexError(f"Remote index {url_manifest} is invalid", e) from e
|
||||||
|
|
||||||
@@ -3128,14 +3086,16 @@ def conditional_fetch(self) -> FetchIndexResult:
|
|||||||
return FetchIndexResult(etag=None, hash=None, data=None, fresh=True)
|
return FetchIndexResult(etag=None, hash=None, data=None, fresh=True)
|
||||||
|
|
||||||
# Otherwise fetch the blob / index.json
|
# Otherwise fetch the blob / index.json
|
||||||
|
try:
|
||||||
response = self.urlopen(
|
response = self.urlopen(
|
||||||
urllib.request.Request(
|
urllib.request.Request(
|
||||||
url=self.ref.blob_url(index_digest),
|
url=self.ref.blob_url(index_digest),
|
||||||
headers={"Accept": "application/vnd.oci.image.layer.v1.tar+gzip"},
|
headers={"Accept": "application/vnd.oci.image.layer.v1.tar+gzip"},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
result = codecs.getreader("utf-8")(response).read()
|
result = codecs.getreader("utf-8")(response).read()
|
||||||
|
except (OSError, ValueError) as e:
|
||||||
|
raise FetchIndexError(f"Remote index {url_manifest} is invalid", e) from e
|
||||||
|
|
||||||
# Make sure the blob we download has the advertised hash
|
# Make sure the blob we download has the advertised hash
|
||||||
if compute_hash(result) != index_digest.digest:
|
if compute_hash(result) != index_digest.digest:
|
||||||
|
|||||||
@@ -5,12 +5,14 @@
|
|||||||
import fnmatch
|
import fnmatch
|
||||||
import glob
|
import glob
|
||||||
import importlib
|
import importlib
|
||||||
import os.path
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import sysconfig
|
import sysconfig
|
||||||
import warnings
|
import warnings
|
||||||
from typing import Dict, Optional, Sequence, Union
|
from typing import Optional, Sequence, Union
|
||||||
|
|
||||||
|
from typing_extensions import TypedDict
|
||||||
|
|
||||||
import archspec.cpu
|
import archspec.cpu
|
||||||
|
|
||||||
@@ -18,13 +20,17 @@
|
|||||||
from llnl.util import tty
|
from llnl.util import tty
|
||||||
|
|
||||||
import spack.platforms
|
import spack.platforms
|
||||||
|
import spack.spec
|
||||||
import spack.store
|
import spack.store
|
||||||
import spack.util.environment
|
import spack.util.environment
|
||||||
import spack.util.executable
|
import spack.util.executable
|
||||||
|
|
||||||
from .config import spec_for_current_python
|
from .config import spec_for_current_python
|
||||||
|
|
||||||
QueryInfo = Dict[str, "spack.spec.Spec"]
|
|
||||||
|
class QueryInfo(TypedDict, total=False):
|
||||||
|
spec: spack.spec.Spec
|
||||||
|
command: spack.util.executable.Executable
|
||||||
|
|
||||||
|
|
||||||
def _python_import(module: str) -> bool:
|
def _python_import(module: str) -> bool:
|
||||||
@@ -211,7 +217,9 @@ def _executables_in_store(
|
|||||||
):
|
):
|
||||||
spack.util.environment.path_put_first("PATH", [bin_dir])
|
spack.util.environment.path_put_first("PATH", [bin_dir])
|
||||||
if query_info is not None:
|
if query_info is not None:
|
||||||
query_info["command"] = spack.util.executable.which(*executables, path=bin_dir)
|
query_info["command"] = spack.util.executable.which(
|
||||||
|
*executables, path=bin_dir, required=True
|
||||||
|
)
|
||||||
query_info["spec"] = concrete_spec
|
query_info["spec"] = concrete_spec
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@@ -226,13 +234,12 @@ def _root_spec(spec_str: str) -> str:
|
|||||||
# Add a compiler and platform requirement to the root spec.
|
# Add a compiler and platform requirement to the root spec.
|
||||||
platform = str(spack.platforms.host())
|
platform = str(spack.platforms.host())
|
||||||
|
|
||||||
# FIXME (compiler as nodes): recover the compiler for source bootstrapping
|
if platform == "darwin":
|
||||||
# if platform == "darwin":
|
spec_str += " %apple-clang"
|
||||||
# spec_str += " %apple-clang"
|
elif platform == "windows":
|
||||||
if platform == "windows":
|
|
||||||
spec_str += " %msvc"
|
spec_str += " %msvc"
|
||||||
# elif platform == "linux":
|
elif platform == "linux":
|
||||||
# spec_str += " %gcc"
|
spec_str += " %gcc"
|
||||||
elif platform == "freebsd":
|
elif platform == "freebsd":
|
||||||
spec_str += " %clang"
|
spec_str += " %clang"
|
||||||
spec_str += f" platform={platform}"
|
spec_str += f" platform={platform}"
|
||||||
|
|||||||
@@ -15,13 +15,11 @@
|
|||||||
|
|
||||||
import archspec.cpu
|
import archspec.cpu
|
||||||
|
|
||||||
import spack.compilers.config
|
import spack.compiler
|
||||||
import spack.compilers.libraries
|
import spack.compilers
|
||||||
import spack.config
|
|
||||||
import spack.platforms
|
import spack.platforms
|
||||||
import spack.spec
|
import spack.spec
|
||||||
import spack.traverse
|
import spack.traverse
|
||||||
import spack.version
|
|
||||||
|
|
||||||
from .config import spec_for_current_python
|
from .config import spec_for_current_python
|
||||||
|
|
||||||
@@ -29,9 +27,9 @@
|
|||||||
class ClingoBootstrapConcretizer:
|
class ClingoBootstrapConcretizer:
|
||||||
def __init__(self, configuration):
|
def __init__(self, configuration):
|
||||||
self.host_platform = spack.platforms.host()
|
self.host_platform = spack.platforms.host()
|
||||||
self.host_os = self.host_platform.operating_system("frontend")
|
self.host_os = self.host_platform.default_operating_system()
|
||||||
self.host_target = archspec.cpu.host().family
|
self.host_target = archspec.cpu.host().family
|
||||||
self.host_architecture = spack.spec.ArchSpec.frontend_arch()
|
self.host_architecture = spack.spec.ArchSpec.default_arch()
|
||||||
self.host_architecture.target = str(self.host_target)
|
self.host_architecture.target = str(self.host_target)
|
||||||
self.host_compiler = self._valid_compiler_or_raise()
|
self.host_compiler = self._valid_compiler_or_raise()
|
||||||
self.host_python = self.python_external_spec()
|
self.host_python = self.python_external_spec()
|
||||||
@@ -40,7 +38,7 @@ def __init__(self, configuration):
|
|||||||
|
|
||||||
self.external_cmake, self.external_bison = self._externals_from_yaml(configuration)
|
self.external_cmake, self.external_bison = self._externals_from_yaml(configuration)
|
||||||
|
|
||||||
def _valid_compiler_or_raise(self):
|
def _valid_compiler_or_raise(self) -> "spack.compiler.Compiler":
|
||||||
if str(self.host_platform) == "linux":
|
if str(self.host_platform) == "linux":
|
||||||
compiler_name = "gcc"
|
compiler_name = "gcc"
|
||||||
elif str(self.host_platform) == "darwin":
|
elif str(self.host_platform) == "darwin":
|
||||||
@@ -48,30 +46,17 @@ def _valid_compiler_or_raise(self):
|
|||||||
elif str(self.host_platform) == "windows":
|
elif str(self.host_platform) == "windows":
|
||||||
compiler_name = "msvc"
|
compiler_name = "msvc"
|
||||||
elif str(self.host_platform) == "freebsd":
|
elif str(self.host_platform) == "freebsd":
|
||||||
compiler_name = "llvm"
|
compiler_name = "clang"
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f"Cannot bootstrap clingo from sources on {self.host_platform}")
|
raise RuntimeError(f"Cannot bootstrap clingo from sources on {self.host_platform}")
|
||||||
|
candidates = spack.compilers.compilers_for_spec(
|
||||||
candidates = [
|
compiler_name, arch_spec=self.host_architecture
|
||||||
x
|
)
|
||||||
for x in spack.compilers.config.CompilerFactory.from_packages_yaml(spack.config.CONFIG)
|
|
||||||
if x.name == compiler_name
|
|
||||||
]
|
|
||||||
if not candidates:
|
if not candidates:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"Cannot find any version of {compiler_name} to bootstrap clingo from sources"
|
f"Cannot find any version of {compiler_name} to bootstrap clingo from sources"
|
||||||
)
|
)
|
||||||
candidates.sort(key=lambda x: x.version, reverse=True)
|
candidates.sort(key=lambda x: x.spec.version, reverse=True)
|
||||||
best = candidates[0]
|
|
||||||
# Get compilers for bootstrapping from the 'builtin' repository
|
|
||||||
best.namespace = "builtin"
|
|
||||||
# If the compiler does not support C++ 14, fail with a legible error message
|
|
||||||
try:
|
|
||||||
_ = best.package.standard_flag(language="cxx", standard="14")
|
|
||||||
except RuntimeError as e:
|
|
||||||
raise RuntimeError(
|
|
||||||
"cannot find a compiler supporting C++ 14 [needed to bootstrap clingo]"
|
|
||||||
) from e
|
|
||||||
return candidates[0]
|
return candidates[0]
|
||||||
|
|
||||||
def _externals_from_yaml(
|
def _externals_from_yaml(
|
||||||
@@ -90,6 +75,9 @@ def _externals_from_yaml(
|
|||||||
if not s.satisfies(requirements[pkg_name]):
|
if not s.satisfies(requirements[pkg_name]):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if not s.intersects(f"%{self.host_compiler.spec}"):
|
||||||
|
continue
|
||||||
|
|
||||||
if not s.intersects(f"arch={self.host_architecture}"):
|
if not s.intersects(f"arch={self.host_architecture}"):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -122,14 +110,11 @@ def concretize(self) -> "spack.spec.Spec":
|
|||||||
# Tweak it to conform to the host architecture
|
# Tweak it to conform to the host architecture
|
||||||
for node in s.traverse():
|
for node in s.traverse():
|
||||||
node.architecture.os = str(self.host_os)
|
node.architecture.os = str(self.host_os)
|
||||||
|
node.compiler = self.host_compiler.spec
|
||||||
node.architecture = self.host_architecture
|
node.architecture = self.host_architecture
|
||||||
|
|
||||||
if node.name == "gcc-runtime":
|
if node.name == "gcc-runtime":
|
||||||
node.versions = self.host_compiler.versions
|
node.versions = self.host_compiler.spec.versions
|
||||||
|
|
||||||
# Can't use re2c@3.1 with Python 3.6
|
|
||||||
if self.host_python.satisfies("@3.6"):
|
|
||||||
s["re2c"].versions.versions = [spack.version.from_string("=2.2")]
|
|
||||||
|
|
||||||
for edge in spack.traverse.traverse_edges([s], cover="edges"):
|
for edge in spack.traverse.traverse_edges([s], cover="edges"):
|
||||||
if edge.spec.name == "python":
|
if edge.spec.name == "python":
|
||||||
@@ -141,9 +126,6 @@ def concretize(self) -> "spack.spec.Spec":
|
|||||||
if edge.spec.name == "cmake" and self.external_cmake:
|
if edge.spec.name == "cmake" and self.external_cmake:
|
||||||
edge.spec = self.external_cmake
|
edge.spec = self.external_cmake
|
||||||
|
|
||||||
if edge.spec.name == self.host_compiler.name:
|
|
||||||
edge.spec = self.host_compiler
|
|
||||||
|
|
||||||
if "libc" in edge.virtuals:
|
if "libc" in edge.virtuals:
|
||||||
edge.spec = self.host_libc
|
edge.spec = self.host_libc
|
||||||
|
|
||||||
@@ -159,12 +141,12 @@ def python_external_spec(self) -> "spack.spec.Spec":
|
|||||||
return self._external_spec(result)
|
return self._external_spec(result)
|
||||||
|
|
||||||
def libc_external_spec(self) -> "spack.spec.Spec":
|
def libc_external_spec(self) -> "spack.spec.Spec":
|
||||||
detector = spack.compilers.libraries.CompilerPropertyDetector(self.host_compiler)
|
result = self.host_compiler.default_libc
|
||||||
result = detector.default_libc()
|
|
||||||
return self._external_spec(result)
|
return self._external_spec(result)
|
||||||
|
|
||||||
def _external_spec(self, initial_spec) -> "spack.spec.Spec":
|
def _external_spec(self, initial_spec) -> "spack.spec.Spec":
|
||||||
initial_spec.namespace = "builtin"
|
initial_spec.namespace = "builtin"
|
||||||
|
initial_spec.compiler = self.host_compiler.spec
|
||||||
initial_spec.architecture = self.host_architecture
|
initial_spec.architecture = self.host_architecture
|
||||||
for flag_type in spack.spec.FlagMap.valid_compiler_flags():
|
for flag_type in spack.spec.FlagMap.valid_compiler_flags():
|
||||||
initial_spec.compiler_flags[flag_type] = []
|
initial_spec.compiler_flags[flag_type] = []
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
"""Manage configuration swapping for bootstrapping purposes"""
|
"""Manage configuration swapping for bootstrapping purposes"""
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
import os.path
|
import os
|
||||||
import sys
|
import sys
|
||||||
from typing import Any, Dict, Generator, MutableSequence, Sequence
|
from typing import Any, Dict, Generator, MutableSequence, Sequence
|
||||||
|
|
||||||
from llnl.util import tty
|
from llnl.util import tty
|
||||||
|
|
||||||
import spack.compilers.config
|
import spack.compilers
|
||||||
import spack.config
|
import spack.config
|
||||||
import spack.environment
|
import spack.environment
|
||||||
import spack.modules
|
import spack.modules
|
||||||
@@ -141,9 +141,9 @@ def _bootstrap_config_scopes() -> Sequence["spack.config.ConfigScope"]:
|
|||||||
|
|
||||||
|
|
||||||
def _add_compilers_if_missing() -> None:
|
def _add_compilers_if_missing() -> None:
|
||||||
arch = spack.spec.ArchSpec.frontend_arch()
|
arch = spack.spec.ArchSpec.default_arch()
|
||||||
if not spack.compilers.config.compilers_for_arch(arch):
|
if not spack.compilers.compilers_for_arch(arch):
|
||||||
spack.compilers.config.find_compilers()
|
spack.compilers.find_compilers()
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
import functools
|
import functools
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import os.path
|
|
||||||
import sys
|
import sys
|
||||||
import uuid
|
import uuid
|
||||||
from typing import Any, Callable, Dict, List, Optional, Tuple
|
from typing import Any, Callable, Dict, List, Optional, Tuple
|
||||||
@@ -34,8 +33,10 @@
|
|||||||
from llnl.util.lang import GroupedExceptionHandler
|
from llnl.util.lang import GroupedExceptionHandler
|
||||||
|
|
||||||
import spack.binary_distribution
|
import spack.binary_distribution
|
||||||
|
import spack.concretize
|
||||||
import spack.config
|
import spack.config
|
||||||
import spack.detection
|
import spack.detection
|
||||||
|
import spack.error
|
||||||
import spack.mirrors.mirror
|
import spack.mirrors.mirror
|
||||||
import spack.platforms
|
import spack.platforms
|
||||||
import spack.spec
|
import spack.spec
|
||||||
@@ -44,10 +45,17 @@
|
|||||||
import spack.util.executable
|
import spack.util.executable
|
||||||
import spack.util.path
|
import spack.util.path
|
||||||
import spack.util.spack_yaml
|
import spack.util.spack_yaml
|
||||||
|
import spack.util.url
|
||||||
import spack.version
|
import spack.version
|
||||||
from spack.installer import PackageInstaller
|
from spack.installer import PackageInstaller
|
||||||
|
|
||||||
from ._common import _executables_in_store, _python_import, _root_spec, _try_import_from_store
|
from ._common import (
|
||||||
|
QueryInfo,
|
||||||
|
_executables_in_store,
|
||||||
|
_python_import,
|
||||||
|
_root_spec,
|
||||||
|
_try_import_from_store,
|
||||||
|
)
|
||||||
from .clingo import ClingoBootstrapConcretizer
|
from .clingo import ClingoBootstrapConcretizer
|
||||||
from .config import spack_python_interpreter, spec_for_current_python
|
from .config import spack_python_interpreter, spec_for_current_python
|
||||||
|
|
||||||
@@ -89,8 +97,12 @@ def __init__(self, conf: ConfigDictionary) -> None:
|
|||||||
self.name = conf["name"]
|
self.name = conf["name"]
|
||||||
self.metadata_dir = spack.util.path.canonicalize_path(conf["metadata"])
|
self.metadata_dir = spack.util.path.canonicalize_path(conf["metadata"])
|
||||||
|
|
||||||
# Promote (relative) paths to file urls
|
# Check for relative paths, and turn them into absolute paths
|
||||||
self.url = spack.mirrors.mirror.Mirror(conf["info"]["url"]).fetch_url
|
# root is the metadata_dir
|
||||||
|
maybe_url = conf["info"]["url"]
|
||||||
|
if spack.util.url.is_path_instead_of_url(maybe_url) and not os.path.isabs(maybe_url):
|
||||||
|
maybe_url = os.path.join(self.metadata_dir, maybe_url)
|
||||||
|
self.url = spack.mirrors.mirror.Mirror(maybe_url).fetch_url
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mirror_scope(self) -> spack.config.InternalConfigScope:
|
def mirror_scope(self) -> spack.config.InternalConfigScope:
|
||||||
@@ -134,7 +146,7 @@ class BuildcacheBootstrapper(Bootstrapper):
|
|||||||
|
|
||||||
def __init__(self, conf) -> None:
|
def __init__(self, conf) -> None:
|
||||||
super().__init__(conf)
|
super().__init__(conf)
|
||||||
self.last_search: Optional[ConfigDictionary] = None
|
self.last_search: Optional[QueryInfo] = None
|
||||||
self.config_scope_name = f"bootstrap_buildcache-{uuid.uuid4()}"
|
self.config_scope_name = f"bootstrap_buildcache-{uuid.uuid4()}"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -211,14 +223,14 @@ def _install_and_test(
|
|||||||
for _, pkg_hash, pkg_sha256 in item["binaries"]:
|
for _, pkg_hash, pkg_sha256 in item["binaries"]:
|
||||||
self._install_by_hash(pkg_hash, pkg_sha256, bincache_platform)
|
self._install_by_hash(pkg_hash, pkg_sha256, bincache_platform)
|
||||||
|
|
||||||
info: ConfigDictionary = {}
|
info: QueryInfo = {}
|
||||||
if test_fn(query_spec=abstract_spec, query_info=info):
|
if test_fn(query_spec=abstract_spec, query_info=info):
|
||||||
self.last_search = info
|
self.last_search = info
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def try_import(self, module: str, abstract_spec_str: str) -> bool:
|
def try_import(self, module: str, abstract_spec_str: str) -> bool:
|
||||||
info: ConfigDictionary
|
info: QueryInfo
|
||||||
test_fn, info = functools.partial(_try_import_from_store, module), {}
|
test_fn, info = functools.partial(_try_import_from_store, module), {}
|
||||||
if test_fn(query_spec=abstract_spec_str, query_info=info):
|
if test_fn(query_spec=abstract_spec_str, query_info=info):
|
||||||
return True
|
return True
|
||||||
@@ -231,7 +243,7 @@ def try_import(self, module: str, abstract_spec_str: str) -> bool:
|
|||||||
return self._install_and_test(abstract_spec, bincache_platform, data, test_fn)
|
return self._install_and_test(abstract_spec, bincache_platform, data, test_fn)
|
||||||
|
|
||||||
def try_search_path(self, executables: Tuple[str], abstract_spec_str: str) -> bool:
|
def try_search_path(self, executables: Tuple[str], abstract_spec_str: str) -> bool:
|
||||||
info: ConfigDictionary
|
info: QueryInfo
|
||||||
test_fn, info = functools.partial(_executables_in_store, executables), {}
|
test_fn, info = functools.partial(_executables_in_store, executables), {}
|
||||||
if test_fn(query_spec=abstract_spec_str, query_info=info):
|
if test_fn(query_spec=abstract_spec_str, query_info=info):
|
||||||
self.last_search = info
|
self.last_search = info
|
||||||
@@ -249,11 +261,11 @@ class SourceBootstrapper(Bootstrapper):
|
|||||||
|
|
||||||
def __init__(self, conf) -> None:
|
def __init__(self, conf) -> None:
|
||||||
super().__init__(conf)
|
super().__init__(conf)
|
||||||
self.last_search: Optional[ConfigDictionary] = None
|
self.last_search: Optional[QueryInfo] = None
|
||||||
self.config_scope_name = f"bootstrap_source-{uuid.uuid4()}"
|
self.config_scope_name = f"bootstrap_source-{uuid.uuid4()}"
|
||||||
|
|
||||||
def try_import(self, module: str, abstract_spec_str: str) -> bool:
|
def try_import(self, module: str, abstract_spec_str: str) -> bool:
|
||||||
info: ConfigDictionary = {}
|
info: QueryInfo = {}
|
||||||
if _try_import_from_store(module, abstract_spec_str, query_info=info):
|
if _try_import_from_store(module, abstract_spec_str, query_info=info):
|
||||||
self.last_search = info
|
self.last_search = info
|
||||||
return True
|
return True
|
||||||
@@ -270,22 +282,17 @@ def try_import(self, module: str, abstract_spec_str: str) -> bool:
|
|||||||
bootstrapper = ClingoBootstrapConcretizer(configuration=spack.config.CONFIG)
|
bootstrapper = ClingoBootstrapConcretizer(configuration=spack.config.CONFIG)
|
||||||
concrete_spec = bootstrapper.concretize()
|
concrete_spec = bootstrapper.concretize()
|
||||||
else:
|
else:
|
||||||
concrete_spec = spack.spec.Spec(
|
abstract_spec = spack.spec.Spec(
|
||||||
abstract_spec_str + " ^" + spec_for_current_python()
|
abstract_spec_str + " ^" + spec_for_current_python()
|
||||||
)
|
)
|
||||||
concrete_spec.concretize()
|
concrete_spec = spack.concretize.concretize_one(abstract_spec)
|
||||||
|
|
||||||
msg = "[BOOTSTRAP MODULE {0}] Try installing '{1}' from sources"
|
msg = "[BOOTSTRAP MODULE {0}] Try installing '{1}' from sources"
|
||||||
tty.debug(msg.format(module, abstract_spec_str))
|
tty.debug(msg.format(module, abstract_spec_str))
|
||||||
|
|
||||||
# Install the spec that should make the module importable
|
# Install the spec that should make the module importable
|
||||||
with spack.config.override(self.mirror_scope):
|
with spack.config.override(self.mirror_scope):
|
||||||
PackageInstaller(
|
PackageInstaller([concrete_spec.package], fail_fast=True).install()
|
||||||
[concrete_spec.package],
|
|
||||||
fail_fast=True,
|
|
||||||
package_use_cache=False,
|
|
||||||
dependencies_use_cache=False,
|
|
||||||
).install()
|
|
||||||
|
|
||||||
if _try_import_from_store(module, query_spec=concrete_spec, query_info=info):
|
if _try_import_from_store(module, query_spec=concrete_spec, query_info=info):
|
||||||
self.last_search = info
|
self.last_search = info
|
||||||
@@ -293,7 +300,7 @@ def try_import(self, module: str, abstract_spec_str: str) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def try_search_path(self, executables: Tuple[str], abstract_spec_str: str) -> bool:
|
def try_search_path(self, executables: Tuple[str], abstract_spec_str: str) -> bool:
|
||||||
info: ConfigDictionary = {}
|
info: QueryInfo = {}
|
||||||
if _executables_in_store(executables, abstract_spec_str, query_info=info):
|
if _executables_in_store(executables, abstract_spec_str, query_info=info):
|
||||||
self.last_search = info
|
self.last_search = info
|
||||||
return True
|
return True
|
||||||
@@ -304,7 +311,7 @@ def try_search_path(self, executables: Tuple[str], abstract_spec_str: str) -> bo
|
|||||||
# might reduce compilation time by a fair amount
|
# might reduce compilation time by a fair amount
|
||||||
_add_externals_if_missing()
|
_add_externals_if_missing()
|
||||||
|
|
||||||
concrete_spec = spack.spec.Spec(abstract_spec_str).concretized()
|
concrete_spec = spack.concretize.concretize_one(abstract_spec_str)
|
||||||
msg = "[BOOTSTRAP] Try installing '{0}' from sources"
|
msg = "[BOOTSTRAP] Try installing '{0}' from sources"
|
||||||
tty.debug(msg.format(abstract_spec_str))
|
tty.debug(msg.format(abstract_spec_str))
|
||||||
with spack.config.override(self.mirror_scope):
|
with spack.config.override(self.mirror_scope):
|
||||||
@@ -321,10 +328,9 @@ def create_bootstrapper(conf: ConfigDictionary):
|
|||||||
return _bootstrap_methods[btype](conf)
|
return _bootstrap_methods[btype](conf)
|
||||||
|
|
||||||
|
|
||||||
def source_is_enabled(conf: ConfigDictionary):
|
def source_is_enabled(conf: ConfigDictionary) -> bool:
|
||||||
"""Raise ValueError if the source is not enabled for bootstrapping"""
|
"""Returns true if the source is not enabled for bootstrapping"""
|
||||||
trusted, name = spack.config.get("bootstrap:trusted"), conf["name"]
|
return spack.config.get("bootstrap:trusted").get(conf["name"], False)
|
||||||
return trusted.get(name, False)
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_module_importable_or_raise(module: str, abstract_spec: Optional[str] = None):
|
def ensure_module_importable_or_raise(module: str, abstract_spec: Optional[str] = None):
|
||||||
@@ -356,20 +362,21 @@ def ensure_module_importable_or_raise(module: str, abstract_spec: Optional[str]
|
|||||||
for current_config in bootstrapping_sources():
|
for current_config in bootstrapping_sources():
|
||||||
if not source_is_enabled(current_config):
|
if not source_is_enabled(current_config):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
with exception_handler.forward(current_config["name"], Exception):
|
with exception_handler.forward(current_config["name"], Exception):
|
||||||
current_bootstrapper = create_bootstrapper(current_config)
|
if create_bootstrapper(current_config).try_import(module, abstract_spec):
|
||||||
if current_bootstrapper.try_import(module, abstract_spec):
|
|
||||||
return
|
return
|
||||||
|
|
||||||
assert exception_handler, (
|
|
||||||
f"expected at least one exception to have been raised at this point: "
|
|
||||||
f"while bootstrapping {module}"
|
|
||||||
)
|
|
||||||
msg = f'cannot bootstrap the "{module}" Python module '
|
msg = f'cannot bootstrap the "{module}" Python module '
|
||||||
if abstract_spec:
|
if abstract_spec:
|
||||||
msg += f'from spec "{abstract_spec}" '
|
msg += f'from spec "{abstract_spec}" '
|
||||||
msg += exception_handler.grouped_message(with_tracebacks=tty.is_debug())
|
|
||||||
|
if not exception_handler:
|
||||||
|
msg += ": no bootstrapping sources are enabled"
|
||||||
|
elif spack.error.debug or spack.error.SHOW_BACKTRACE:
|
||||||
|
msg += exception_handler.grouped_message(with_tracebacks=True)
|
||||||
|
else:
|
||||||
|
msg += exception_handler.grouped_message(with_tracebacks=False)
|
||||||
|
msg += "\nRun `spack --backtrace ...` for more detailed errors"
|
||||||
raise ImportError(msg)
|
raise ImportError(msg)
|
||||||
|
|
||||||
|
|
||||||
@@ -417,6 +424,7 @@ def ensure_executables_in_path_or_raise(
|
|||||||
current_bootstrapper.last_search["spec"],
|
current_bootstrapper.last_search["spec"],
|
||||||
current_bootstrapper.last_search["command"],
|
current_bootstrapper.last_search["command"],
|
||||||
)
|
)
|
||||||
|
assert cmd is not None, "expected an Executable"
|
||||||
cmd.add_default_envmod(
|
cmd.add_default_envmod(
|
||||||
spack.user_environment.environment_modifications_for_specs(
|
spack.user_environment.environment_modifications_for_specs(
|
||||||
concrete_spec, set_package_py_globals=False
|
concrete_spec, set_package_py_globals=False
|
||||||
@@ -424,18 +432,17 @@ def ensure_executables_in_path_or_raise(
|
|||||||
)
|
)
|
||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
assert exception_handler, (
|
|
||||||
f"expected at least one exception to have been raised at this point: "
|
|
||||||
f"while bootstrapping {executables_str}"
|
|
||||||
)
|
|
||||||
msg = f"cannot bootstrap any of the {executables_str} executables "
|
msg = f"cannot bootstrap any of the {executables_str} executables "
|
||||||
if abstract_spec:
|
if abstract_spec:
|
||||||
msg += f'from spec "{abstract_spec}" '
|
msg += f'from spec "{abstract_spec}" '
|
||||||
if tty.is_debug():
|
|
||||||
|
if not exception_handler:
|
||||||
|
msg += ": no bootstrapping sources are enabled"
|
||||||
|
elif spack.error.debug or spack.error.SHOW_BACKTRACE:
|
||||||
msg += exception_handler.grouped_message(with_tracebacks=True)
|
msg += exception_handler.grouped_message(with_tracebacks=True)
|
||||||
else:
|
else:
|
||||||
msg += exception_handler.grouped_message(with_tracebacks=False)
|
msg += exception_handler.grouped_message(with_tracebacks=False)
|
||||||
msg += "\nRun `spack --debug ...` for more detailed errors"
|
msg += "\nRun `spack --backtrace ...` for more detailed errors"
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user