Compare commits

..

23 Commits

Author SHA1 Message Date
psakievich
2cae2d0f27 Update lib/spack/spack/test/cmd/build_env.py 2024-12-17 15:47:28 -07:00
psakievich
b68b5811b8 Update build_env.py
Co-authored-by: John W. Parent <45471568+johnwparent@users.noreply.github.com>
2024-12-16 20:27:52 -07:00
psakiev
3f88278d48 Update imports 2024-12-10 22:54:56 -07:00
psakiev
1d536ce143 Revert prompt changes for environment activation
I tried consolidating but I am not convinced it will work
correctly
2024-12-10 22:40:34 -07:00
psakiev
20d148e464 Style 2024-12-10 16:24:24 -07:00
Aaron Young
88b5a12e16 Add prompt support for fish. (#47609)
To avoid changing the fish_prompt function, create a SPACK_PROMPT
environment variable, which users can then manually incorporate into
their fish_prompt.fish function.
2024-11-14 16:14:44 -07:00
psakievich
f5fef81779 [@spackbot] updating style on behalf of psakievich 2024-11-14 04:53:17 +00:00
psakiev
8c6773f33e Add a cd test 2024-11-13 16:13:01 -07:00
psakiev
7a79fe88e2 Re-write test and update docs some more 2024-11-12 20:57:32 -07:00
psakiev
5cbbed42b4 Add docs 2024-11-12 18:12:21 -07:00
psakiev
d6b937d94b Style 2024-11-12 17:44:11 -07:00
psakiev
8eb4354b4b Add navigation to dive feature 2024-11-12 17:32:28 -07:00
psakiev
707a8daaea Compatibility 2024-11-12 16:20:39 -07:00
psakiev
ab5c2d5f7c Fixes 2024-11-12 16:09:16 -07:00
psakiev
4d49a658c8 Add completion 2024-11-12 15:28:34 -07:00
psakiev
973f59abbc Merge remote-tracking branch 'origin' into psakiev/dev-build 2024-11-12 13:18:16 -07:00
psakiev
4216a06cd8 Add build-env --dive 2024-11-12 13:16:59 -07:00
psakiev
2acf90f7b7 WIP unify 2024-11-11 17:06:04 -07:00
psakiev
8d5e71f66b Merge remote-tracking branch 'origin' into psakiev/dev-build 2024-11-11 16:46:55 -07:00
psakiev
9b3c200a07 Add prompt capability to dev_build drop-in 2024-11-11 16:44:48 -07:00
Philip Sakievich
43604f639e Update help 2024-11-08 10:01:17 -07:00
Philip Sakievich
33ae096a8b Fix some things from review 2024-11-08 06:32:55 -07:00
Philip Sakievich
259a1d9268 Make dev-build compatible with spack develop 2024-11-07 21:59:21 -07:00
9658 changed files with 44321 additions and 52875 deletions

View File

@@ -66,7 +66,7 @@ jobs:
./share/spack/qa/validate_last_exit.ps1 ./share/spack/qa/validate_last_exit.ps1
spack -d audit externals spack -d audit externals
./share/spack/qa/validate_last_exit.ps1 ./share/spack/qa/validate_last_exit.ps1
- uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
if: ${{ inputs.with_coverage == 'true' && runner.os != 'Windows' }} if: ${{ inputs.with_coverage == 'true' && runner.os != 'Windows' }}
with: with:
name: coverage-audits-${{ matrix.system.os }} name: coverage-audits-${{ matrix.system.os }}

View File

@@ -1,3 +1,5 @@
# (c) 2022 Lawrence Livermore National Laboratory
git config --global user.email "spack@example.com" git config --global user.email "spack@example.com"
git config --global user.name "Test User" git config --global user.name "Test User"
git config --global core.longpaths true git config --global core.longpaths true

View File

@@ -161,7 +161,11 @@ jobs:
source share/spack/setup-env.sh source share/spack/setup-env.sh
spack -d gpg list spack -d gpg list
tree $HOME/.spack/bootstrap/store/ tree $HOME/.spack/bootstrap/store/
- name: Bootstrap File
run: |
source share/spack/setup-env.sh
spack -d python share/spack/qa/bootstrap-file.py
tree $HOME/.spack/bootstrap/store/
windows: windows:
runs-on: "windows-latest" runs-on: "windows-latest"
@@ -192,3 +196,9 @@ jobs:
spack -d gpg list spack -d gpg list
./share/spack/qa/validate_last_exit.ps1 ./share/spack/qa/validate_last_exit.ps1
tree $env:userprofile/.spack/bootstrap/store/ tree $env:userprofile/.spack/bootstrap/store/
- name: Bootstrap File
run: |
./share/spack/setup-env.ps1
spack -d python share/spack/qa/bootstrap-file.py
./share/spack/qa/validate_last_exit.ps1
tree $env:userprofile/.spack/bootstrap/store/

View File

@@ -40,30 +40,24 @@ 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', 'centos:stream9'], [centos-stream9, 'linux/amd64,linux/arm64,linux/ppc64le', 'centos:stream9'],
[leap15, 'linux/amd64,linux/arm64', 'opensuse/leap:15'], [leap15, 'linux/amd64,linux/arm64,linux/ppc64le', 'opensuse/leap:15'],
[ubuntu-focal, 'linux/amd64,linux/arm64', 'ubuntu:20.04'], [ubuntu-focal, 'linux/amd64,linux/arm64,linux/ppc64le', 'ubuntu:20.04'],
[ubuntu-jammy, 'linux/amd64,linux/arm64', 'ubuntu:22.04'], [ubuntu-jammy, 'linux/amd64,linux/arm64,linux/ppc64le', 'ubuntu:22.04'],
[ubuntu-noble, 'linux/amd64,linux/arm64', 'ubuntu:24.04'], [ubuntu-noble, 'linux/amd64,linux/arm64,linux/ppc64le', 'ubuntu:24.04'],
[almalinux8, 'linux/amd64,linux/arm64', 'almalinux:8'], [almalinux8, 'linux/amd64,linux/arm64,linux/ppc64le', 'almalinux:8'],
[almalinux9, 'linux/amd64,linux/arm64', 'almalinux:9'], [almalinux9, 'linux/amd64,linux/arm64,linux/ppc64le', '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', 'fedora:39'], [fedora39, 'linux/amd64,linux/arm64,linux/ppc64le', 'fedora:39'],
[fedora40, 'linux/amd64,linux/arm64', 'fedora:40']] [fedora40, 'linux/amd64,linux/arm64,linux/ppc64le', 'fedora:40']]
name: Build ${{ matrix.dockerfile[0] }} name: Build ${{ matrix.dockerfile[0] }}
if: github.repository == 'spack/spack' if: github.repository == 'spack/spack'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Determine latest release tag - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81
id: latest
run: |
git fetch --quiet --tags
echo "tag=$(git tag --list --sort=-v:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1)" | tee -a $GITHUB_OUTPUT
- uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96
id: docker_meta id: docker_meta
with: with:
images: | images: |
@@ -77,7 +71,6 @@ jobs:
type=semver,pattern={{major}} type=semver,pattern={{major}}
type=ref,event=branch type=ref,event=branch
type=ref,event=pr type=ref,event=pr
type=raw,value=latest,enable=${{ github.ref == format('refs/tags/{0}', steps.latest.outputs.tag) }}
- name: Generate the Dockerfile - name: Generate the Dockerfile
env: env:
@@ -94,7 +87,7 @@ jobs:
fi fi
- name: Upload Dockerfile - name: Upload Dockerfile
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with: with:
name: dockerfiles_${{ matrix.dockerfile[0] }} name: dockerfiles_${{ matrix.dockerfile[0] }}
path: dockerfiles path: dockerfiles
@@ -103,7 +96,7 @@ jobs:
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349
- name: Log in to GitHub Container Registry - name: Log in to GitHub Container Registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
@@ -120,7 +113,7 @@ jobs:
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build & Deploy ${{ matrix.dockerfile[0] }} - name: Build & Deploy ${{ matrix.dockerfile[0] }}
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75
with: with:
context: dockerfiles/${{ matrix.dockerfile[0] }} context: dockerfiles/${{ matrix.dockerfile[0] }}
platforms: ${{ matrix.dockerfile[1] }} platforms: ${{ matrix.dockerfile[1] }}
@@ -133,7 +126,7 @@ jobs:
needs: deploy-images needs: deploy-images
steps: steps:
- name: Merge Artifacts - name: Merge Artifacts
uses: actions/upload-artifact/merge@6f51ac03b9356f520e9adb1b1b7802705f340c2b uses: actions/upload-artifact/merge@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with: with:
name: dockerfiles name: dockerfiles
pattern: dockerfiles_* pattern: dockerfiles_*

View File

@@ -81,10 +81,6 @@ 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() }}

View File

@@ -29,8 +29,6 @@ jobs:
- run: coverage xml - run: coverage xml
- name: "Upload coverage report to CodeCov" - name: "Upload coverage report to CodeCov"
uses: codecov/codecov-action@1e68e06f1dbfde0e4cefc87efeba9e4643565303 uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238
with: with:
verbose: true verbose: true
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}

View File

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

View File

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

View File

@@ -15,17 +15,17 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
on_develop: on_develop:
- ${{ github.ref == 'refs/heads/develop' }} - ${{ github.ref == 'refs/heads/develop' }}
include: include:
- python-version: '3.6' - python-version: '3.6'
os: ubuntu-20.04 os: ubuntu-20.04
on_develop: ${{ github.ref == 'refs/heads/develop' }} on_develop: ${{ github.ref == 'refs/heads/develop' }}
- python-version: '3.7'
os: ubuntu-22.04
on_develop: ${{ github.ref == 'refs/heads/develop' }}
exclude: exclude:
- python-version: '3.7'
os: ubuntu-latest
on_develop: false
- python-version: '3.8' - python-version: '3.8'
os: ubuntu-latest os: ubuntu-latest
on_develop: false on_develop: false
@@ -52,13 +52,7 @@ jobs:
# Needed for unit tests # Needed for unit tests
sudo apt-get -y install \ sudo apt-get -y install \
coreutils cvs gfortran graphviz gnupg2 mercurial ninja-build \ coreutils cvs gfortran graphviz gnupg2 mercurial ninja-build \
cmake bison libbison-dev subversion cmake bison libbison-dev kcov
# On ubuntu 24.04, kcov was removed. It may come back in some future Ubuntu
- name: Set up Homebrew
id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@40e9946c182a64b3db1bf51be0dcb915f7802aa9
- name: Install kcov with brew
run: "brew install kcov"
- name: Install Python packages - name: Install Python packages
run: | run: |
pip install --upgrade pip setuptools pytest pytest-xdist pytest-cov pip install --upgrade pip setuptools pytest pytest-xdist pytest-cov
@@ -86,7 +80,7 @@ jobs:
UNIT_TEST_COVERAGE: ${{ matrix.python-version == '3.11' }} UNIT_TEST_COVERAGE: ${{ matrix.python-version == '3.11' }}
run: | run: |
share/spack/qa/run-unit-tests share/spack/qa/run-unit-tests
- uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with: with:
name: coverage-${{ matrix.os }}-python${{ matrix.python-version }} name: coverage-${{ matrix.os }}-python${{ matrix.python-version }}
path: coverage path: coverage
@@ -105,13 +99,7 @@ jobs:
run: | run: |
sudo apt-get -y update sudo apt-get -y update
# Needed for shell tests # Needed for shell tests
sudo apt-get install -y coreutils csh zsh tcsh fish dash bash subversion sudo apt-get install -y coreutils kcov csh zsh tcsh fish dash bash
# On ubuntu 24.04, kcov was removed. It may come back in some future Ubuntu
- name: Set up Homebrew
id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@40e9946c182a64b3db1bf51be0dcb915f7802aa9
- name: Install kcov with brew
run: "brew install kcov"
- name: Install Python packages - name: Install Python packages
run: | run: |
pip install --upgrade pip setuptools pytest coverage[toml] pytest-xdist pip install --upgrade pip setuptools pytest coverage[toml] pytest-xdist
@@ -125,7 +113,7 @@ jobs:
COVERAGE: true COVERAGE: true
run: | run: |
share/spack/qa/run-shell-tests share/spack/qa/run-shell-tests
- uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with: with:
name: coverage-shell name: coverage-shell
path: coverage path: coverage
@@ -140,13 +128,13 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
dnf install -y \ dnf install -y \
bzip2 curl gcc-c++ gcc gcc-gfortran git gnupg2 gzip \ bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \
make patch tcl unzip which xz make patch tcl unzip which xz
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Setup repo and non-root user - name: Setup repo and non-root user
run: | run: |
git --version git --version
git config --global --add safe.directory '*' git config --global --add safe.directory /__w/spack/spack
git fetch --unshallow git fetch --unshallow
. .github/workflows/bin/setup_git.sh . .github/workflows/bin/setup_git.sh
useradd spack-test useradd spack-test
@@ -187,7 +175,7 @@ jobs:
spack bootstrap status spack bootstrap status
spack solve zlib 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@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with: with:
name: coverage-clingo-cffi name: coverage-clingo-cffi
path: coverage path: coverage
@@ -225,7 +213,7 @@ jobs:
$(which spack) solve zlib $(which spack) solve zlib
common_args=(--dist loadfile --tx '4*popen//python=./bin/spack-tmpconfig python -u ./bin/spack python' -x) 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@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with: with:
name: coverage-${{ matrix.os }}-python${{ matrix.python-version }} name: coverage-${{ matrix.os }}-python${{ matrix.python-version }}
path: coverage path: coverage
@@ -256,7 +244,7 @@ jobs:
run: | run: |
spack unit-test -x --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@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with: with:
name: coverage-windows name: coverage-windows
path: coverage path: coverage

View File

@@ -13,14 +13,15 @@ concurrency:
jobs: jobs:
# Validate that the code can be run on all the Python versions supported by Spack # Validate that the code can be run on all the Python versions
# supported by Spack
validate: validate:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b
with: with:
python-version: '3.13' python-version: '3.11'
cache: 'pip' cache: 'pip'
- name: Install Python Packages - name: Install Python Packages
run: | run: |
@@ -39,7 +40,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b
with: with:
python-version: '3.13' python-version: '3.11'
cache: 'pip' cache: 'pip'
- name: Install Python packages - name: Install Python packages
run: | run: |
@@ -58,7 +59,7 @@ jobs:
secrets: inherit secrets: inherit
with: with:
with_coverage: ${{ inputs.with_coverage }} with_coverage: ${{ inputs.with_coverage }}
python_version: '3.13' python_version: '3.11'
# Check that spack can bootstrap the development environment on Python 3.6 - RHEL8 # Check that spack can bootstrap the development environment on Python 3.6 - RHEL8
bootstrap-dev-rhel8: bootstrap-dev-rhel8:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -73,7 +74,7 @@ jobs:
- name: Setup repo and non-root user - name: Setup repo and non-root user
run: | run: |
git --version git --version
git config --global --add safe.directory '*' git config --global --add safe.directory /__w/spack/spack
git fetch --unshallow git fetch --unshallow
. .github/workflows/bin/setup_git.sh . .github/workflows/bin/setup_git.sh
useradd spack-test useradd spack-test
@@ -86,21 +87,62 @@ 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
import-check:
# Further style checks from pylint
pylint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: julia-actions/setup-julia@v2
with: with:
fetch-depth: 0 version: '1.10'
- uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b - uses: julia-actions/cache@v2
with:
python-version: '3.13' # PR: use the base of the PR as the old commit
cache: 'pip' - name: Checkout PR base commit
- name: Install Python packages if: github.event_name == 'pull_request'
run: | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
pip install --upgrade pip setuptools pylint with:
- name: Pylint (Spack Core) ref: ${{ github.event.pull_request.base.sha }}
run: | path: old
pylint -j 4 --disable=all --enable=unspecified-encoding --ignore-paths=lib/spack/external lib # 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: 9f60f51bc7134e0be73f27623f1b0357d1718427
path: circular-import-fighter
- name: Install dependencies
working-directory: circular-import-fighter
run: make -j dependencies
- name: Import cycles before
working-directory: circular-import-fighter
run: make SPACK_ROOT=../old && cp solution solution.old
- name: Import cycles after
working-directory: circular-import-fighter
run: make clean-graph && make SPACK_ROOT=../new && cp solution solution.new
- name: Compare import cycles
working-directory: circular-import-fighter
run: |
edges_before="$(grep -oP 'edges to delete: \K\d+' solution.old)"
edges_after="$(grep -oP 'edges to delete: \K\d+' 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"Import cycles before"\033[0m and '
printf '\033[1;97m"Import cycles after"\033[0m to see problematic imports.\n'
exit 1
else
printf '\033[1;32mImport check passed: %s <= %s\033[0m\n' "$edges_after" "$edges_before"
fi

1
.gitignore vendored
View File

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

View File

@@ -8,9 +8,8 @@ or http://www.apache.org/licenses/LICENSE-2.0) or the MIT license,
Copyrights and patents in the Spack project are retained by contributors. Copyrights and patents in the Spack project are retained by contributors.
No copyright assignment is required to contribute to Spack. No copyright assignment is required to contribute to Spack.
Spack was originally developed in 2013 by Lawrence Livermore National Spack was originally distributed under the LGPL-2.1 license. Consent from
Security, LLC. It was originally distributed under the LGPL-2.1 license. contributors to relicense to Apache-2.0/MIT is documented at
Consent from contributors to relicense to Apache-2.0/MIT is documented at
https://github.com/spack/spack/issues/9137. https://github.com/spack/spack/issues/9137.
@@ -103,6 +102,6 @@ PackageName: sbang
PackageHomePage: https://github.com/spack/sbang PackageHomePage: https://github.com/spack/sbang
PackageLicenseDeclared: Apache-2.0 OR MIT PackageLicenseDeclared: Apache-2.0 OR MIT
PackageName: typing_extensions PackageName: six
PackageHomePage: https://pypi.org/project/typing-extensions/ PackageHomePage: https://pypi.python.org/pypi/six
PackageLicenseDeclared: Python-2.0 PackageLicenseDeclared: MIT

View File

@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) Spack Project Developers. Copyright (c) 2013-2024 LLNS, LLC and other Spack Project Developers.
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -70,7 +70,7 @@ Tutorial
---------------- ----------------
We maintain a We maintain a
[**hands-on tutorial**](https://spack-tutorial.readthedocs.io/). [**hands-on tutorial**](https://spack.readthedocs.io/en/latest/tutorial.html).
It covers basic to advanced usage, packaging, developer features, and large HPC It covers basic to advanced usage, packaging, developer features, and large HPC
deployments. You can do all of the exercises on your own laptop using a deployments. You can do all of the exercises on your own laptop using a
Docker container. Docker container.

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import subprocess import subprocess

View File

@@ -1,6 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# Copyright sbang project developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# sbang project developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,7 +1,8 @@
#!/bin/sh #!/bin/sh
# -*- python -*- # -*- python -*-
# #
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -25,6 +26,7 @@ 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)

View File

@@ -1,6 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
:: Copyright Spack Project Developers. See COPYRIGHT file for details. :: Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
:: Spack Project Developers. See the top-level COPYRIGHT file for details.
:: ::
:: SPDX-License-Identifier: (Apache-2.0 OR MIT) :: SPDX-License-Identifier: (Apache-2.0 OR MIT)
::####################################################################### ::#######################################################################

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
# ####################################################################### # #######################################################################

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -39,53 +39,11 @@ concretizer:
# Option to deal with possible duplicate nodes (i.e. different nodes from the same package) in the DAG. # Option to deal with possible duplicate nodes (i.e. different nodes from the same package) in the DAG.
duplicates: duplicates:
# "none": allows a single node for any package in the DAG. # "none": allows a single node for any package in the DAG.
# "minimal": allows the duplication of 'build-tools' nodes only # "minimal": allows the duplication of 'build-tools' nodes only (e.g. py-setuptools, cmake etc.)
# (e.g. py-setuptools, cmake etc.)
# "full" (experimental): allows separation of the entire build-tool stack (e.g. the entire "cmake" subDAG) # "full" (experimental): allows separation of the entire build-tool stack (e.g. the entire "cmake" subDAG)
strategy: minimal strategy: minimal
# Maximum number of duplicates in a DAG, when using a strategy that allows duplicates. "default" is the
# number used if there isn't a more specific alternative
max_dupes:
default: 1
# Virtuals
c: 2
cxx: 2
fortran: 1
# Regular packages
cmake: 2
gmake: 2
python: 2
python-venv: 2
py-cython: 2
py-flit-core: 2
py-pip: 2
py-setuptools: 2
py-wheel: 2
xcb-proto: 2
# Compilers
gcc: 2
llvm: 2
# Option to specify compatibility between operating systems for reuse of compilers and packages # Option to specify compatibility between operating systems for reuse of compilers and packages
# Specified as a key: [list] where the key is the os that is being targeted, and the list contains the OS's # Specified as a key: [list] where the key is the os that is being targeted, and the list contains the OS's
# it can reuse. Note this is a directional compatibility so mutual compatibility between two OS's # it can reuse. Note this is a directional compatibility so mutual compatibility between two OS's
# requires two entries i.e. os_compatible: {sonoma: [monterey], monterey: [sonoma]} # requires two entries i.e. os_compatible: {sonoma: [monterey], monterey: [sonoma]}
os_compatible: {} os_compatible: {}
# Option to specify whether to support splicing. Splicing allows for
# the relinking of concrete package dependencies in order to better
# reuse already built packages with ABI compatible dependencies
splice:
explicit: []
automatic: false
# Maximum time, in seconds, allowed for the 'solve' phase. If set to 0, there is no time limit.
timeout: 0
# If set to true, exceeding the timeout will always result in a concretization error. If false,
# the best (suboptimal) model computed before the timeout is used.
#
# Setting this to false yields unreproducible results, so we advise to use that value only
# for debugging purposes (e.g. check which constraints can help Spack concretize faster).
error_on_timeout: true
# Static analysis may reduce the concretization time by generating smaller ASP problems, in
# cases where there are requirements that prevent part of the search space to be explored.
static_analysis: false

View File

@@ -194,12 +194,6 @@ config:
# executables with many dependencies, in particular on slow filesystems. # executables with many dependencies, in particular on slow filesystems.
bind: false bind: false
# Controls the handling of missing dynamic libraries after installation.
# Options are ignore (default), warn, or error. If set to error, the
# installation fails if installed binaries reference dynamic libraries that
# are not found in their specified rpaths.
missing_library_policy: ignore
# Set to 'false' to allow installation on filesystems that doesn't allow setgid bit # Set to 'false' to allow installation on filesystems that doesn't allow setgid bit
# manipulation by unprivileged user (e.g. AFS) # manipulation by unprivileged user (e.g. AFS)
@@ -226,3 +220,4 @@ config:
concretise: concretize concretise: concretize
containerise: containerize containerise: containerize
rm: remove rm: remove
dev-dive: build-env --cd build-dir --dive

View File

@@ -36,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] java: [openjdk, jdk, ibm-java]
jpeg: [libjpeg-turbo, libjpeg] jpeg: [libjpeg-turbo, libjpeg]
lapack: [openblas, amdlibflame] lapack: [openblas, amdlibflame]
libc: [glibc, musl] libc: [glibc, musl]
@@ -65,7 +65,6 @@ packages:
unwind: [libunwind] unwind: [libunwind]
uuid: [util-linux-uuid, libuuid] uuid: [util-linux-uuid, libuuid]
wasi-sdk: [wasi-sdk-prebuilt] wasi-sdk: [wasi-sdk-prebuilt]
xkbdata-api: [xkeyboard-config, xkbdata]
xxd: [xxd-standalone, vim] xxd: [xxd-standalone, vim]
yacc: [bison, byacc] yacc: [bison, byacc]
ziglang: [zig] ziglang: [zig]
@@ -73,27 +72,13 @@ 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:
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

View File

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

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

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

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -264,30 +265,25 @@ infrastructure, or to cache Spack built binaries in Github Actions and
GitLab CI. GitLab CI.
To get started, configure an OCI mirror using ``oci://`` as the scheme, To get started, configure an OCI mirror using ``oci://`` as the scheme,
and optionally specify variables that hold the username and password (or and optionally specify a username and password (or personal access token):
personal access token) for the registry:
.. code-block:: console .. code-block:: console
$ spack mirror add --oci-username-variable REGISTRY_USER \ $ spack mirror add --oci-username username --oci-password password my_registry oci://example.com/my_image
--oci-password-variable REGISTRY_TOKEN \
my_registry oci://example.com/my_image
Spack follows the naming conventions of Docker, with Dockerhub as the default Spack follows the naming conventions of Docker, with Dockerhub as the default
registry. To use Dockerhub, you can omit the registry domain: registry. To use Dockerhub, you can omit the registry domain:
.. code-block:: console .. code-block:: console
$ spack mirror add ... my_registry oci://username/my_image $ spack mirror add --oci-username username --oci-password password my_registry oci://username/my_image
From here, you can use the mirror as any other build cache: From here, you can use the mirror as any other build cache:
.. code-block:: console .. code-block:: console
$ export REGISTRY_USER=...
$ export REGISTRY_TOKEN=...
$ spack buildcache push my_registry <specs...> # push to the registry $ spack buildcache push my_registry <specs...> # push to the registry
$ spack install <specs...> # or install from the registry $ spack install <specs...> # install from the registry
A unique feature of buildcaches on top of OCI registries is that it's incredibly A unique feature of buildcaches on top of OCI registries is that it's incredibly
easy to generate get a runnable container image with the binaries installed. This easy to generate get a runnable container image with the binaries installed. This

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -170,7 +171,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

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -236,35 +237,3 @@ is optional -- by default, splices will be transitive.
``mpich/abcdef`` instead of ``mvapich2`` as the MPI provider. Spack ``mpich/abcdef`` instead of ``mvapich2`` as the MPI provider. Spack
will warn the user in this case, but will not fail the will warn the user in this case, but will not fail the
concretization. concretization.
.. _automatic_splicing:
^^^^^^^^^^^^^^^^^^
Automatic Splicing
^^^^^^^^^^^^^^^^^^
The Spack solver can be configured to do automatic splicing for
ABI-compatible packages. Automatic splices are enabled in the concretizer
config section
.. code-block:: yaml
concretizer:
splice:
automatic: True
Packages can include ABI-compatibility information using the
``can_splice`` directive. See :ref:`the packaging
guide<abi_compatibility>` for instructions on specifying ABI
compatibility using the ``can_splice`` directive.
.. note::
The ``can_splice`` directive is experimental and may be changed in
future versions.
When automatic splicing is enabled, the concretizer will combine any
number of ABI-compatible specs if possible to reuse installed packages
and packages available from binary caches. The end result of these
specs is equivalent to a series of transitive/intransitive splices,
but the series may be non-obvious.

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -272,9 +273,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.
^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
Adding flags to configure Addings 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 +286,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,10 +300,7 @@ 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):
args = [] return [self.enable_or_disable("mpi")]
...
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
@@ -347,14 +345,7 @@ 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:

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -56,13 +57,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

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -24,14 +25,6 @@ QMake does not appear to have a standardized way of specifying
the installation directory, so you may have to set environment the installation directory, so you may have to set environment
variables or edit ``*.pro`` files to get things working properly. variables or edit ``*.pro`` files to get things working properly.
QMake packages will depend on the virtual ``qmake`` package which
is provided by multiple versions of Qt: ``qt`` provides Qt up to
Qt5, and ``qt-base`` provides Qt from version Qt6 onwards. This
split was motivated by the desire to split the single Qt package
into its components to allow for more fine-grained installation.
To depend on a specific version, refer to the documentation on
:ref:`virtual-dependencies`.
^^^^^^ ^^^^^^
Phases Phases
^^^^^^ ^^^^^^

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -209,7 +210,7 @@ def setup(sphinx):
# Spack classes that are private and we don't want to expose # Spack classes that are private and we don't want to expose
("py:class", "spack.provider_index._IndexBase"), ("py:class", "spack.provider_index._IndexBase"),
("py:class", "spack.repo._PrependFileLoader"), ("py:class", "spack.repo._PrependFileLoader"),
("py:class", "spack.build_systems._checks.BuilderWithDefaults"), ("py:class", "spack.build_systems._checks.BaseBuilder"),
# Spack classes that intersphinx is unable to resolve # Spack classes that intersphinx is unable to resolve
("py:class", "spack.version.StandardVersion"), ("py:class", "spack.version.StandardVersion"),
("py:class", "spack.spec.DependencySpec"), ("py:class", "spack.spec.DependencySpec"),
@@ -223,10 +224,6 @@ def setup(sphinx):
("py:class", "spack.compiler.CompilerCache"), ("py:class", "spack.compiler.CompilerCache"),
# TypeVar that is not handled correctly # TypeVar that is not handled correctly
("py:class", "llnl.util.lang.T"), ("py:class", "llnl.util.lang.T"),
("py:class", "llnl.util.lang.KT"),
("py:class", "llnl.util.lang.VT"),
("py:obj", "llnl.util.lang.KT"),
("py:obj", "llnl.util.lang.VT"),
] ]
# The reST default role (used for this markup: `text`) to use for all documents. # The reST default role (used for this markup: `text`) to use for all documents.

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -25,23 +26,14 @@ These settings can be overridden in ``etc/spack/config.yaml`` or
The location where Spack will install packages and their dependencies. The location where Spack will install packages and their dependencies.
Default is ``$spack/opt/spack``. Default is ``$spack/opt/spack``.
--------------- ---------------------------------------------------
``projections`` ``install_hash_length`` and ``install_path_scheme``
--------------- ---------------------------------------------------
.. warning:: The default Spack installation path can be very long and can create problems
for scripts with hardcoded shebangs. Additionally, when using the Intel
Modifying projections of the install tree is strongly discouraged. compiler, and if there is also a long list of dependencies, the compiler may
segfault. If you see the following:
By default Spack installs all packages into a unique directory relative to the install
tree root with the following layout:
.. code-block::
{architecture}/{compiler.name}-{compiler.version}/{name}-{version}-{hash}
In very rare cases, it may be necessary to reduce the length of this path. For example,
very old versions of the Intel compiler are known to segfault when input paths are too long:
.. code-block:: console .. code-block:: console
@@ -49,25 +41,36 @@ very old versions of the Intel compiler are known to segfault when input paths a
** Segmentation violation signal raised. ** ** Segmentation violation signal raised. **
Access violation or stack overflow. Please contact Intel Support for assistance. Access violation or stack overflow. Please contact Intel Support for assistance.
Another case is Python and R packages with many runtime dependencies, which can result it may be because variables containing dependency specs may be too long. There
in very large ``PYTHONPATH`` and ``R_LIBS`` environment variables. This can cause the are two parameters to help with long path names. Firstly, the
``execve`` system call to fail with ``E2BIG``, preventing processes from starting. ``install_hash_length`` parameter can set the length of the hash in the
installation path from 1 to 32. The default path uses the full 32 characters.
For this reason, Spack allows users to modify the installation layout through custom Secondly, it is also possible to modify the entire installation
projections. For example scheme. By default Spack uses
``{architecture}/{compiler.name}-{compiler.version}/{name}-{version}-{hash}``
where the tokens that are available for use in this directive are the
same as those understood by the :meth:`~spack.spec.Spec.format`
method. Using this parameter it is possible to use a different package
layout or reduce the depth of the installation paths. For example
.. code-block:: yaml .. code-block:: yaml
config: config:
install_tree: install_path_scheme: '{name}/{version}/{hash:7}'
root: $spack/opt/spack
projections:
all: "{name}/{version}/{hash:16}"
would install packages into sub-directories using only the package name, version and a would install packages into sub-directories using only the package
hash length of 16 characters. name, version and a hash length of 7 characters.
Notice that reducing the hash length increases the likelihood of hash collisions. When using either parameter to set the hash length it only affects the
representation of the hash in the installation directory. You
should be aware that the smaller the hash length the more likely
naming conflicts will occur. These parameters are independent of those
used to configure module names.
.. warning:: Modifying the installation hash length or path scheme after
packages have been installed will prevent Spack from being
able to find the old installation directories.
-------------------- --------------------
``build_stage`` ``build_stage``
@@ -125,8 +128,6 @@ are stored in ``$spack/var/spack/cache``. These are stored indefinitely
by default. Can be purged with :ref:`spack clean --downloads by default. Can be purged with :ref:`spack clean --downloads
<cmd-spack-clean>`. <cmd-spack-clean>`.
.. _Misc Cache:
-------------------- --------------------
``misc_cache`` ``misc_cache``
-------------------- --------------------
@@ -336,52 +337,3 @@ create a new alias called ``inst`` that will always call ``install -v``:
aliases: aliases:
inst: install -v inst: install -v
-------------------------------
``concretization_cache:enable``
-------------------------------
When set to ``true``, Spack will utilize a cache of solver outputs from
successful concretization runs. When enabled, Spack will check the concretization
cache prior to running the solver. If a previous request to solve a given
problem is present in the cache, Spack will load the concrete specs and other
solver data from the cache rather than running the solver. Specs not previously
concretized will be added to the cache on a successful solve. The cache additionally
holds solver statistics, so commands like ``spack solve`` will still return information
about the run that produced a given solver result.
This cache is a subcache of the :ref:`Misc Cache` and as such will be cleaned when the Misc
Cache is cleaned.
When ``false`` or ommitted, all concretization requests will be performed from scatch
----------------------------
``concretization_cache:url``
----------------------------
Path to the location where Spack will root the concretization cache. Currently this only supports
paths on the local filesystem.
Default location is under the :ref:`Misc Cache` at: ``$misc_cache/concretization``
------------------------------------
``concretization_cache:entry_limit``
------------------------------------
Sets a limit on the number of concretization results that Spack will cache. The limit is evaluated
after each concretization run; if Spack has stored more results than the limit allows, the
oldest concretization results are pruned until 10% of the limit has been removed.
Setting this value to 0 disables the automatic pruning. It is expected users will be
responsible for maintaining this cache.
-----------------------------------
``concretization_cache:size_limit``
-----------------------------------
Sets a limit on the size of the concretization cache in bytes. The limit is evaluated
after each concretization run; if Spack has stored more results than the limit allows, the
oldest concretization results are pruned until 10% of the limit has been removed.
Setting this value to 0 disables the automatic pruning. It is expected users will be
responsible for maintaining this cache.

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -37,11 +38,9 @@ just have to configure and OCI registry and run ``spack buildcache push``.
spack -e . install spack -e . install
# Configure the registry # Configure the registry
spack -e . mirror add --oci-username-variable REGISTRY_USER \ spack -e . mirror add --oci-username ... --oci-password ... container-registry oci://example.com/name/image
--oci-password-variable REGISTRY_TOKEN \
container-registry oci://example.com/name/image
# Push the image (do set REGISTRY_USER and REGISTRY_TOKEN) # Push the image
spack -e . buildcache push --update-index --base-image ubuntu:22.04 --tag my_env container-registry spack -e . buildcache push --update-index --base-image ubuntu:22.04 --tag my_env container-registry
The resulting container image can then be run as follows: The resulting container image can then be run as follows:

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -361,6 +362,7 @@ 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``

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -177,8 +178,8 @@ Spec-related modules
Contains :class:`~spack.spec.Spec`. Also implements most of the logic for concretization Contains :class:`~spack.spec.Spec`. Also implements most of the logic for concretization
of specs. of specs.
:mod:`spack.spec_parser` :mod:`spack.parser`
Contains :class:`~spack.spec_parser.SpecParser` and functions related to parsing specs. Contains :class:`~spack.parser.SpecParser` and functions related to parsing specs.
:mod:`spack.version` :mod:`spack.version`
Implements a simple :class:`~spack.version.Version` class with simple Implements a simple :class:`~spack.version.Version` class with simple
@@ -543,10 +544,10 @@ With either interpreter you can run a single command:
.. code-block:: console .. code-block:: console
$ spack python -c 'from spack.concretize import concretize_one; concretize_one("python")' $ spack python -c 'from spack.spec import Spec; Spec("python").concretized()'
... ...
$ spack python -i ipython -c 'from spack.concretize import concretize_one; concretize_one("python")' $ spack python -i ipython -c 'from spack.spec import Spec; Spec("python").concretized()'
Out[1]: ... Out[1]: ...
or a file: or a file:

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -112,19 +113,6 @@ 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
@@ -482,6 +470,48 @@ The supplied location will become the build-directory for that package in all fu
developers to only redirect the build directory if they understand their package's developers to only redirect the build directory if they understand their package's
build-system. build-system.
When doing active development it can often be nice to work inside the build environment
to run tests, and compile the code natively (i.e. run ``make`` or ``ninja``) without the
overhead of calling ``spack install``.
The spack command ``build-env`` allows users to run processes inside the build environment
or to dive directly into it. An additional convenience alias is ``spack dev-dive [spec]``.
This will navigate to the package's build directory and then launch a subshell with the
build environment active. Users can query if they are currently in a build environment
subshell by running ``spack build-env --status``. When users are finished exploring or
working in the subshell they can call ``exit`` to leave the build subshell.
.. code-block:: console
# create and setup a spack environment for development
# ====
$ spack env activate --temp
$ spack add zlib-ng
$ spack stage -p $SPACK_ENV zlib-ng
$ spack develop zlib-ng
# build and make changes
# =====
$ spack install -u autoreconf zlib-ng
# [ fails ]
$ spack dev-dive zlib-ng
# prompt changed, confirm the location is the build directory
zlib-ng-build-env $ pwd
/private/var/folders/ln/1_3kxbwd35s_ylsjlm3zmqmc00307v/T/spack-ne8_m488/zlib-ng
# confirm build-env in case we forget where we are in subshell hierarchy
zlib-ng-build-env $ spack build-env --status
==> In build env zlib-ng-wrsaadvkbg7rjj7kfjw5rhdrrfdswcmm
# [ fix code ]
zlib-ng-build-env $ make -j6
# [ builds now ]
zlib-ng-build-env $ exit
# exit subshell and rebuild environment
# ====
$ spack build-env --status
==> build environment not detected
$ spack install
^^^^^^^ ^^^^^^^
Loading Loading
^^^^^^^ ^^^^^^^
@@ -1054,7 +1084,7 @@ file snippet we define a view named ``mpis``, rooted at
``/path/to/view`` in which all projections use the package name, ``/path/to/view`` in which all projections use the package name,
version, and compiler name to determine the path for a given version, and compiler name to determine the path for a given
package. This view selects all packages that depend on MPI, and package. This view selects all packages that depend on MPI, and
excludes those built with the GCC compiler at version 18.5. excludes those built with the PGI compiler at version 18.5.
The root specs with their (transitive) link and run type dependencies The root specs with their (transitive) link and run type dependencies
will be put in the view due to the ``link: all`` option, will be put in the view due to the ``link: all`` option,
and the files in the view will be symlinks to the spack install and the files in the view will be symlinks to the spack install
@@ -1068,7 +1098,7 @@ directories.
mpis: mpis:
root: /path/to/view root: /path/to/view
select: [^mpi] select: [^mpi]
exclude: ['%gcc@18.5'] exclude: ['%pgi@18.5']
projections: projections:
all: '{name}/{version}-{compiler.name}' all: '{name}/{version}-{compiler.name}'
link: all link: all

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -34,7 +35,7 @@ A build matrix showing which packages are working on which systems is shown belo
.. code-block:: console .. code-block:: console
apt update apt update
apt install bzip2 ca-certificates g++ gcc gfortran git gzip lsb-release patch python3 tar unzip xz-utils zstd apt install bzip2 ca-certificates file g++ gcc gfortran git gzip lsb-release patch python3 tar unzip xz-utils zstd
.. tab-item:: RHEL .. tab-item:: RHEL
@@ -147,22 +148,20 @@ The first time you concretize a spec, Spack will bootstrap automatically:
-------------------------------- --------------------------------
zlib@1.2.13%gcc@9.4.0+optimize+pic+shared build_system=makefile arch=linux-ubuntu20.04-icelake zlib@1.2.13%gcc@9.4.0+optimize+pic+shared build_system=makefile arch=linux-ubuntu20.04-icelake
The default bootstrap behavior is to use pre-built binaries. You can verify the
active bootstrap repositories with:
.. command-output:: spack bootstrap list
If for security concerns you cannot bootstrap ``clingo`` from pre-built If for security concerns you cannot bootstrap ``clingo`` from pre-built
binaries, you have to disable fetching the binaries we generated with Github Actions. binaries, you have to disable fetching the binaries we generated with Github Actions.
.. code-block:: console .. code-block:: console
$ spack bootstrap disable github-actions-v0.6 $ spack bootstrap disable github-actions-v0.4
==> "github-actions-v0.6" is now disabled and will not be used for bootstrapping ==> "github-actions-v0.4" is now disabled and will not be used for bootstrapping
$ spack bootstrap disable github-actions-v0.5 $ spack bootstrap disable github-actions-v0.3
==> "github-actions-v0.5" is now disabled and will not be used for bootstrapping ==> "github-actions-v0.3" is now disabled and will not be used for bootstrapping
You can verify that the new settings are effective with:
.. command-output:: spack bootstrap list
You can verify that the new settings are effective with ``spack bootstrap list``.
.. note:: .. note::
@@ -284,6 +283,10 @@ compilers`` or ``spack compiler list``:
intel@14.0.1 intel@13.0.1 intel@12.1.2 intel@10.1 intel@14.0.1 intel@13.0.1 intel@12.1.2 intel@10.1
-- clang ------------------------------------------------------- -- clang -------------------------------------------------------
clang@3.4 clang@3.3 clang@3.2 clang@3.1 clang@3.4 clang@3.3 clang@3.2 clang@3.1
-- pgi ---------------------------------------------------------
pgi@14.3-0 pgi@13.2-0 pgi@12.1-0 pgi@10.9-0 pgi@8.0-1
pgi@13.10-0 pgi@13.1-1 pgi@11.10-0 pgi@10.2-0 pgi@7.1-3
pgi@13.6-0 pgi@12.8-0 pgi@11.1-0 pgi@9.0-4 pgi@7.0-6
Any of these compilers can be used to build Spack packages. More on Any of these compilers can be used to build Spack packages. More on
how this is done is in :ref:`sec-specs`. how this is done is in :ref:`sec-specs`.
@@ -803,6 +806,65 @@ flags to the ``icc`` command:
spec: intel@15.0.24.4.9.3 spec: intel@15.0.24.4.9.3
^^^
PGI
^^^
PGI comes with two sets of compilers for C++ and Fortran,
distinguishable by their names. "Old" compilers:
.. code-block:: yaml
cc: /soft/pgi/15.10/linux86-64/15.10/bin/pgcc
cxx: /soft/pgi/15.10/linux86-64/15.10/bin/pgCC
f77: /soft/pgi/15.10/linux86-64/15.10/bin/pgf77
fc: /soft/pgi/15.10/linux86-64/15.10/bin/pgf90
"New" compilers:
.. code-block:: yaml
cc: /soft/pgi/15.10/linux86-64/15.10/bin/pgcc
cxx: /soft/pgi/15.10/linux86-64/15.10/bin/pgc++
f77: /soft/pgi/15.10/linux86-64/15.10/bin/pgfortran
fc: /soft/pgi/15.10/linux86-64/15.10/bin/pgfortran
Older installations of PGI contains just the old compilers; whereas
newer installations contain the old and the new. The new compiler is
considered preferable, as some packages
(``hdf``) will not build with the old compiler.
When auto-detecting a PGI compiler, there are cases where Spack will
find the old compilers, when you really want it to find the new
compilers. It is best to check this ``compilers.yaml``; and if the old
compilers are being used, change ``pgf77`` and ``pgf90`` to
``pgfortran``.
Other issues:
* There are reports that some packages will not build with PGI,
including ``libpciaccess`` and ``openssl``. A workaround is to
build these packages with another compiler and then use them as
dependencies for PGI-build packages. For example:
.. code-block:: console
$ spack install openmpi%pgi ^libpciaccess%gcc
* PGI requires a license to use; see :ref:`licensed-compilers` for more
information on installation.
.. note::
It is believed the problem with HDF 4 is that everything is
compiled with the ``F77`` compiler, but at some point some Fortran
90 code slipped in there. So compilers that can handle both FORTRAN
77 and Fortran 90 (``gfortran``, ``pgfortran``, etc) are fine. But
compilers specific to one or the other (``pgf77``, ``pgf90``) won't
work.
^^^ ^^^
NAG NAG
^^^ ^^^
@@ -1327,7 +1389,6 @@ Required:
* Microsoft Visual Studio * Microsoft Visual Studio
* Python * Python
* Git * Git
* 7z
Optional: Optional:
* Intel Fortran (needed for some packages) * Intel Fortran (needed for some packages)
@@ -1393,13 +1454,6 @@ as the project providing Git support on Windows. This is additionally the recomm
for installing Git on Windows, a link to which can be found above. Spack requires the for installing Git on Windows, a link to which can be found above. Spack requires the
utilities vendored by this project. utilities vendored by this project.
"""
7zip
"""
A tool for extracting ``.xz`` files is required for extracting source tarballs. The latest 7zip
can be located at https://sourceforge.net/projects/sevenzip/.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Step 2: Install and setup Spack Step 2: Install and setup Spack
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -456,13 +457,14 @@ For instance, the following config options,
tcl: tcl:
all: all:
suffixes: suffixes:
^python@3: 'python{^python.version.up_to_2}' ^python@3: 'python{^python.version}'
^openblas: 'openblas' ^openblas: 'openblas'
will add a ``python3.12`` to module names of packages compiled with Python 3.12, and similarly for will add a ``python-3.12.1`` version string to any packages compiled with
all specs depending on ``python@3``. This is useful to know which version of Python a set of Python Python matching the spec, ``python@3``. This is useful to know which
extensions is associated with. Likewise, the ``openblas`` string is attached to any program that version of Python a set of Python extensions is associated with. Likewise, the
has openblas in the spec, most likely via the ``+blas`` variant specification. ``openblas`` string is attached to any program that has openblas in the spec,
most likely via the ``+blas`` variant specification.
The most heavyweight solution to module naming is to change the entire 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

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -236,7 +237,8 @@ for details):
.. code-block:: python .. code-block:: python
:linenos: :linenos:
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -1926,29 +1928,71 @@ to the empty list.
String. A URL pointing to license setup instructions for the software. String. A URL pointing to license setup instructions for the software.
Defaults to the empty string. Defaults to the empty string.
For example, let's take a look at the Arm Forge package. For example, let's take a look at the package for the PGI compilers.
.. code-block:: python .. code-block:: python
# Licensing # Licensing
license_required = True license_required = True
license_comment = "#" license_comment = "#"
license_files = ["licences/Licence"] license_files = ["license.dat"]
license_vars = [ license_vars = ["PGROUPD_LICENSE_FILE", "LM_LICENSE_FILE"]
"ALLINEA_LICENSE_DIR", license_url = "http://www.pgroup.com/doc/pgiinstall.pdf"
"ALLINEA_LICENCE_DIR",
"ALLINEA_LICENSE_FILE",
"ALLINEA_LICENCE_FILE",
]
license_url = "https://developer.arm.com/documentation/101169/latest/Use-Arm-Licence-Server"
Arm Forge requires a license. Its license manager uses the ``#`` symbol to denote a comment. As you can see, PGI requires a license. Its license manager, FlexNet, uses
It expects the license file to be named ``License`` and to be located in a ``licenses`` directory the ``#`` symbol to denote a comment. It expects the license file to be
in the installation prefix. named ``license.dat`` and to be located directly in the installation prefix.
If you would like the installation file to be located elsewhere, simply set
``PGROUPD_LICENSE_FILE`` or ``LM_LICENSE_FILE`` after installation. For
further instructions on installation and licensing, see the URL provided.
If you would like the installation file to be located elsewhere, simply set ``ALLINEA_LICENSE_DIR`` or Let's walk through a sample PGI installation to see exactly what Spack is
one of the other license variables after installation. For further instructions on installation and and isn't capable of. Since PGI does not provide a download URL, it must
licensing, see the URL provided. be downloaded manually. It can either be added to a mirror or located in
the current directory when ``spack install pgi`` is run. See :ref:`mirrors`
for instructions on setting up a mirror.
After running ``spack install pgi``, the first thing that will happen is
Spack will create a global license file located at
``$SPACK_ROOT/etc/spack/licenses/pgi/license.dat``. It will then open up the
file using :ref:`your favorite editor <controlling-the-editor>`. It will look like
this:
.. code-block:: sh
# A license is required to use pgi.
#
# The recommended solution is to store your license key in this global
# license file. After installation, the following symlink(s) will be
# added to point to this file (relative to the installation prefix):
#
# license.dat
#
# Alternatively, use one of the following environment variable(s):
#
# PGROUPD_LICENSE_FILE
# LM_LICENSE_FILE
#
# If you choose to store your license in a non-standard location, you may
# set one of these variable(s) to the full pathname to the license file, or
# port@host if you store your license keys on a dedicated license server.
# You will likely want to set this variable in a module file so that it
# gets loaded every time someone tries to use pgi.
#
# For further information on how to acquire a license, please refer to:
#
# http://www.pgroup.com/doc/pgiinstall.pdf
#
# You may enter your license below.
You can add your license directly to this file, or tell FlexNet to use a
license stored on a separate license server. Here is an example that
points to a license server called licman1:
.. code-block:: none
SERVER licman1.mcs.anl.gov 00163eb7fba5 27200
USE_SERVER
If your package requires the license to install, you can reference the If your package requires the license to install, you can reference the
location of this global license using ``self.global_license_file``. location of this global license using ``self.global_license_file``.
@@ -2923,9 +2967,9 @@ make sense during the build phase may not be needed at runtime, and vice versa.
it makes sense to let a dependency set the environment variables for its dependents. To allow all it makes sense to let a dependency set the environment variables for its dependents. To allow all
this, Spack provides four different methods that can be overridden in a package: this, Spack provides four different methods that can be overridden in a package:
1. :meth:`setup_build_environment <spack.builder.BaseBuilder.setup_build_environment>` 1. :meth:`setup_build_environment <spack.builder.Builder.setup_build_environment>`
2. :meth:`setup_run_environment <spack.package_base.PackageBase.setup_run_environment>` 2. :meth:`setup_run_environment <spack.package_base.PackageBase.setup_run_environment>`
3. :meth:`setup_dependent_build_environment <spack.builder.BaseBuilder.setup_dependent_build_environment>` 3. :meth:`setup_dependent_build_environment <spack.builder.Builder.setup_dependent_build_environment>`
4. :meth:`setup_dependent_run_environment <spack.package_base.PackageBase.setup_dependent_run_environment>` 4. :meth:`setup_dependent_run_environment <spack.package_base.PackageBase.setup_dependent_run_environment>`
The Qt package, for instance, uses this call: The Qt package, for instance, uses this call:
@@ -4898,15 +4942,15 @@ If your package has a virtual dependency like ``mpi``, then referring to
``spec["mpi"]`` within ``install()`` will get you the concrete ``mpi`` ``spec["mpi"]`` within ``install()`` will get you the concrete ``mpi``
implementation in your dependency DAG. That is a spec object just like implementation in your dependency DAG. That is a spec object just like
the one passed to install, only the MPI implementations all set some the one passed to install, only the MPI implementations all set some
additional properties on it to help you out. E.g., in openmpi, you'll additional properties on it to help you out. E.g., in mvapich2, you'll
find this: find this:
.. literalinclude:: _spack_root/var/spack/repos/builtin/packages/openmpi/package.py .. literalinclude:: _spack_root/var/spack/repos/builtin/packages/mvapich2/package.py
:pyobject: Openmpi.setup_dependent_package :pyobject: Mvapich2.setup_dependent_package
That code allows the ``openmpi`` package to associate an ``mpicc`` property That code allows the mvapich2 package to associate an ``mpicc`` property
with the ``openmpi`` node in the DAG, so that dependents can access it. with the ``mvapich2`` node in the DAG, so that dependents can access it.
``mvapich2`` and ``mpich`` do similar things. So, no matter what MPI ``openmpi`` and ``mpich`` do similar things. So, no matter what MPI
you're using, spec["mpi"].mpicc gets you the location of the MPI you're using, spec["mpi"].mpicc gets you the location of the MPI
compilers. This allows us to have a fairly simple polymorphic interface compilers. This allows us to have a fairly simple polymorphic interface
for information about virtual dependencies like MPI. for information about virtual dependencies like MPI.
@@ -5135,7 +5179,7 @@ other checks.
- Not applicable - Not applicable
* - :ref:`PythonPackage <pythonpackage>` * - :ref:`PythonPackage <pythonpackage>`
- Not applicable - Not applicable
- ``test_imports`` (module imports) - ``test`` (module imports)
* - :ref:`QMakePackage <qmakepackage>` * - :ref:`QMakePackage <qmakepackage>`
- ``check`` (``make check``) - ``check`` (``make check``)
- Not applicable - Not applicable
@@ -5144,7 +5188,7 @@ other checks.
- Not applicable - Not applicable
* - :ref:`SIPPackage <sippackage>` * - :ref:`SIPPackage <sippackage>`
- Not applicable - Not applicable
- ``test_imports`` (module imports) - ``test`` (module imports)
* - :ref:`WafPackage <wafpackage>` * - :ref:`WafPackage <wafpackage>`
- ``build_test`` (must be overridden) - ``build_test`` (must be overridden)
- ``install_test`` (must be overridden) - ``install_test`` (must be overridden)
@@ -7037,7 +7081,34 @@ provide them after the spec argument to ``spack build-env``:
$ spack build-env mpileaks@1.1%intel ./configure $ spack build-env mpileaks@1.1%intel ./configure
This will cd to the build directory and then run ``configure`` in the This will cd to the build directory and then run ``configure`` in the
package's build environment. package's build environment. This could also be done in one command as follows.
.. code-block:: console
$ spack build-env --cd build-dir mpileaks@1.1%intel ./configure
Furthermore, ``spack build-env`` has the ability to dive into the build environment
in a subshell to allow you to work natively without polluting your current shell.
.. code-block:: console
$ spack build-env --cd build-dir --dive mpileaks@1.1%intel
mpileaks-build-env $ ./configure
Note that the command prompt changed for this case. This will happen automatically
if a Bourne or C-Shell to indicate that the user is in the build environment subshell.
While automatic prompt changes only occur for a selection of shells, any shell can
query if they are in the build environment with the ``spack build-env --status``
flag.
.. code-block:: console
$ spack build-env --dive mpileaks@1.1%intel
$ spack build-env --status
==> In build env mpileaks-wrsaadvkbg7rjj7kfjw5rhdrrfdswcmm
$ exit
$ spack build-env --status
==> build environment not detected
.. _cmd-spack-location: .. _cmd-spack-location:
@@ -7069,46 +7140,6 @@ might write:
CXXFLAGS += -I$DWARF_PREFIX/include CXXFLAGS += -I$DWARF_PREFIX/include
CXXFLAGS += -L$DWARF_PREFIX/lib CXXFLAGS += -L$DWARF_PREFIX/lib
.. _abi_compatibility:
----------------------------
Specifying ABI Compatibility
----------------------------
Packages can include ABI-compatibility information using the
``can_splice`` directive. For example, if ``Foo`` version 1.1 can
always replace version 1.0, then the package could have:
.. code-block:: python
can_splice("foo@1.0", when="@1.1")
For virtual packages, packages can also specify ABI-compabitiliby with
other packages providing the same virtual. For example, ``zlib-ng``
could specify:
.. code-block:: python
can_splice("zlib@1.3.1", when="@2.2+compat")
Some packages have ABI-compatibility that is dependent on matching
variant values, either for all variants or for some set of
ABI-relevant variants. In those cases, it is not necessary to specify
the full combinatorial explosion. The ``match_variants`` keyword can
cover all single-value variants.
.. code-block:: python
can_splice("foo@1.1", when="@1.2", match_variants=["bar"]) # any value for bar as long as they're the same
can_splice("foo@1.2", when="@1.3", match_variants="*") # any variant values if all single-value variants match
The concretizer will use ABI compatibility to determine automatic
splices when :ref:`automatic splicing<automatic_splicing>` is enabled.
.. note::
The ``can_splice`` directive is experimental, and may be replaced
by a higher-level interface in future versions of Spack.
.. _package_class_structure: .. _package_class_structure:

View File

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

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

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

View File

@@ -1,4 +1,5 @@
.. Copyright Spack Project Developers. See COPYRIGHT file for details. .. Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
Spack Project Developers. See the top-level COPYRIGHT file for details.
SPDX-License-Identifier: (Apache-2.0 OR MIT) SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -8,6 +8,7 @@ unzip, , , Compress/Decompress archives
bzip2, , , Compress/Decompress archives bzip2, , , Compress/Decompress archives
xz, , , Compress/Decompress archives xz, , , Compress/Decompress archives
zstd, , Optional, Compress/Decompress archives zstd, , Optional, Compress/Decompress archives
file, , , Create/Use Buildcaches
lsb-release, , , Linux: identify operating system version lsb-release, , , Linux: identify operating system version
gnupg2, , , Sign/Verify Buildcaches gnupg2, , , Sign/Verify Buildcaches
git, , , Manage Software Repositories git, , , Manage Software Repositories
1 Name Supported Versions Notes Requirement Reason
8 bzip2 Compress/Decompress archives
9 xz Compress/Decompress archives
10 zstd Optional Compress/Decompress archives
11 file Create/Use Buildcaches
12 lsb-release Linux: identify operating system version
13 gnupg2 Sign/Verify Buildcaches
14 git Manage Software Repositories

3
lib/spack/env/cc vendored
View File

@@ -1,7 +1,8 @@
#!/bin/sh -f #!/bin/sh -f
# shellcheck disable=SC2034 # evals in this script fool shellcheck # shellcheck disable=SC2034 # evals in this script fool shellcheck
# #
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,254 +0,0 @@
A. HISTORY OF THE SOFTWARE
==========================
Python was created in the early 1990s by Guido van Rossum at Stichting
Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
as a successor of a language called ABC. Guido remains Python's
principal author, although it includes many contributions from others.
In 1995, Guido continued his work on Python at the Corporation for
National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
in Reston, Virginia where he released several versions of the
software.
In May 2000, Guido and the Python core development team moved to
BeOpen.com to form the BeOpen PythonLabs team. In October of the same
year, the PythonLabs team moved to Digital Creations (now Zope
Corporation, see http://www.zope.com). In 2001, the Python Software
Foundation (PSF, see http://www.python.org/psf/) was formed, a
non-profit organization created specifically to own Python-related
Intellectual Property. Zope Corporation is a sponsoring member of
the PSF.
All Python releases are Open Source (see http://www.opensource.org for
the Open Source Definition). Historically, most, but not all, Python
releases have also been GPL-compatible; the table below summarizes
the various releases.
Release Derived Year Owner GPL-
from compatible? (1)
0.9.0 thru 1.2 1991-1995 CWI yes
1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
1.6 1.5.2 2000 CNRI no
2.0 1.6 2000 BeOpen.com no
1.6.1 1.6 2001 CNRI yes (2)
2.1 2.0+1.6.1 2001 PSF no
2.0.1 2.0+1.6.1 2001 PSF yes
2.1.1 2.1+2.0.1 2001 PSF yes
2.1.2 2.1.1 2002 PSF yes
2.1.3 2.1.2 2002 PSF yes
2.2 and above 2.1.1 2001-now PSF yes
Footnotes:
(1) GPL-compatible doesn't mean that we're distributing Python under
the GPL. All Python licenses, unlike the GPL, let you distribute
a modified version without making your changes open source. The
GPL-compatible licenses make it possible to combine Python with
other software that is released under the GPL; the others don't.
(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
because its license has a choice of law clause. According to
CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
is "not incompatible" with the GPL.
Thanks to the many outside volunteers who have worked under Guido's
direction to make these releases possible.
B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
===============================================================
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------
1. This LICENSE AGREEMENT is between the Python Software Foundation
("PSF"), and the Individual or Organization ("Licensee") accessing and
otherwise using this software ("Python") in source or binary form and
its associated documentation.
2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013, 2014 Python Software Foundation; All Rights Reserved" are
retained in Python alone or in any derivative version prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python.
4. PSF is making Python available to Licensee on an "AS IS"
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. Nothing in this License Agreement shall be deemed to create any
relationship of agency, partnership, or joint venture between PSF and
Licensee. This License Agreement does not grant permission to use PSF
trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.
8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
-------------------------------------------
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
Individual or Organization ("Licensee") accessing and otherwise using
this software in source or binary form and its associated
documentation ("the Software").
2. Subject to the terms and conditions of this BeOpen Python License
Agreement, BeOpen hereby grants Licensee a non-exclusive,
royalty-free, world-wide license to reproduce, analyze, test, perform
and/or display publicly, prepare derivative works, distribute, and
otherwise use the Software alone or in any derivative version,
provided, however, that the BeOpen Python License is retained in the
Software, alone or in any derivative version prepared by Licensee.
3. BeOpen is making the Software available to Licensee on an "AS IS"
basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
5. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
6. This License Agreement shall be governed by and interpreted in all
respects by the law of the State of California, excluding conflict of
law provisions. Nothing in this License Agreement shall be deemed to
create any relationship of agency, partnership, or joint venture
between BeOpen and Licensee. This License Agreement does not grant
permission to use BeOpen trademarks or trade names in a trademark
sense to endorse or promote products or services of Licensee, or any
third party. As an exception, the "BeOpen Python" logos available at
http://www.pythonlabs.com/logos.html may be used according to the
permissions granted on that web page.
7. By copying, installing or otherwise using the software, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
---------------------------------------
1. This LICENSE AGREEMENT is between the Corporation for National
Research Initiatives, having an office at 1895 Preston White Drive,
Reston, VA 20191 ("CNRI"), and the Individual or Organization
("Licensee") accessing and otherwise using Python 1.6.1 software in
source or binary form and its associated documentation.
2. Subject to the terms and conditions of this License Agreement, CNRI
hereby grants Licensee a nonexclusive, royalty-free, world-wide
license to reproduce, analyze, test, perform and/or display publicly,
prepare derivative works, distribute, and otherwise use Python 1.6.1
alone or in any derivative version, provided, however, that CNRI's
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
1995-2001 Corporation for National Research Initiatives; All Rights
Reserved" are retained in Python 1.6.1 alone or in any derivative
version prepared by Licensee. Alternately, in lieu of CNRI's License
Agreement, Licensee may substitute the following text (omitting the
quotes): "Python 1.6.1 is made available subject to the terms and
conditions in CNRI's License Agreement. This Agreement together with
Python 1.6.1 may be located on the Internet using the following
unique, persistent identifier (known as a handle): 1895.22/1013. This
Agreement may also be obtained from a proxy server on the Internet
using the following URL: http://hdl.handle.net/1895.22/1013".
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python 1.6.1 or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python 1.6.1.
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. This License Agreement shall be governed by the federal
intellectual property law of the United States, including without
limitation the federal copyright law, and, to the extent such
U.S. federal law does not apply, by the law of the Commonwealth of
Virginia, excluding Virginia's conflict of law provisions.
Notwithstanding the foregoing, with regard to derivative works based
on Python 1.6.1 that incorporate non-separable material that was
previously distributed under the GNU General Public License (GPL), the
law of the Commonwealth of Virginia shall govern this License
Agreement only as to issues arising under or with respect to
Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
License Agreement shall be deemed to create any relationship of
agency, partnership, or joint venture between CNRI and Licensee. This
License Agreement does not grant permission to use CNRI trademarks or
trade name in a trademark sense to endorse or promote products or
services of Licensee, or any third party.
8. By clicking on the "ACCEPT" button where indicated, or by copying,
installing or otherwise using Python 1.6.1, Licensee agrees to be
bound by the terms and conditions of this License Agreement.
ACCEPT
CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
--------------------------------------------------
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
The Netherlands. All rights reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
from typing_extensions import *

View File

@@ -8,4 +8,3 @@ six==1.16.0
macholib==1.16.2 macholib==1.16.2
altgraph==0.17.3 altgraph==0.17.3
ruamel.yaml==0.17.21 ruamel.yaml==0.17.21
typing_extensions==4.1.1

View File

@@ -1,3 +1,4 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""Path primitives that just require Python standard library.""" """Path primitives that just require Python standard library."""
@@ -65,7 +66,7 @@ def _is_url(path_or_url: str) -> bool:
return result return result
def _system_path_filter(_func=None, arg_slice: Optional[slice] = None): def system_path_filter(_func=None, arg_slice: Optional[slice] = None):
"""Filters function arguments to account for platform path separators. """Filters function arguments to account for platform path separators.
Optional slicing range can be specified to select specific arguments Optional slicing range can be specified to select specific arguments
@@ -99,16 +100,6 @@ def path_filter_caller(*args, **kwargs):
return holder_func return holder_func
def _noop_decorator(_func=None, arg_slice: Optional[slice] = None):
return _func if _func else lambda x: x
if sys.platform == "win32":
system_path_filter = _system_path_filter
else:
system_path_filter = _noop_decorator
def sanitize_win_longpath(path: str) -> str: def sanitize_win_longpath(path: str) -> str:
"""Strip Windows extended path prefix from strings """Strip Windows extended path prefix from strings
Returns sanitized string. Returns sanitized string.

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""String manipulation functions that do not have other dependencies than Python """String manipulation functions that do not have other dependencies than Python

View File

@@ -1,9 +1,10 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # 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 import os.path
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

View File

@@ -1,3 +1,4 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import collections import collections
@@ -7,7 +8,6 @@
import fnmatch import fnmatch
import glob import glob
import hashlib import hashlib
import io
import itertools import itertools
import numbers import numbers
import os import os
@@ -21,11 +21,9 @@
from contextlib import contextmanager from contextlib import contextmanager
from itertools import accumulate from itertools import accumulate
from typing import ( from typing import (
IO,
Callable, Callable,
Deque, Deque,
Dict, Dict,
Generator,
Iterable, Iterable,
List, List,
Match, Match,
@@ -77,6 +75,7 @@
"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",
@@ -301,32 +300,35 @@ def filter_file(
ignore_absent: bool = False, ignore_absent: bool = False,
start_at: Optional[str] = None, start_at: Optional[str] = None,
stop_at: Optional[str] = None, stop_at: Optional[str] = None,
encoding: Optional[str] = "utf-8",
) -> None: ) -> None:
r"""Like sed, but uses python regular expressions. r"""Like sed, but uses python regular expressions.
Filters every line of each file through regex and replaces the file with a filtered version. Filters every line of each file through regex and replaces the file
Preserves mode of filtered files. with a filtered version. Preserves mode of filtered files.
As with re.sub, ``repl`` can be either a string or a callable. If it is a callable, it is As with re.sub, ``repl`` can be either a string or a callable.
passed the match object and should return a suitable replacement string. If it is a string, it If it is a callable, it is passed the match object and should
can contain ``\1``, ``\2``, etc. to represent back-substitution as sed would allow. return a suitable replacement string. If it is a string, it
can contain ``\1``, ``\2``, etc. to represent back-substitution
as sed would allow.
Args: Args:
regex: The regular expression to search for regex (str): The regular expression to search for
repl: The string to replace matches with repl (str): The string to replace matches with
*filenames: One or more files to search and replace string: Treat regex as a plain string. *filenames: One or more files to search and replace
Default it False backup: Make backup file(s) suffixed with ``~``. Default is False string (bool): Treat regex as a plain string. Default it False
ignore_absent: Ignore any files that don't exist. Default is False backup (bool): Make backup file(s) suffixed with ``~``. Default is False
start_at: Marker used to start applying the replacements. If a text line matches this ignore_absent (bool): Ignore any files that don't exist.
marker filtering is started at the next line. All contents before the marker and the Default is False
marker itself are copied verbatim. Default is to start filtering from the first line of start_at (str): Marker used to start applying the replacements. If a
the file. text line matches this marker filtering is started at the next line.
stop_at: Marker used to stop scanning the file further. If a text line matches this marker All contents before the marker and the marker itself are copied
filtering is stopped and the rest of the file is copied verbatim. Default is to filter verbatim. Default is to start filtering from the first line of the
until the end of the file. file.
encoding: The encoding to use when reading and writing the files. Default is None, which stop_at (str): Marker used to stop scanning the file further. If a text
uses the system's default encoding. line matches this marker filtering is stopped and the rest of the
file is copied verbatim. Default is to filter until the end of the
file.
""" """
# Allow strings to use \1, \2, etc. for replacement, like sed # Allow strings to use \1, \2, etc. for replacement, like sed
if not callable(repl): if not callable(repl):
@@ -342,56 +344,72 @@ def groupid_to_group(x):
if string: if string:
regex = re.escape(regex) regex = re.escape(regex)
regex_compiled = re.compile(regex) for filename in path_to_os_path(*filenames):
for path in path_to_os_path(*filenames): msg = 'FILTER FILE: {0} [replacing "{1}"]'
if ignore_absent and not os.path.exists(path): tty.debug(msg.format(filename, regex))
tty.debug(f'FILTER FILE: file "{path}" not found. Skipping to next file.')
backup_filename = filename + "~"
tmp_filename = filename + ".spack~"
if ignore_absent and not os.path.exists(filename):
msg = 'FILTER FILE: file "{0}" not found. Skipping to next file.'
tty.debug(msg.format(filename))
continue continue
else:
tty.debug(f'FILTER FILE: {path} [replacing "{regex}"]')
fd, temp_path = tempfile.mkstemp( # Create backup file. Don't overwrite an existing backup
prefix=f"{os.path.basename(path)}.", dir=os.path.dirname(path) # file in case this file is being filtered multiple times.
) if not os.path.exists(backup_filename):
os.close(fd) shutil.copy(filename, backup_filename)
shutil.copy(path, temp_path) # Create a temporary file to read from. We cannot use backup_filename
errored = False # in case filter_file is invoked multiple times on the same file.
shutil.copy(filename, tmp_filename)
try: try:
# Open as a text file and filter until the end of the file is reached, or we found a # Open as a text file and filter until the end of the file is
# marker in the line if it was specified. To avoid translating line endings (\n to # reached, or we found a marker in the line if it was specified
# \r\n and vice-versa) use newline="". #
with open( # To avoid translating line endings (\n to \r\n and vice-versa)
temp_path, mode="r", errors="surrogateescape", newline="", encoding=encoding # we force os.open to ignore translations and use the line endings
) as input_file, open( # the file comes with
path, mode="w", errors="surrogateescape", newline="", encoding=encoding with open(tmp_filename, mode="r", errors="surrogateescape", newline="") as input_file:
) as output_file: with open(filename, mode="w", errors="surrogateescape", newline="") as output_file:
if start_at is None and stop_at is None: # common case, avoids branching in loop do_filtering = start_at is None
for line in input_file: # Using iter and readline is a workaround needed not to
output_file.write(re.sub(regex_compiled, repl, line)) # disable input_file.tell(), which will happen if we call
else: # input_file.next() implicitly via the for loop
# state is -1 before start_at; 0 between; 1 after stop_at for line in iter(input_file.readline, ""):
state = 0 if start_at is None else -1 if stop_at is not None:
for line in input_file: current_position = input_file.tell()
if state == 0:
if stop_at == line.strip(): if stop_at == line.strip():
state = 1 output_file.write(line)
else: break
line = re.sub(regex_compiled, repl, line) if do_filtering:
elif state == -1 and start_at == line.strip(): filtered_line = re.sub(regex, repl, line)
state = 0 output_file.write(filtered_line)
output_file.write(line) else:
do_filtering = start_at == line.strip()
output_file.write(line)
else:
current_position = None
# If we stopped filtering at some point, reopen the file in
# binary mode and copy verbatim the remaining part
if current_position and stop_at:
with open(tmp_filename, mode="rb") as input_binary_buffer:
input_binary_buffer.seek(current_position)
with open(filename, mode="ab") as output_binary_buffer:
output_binary_buffer.writelines(input_binary_buffer.readlines())
except BaseException: except BaseException:
# restore the original file # clean up the original file on failure.
os.rename(temp_path, path) shutil.move(backup_filename, filename)
errored = True
raise raise
finally: finally:
if not errored and not backup: os.remove(tmp_filename)
os.unlink(temp_path) if not backup and os.path.exists(backup_filename):
os.remove(backup_filename)
class FileFilter: class FileFilter:
@@ -670,7 +688,7 @@ def copy(src, dest, _permissions=False):
_permissions (bool): for internal use only _permissions (bool): for internal use only
Raises: Raises:
OSError: if *src* does not match any files or directories IOError: 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
""" """
@@ -681,7 +699,7 @@ def copy(src, dest, _permissions=False):
files = glob.glob(src) files = glob.glob(src)
if not files: if not files:
raise OSError("No such file or directory: '{0}'".format(src)) raise IOError("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)
@@ -712,7 +730,7 @@ def install(src, dest):
dest (str): the destination file or directory dest (str): the destination file or directory
Raises: Raises:
OSError: if *src* does not match any files or directories IOError: 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
""" """
@@ -750,7 +768,7 @@ def copy_tree(
_permissions (bool): for internal use only _permissions (bool): for internal use only
Raises: Raises:
OSError: if *src* does not match any files or directories IOError: 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:
@@ -764,7 +782,7 @@ def copy_tree(
files = glob.glob(src) files = glob.glob(src)
if not files: if not files:
raise OSError("No such file or directory: '{0}'".format(src)) raise IOError("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
@@ -845,7 +863,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:
OSError: if *src* does not match any files or directories IOError: 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)
@@ -1096,12 +1114,12 @@ def hash_directory(directory, ignore=[]):
@contextmanager @contextmanager
@system_path_filter @system_path_filter
def write_tmp_and_move(filename: str, *, encoding: Optional[str] = None): def write_tmp_and_move(filename):
"""Write to a temporary file, then move into place.""" """Write to a temporary file, then move into place."""
dirname = os.path.dirname(filename) dirname = os.path.dirname(filename)
basename = os.path.basename(filename) basename = os.path.basename(filename)
tmp = os.path.join(dirname, ".%s.tmp" % basename) tmp = os.path.join(dirname, ".%s.tmp" % basename)
with open(tmp, "w", encoding=encoding) as f: with open(tmp, "w") as f:
yield f yield f
shutil.move(tmp, filename) shutil.move(tmp, filename)
@@ -1471,36 +1489,15 @@ def set_executable(path):
@system_path_filter @system_path_filter
def recursive_mtime_greater_than(path: str, time: float) -> bool: def last_modification_time_recursive(path):
"""Returns true if any file or dir recursively under `path` has mtime greater than `time`.""" path = os.path.abspath(path)
# use bfs order to increase likelihood of early return times = [os.stat(path).st_mtime]
queue: Deque[str] = collections.deque([path]) times.extend(
os.lstat(os.path.join(root, name)).st_mtime
if os.stat(path).st_mtime > time: for root, dirs, files in os.walk(path)
return True for name in dirs + files
)
while queue: return max(times)
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
@@ -1762,7 +1759,8 @@ def find(
def _log_file_access_issue(e: OSError, path: str) -> None: def _log_file_access_issue(e: OSError, path: str) -> None:
tty.debug(f"find must skip {path}: {e}") errno_name = errno.errorcode.get(e.errno, "UNKNOWN")
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]:
@@ -2456,69 +2454,26 @@ class WindowsSimulatedRPath:
and vis versa. and vis versa.
""" """
def __init__( def __init__(self, package, link_install_prefix=True):
self,
package,
base_modification_prefix: Optional[Union[str, pathlib.Path]] = None,
link_install_prefix: bool = True,
):
""" """
Args: Args:
package (spack.package_base.PackageBase): Package requiring links package (spack.package_base.PackageBase): Package requiring links
base_modification_prefix (str|pathlib.Path): Path representation indicating
the root directory in which to establish the simulated rpath, ie where the
symlinks that comprise the "rpath" behavior will be installed.
Note: This is a mutually exclusive option with `link_install_prefix` using
both is an error.
Default: None
link_install_prefix (bool): Link against package's own install or stage root. link_install_prefix (bool): Link against package's own install or stage root.
Packages that run their own executables during build and require rpaths to Packages that run their own executables during build and require rpaths to
the build directory during build time require this option. the build directory during build time require this option. Default: install
Default: install
root root
Note: This is a mutually exclusive option with `base_modification_prefix`, using
both is an error.
""" """
self.pkg = package self.pkg = package
self._addl_rpaths: set[str] = set() self._addl_rpaths = set()
if link_install_prefix and base_modification_prefix:
raise RuntimeError(
"Invalid combination of arguments given to WindowsSimulated RPath.\n"
"Select either `link_install_prefix` to create an install prefix rpath"
" or specify a `base_modification_prefix` for any other link type. "
"Specifying both arguments is invalid."
)
if not (link_install_prefix or base_modification_prefix):
raise RuntimeError(
"Insufficient arguments given to WindowsSimulatedRpath.\n"
"WindowsSimulatedRPath requires one of link_install_prefix"
" or base_modification_prefix to be specified."
" Neither was provided."
)
self.link_install_prefix = link_install_prefix self.link_install_prefix = link_install_prefix
if base_modification_prefix: self._additional_library_dependents = set()
self.base_modification_prefix = pathlib.Path(base_modification_prefix)
else:
self.base_modification_prefix = pathlib.Path(self.pkg.prefix)
self._additional_library_dependents: set[pathlib.Path] = set()
if not self.link_install_prefix:
tty.debug(f"Generating rpath for non install context: {base_modification_prefix}")
@property @property
def library_dependents(self): def library_dependents(self):
""" """
Set of directories where package binaries/libraries are located. Set of directories where package binaries/libraries are located.
""" """
base_pths = set() return set([pathlib.Path(self.pkg.prefix.bin)]) | self._additional_library_dependents
if self.link_install_prefix:
base_pths.add(pathlib.Path(self.pkg.prefix.bin))
base_pths |= self._additional_library_dependents
return base_pths
def add_library_dependent(self, *dest): def add_library_dependent(self, *dest):
""" """
@@ -2534,12 +2489,6 @@ def add_library_dependent(self, *dest):
new_pth = pathlib.Path(pth).parent new_pth = pathlib.Path(pth).parent
else: else:
new_pth = pathlib.Path(pth) new_pth = pathlib.Path(pth)
path_is_in_prefix = new_pth.is_relative_to(self.base_modification_prefix)
if not path_is_in_prefix:
raise RuntimeError(
f"Attempting to generate rpath symlink out of rpath context:\
{str(self.base_modification_prefix)}"
)
self._additional_library_dependents.add(new_pth) self._additional_library_dependents.add(new_pth)
@property @property
@@ -2628,33 +2577,6 @@ def establish_link(self):
self._link(library, lib_dir) self._link(library, lib_dir)
def make_package_test_rpath(pkg, test_dir: Union[str, pathlib.Path]):
"""Establishes a temp Windows simulated rpath for the pkg in the testing directory
so an executable can test the libraries/executables with proper access
to dependent dlls
Note: this is a no-op on all other platforms besides Windows
Args:
pkg (spack.package_base.PackageBase): the package for which the rpath should be computed
test_dir: the testing directory in which we should construct an rpath
"""
# link_install_prefix as false ensures we're not linking into the install prefix
mini_rpath = WindowsSimulatedRPath(pkg, link_install_prefix=False)
# add the testing directory as a location to install rpath symlinks
mini_rpath.add_library_dependent(test_dir)
# check for whether build_directory is available, if not
# assume the stage root is the build dir
build_dir_attr = getattr(pkg, "build_directory", None)
build_directory = build_dir_attr if build_dir_attr else pkg.stage.path
# add the build dir & build dir bin
mini_rpath.add_rpath(os.path.join(build_directory, "bin"))
mini_rpath.add_rpath(os.path.join(build_directory))
# construct rpath
mini_rpath.establish_link()
@system_path_filter @system_path_filter
@memoized @memoized
def can_access_dir(path): def can_access_dir(path):
@@ -2850,6 +2772,22 @@ def prefixes(path):
return paths return paths
@system_path_filter
def md5sum(file):
"""Compute the MD5 sum of a file.
Args:
file (str): file to be checksummed
Returns:
MD5 sum of the file's content
"""
md5 = hashlib.md5()
with open(file, "rb") as f:
md5.update(f.read())
return md5.digest()
@system_path_filter @system_path_filter
def remove_directory_contents(dir): def remove_directory_contents(dir):
"""Remove all contents of a directory.""" """Remove all contents of a directory."""
@@ -2883,20 +2821,6 @@ def keep_modification_time(*filenames):
os.utime(f, (os.path.getatime(f), mtime)) os.utime(f, (os.path.getatime(f), mtime))
@contextmanager
def temporary_file_position(stream):
orig_pos = stream.tell()
yield
stream.seek(orig_pos)
@contextmanager
def current_file_position(stream: IO[str], loc: int, relative_to=io.SEEK_CUR):
with temporary_file_position(stream):
stream.seek(loc, relative_to)
yield
@contextmanager @contextmanager
def temporary_dir( def temporary_dir(
suffix: Optional[str] = None, prefix: Optional[str] = None, dir: Optional[str] = None suffix: Optional[str] = None, prefix: Optional[str] = None, dir: Optional[str] = None
@@ -2914,25 +2838,6 @@ def temporary_dir(
remove_directory_contents(tmp_dir) remove_directory_contents(tmp_dir)
@contextmanager
def edit_in_place_through_temporary_file(file_path: str) -> Generator[str, None, None]:
"""Context manager for modifying ``file_path`` in place, preserving its inode and hardlinks,
for functions or external tools that do not support in-place editing. Notice that this function
is unsafe in that it works with paths instead of a file descriptors, but this is by design,
since we assume the call site will create a new inode at the same path."""
tmp_fd, tmp_path = tempfile.mkstemp(
dir=os.path.dirname(file_path), prefix=f"{os.path.basename(file_path)}."
)
# windows cannot replace a file with open fds, so close since the call site needs to replace.
os.close(tmp_fd)
try:
shutil.copyfile(file_path, tmp_path, follow_symlinks=True)
yield tmp_path
shutil.copyfile(tmp_path, file_path, follow_symlinks=True)
finally:
os.unlink(tmp_path)
def filesummary(path, print_bytes=16) -> Tuple[int, bytes]: def filesummary(path, print_bytes=16) -> Tuple[int, bytes]:
"""Create a small summary of the given file. Does not error """Create a small summary of the given file. Does not error
when file does not exist. when file does not exist.

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -14,7 +15,7 @@
import typing import typing
import warnings import warnings
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Callable, Dict, Iterable, List, Mapping, Optional, Tuple, TypeVar from typing import Callable, Dict, Iterable, List, Tuple, TypeVar
# Ignore emacs backups when listing modules # Ignore emacs backups when listing modules
ignore_modules = r"^\.#|~$" ignore_modules = r"^\.#|~$"
@@ -862,10 +863,8 @@ def elide_list(line_list: List[str], max_num: int = 10) -> List[str]:
if sys.version_info >= (3, 9): if sys.version_info >= (3, 9):
PatternStr = re.Pattern[str] PatternStr = re.Pattern[str]
PatternBytes = re.Pattern[bytes]
else: else:
PatternStr = typing.Pattern[str] PatternStr = typing.Pattern[str]
PatternBytes = typing.Pattern[bytes]
def fnmatch_translate_multiple(named_patterns: Dict[str, str]) -> str: def fnmatch_translate_multiple(named_patterns: Dict[str, str]) -> str:
@@ -1080,88 +1079,3 @@ def __set__(self, instance, value):
def factory(self, instance, owner): def factory(self, instance, owner):
raise NotImplementedError("must be implemented by derived classes") raise NotImplementedError("must be implemented by derived classes")
KT = TypeVar("KT")
VT = TypeVar("VT")
class PriorityOrderedMapping(Mapping[KT, VT]):
"""Mapping that iterates over key according to an integer priority. If the priority is
the same for two keys, insertion order is what matters.
The priority is set when the key/value pair is added. If not set, the highest current priority
is used.
"""
_data: Dict[KT, VT]
_priorities: List[Tuple[int, KT]]
def __init__(self) -> None:
self._data = {}
# Tuple of (priority, key)
self._priorities = []
def __getitem__(self, key: KT) -> VT:
return self._data[key]
def __len__(self) -> int:
return len(self._data)
def __iter__(self):
yield from (key for _, key in self._priorities)
def __reversed__(self):
yield from (key for _, key in reversed(self._priorities))
def reversed_keys(self):
"""Iterates over keys from the highest priority, to the lowest."""
return reversed(self)
def reversed_values(self):
"""Iterates over values from the highest priority, to the lowest."""
yield from (self._data[key] for _, key in reversed(self._priorities))
def _highest_priority(self) -> int:
if not self._priorities:
return 0
result, _ = self._priorities[-1]
return result
def add(self, key: KT, *, value: VT, priority: Optional[int] = None) -> None:
"""Adds a key/value pair to the mapping, with a specific priority.
If the priority is None, then it is assumed to be the highest priority value currently
in the container.
Raises:
ValueError: when the same priority is already in the mapping
"""
if priority is None:
priority = self._highest_priority()
if key in self._data:
self.remove(key)
self._priorities.append((priority, key))
# We rely on sort being stable
self._priorities.sort(key=lambda x: x[0])
self._data[key] = value
assert len(self._data) == len(self._priorities)
def remove(self, key: KT) -> VT:
"""Removes a key from the mapping.
Returns:
The value associated with the key being removed
Raises:
KeyError: if the key is not in the mapping
"""
if key not in self._data:
raise KeyError(f"cannot find {key}")
popped_item = self._data.pop(key)
self._priorities = [(p, k) for p, k in self._priorities if k != key]
assert len(self._data) == len(self._priorities)
return popped_item

View File

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

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
@@ -95,8 +96,8 @@ def get_fh(self, path: str) -> IO:
Arguments: Arguments:
path: path to lock file we want a filehandle for path: path to lock file we want a filehandle for
""" """
# Open writable files as rb+ so we can upgrade to write later # Open writable files as 'r+' so we can upgrade to write later
os_mode, fh_mode = (os.O_RDWR | os.O_CREAT), "rb+" os_mode, fh_mode = (os.O_RDWR | os.O_CREAT), "r+"
pid = os.getpid() pid = os.getpid()
open_file = None # OpenFile object, if there is one open_file = None # OpenFile object, if there is one
@@ -123,7 +124,7 @@ def get_fh(self, path: str) -> IO:
# we know path exists but not if it's writable. If it's read-only, # we know path exists but not if it's writable. If it's read-only,
# only open the file for reading (and fail if we're trying to get # only open the file for reading (and fail if we're trying to get
# an exclusive (write) lock on it) # an exclusive (write) lock on it)
os_mode, fh_mode = os.O_RDONLY, "rb" os_mode, fh_mode = os.O_RDONLY, "r"
fd = os.open(path, os_mode) fd = os.open(path, os_mode)
fh = os.fdopen(fd, fh_mode) fh = os.fdopen(fd, fh_mode)
@@ -242,7 +243,7 @@ def __init__(
helpful for distinguishing between different Spack locks. helpful for distinguishing between different Spack locks.
""" """
self.path = path self.path = path
self._file: Optional[IO[bytes]] = None self._file: Optional[IO] = None
self._reads = 0 self._reads = 0
self._writes = 0 self._writes = 0
@@ -269,7 +270,7 @@ def __init__(
@staticmethod @staticmethod
def _poll_interval_generator( def _poll_interval_generator(
_wait_times: Optional[Tuple[float, float, float]] = None, _wait_times: Optional[Tuple[float, float, float]] = None
) -> Generator[float, None, None]: ) -> Generator[float, None, None]:
"""This implements a backoff scheme for polling a contended resource """This implements a backoff scheme for polling a contended resource
by suggesting a succession of wait times between polls. by suggesting a succession of wait times between polls.
@@ -328,9 +329,9 @@ def _lock(self, op: int, timeout: Optional[float] = None) -> Tuple[float, int]:
self._ensure_parent_directory() self._ensure_parent_directory()
self._file = FILE_TRACKER.get_fh(self.path) self._file = FILE_TRACKER.get_fh(self.path)
if LockType.to_module(op) == fcntl.LOCK_EX and self._file.mode == "rb": if LockType.to_module(op) == fcntl.LOCK_EX and self._file.mode == "r":
# Attempt to upgrade to write lock w/a read-only file. # Attempt to upgrade to write lock w/a read-only file.
# If the file were writable, we'd have opened it rb+ # If the file were writable, we'd have opened it 'r+'
raise LockROFileError(self.path) raise LockROFileError(self.path)
self._log_debug( self._log_debug(
@@ -391,7 +392,7 @@ def _poll_lock(self, op: int) -> bool:
return True return True
except OSError as e: except IOError 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
@@ -425,7 +426,7 @@ def _read_log_debug_data(self) -> None:
line = self._file.read() line = self._file.read()
if line: if line:
pid, host = line.decode("utf-8").strip().split(",") pid, host = line.strip().split(",")
_, _, pid = pid.rpartition("=") _, _, pid = pid.rpartition("=")
_, _, self.host = host.rpartition("=") _, _, self.host = host.rpartition("=")
self.pid = int(pid) self.pid = int(pid)
@@ -441,7 +442,7 @@ def _write_log_debug_data(self) -> None:
# write pid, host to disk to sync over FS # write pid, host to disk to sync over FS
self._file.seek(0) self._file.seek(0)
self._file.write(f"pid={self.pid},host={self.host}".encode("utf-8")) self._file.write("pid=%s,host=%s" % (self.pid, self.host))
self._file.truncate() self._file.truncate()
self._file.flush() self._file.flush()
os.fsync(self._file.fileno()) os.fsync(self._file.fileno())

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os import os

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

View File

@@ -1,4 +1,5 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)

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