Compare commits

...

2 Commits

Author SHA1 Message Date
Harmen Stoppels
6c5711e7b6 minimize gha 2024-09-19 21:51:15 +02:00
Harmen Stoppels
f772d97865 revert 02320b18f32e9119e83ba620bf19a2bd8265564d..HEAD 2024-09-19 21:36:02 +02:00
321 changed files with 2101 additions and 3297 deletions

View File

@@ -1,74 +0,0 @@
name: audit
on:
workflow_call:
inputs:
with_coverage:
required: true
type: string
python_version:
required: true
type: string
concurrency:
group: audit-${{inputs.python_version}}-${{github.ref}}-${{github.event.pull_request.number || github.run_number}}
cancel-in-progress: true
jobs:
# Run audits on all the packages in the built-in repository
package-audits:
runs-on: ${{ matrix.system.os }}
strategy:
matrix:
system:
- { os: windows-latest, shell: 'powershell Invoke-Expression -Command "./share/spack/qa/windows_test_setup.ps1"; {0}' }
- { os: ubuntu-latest, shell: bash }
- { os: macos-latest, shell: bash }
defaults:
run:
shell: ${{ matrix.system.shell }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
with:
python-version: ${{inputs.python_version}}
- name: Install Python packages
run: |
pip install --upgrade pip setuptools pytest coverage[toml]
- name: Setup for Windows run
if: runner.os == 'Windows'
run: |
python -m pip install --upgrade pywin32
- name: Package audits (with coverage)
env:
COVERAGE_FILE: coverage/.coverage-audits-${{ matrix.system.os }}
if: ${{ inputs.with_coverage == 'true' && runner.os != 'Windows' }}
run: |
. share/spack/setup-env.sh
coverage run $(which spack) audit packages
coverage run $(which spack) audit configs
coverage run $(which spack) -d audit externals
coverage combine
- name: Package audits (without coverage)
if: ${{ inputs.with_coverage == 'false' && runner.os != 'Windows' }}
run: |
. share/spack/setup-env.sh
spack -d audit packages
spack -d audit configs
spack -d audit externals
- name: Package audits (without coverage)
if: ${{ runner.os == 'Windows' }}
run: |
. share/spack/setup-env.sh
spack -d audit packages
./share/spack/qa/validate_last_exit.ps1
spack -d audit configs
./share/spack/qa/validate_last_exit.ps1
spack -d audit externals
./share/spack/qa/validate_last_exit.ps1
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874
if: ${{ inputs.with_coverage == 'true' && runner.os != 'Windows' }}
with:
name: coverage-audits-${{ matrix.system.os }}
path: coverage
include-hidden-files: true

View File

@@ -1,201 +0,0 @@
name: Bootstrapping
on:
# This Workflow can be triggered manually
workflow_dispatch:
workflow_call:
schedule:
# nightly at 2:16 AM
- cron: '16 2 * * *'
concurrency:
group: bootstrap-${{github.ref}}-${{github.event.pull_request.number || github.run_number}}
cancel-in-progress: true
jobs:
distros-clingo-sources:
runs-on: ubuntu-latest
container: ${{ matrix.image }}
strategy:
matrix:
image: ["fedora:latest", "opensuse/leap:latest"]
steps:
- name: Setup Fedora
if: ${{ matrix.image == 'fedora:latest' }}
run: |
dnf install -y \
bzip2 curl file gcc-c++ gcc gcc-gfortran git gzip \
make patch unzip which xz python3 python3-devel tree \
cmake bison bison-devel libstdc++-static
- name: Setup OpenSUSE
if: ${{ matrix.image == 'opensuse/leap:latest' }}
run: |
# Harden CI by applying the workaround described here: https://www.suse.com/support/kb/doc/?id=000019505
zypper update -y || zypper update -y
zypper install -y \
bzip2 curl file gcc-c++ gcc gcc-fortran tar git gpg2 gzip \
make patch unzip which xz python3 python3-devel tree \
cmake bison
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
- name: Bootstrap clingo
run: |
source share/spack/setup-env.sh
spack bootstrap disable github-actions-v0.5
spack bootstrap disable github-actions-v0.4
spack external find cmake bison
spack -d solve zlib
tree ~/.spack/bootstrap/store/
clingo-sources:
runs-on: ${{ matrix.runner }}
strategy:
matrix:
runner: ['macos-13', 'macos-14', "ubuntu-latest", "windows-latest"]
steps:
- name: Setup macOS
if: ${{ matrix.runner != 'ubuntu-latest' && matrix.runner != 'windows-latest' }}
run: |
brew install cmake bison tree
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
with:
python-version: "3.12"
- name: Bootstrap clingo
env:
SETUP_SCRIPT_EXT: ${{ matrix.runner == 'windows-latest' && 'ps1' || 'sh' }}
SETUP_SCRIPT_SOURCE: ${{ matrix.runner == 'windows-latest' && './' || 'source ' }}
USER_SCOPE_PARENT_DIR: ${{ matrix.runner == 'windows-latest' && '$env:userprofile' || '$HOME' }}
VALIDATE_LAST_EXIT: ${{ matrix.runner == 'windows-latest' && './share/spack/qa/validate_last_exit.ps1' || '' }}
run: |
${{ env.SETUP_SCRIPT_SOURCE }}share/spack/setup-env.${{ env.SETUP_SCRIPT_EXT }}
spack bootstrap disable github-actions-v0.5
spack bootstrap disable github-actions-v0.4
spack external find --not-buildable cmake bison
spack -d solve zlib
${{ env.VALIDATE_LAST_EXIT }}
tree ${{ env.USER_SCOPE_PARENT_DIR }}/.spack/bootstrap/store/
gnupg-sources:
runs-on: ${{ matrix.runner }}
strategy:
matrix:
runner: [ 'macos-13', 'macos-14', "ubuntu-latest" ]
steps:
- name: Setup macOS
if: ${{ matrix.runner != 'ubuntu-latest' }}
run: |
brew install tree gawk
sudo rm -rf $(command -v gpg gpg2)
- name: Setup Ubuntu
if: ${{ matrix.runner == 'ubuntu-latest' }}
run: sudo rm -rf $(command -v gpg gpg2 patchelf)
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
- name: Bootstrap GnuPG
run: |
source share/spack/setup-env.sh
spack solve zlib
spack bootstrap disable github-actions-v0.5
spack bootstrap disable github-actions-v0.4
spack -d gpg list
tree ~/.spack/bootstrap/store/
from-binaries:
runs-on: ${{ matrix.runner }}
strategy:
matrix:
runner: ['macos-13', 'macos-14', "ubuntu-latest", "windows-latest"]
steps:
- name: Setup macOS
if: ${{ matrix.runner != 'ubuntu-latest' && matrix.runner != 'windows-latest'}}
run: |
brew install tree
# Remove GnuPG since we want to bootstrap it
sudo rm -rf /usr/local/bin/gpg
- name: Setup Ubuntu
if: ${{ matrix.runner == 'ubuntu-latest' }}
run: |
sudo rm -rf $(which gpg) $(which gpg2) $(which patchelf)
- name: Setup Windows
if: ${{ matrix.runner == 'windows-latest' }}
run: |
Remove-Item -Path (Get-Command gpg).Path
Remove-Item -Path (Get-Command file).Path
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
with:
python-version: |
3.8
3.9
3.10
3.11
3.12
- name: Set bootstrap sources
env:
SETUP_SCRIPT_EXT: ${{ matrix.runner == 'windows-latest' && 'ps1' || 'sh' }}
SETUP_SCRIPT_SOURCE: ${{ matrix.runner == 'windows-latest' && './' || 'source ' }}
run: |
${{ env.SETUP_SCRIPT_SOURCE }}share/spack/setup-env.${{ env.SETUP_SCRIPT_EXT }}
spack bootstrap disable github-actions-v0.4
- name: Disable from source bootstrap
if: ${{ matrix.runner != 'windows-latest' }}
run: |
source share/spack/setup-env.sh
spack bootstrap disable spack-install
- name: Bootstrap clingo
# No binary clingo on Windows yet
if: ${{ matrix.runner != 'windows-latest' }}
run: |
set -e
for ver in '3.8' '3.9' '3.10' '3.11' '3.12' ; do
not_found=1
ver_dir="$(find $RUNNER_TOOL_CACHE/Python -wholename "*/${ver}.*/*/bin" | grep . || true)"
if [[ -d "$ver_dir" ]] ; then
echo "Testing $ver_dir"
if $ver_dir/python --version ; then
export PYTHON="$ver_dir/python"
not_found=0
old_path="$PATH"
export PATH="$ver_dir:$PATH"
./bin/spack-tmpconfig -b ./.github/workflows/bin/bootstrap-test.sh
export PATH="$old_path"
fi
fi
if (($not_found)) ; then
echo Required python version $ver not found in runner!
exit 1
fi
done
- name: Bootstrap GnuPG
env:
SETUP_SCRIPT_EXT: ${{ matrix.runner == 'windows-latest' && 'ps1' || 'sh' }}
SETUP_SCRIPT_SOURCE: ${{ matrix.runner == 'windows-latest' && './' || 'source ' }}
USER_SCOPE_PARENT_DIR: ${{ matrix.runner == 'windows-latest' && '$env:userprofile' || '$HOME' }}
VALIDATE_LAST_EXIT: ${{ matrix.runner == 'windows-latest' && './share/spack/qa/validate_last_exit.ps1' || '' }}
run: |
${{ env.SETUP_SCRIPT_SOURCE }}share/spack/setup-env.${{ env.SETUP_SCRIPT_EXT }}
spack -d gpg list
${{ env.VALIDATE_LAST_EXIT }}
tree ${{ env.USER_SCOPE_PARENT_DIR }}/.spack/bootstrap/store/
- name: Bootstrap File
env:
SETUP_SCRIPT_EXT: ${{ matrix.runner == 'windows-latest' && 'ps1' || 'sh' }}
SETUP_SCRIPT_SOURCE: ${{ matrix.runner == 'windows-latest' && './' || 'source ' }}
USER_SCOPE_PARENT_DIR: ${{ matrix.runner == 'windows-latest' && '$env:userprofile' || '$HOME' }}
VALIDATE_LAST_EXIT: ${{ matrix.runner == 'windows-latest' && './share/spack/qa/validate_last_exit.ps1' || '' }}
run: |
${{ env.SETUP_SCRIPT_SOURCE }}share/spack/setup-env.${{ env.SETUP_SCRIPT_EXT }}
spack -d python share/spack/qa/bootstrap-file.py
${{ env.VALIDATE_LAST_EXIT }}
tree ${{ env.USER_SCOPE_PARENT_DIR }}/.spack/bootstrap/store/

View File

@@ -1,133 +0,0 @@
name: Containers
on:
# This Workflow can be triggered manually
workflow_dispatch:
# Build new Spack develop containers nightly.
schedule:
- cron: '34 0 * * *'
# Run on pull requests that modify this file
pull_request:
branches:
- develop
paths:
- '.github/workflows/build-containers.yml'
- 'share/spack/docker/*'
- 'share/spack/templates/container/*'
- 'lib/spack/spack/container/*'
# Let's also build & tag Spack containers on releases.
release:
types: [published]
concurrency:
group: build_containers-${{github.ref}}-${{github.event.pull_request.number || github.run_number}}
cancel-in-progress: true
jobs:
deploy-images:
runs-on: ubuntu-latest
permissions:
packages: write
strategy:
# Even if one container fails to build we still want the others
# to continue their builds.
fail-fast: false
# A matrix of Dockerfile paths, associated tags, and which architectures
# they support.
matrix:
# Meaning of the various items in the matrix list
# 0: Container name (e.g. ubuntu-bionic)
# 1: Platforms to build for
# 2: Base image (e.g. ubuntu:22.04)
dockerfile: [[amazon-linux, 'linux/amd64,linux/arm64', 'amazonlinux:2'],
[centos-stream9, 'linux/amd64,linux/arm64,linux/ppc64le', 'centos:stream9'],
[leap15, 'linux/amd64,linux/arm64,linux/ppc64le', 'opensuse/leap:15'],
[ubuntu-focal, 'linux/amd64,linux/arm64,linux/ppc64le', 'ubuntu:20.04'],
[ubuntu-jammy, 'linux/amd64,linux/arm64,linux/ppc64le', 'ubuntu:22.04'],
[ubuntu-noble, 'linux/amd64,linux/arm64,linux/ppc64le', 'ubuntu:24.04'],
[almalinux8, 'linux/amd64,linux/arm64,linux/ppc64le', 'almalinux:8'],
[almalinux9, 'linux/amd64,linux/arm64,linux/ppc64le', 'almalinux:9'],
[rockylinux8, 'linux/amd64,linux/arm64', 'rockylinux:8'],
[rockylinux9, 'linux/amd64,linux/arm64', 'rockylinux:9'],
[fedora39, 'linux/amd64,linux/arm64,linux/ppc64le', 'fedora:39'],
[fedora40, 'linux/amd64,linux/arm64,linux/ppc64le', 'fedora:40']]
name: Build ${{ matrix.dockerfile[0] }}
if: github.repository == 'spack/spack'
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81
id: docker_meta
with:
images: |
ghcr.io/${{ github.repository_owner }}/${{ matrix.dockerfile[0] }}
${{ github.repository_owner }}/${{ matrix.dockerfile[0] }}
tags: |
type=schedule,pattern=nightly
type=schedule,pattern=develop
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=ref,event=branch
type=ref,event=pr
- name: Generate the Dockerfile
env:
SPACK_YAML_OS: "${{ matrix.dockerfile[2] }}"
run: |
.github/workflows/bin/generate_spack_yaml_containerize.sh
. share/spack/setup-env.sh
mkdir -p dockerfiles/${{ matrix.dockerfile[0] }}
spack containerize --last-stage=bootstrap | tee dockerfiles/${{ matrix.dockerfile[0] }}/Dockerfile
printf "Preparing to build ${{ env.container }} from dockerfiles/${{ matrix.dockerfile[0] }}/Dockerfile"
if [ ! -f "dockerfiles/${{ matrix.dockerfile[0] }}/Dockerfile" ]; then
printf "dockerfiles/${{ matrix.dockerfile[0] }}/Dockerfile does not exist"
exit 1;
fi
- name: Upload Dockerfile
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874
with:
name: dockerfiles_${{ matrix.dockerfile[0] }}
path: dockerfiles
- name: Set up QEMU
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db
- name: Log in to GitHub Container Registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build & Deploy ${{ matrix.dockerfile[0] }}
uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85
with:
context: dockerfiles/${{ matrix.dockerfile[0] }}
platforms: ${{ matrix.dockerfile[1] }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}
merge-dockerfiles:
runs-on: ubuntu-latest
needs: deploy-images
steps:
- name: Merge Artifacts
uses: actions/upload-artifact/merge@50769540e7f4bd5e21e526ee35c689e35e0d6874
with:
name: dockerfiles
pattern: dockerfiles_*
delete-merged: true

View File

@@ -74,41 +74,3 @@ jobs:
# job outputs: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idoutputs # job outputs: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idoutputs
# setting environment variables from earlier steps: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable # setting environment variables from earlier steps: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
# #
bootstrap:
if: ${{ github.repository == 'spack/spack' && needs.changes.outputs.bootstrap == 'true' }}
needs: [ prechecks, changes ]
uses: ./.github/workflows/bootstrap.yml
secrets: inherit
unit-tests:
if: ${{ github.repository == 'spack/spack' && needs.changes.outputs.core == 'true' }}
needs: [ prechecks, changes ]
uses: ./.github/workflows/unit_tests.yaml
secrets: inherit
upload-coverage:
needs: [ unit-tests, prechecks ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
- name: Download coverage files
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16
with:
pattern: coverage-*
path: coverage
merge-multiple: true
- run: pip install --upgrade coverage
- run: ls -la coverage
- run: coverage combine -a coverage/.coverage*
- run: coverage xml
- name: "Upload coverage"
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
with:
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
all:
needs: [ upload-coverage, bootstrap ]
runs-on: ubuntu-latest
steps:
- name: Success
run: "true"

View File

@@ -1,31 +0,0 @@
name: Windows Paraview Nightly
on:
schedule:
- cron: '0 2 * * *' # Run at 2 am
defaults:
run:
shell:
powershell Invoke-Expression -Command "./share/spack/qa/windows_test_setup.ps1"; {0}
jobs:
build-paraview-deps:
runs-on: windows-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
with:
python-version: 3.9
- name: Install Python packages
run: |
python -m pip install --upgrade pip six pywin32 setuptools coverage
- name: Build Test
run: |
spack compiler find
spack external find cmake ninja win-sdk win-wdk wgl msmpi
spack -d install -y --cdash-upload-url https://cdash.spack.io/submit.php?project=Spack+on+Windows --cdash-track Nightly --only dependencies paraview
exit 0

View File

@@ -1,250 +0,0 @@
name: unit tests
on:
workflow_dispatch:
workflow_call:
concurrency:
group: unit_tests-${{github.ref}}-${{github.event.pull_request.number || github.run_number}}
cancel-in-progress: true
jobs:
# Run unit tests with different configurations on linux
ubuntu:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
on_develop:
- ${{ github.ref == 'refs/heads/develop' }}
include:
- python-version: '3.6'
os: ubuntu-20.04
on_develop: ${{ github.ref == 'refs/heads/develop' }}
exclude:
- python-version: '3.7'
os: ubuntu-latest
on_develop: false
- python-version: '3.8'
os: ubuntu-latest
on_develop: false
- python-version: '3.9'
os: ubuntu-latest
on_develop: false
- python-version: '3.10'
os: ubuntu-latest
on_develop: false
- python-version: '3.11'
os: ubuntu-latest
on_develop: false
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
with:
python-version: ${{ matrix.python-version }}
- name: Install System packages
run: |
sudo apt-get -y update
# Needed for unit tests
sudo apt-get -y install \
coreutils cvs gfortran graphviz gnupg2 mercurial ninja-build \
cmake bison libbison-dev kcov
- name: Install Python packages
run: |
pip install --upgrade pip setuptools pytest pytest-xdist pytest-cov
pip install --upgrade flake8 "isort>=4.3.5" "mypy>=0.900" "click" "black"
- name: Setup git configuration
run: |
# Need this for the git tests to succeed.
git --version
. .github/workflows/bin/setup_git.sh
- name: Bootstrap clingo
if: ${{ matrix.concretizer == 'clingo' }}
env:
SPACK_PYTHON: python
run: |
. share/spack/setup-env.sh
spack bootstrap disable spack-install
spack bootstrap now
spack -v solve zlib
- name: Run unit tests
env:
SPACK_PYTHON: python
SPACK_TEST_PARALLEL: 2
COVERAGE: true
COVERAGE_FILE: coverage/.coverage-${{ matrix.os }}-python${{ matrix.python-version }}
UNIT_TEST_COVERAGE: ${{ matrix.python-version == '3.11' }}
run: |
share/spack/qa/run-unit-tests
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874
with:
name: coverage-${{ matrix.os }}-python${{ matrix.python-version }}
path: coverage
include-hidden-files: true
# Test shell integration
shell:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
with:
python-version: '3.11'
- name: Install System packages
run: |
sudo apt-get -y update
# Needed for shell tests
sudo apt-get install -y coreutils kcov csh zsh tcsh fish dash bash
- name: Install Python packages
run: |
pip install --upgrade pip setuptools pytest coverage[toml] pytest-xdist
- name: Setup git configuration
run: |
# Need this for the git tests to succeed.
git --version
. .github/workflows/bin/setup_git.sh
- name: Run shell tests
env:
COVERAGE: true
run: |
share/spack/qa/run-shell-tests
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874
with:
name: coverage-shell
path: coverage
include-hidden-files: true
# Test RHEL8 UBI with platform Python. This job is run
# only on PRs modifying core Spack
rhel8-platform-python:
runs-on: ubuntu-latest
container: registry.access.redhat.com/ubi8/ubi
steps:
- name: Install dependencies
run: |
dnf install -y \
bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \
make patch tcl unzip which xz
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Setup repo and non-root user
run: |
git --version
git config --global --add safe.directory /__w/spack/spack
git fetch --unshallow
. .github/workflows/bin/setup_git.sh
useradd spack-test
chown -R spack-test .
- name: Run unit tests
shell: runuser -u spack-test -- bash {0}
run: |
source share/spack/setup-env.sh
spack -d bootstrap now --dev
spack unit-test -k 'not cvs and not svn and not hg' -x --verbose
# Test for the clingo based solver (using clingo-cffi)
clingo-cffi:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
with:
python-version: '3.11'
- name: Install System packages
run: |
sudo apt-get -y update
sudo apt-get -y install coreutils cvs gfortran graphviz gnupg2 mercurial ninja-build kcov
- name: Install Python packages
run: |
pip install --upgrade pip setuptools pytest coverage[toml] pytest-cov clingo pytest-xdist
pip install --upgrade flake8 "isort>=4.3.5" "mypy>=0.900" "click" "black"
- name: Setup git configuration
run: |
# Need this for the git tests to succeed.
git --version
. .github/workflows/bin/setup_git.sh
- name: Run unit tests (full suite with coverage)
env:
COVERAGE: true
COVERAGE_FILE: coverage/.coverage-clingo-cffi
run: |
share/spack/qa/run-unit-tests
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874
with:
name: coverage-clingo-cffi
path: coverage
include-hidden-files: true
# Run unit tests on MacOS
macos:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-13, macos-14]
python-version: ["3.11"]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
with:
python-version: ${{ matrix.python-version }}
- name: Install Python packages
run: |
pip install --upgrade pip setuptools
pip install --upgrade pytest coverage[toml] pytest-xdist pytest-cov
- name: Setup Homebrew packages
run: |
brew install dash fish gcc gnupg2 kcov
- name: Run unit tests
env:
SPACK_TEST_PARALLEL: 4
COVERAGE_FILE: coverage/.coverage-${{ matrix.os }}-python${{ matrix.python-version }}
run: |
git --version
. .github/workflows/bin/setup_git.sh
. share/spack/setup-env.sh
$(which spack) bootstrap disable spack-install
$(which spack) solve zlib
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[@]}"
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874
with:
name: coverage-${{ matrix.os }}-python${{ matrix.python-version }}
path: coverage
include-hidden-files: true
# Run unit tests on Windows
windows:
defaults:
run:
shell:
powershell Invoke-Expression -Command "./share/spack/qa/windows_test_setup.ps1"; {0}
runs-on: windows-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
with:
python-version: 3.9
- name: Install Python packages
run: |
python -m pip install --upgrade pip pywin32 setuptools pytest-cov clingo
- name: Create local develop
run: |
./.github/workflows/bin/setup_git.ps1
- name: Unit Test
env:
COVERAGE_FILE: coverage/.coverage-windows
run: |
spack unit-test -x --verbose --cov --cov-config=pyproject.toml
./share/spack/qa/validate_last_exit.ps1
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874
with:
name: coverage-windows
path: coverage
include-hidden-files: true

View File

@@ -54,95 +54,4 @@ jobs:
- name: Run style tests - name: Run style tests
run: | run: |
share/spack/qa/run-style-tests share/spack/qa/run-style-tests
audit:
uses: ./.github/workflows/audit.yaml
secrets: inherit
with:
with_coverage: ${{ inputs.with_coverage }}
python_version: '3.11'
# Check that spack can bootstrap the development environment on Python 3.6 - RHEL8
bootstrap-dev-rhel8:
runs-on: ubuntu-latest
container: registry.access.redhat.com/ubi8/ubi
steps:
- name: Install dependencies
run: |
dnf install -y \
bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \
make patch tcl unzip which xz
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Setup repo and non-root user
run: |
git --version
git config --global --add safe.directory /__w/spack/spack
git fetch --unshallow
. .github/workflows/bin/setup_git.sh
useradd spack-test
chown -R spack-test .
- name: Bootstrap Spack development environment
shell: runuser -u spack-test -- bash {0}
run: |
source share/spack/setup-env.sh
spack debug report
spack -d bootstrap now --dev
spack style -t black
spack unit-test -V
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@692973e3d937129bcbf40652eb9f2f61becf3332
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@692973e3d937129bcbf40652eb9f2f61becf3332
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@692973e3d937129bcbf40652eb9f2f61becf3332
with:
path: new
- name: Install circular import checker
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
repository: haampie/circular-import-fighter
ref: 555519c6fd5564fd2eb844e7b87e84f4d12602e2
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

View File

@@ -5,9 +5,9 @@
.. chain: .. chain:
============================================= ============================
Chaining Spack Installations (upstreams.yaml) Chaining Spack Installations
============================================= ============================
You can point your Spack installation to another installation to use any You can point your Spack installation to another installation to use any
packages that are installed there. To register the other Spack instance, packages that are installed there. To register the other Spack instance,

View File

@@ -893,8 +893,9 @@ The valid variables for a ``when`` clause are:
#. ``env``. The user environment (usually ``os.environ`` in Python). #. ``env``. The user environment (usually ``os.environ`` in Python).
#. ``hostname``. The hostname of the system (if ``hostname`` is an #. ``hostname``. The hostname of the system.
executable in the user's PATH).
#. ``full_hostname``. The fully qualified hostname of the system.
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
SpecLists as Constraints SpecLists as Constraints

View File

@@ -18,7 +18,7 @@
* Homepage: https://pypi.python.org/pypi/archspec * Homepage: https://pypi.python.org/pypi/archspec
* Usage: Labeling, comparison and detection of microarchitectures * Usage: Labeling, comparison and detection of microarchitectures
* Version: 0.2.5-dev (commit cbb1fd5eb397a70d466e5160b393b87b0dbcc78f) * Version: 0.2.5-dev (commit 7e6740012b897ae4a950f0bba7e9726b767e921f)
astunparse astunparse
---------------- ----------------

View File

@@ -2844,7 +2844,8 @@
"asimdrdm", "asimdrdm",
"lrcpc", "lrcpc",
"dcpop", "dcpop",
"asimddp" "asimddp",
"ssbs"
], ],
"compilers" : { "compilers" : {
"gcc": [ "gcc": [
@@ -2941,6 +2942,7 @@
"uscat", "uscat",
"ilrcpc", "ilrcpc",
"flagm", "flagm",
"ssbs",
"dcpodp", "dcpodp",
"svei8mm", "svei8mm",
"svebf16", "svebf16",
@@ -3008,7 +3010,7 @@
}, },
{ {
"versions": "11:", "versions": "11:",
"flags" : "-march=armv8.4-a+sve+fp16+bf16+crypto+i8mm+rng" "flags" : "-march=armv8.4-a+sve+ssbs+fp16+bf16+crypto+i8mm+rng"
}, },
{ {
"versions": "12:", "versions": "12:",
@@ -3064,6 +3066,7 @@
"uscat", "uscat",
"ilrcpc", "ilrcpc",
"flagm", "flagm",
"ssbs",
"sb", "sb",
"dcpodp", "dcpodp",
"sve2", "sve2",
@@ -3176,6 +3179,7 @@
"uscat", "uscat",
"ilrcpc", "ilrcpc",
"flagm", "flagm",
"ssbs",
"sb", "sb",
"dcpodp", "dcpodp",
"sve2", "sve2",

View File

@@ -3,13 +3,6 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import re
from typing import Optional
import spack.paths
import spack.util.git
#: PEP440 canonical <major>.<minor>.<micro>.<devN> string #: PEP440 canonical <major>.<minor>.<micro>.<devN> string
__version__ = "0.23.0.dev0" __version__ = "0.23.0.dev0"
spack_version = __version__ spack_version = __version__
@@ -26,47 +19,4 @@ def __try_int(v):
spack_version_info = tuple([__try_int(v) for v in __version__.split(".")]) spack_version_info = tuple([__try_int(v) for v in __version__.split(".")])
def get_spack_commit() -> Optional[str]: __all__ = ["spack_version_info", "spack_version"]
"""Get the Spack git commit sha.
Returns:
(str or None) the commit sha if available, otherwise None
"""
git_path = os.path.join(spack.paths.prefix, ".git")
if not os.path.exists(git_path):
return None
git = spack.util.git.git()
if not git:
return None
rev = git(
"-C",
spack.paths.prefix,
"rev-parse",
"HEAD",
output=str,
error=os.devnull,
fail_on_error=False,
)
if git.returncode != 0:
return None
match = re.match(r"[a-f\d]{7,}$", rev)
return match.group(0) if match else None
def get_version() -> str:
"""Get a descriptive version of this instance of Spack.
Outputs '<PEP440 version> (<git commit sha>)'.
The commit sha is only added when available.
"""
commit = get_spack_commit()
if commit:
return f"{spack_version} ({commit})"
return spack_version
__all__ = ["spack_version_info", "spack_version", "get_version", "get_spack_commit"]

View File

@@ -51,10 +51,9 @@ def _search_duplicate_compilers(error_cls):
import llnl.util.lang import llnl.util.lang
import spack.builder
import spack.config import spack.config
import spack.fetch_strategy
import spack.patch import spack.patch
import spack.paths
import spack.repo import spack.repo
import spack.spec import spack.spec
import spack.util.crypto import spack.util.crypto
@@ -282,7 +281,7 @@ def _avoid_mismatched_variants(error_cls):
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name) pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
for variant in current_spec.variants.values(): for variant in current_spec.variants.values():
# Variant does not exist at all # Variant does not exist at all
if variant.name not in pkg_cls.variant_names(): if variant.name not in pkg_cls.variants:
summary = ( summary = (
f"Setting a preference for the '{pkg_name}' package to the " f"Setting a preference for the '{pkg_name}' package to the "
f"non-existing variant '{variant.name}'" f"non-existing variant '{variant.name}'"
@@ -291,8 +290,9 @@ def _avoid_mismatched_variants(error_cls):
continue continue
# Variant cannot accept this value # Variant cannot accept this value
s = spack.spec.Spec(pkg_name)
try: try:
spack.variant.prevalidate_variant_value(pkg_cls, variant, strict=True) s.update_variant_validate(variant.name, variant.value)
except Exception: except Exception:
summary = ( summary = (
f"Setting the variant '{variant.name}' of the '{pkg_name}' package " f"Setting the variant '{variant.name}' of the '{pkg_name}' package "
@@ -662,15 +662,9 @@ def _ensure_env_methods_are_ported_to_builders(pkgs, error_cls):
errors = [] errors = []
for pkg_name in pkgs: for pkg_name in pkgs:
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name) pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
buildsystem_variant, _ = pkg_cls.variants["build_system"]
# values are either Value objects (for conditional values) or the values themselves buildsystem_names = [getattr(x, "value", x) for x in buildsystem_variant.values]
build_system_names = set( builder_cls_names = [spack.builder.BUILDER_CLS[x].__name__ for x in buildsystem_names]
v.value if isinstance(v, spack.variant.Value) else v
for _, variant in pkg_cls.variant_definitions("build_system")
for v in variant.values
)
builder_cls_names = [spack.builder.BUILDER_CLS[x].__name__ for x in build_system_names]
module = pkg_cls.module module = pkg_cls.module
has_builders_in_package_py = any( has_builders_in_package_py = any(
getattr(module, name, False) for name in builder_cls_names getattr(module, name, False) for name in builder_cls_names
@@ -937,22 +931,20 @@ def check_virtual_with_variants(spec, msg):
# check variants # check variants
dependency_variants = dep.spec.variants dependency_variants = dep.spec.variants
for name, variant in dependency_variants.items(): for name, value in dependency_variants.items():
try: try:
spack.variant.prevalidate_variant_value( v, _ = dependency_pkg_cls.variants[name]
dependency_pkg_cls, variant, dep.spec, strict=True v.validate_or_raise(value, pkg_cls=dependency_pkg_cls)
)
except Exception as e: except Exception as e:
summary = ( summary = (
f"{pkg_name}: wrong variant used for dependency in 'depends_on()'" f"{pkg_name}: wrong variant used for dependency in 'depends_on()'"
) )
error_msg = str(e)
if isinstance(e, KeyError): if isinstance(e, KeyError):
error_msg = ( error_msg = (
f"variant {str(e).strip()} does not exist in package {dep_name}" f"variant {str(e).strip()} does not exist in package {dep_name}"
f" in package '{dep_name}'"
) )
error_msg += f" in package '{dep_name}'"
errors.append( errors.append(
error_cls(summary=summary, details=[error_msg, f"in {filename}"]) error_cls(summary=summary, details=[error_msg, f"in {filename}"])
@@ -964,38 +956,39 @@ def check_virtual_with_variants(spec, msg):
@package_directives @package_directives
def _ensure_variant_defaults_are_parsable(pkgs, error_cls): def _ensure_variant_defaults_are_parsable(pkgs, error_cls):
"""Ensures that variant defaults are present and parsable from cli""" """Ensures that variant defaults are present and parsable from cli"""
def check_variant(pkg_cls, variant, vname):
# bool is a subclass of int in python. Permitting a default that is an instance
# of 'int' means both foo=false and foo=0 are accepted. Other falsish values are
# not allowed, since they can't be parsed from CLI ('foo=')
default_is_parsable = isinstance(variant.default, int) or variant.default
if not default_is_parsable:
msg = f"Variant '{vname}' of package '{pkg_cls.name}' has an unparsable default value"
return [error_cls(msg, [])]
try:
vspec = variant.make_default()
except spack.variant.MultipleValuesInExclusiveVariantError:
msg = f"Can't create default value for variant '{vname}' in package '{pkg_cls.name}'"
return [error_cls(msg, [])]
try:
variant.validate_or_raise(vspec, pkg_cls.name)
except spack.variant.InvalidVariantValueError:
msg = "Default value of variant '{vname}' in package '{pkg.name}' is invalid"
question = "Is it among the allowed values?"
return [error_cls(msg, [question])]
return []
errors = [] errors = []
for pkg_name in pkgs: for pkg_name in pkgs:
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name) pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
for vname in pkg_cls.variant_names(): for variant_name, entry in pkg_cls.variants.items():
for _, variant_def in pkg_cls.variant_definitions(vname): variant, _ = entry
errors.extend(check_variant(pkg_cls, variant_def, vname)) default_is_parsable = (
# Permitting a default that is an instance on 'int' permits
# to have foo=false or foo=0. Other falsish values are
# not allowed, since they can't be parsed from cli ('foo=')
isinstance(variant.default, int)
or variant.default
)
if not default_is_parsable:
error_msg = "Variant '{}' of package '{}' has a bad default value"
errors.append(error_cls(error_msg.format(variant_name, pkg_name), []))
continue
try:
vspec = variant.make_default()
except spack.variant.MultipleValuesInExclusiveVariantError:
error_msg = "Cannot create a default value for the variant '{}' in package '{}'"
errors.append(error_cls(error_msg.format(variant_name, pkg_name), []))
continue
try:
variant.validate_or_raise(vspec, pkg_cls=pkg_cls)
except spack.variant.InvalidVariantValueError:
error_msg = (
"The default value of the variant '{}' in package '{}' failed validation"
)
question = "Is it among the allowed values?"
errors.append(error_cls(error_msg.format(variant_name, pkg_name), [question]))
return errors return errors
@@ -1005,11 +998,11 @@ def _ensure_variants_have_descriptions(pkgs, error_cls):
errors = [] errors = []
for pkg_name in pkgs: for pkg_name in pkgs:
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name) pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
for name in pkg_cls.variant_names(): for variant_name, entry in pkg_cls.variants.items():
for when, variant in pkg_cls.variant_definitions(name): variant, _ = entry
if not variant.description: if not variant.description:
msg = f"Variant '{name}' in package '{pkg_name}' is missing a description" error_msg = "Variant '{}' in package '{}' is missing a description"
errors.append(error_cls(msg, [])) errors.append(error_cls(error_msg.format(variant_name, pkg_name), []))
return errors return errors
@@ -1066,26 +1059,29 @@ def _version_constraints_are_satisfiable_by_some_version_in_repo(pkgs, error_cls
def _analyze_variants_in_directive(pkg, constraint, directive, error_cls): def _analyze_variants_in_directive(pkg, constraint, directive, error_cls):
variant_exceptions = (
spack.variant.InconsistentValidationError,
spack.variant.MultipleValuesInExclusiveVariantError,
spack.variant.InvalidVariantValueError,
KeyError,
)
errors = [] errors = []
variant_names = pkg.variant_names()
summary = f"{pkg.name}: wrong variant in '{directive}' directive"
filename = spack.repo.PATH.filename_for_package_name(pkg.name)
for name, v in constraint.variants.items(): for name, v in constraint.variants.items():
if name not in variant_names:
msg = f"variant {name} does not exist in {pkg.name}"
errors.append(error_cls(summary=summary, details=[msg, f"in {filename}"]))
continue
try: try:
spack.variant.prevalidate_variant_value(pkg, v, constraint, strict=True) variant, _ = pkg.variants[name]
except ( variant.validate_or_raise(v, pkg_cls=pkg)
spack.variant.InconsistentValidationError, except variant_exceptions as e:
spack.variant.MultipleValuesInExclusiveVariantError, summary = pkg.name + ': wrong variant in "{0}" directive'
spack.variant.InvalidVariantValueError, summary = summary.format(directive)
) as e: filename = spack.repo.PATH.filename_for_package_name(pkg.name)
msg = str(e).strip()
errors.append(error_cls(summary=summary, details=[msg, f"in {filename}"])) error_msg = str(e).strip()
if isinstance(e, KeyError):
error_msg = "the variant {0} does not exist".format(error_msg)
err = error_cls(summary=summary, details=[error_msg, "in " + filename])
errors.append(err)
return errors return errors
@@ -1123,10 +1119,9 @@ def _extracts_errors(triggers, summary):
for dname in dnames for dname in dnames
) )
for when, variants_by_name in pkg_cls.variants.items(): for vname, (variant, triggers) in pkg_cls.variants.items():
for vname, variant in variants_by_name.items(): summary = f"{pkg_name}: wrong 'when=' condition for the '{vname}' variant"
summary = f"{pkg_name}: wrong 'when=' condition for the '{vname}' variant" errors.extend(_extracts_errors(triggers, summary))
errors.extend(_extracts_errors([when], summary))
for when, providers, details in _error_items(pkg_cls.provided): for when, providers, details in _error_items(pkg_cls.provided):
errors.extend( errors.extend(

View File

@@ -33,6 +33,7 @@
from llnl.util.symlink import readlink from llnl.util.symlink import readlink
import spack.caches import spack.caches
import spack.cmd
import spack.config as config import spack.config as config
import spack.database as spack_db import spack.database as spack_db
import spack.error import spack.error
@@ -43,9 +44,9 @@
import spack.oci.image import spack.oci.image
import spack.oci.oci import spack.oci.oci
import spack.oci.opener import spack.oci.opener
import spack.paths
import spack.platforms import spack.platforms
import spack.relocate as relocate import spack.relocate as relocate
import spack.repo
import spack.spec import spack.spec
import spack.stage import spack.stage
import spack.store import spack.store
@@ -1446,9 +1447,7 @@ def _oci_push_pkg_blob(
filename = os.path.join(tmpdir, f"{spec.dag_hash()}.tar.gz") filename = os.path.join(tmpdir, f"{spec.dag_hash()}.tar.gz")
# Create an oci.image.layer aka tarball of the package # Create an oci.image.layer aka tarball of the package
compressed_tarfile_checksum, tarfile_checksum = _do_create_tarball( compressed_tarfile_checksum, tarfile_checksum = spack.oci.oci.create_tarball(spec, filename)
filename, spec.prefix, get_buildinfo_dict(spec)
)
blob = spack.oci.oci.Blob( blob = spack.oci.oci.Blob(
Digest.from_sha256(compressed_tarfile_checksum), Digest.from_sha256(compressed_tarfile_checksum),
@@ -2698,9 +2697,6 @@ def get_keys(install=False, trust=False, force=False, mirrors=None):
for mirror in mirror_collection.values(): for mirror in mirror_collection.values():
fetch_url = mirror.fetch_url fetch_url = mirror.fetch_url
# TODO: oci:// does not support signing.
if fetch_url.startswith("oci://"):
continue
keys_url = url_util.join( keys_url = url_util.join(
fetch_url, BUILD_CACHE_RELATIVE_PATH, BUILD_CACHE_KEYS_RELATIVE_PATH fetch_url, BUILD_CACHE_RELATIVE_PATH, BUILD_CACHE_KEYS_RELATIVE_PATH
) )

View File

@@ -14,7 +14,6 @@
import spack.compilers import spack.compilers
import spack.config import spack.config
import spack.environment import spack.environment
import spack.modules
import spack.paths import spack.paths
import spack.platforms import spack.platforms
import spack.repo import spack.repo

View File

@@ -37,10 +37,16 @@
import spack.binary_distribution import spack.binary_distribution
import spack.config import spack.config
import spack.detection import spack.detection
import spack.environment
import spack.modules
import spack.paths
import spack.platforms import spack.platforms
import spack.platforms.linux
import spack.repo
import spack.spec import spack.spec
import spack.store import spack.store
import spack.user_environment import spack.user_environment
import spack.util.environment
import spack.util.executable import spack.util.executable
import spack.util.path import spack.util.path
import spack.util.spack_yaml import spack.util.spack_yaml

View File

@@ -14,9 +14,9 @@
from llnl.util import tty from llnl.util import tty
import spack.environment import spack.environment
import spack.spec
import spack.tengine import spack.tengine
import spack.util.path import spack.util.cpus
import spack.util.executable
from ._common import _root_spec from ._common import _root_spec
from .config import root_path, spec_for_current_python, store_path from .config import root_path, spec_for_current_python, store_path

View File

@@ -53,7 +53,6 @@
from llnl.util.tty.color import cescape, colorize from llnl.util.tty.color import cescape, colorize
from llnl.util.tty.log import MultiProcessFd from llnl.util.tty.log import MultiProcessFd
import spack.build_systems._checks
import spack.build_systems.cmake import spack.build_systems.cmake
import spack.build_systems.meson import spack.build_systems.meson
import spack.build_systems.python import spack.build_systems.python
@@ -62,20 +61,26 @@
import spack.config import spack.config
import spack.deptypes as dt import spack.deptypes as dt
import spack.error import spack.error
import spack.multimethod import spack.main
import spack.package_base import spack.package_base
import spack.paths import spack.paths
import spack.platforms import spack.platforms
import spack.repo
import spack.schema.environment import spack.schema.environment
import spack.spec import spack.spec
import spack.stage import spack.stage
import spack.store import spack.store
import spack.subprocess_context import spack.subprocess_context
import spack.user_environment
import spack.util.executable import spack.util.executable
import spack.util.path
import spack.util.pattern
from spack import traverse from spack import traverse
from spack.context import Context from spack.context import Context
from spack.error import InstallError, NoHeadersError, NoLibrariesError from spack.error import NoHeadersError, NoLibrariesError
from spack.install_test import spack_install_test_log from spack.install_test import spack_install_test_log
from spack.installer import InstallError
from spack.util.cpus import determine_number_of_jobs
from spack.util.environment import ( from spack.util.environment import (
SYSTEM_DIR_CASE_ENTRY, SYSTEM_DIR_CASE_ENTRY,
EnvironmentModifications, EnvironmentModifications,
@@ -450,7 +455,7 @@ def set_wrapper_variables(pkg, env):
env.set(SPACK_DEBUG, "TRUE") env.set(SPACK_DEBUG, "TRUE")
env.set(SPACK_SHORT_SPEC, pkg.spec.short_spec) env.set(SPACK_SHORT_SPEC, pkg.spec.short_spec)
env.set(SPACK_DEBUG_LOG_ID, pkg.spec.format("{name}-{hash:7}")) env.set(SPACK_DEBUG_LOG_ID, pkg.spec.format("{name}-{hash:7}"))
env.set(SPACK_DEBUG_LOG_DIR, spack.paths.spack_working_dir) env.set(SPACK_DEBUG_LOG_DIR, spack.main.spack_working_dir)
if spack.config.get("config:ccache"): if spack.config.get("config:ccache"):
# Enable ccache in the compiler wrapper # Enable ccache in the compiler wrapper
@@ -557,7 +562,7 @@ def set_package_py_globals(pkg, context: Context = Context.BUILD):
module.std_meson_args = spack.build_systems.meson.MesonBuilder.std_args(pkg) module.std_meson_args = spack.build_systems.meson.MesonBuilder.std_args(pkg)
module.std_pip_args = spack.build_systems.python.PythonPipBuilder.std_args(pkg) module.std_pip_args = spack.build_systems.python.PythonPipBuilder.std_args(pkg)
jobs = spack.config.determine_number_of_jobs(parallel=pkg.parallel) jobs = determine_number_of_jobs(parallel=pkg.parallel)
module.make_jobs = jobs module.make_jobs = jobs
# TODO: make these build deps that can be installed if not found. # TODO: make these build deps that can be installed if not found.
@@ -1134,7 +1139,7 @@ def _setup_pkg_and_run(
return_value = function(pkg, kwargs) return_value = function(pkg, kwargs)
write_pipe.send(return_value) write_pipe.send(return_value)
except spack.error.StopPhase as e: except StopPhase as e:
# Do not create a full ChildError from this, it's not an error # Do not create a full ChildError from this, it's not an error
# it's a control statement. # it's a control statement.
write_pipe.send(e) write_pipe.send(e)
@@ -1295,7 +1300,7 @@ def exitcode_msg(p):
p.join() p.join()
# If returns a StopPhase, raise it # If returns a StopPhase, raise it
if isinstance(child_result, spack.error.StopPhase): if isinstance(child_result, StopPhase):
# do not print # do not print
raise child_result raise child_result
@@ -1504,6 +1509,17 @@ def _make_child_error(msg, module, name, traceback, log, log_type, context):
return ChildError(msg, module, name, traceback, log, log_type, context) return ChildError(msg, module, name, traceback, log, log_type, context)
class StopPhase(spack.error.SpackError):
"""Pickle-able exception to control stopped builds."""
def __reduce__(self):
return _make_stop_phase, (self.message, self.long_message)
def _make_stop_phase(msg, long_msg):
return StopPhase(msg, long_msg)
def write_log_summary(out, log_type, log, last=None): def write_log_summary(out, log_type, log, last=None):
errors, warnings = parse_log_events(log) errors, warnings = parse_log_events(log)
nerr = len(errors) nerr = len(errors)

View File

@@ -8,7 +8,7 @@
import llnl.util.lang import llnl.util.lang
import spack.builder import spack.builder
import spack.error import spack.installer
import spack.relocate import spack.relocate
import spack.spec import spack.spec
import spack.store import spack.store
@@ -34,7 +34,7 @@ def check_paths(path_list, filetype, predicate):
if not predicate(abs_path): if not predicate(abs_path):
msg = "Install failed for {0}. No such {1} in prefix: {2}" msg = "Install failed for {0}. No such {1} in prefix: {2}"
msg = msg.format(pkg.name, filetype, path) msg = msg.format(pkg.name, filetype, path)
raise spack.error.InstallError(msg) raise spack.installer.InstallError(msg)
check_paths(pkg.sanity_check_is_file, "file", os.path.isfile) check_paths(pkg.sanity_check_is_file, "file", os.path.isfile)
check_paths(pkg.sanity_check_is_dir, "directory", os.path.isdir) check_paths(pkg.sanity_check_is_dir, "directory", os.path.isdir)
@@ -42,7 +42,7 @@ def check_paths(path_list, filetype, predicate):
ignore_file = llnl.util.lang.match_predicate(spack.store.STORE.layout.hidden_file_regexes) ignore_file = llnl.util.lang.match_predicate(spack.store.STORE.layout.hidden_file_regexes)
if all(map(ignore_file, os.listdir(pkg.prefix))): if all(map(ignore_file, os.listdir(pkg.prefix))):
msg = "Install failed for {0}. Nothing was installed!" msg = "Install failed for {0}. Nothing was installed!"
raise spack.error.InstallError(msg.format(pkg.name)) raise spack.installer.InstallError(msg.format(pkg.name))
def apply_macos_rpath_fixups(builder: spack.builder.Builder): def apply_macos_rpath_fixups(builder: spack.builder.Builder):

View File

@@ -13,7 +13,6 @@
import spack.build_environment import spack.build_environment
import spack.builder import spack.builder
import spack.error
import spack.package_base import spack.package_base
from spack.directives import build_system, conflicts, depends_on from spack.directives import build_system, conflicts, depends_on
from spack.multimethod import when from spack.multimethod import when
@@ -249,7 +248,7 @@ def runs_ok(script_abs_path):
# An external gnuconfig may not not have a prefix. # An external gnuconfig may not not have a prefix.
if gnuconfig_dir is None: if gnuconfig_dir is None:
raise spack.error.InstallError( raise spack.build_environment.InstallError(
"Spack could not find substitutes for GNU config files because no " "Spack could not find substitutes for GNU config files because no "
"prefix is available for the `gnuconfig` package. Make sure you set a " "prefix is available for the `gnuconfig` package. Make sure you set a "
"prefix path instead of modules for external `gnuconfig`." "prefix path instead of modules for external `gnuconfig`."
@@ -269,7 +268,7 @@ def runs_ok(script_abs_path):
msg += ( msg += (
" or the `gnuconfig` package prefix is misconfigured as" " an external package" " or the `gnuconfig` package prefix is misconfigured as" " an external package"
) )
raise spack.error.InstallError(msg) raise spack.build_environment.InstallError(msg)
# Filter working substitutes # Filter working substitutes
candidates = [f for f in candidates if runs_ok(f)] candidates = [f for f in candidates if runs_ok(f)]
@@ -294,7 +293,9 @@ def runs_ok(script_abs_path):
and set the prefix to the directory containing the `config.guess` and and set the prefix to the directory containing the `config.guess` and
`config.sub` files. `config.sub` files.
""" """
raise spack.error.InstallError(msg.format(", ".join(to_be_found), self.name)) raise spack.build_environment.InstallError(
msg.format(", ".join(to_be_found), self.name)
)
# Copy the good files over the bad ones # Copy the good files over the bad ones
for abs_path in to_be_patched: for abs_path in to_be_patched:
@@ -687,8 +688,9 @@ def _activate_or_not(
variant = variant or name variant = variant or name
# Defensively look that the name passed as argument is among variants # Defensively look that the name passed as argument is among
if not self.pkg.has_variant(variant): # variants
if variant not in self.pkg.variants:
msg = '"{0}" is not a variant of "{1}"' msg = '"{0}" is not a variant of "{1}"'
raise KeyError(msg.format(variant, self.pkg.name)) raise KeyError(msg.format(variant, self.pkg.name))
@@ -697,19 +699,27 @@ def _activate_or_not(
# Create a list of pairs. Each pair includes a configuration # Create a list of pairs. Each pair includes a configuration
# option and whether or not that option is activated # option and whether or not that option is activated
vdef = self.pkg.get_variant(variant) variant_desc, _ = self.pkg.variants[variant]
if set(vdef.values) == set((True, False)): if set(variant_desc.values) == set((True, False)):
# BoolValuedVariant carry information about a single option. # BoolValuedVariant carry information about a single option.
# Nonetheless, for uniformity of treatment we'll package them # Nonetheless, for uniformity of treatment we'll package them
# in an iterable of one element. # in an iterable of one element.
options = [(name, f"+{variant}" in spec)] condition = "+{name}".format(name=variant)
options = [(name, condition in spec)]
else: else:
condition = "{variant}={value}"
# "feature_values" is used to track values which correspond to # "feature_values" is used to track values which correspond to
# features which can be enabled or disabled as understood by the # features which can be enabled or disabled as understood by the
# package's build system. It excludes values which have special # package's build system. It excludes values which have special
# meanings and do not correspond to features (e.g. "none") # meanings and do not correspond to features (e.g. "none")
feature_values = getattr(vdef.values, "feature_values", None) or vdef.values feature_values = (
options = [(value, f"{variant}={value}" in spec) for value in feature_values] getattr(variant_desc.values, "feature_values", None) or variant_desc.values
)
options = [
(value, condition.format(variant=variant, value=value) in spec)
for value in feature_values
]
# For each allowed value in the list of values # For each allowed value in the list of values
for option_value, activated in options: for option_value, activated in options:

View File

@@ -89,7 +89,7 @@ def define_cmake_cache_from_variant(self, cmake_var, variant=None, comment=""):
if variant is None: if variant is None:
variant = cmake_var.lower() variant = cmake_var.lower()
if not self.pkg.has_variant(variant): if variant not in self.pkg.variants:
raise KeyError('"{0}" is not a variant of "{1}"'.format(variant, self.pkg.name)) raise KeyError('"{0}" is not a variant of "{1}"'.format(variant, self.pkg.name))
if variant not in self.pkg.spec.variants: if variant not in self.pkg.spec.variants:

View File

@@ -15,7 +15,6 @@
import spack.build_environment import spack.build_environment
import spack.builder import spack.builder
import spack.deptypes as dt import spack.deptypes as dt
import spack.error
import spack.package_base import spack.package_base
from spack.directives import build_system, conflicts, depends_on, variant from spack.directives import build_system, conflicts, depends_on, variant
from spack.multimethod import when from spack.multimethod import when
@@ -146,7 +145,6 @@ def _values(x):
default=default, default=default,
values=_values, values=_values,
description="the build system generator to use", description="the build system generator to use",
when="build_system=cmake",
) )
for x in not_used: for x in not_used:
conflicts(f"generator={x}") conflicts(f"generator={x}")
@@ -346,7 +344,7 @@ def std_args(pkg, generator=None):
msg = "Invalid CMake generator: '{0}'\n".format(generator) msg = "Invalid CMake generator: '{0}'\n".format(generator)
msg += "CMakePackage currently supports the following " msg += "CMakePackage currently supports the following "
msg += "primary generators: '{0}'".format("', '".join(valid_primary_generators)) msg += "primary generators: '{0}'".format("', '".join(valid_primary_generators))
raise spack.error.InstallError(msg) raise spack.package_base.InstallError(msg)
try: try:
build_type = pkg.spec.variants["build_type"].value build_type = pkg.spec.variants["build_type"].value
@@ -506,7 +504,7 @@ def define_from_variant(self, cmake_var, variant=None):
if variant is None: if variant is None:
variant = cmake_var.lower() variant = cmake_var.lower()
if not self.pkg.has_variant(variant): if variant not in self.pkg.variants:
raise KeyError('"{0}" is not a variant of "{1}"'.format(variant, self.pkg.name)) raise KeyError('"{0}" is not a variant of "{1}"'.format(variant, self.pkg.name))
if variant not in self.pkg.spec.variants: if variant not in self.pkg.spec.variants:

View File

@@ -14,7 +14,6 @@
import spack.compiler import spack.compiler
import spack.package_base import spack.package_base
import spack.util.executable
# Local "type" for type hints # Local "type" for type hints
Path = Union[str, pathlib.Path] Path = Union[str, pathlib.Path]

View File

@@ -22,10 +22,9 @@
install, install,
) )
import spack.builder
import spack.error import spack.error
from spack.build_environment import dso_suffix from spack.build_environment import dso_suffix
from spack.error import InstallError from spack.package_base import InstallError
from spack.util.environment import EnvironmentModifications from spack.util.environment import EnvironmentModifications
from spack.util.executable import Executable from spack.util.executable import Executable
from spack.util.prefix import Prefix from spack.util.prefix import Prefix

View File

@@ -15,7 +15,7 @@
import spack.util.path import spack.util.path
from spack.build_environment import dso_suffix from spack.build_environment import dso_suffix
from spack.directives import conflicts, license, redistribute, variant from spack.directives import conflicts, license, redistribute, variant
from spack.error import InstallError from spack.package_base import InstallError
from spack.util.environment import EnvironmentModifications from spack.util.environment import EnvironmentModifications
from spack.util.executable import Executable from spack.util.executable import Executable

View File

@@ -24,8 +24,6 @@
import spack.detection import spack.detection
import spack.multimethod import spack.multimethod
import spack.package_base import spack.package_base
import spack.platforms
import spack.repo
import spack.spec import spack.spec
import spack.store import spack.store
from spack.directives import build_system, depends_on, extends from spack.directives import build_system, depends_on, extends

View File

@@ -11,9 +11,9 @@
import spack.builder import spack.builder
from spack.build_environment import SPACK_NO_PARALLEL_MAKE from spack.build_environment import SPACK_NO_PARALLEL_MAKE
from spack.config import determine_number_of_jobs
from spack.directives import build_system, extends, maintainers from spack.directives import build_system, extends, maintainers
from spack.package_base import PackageBase from spack.package_base import PackageBase
from spack.util.cpus import determine_number_of_jobs
from spack.util.environment import env_flag from spack.util.environment import env_flag
from spack.util.executable import Executable, ProcessError from spack.util.executable import Executable, ProcessError

View File

@@ -10,7 +10,7 @@
from llnl.util import lang from llnl.util import lang
import spack.error import spack.build_environment
import spack.multimethod import spack.multimethod
#: Builder classes, as registered by the "builder" decorator #: Builder classes, as registered by the "builder" decorator
@@ -461,13 +461,15 @@ def _on_phase_start(self, instance):
# If a phase has a matching stop_before_phase attribute, # If a phase has a matching stop_before_phase attribute,
# stop the installation process raising a StopPhase # stop the installation process raising a StopPhase
if getattr(instance, "stop_before_phase", None) == self.name: if getattr(instance, "stop_before_phase", None) == self.name:
raise spack.error.StopPhase("Stopping before '{0}' phase".format(self.name)) raise spack.build_environment.StopPhase(
"Stopping before '{0}' phase".format(self.name)
)
def _on_phase_exit(self, instance): def _on_phase_exit(self, instance):
# If a phase has a matching last_phase attribute, # If a phase has a matching last_phase attribute,
# stop the installation process raising a StopPhase # stop the installation process raising a StopPhase
if getattr(instance, "last_phase", None) == self.name: if getattr(instance, "last_phase", None) == self.name:
raise spack.error.StopPhase("Stopping at '{0}' phase".format(self.name)) raise spack.build_environment.StopPhase("Stopping at '{0}' phase".format(self.name))
def copy(self): def copy(self):
return copy.deepcopy(self) return copy.deepcopy(self)

View File

@@ -11,7 +11,9 @@
from llnl.util.filesystem import mkdirp from llnl.util.filesystem import mkdirp
import spack.config import spack.config
import spack.error
import spack.fetch_strategy import spack.fetch_strategy
import spack.mirror
import spack.paths import spack.paths
import spack.util.file_cache import spack.util.file_cache
import spack.util.path import spack.util.path

View File

@@ -31,7 +31,6 @@
import spack import spack
import spack.binary_distribution as bindist import spack.binary_distribution as bindist
import spack.concretize
import spack.config as cfg import spack.config as cfg
import spack.environment as ev import spack.environment as ev
import spack.main import spack.main
@@ -39,6 +38,7 @@
import spack.paths import spack.paths
import spack.repo import spack.repo
import spack.spec import spack.spec
import spack.stage
import spack.util.git import spack.util.git
import spack.util.gpg as gpg_util import spack.util.gpg as gpg_util
import spack.util.spack_yaml as syaml import spack.util.spack_yaml as syaml
@@ -1219,8 +1219,8 @@ def main_script_replacements(cmd):
# Capture the version of Spack used to generate the pipeline, that can be # Capture the version of Spack used to generate the pipeline, that can be
# passed to `git checkout` for version consistency. If we aren't in a Git # passed to `git checkout` for version consistency. If we aren't in a Git
# repository, presume we are a Spack release and use the Git tag instead. # repository, presume we are a Spack release and use the Git tag instead.
spack_version = spack.get_version() spack_version = spack.main.get_version()
version_to_clone = spack.get_spack_commit() or f"v{spack.spack_version}" version_to_clone = spack.main.get_spack_commit() or f"v{spack.spack_version}"
output_object["variables"] = { output_object["variables"] = {
"SPACK_ARTIFACTS_ROOT": rel_artifacts_root, "SPACK_ARTIFACTS_ROOT": rel_artifacts_root,

View File

@@ -17,7 +17,7 @@
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
from llnl.util.tty.color import colorize from llnl.util.tty.color import colorize
import spack.config # breaks a cycle. import spack.config
import spack.environment as ev import spack.environment as ev
import spack.error import spack.error
import spack.extensions import spack.extensions

View File

@@ -11,7 +11,6 @@
import llnl.util.tty.color as color import llnl.util.tty.color as color
import spack.platforms import spack.platforms
import spack.spec
description = "print architecture information about this machine" description = "print architecture information about this machine"
section = "system" section = "system"

View File

@@ -16,11 +16,11 @@
import spack.bootstrap.config import spack.bootstrap.config
import spack.bootstrap.core import spack.bootstrap.core
import spack.config import spack.config
import spack.main
import spack.mirror import spack.mirror
import spack.spec import spack.spec
import spack.stage import spack.stage
import spack.util.path import spack.util.path
import spack.util.spack_yaml
from spack.cmd.common import arguments from spack.cmd.common import arguments
description = "manage bootstrap configuration" description = "manage bootstrap configuration"

View File

@@ -23,9 +23,14 @@
import spack.error import spack.error
import spack.mirror import spack.mirror
import spack.oci.oci import spack.oci.oci
import spack.oci.opener
import spack.relocate
import spack.repo
import spack.spec import spack.spec
import spack.stage import spack.stage
import spack.store import spack.store
import spack.user_environment
import spack.util.crypto
import spack.util.parallel import spack.util.parallel
import spack.util.url as url_util import spack.util.url as url_util
import spack.util.web as web_util import spack.util.web as web_util

View File

@@ -4,7 +4,6 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import spack.cmd import spack.cmd
import spack.spec
from spack.cmd.common import arguments from spack.cmd.common import arguments
description = "change an existing spec in an environment" description = "change an existing spec in an environment"

View File

@@ -15,6 +15,7 @@
import spack.repo import spack.repo
import spack.spec import spack.spec
import spack.stage import spack.stage
import spack.util.crypto
import spack.util.web as web_util import spack.util.web as web_util
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.package_base import ( from spack.package_base import (

View File

@@ -19,6 +19,7 @@
import spack.cmd.buildcache as buildcache import spack.cmd.buildcache as buildcache
import spack.config as cfg import spack.config as cfg
import spack.environment as ev import spack.environment as ev
import spack.environment.depfile
import spack.hash_types as ht import spack.hash_types as ht
import spack.mirror import spack.mirror
import spack.util.gpg as gpg_util import spack.util.gpg as gpg_util

View File

@@ -10,9 +10,11 @@
import llnl.util.filesystem import llnl.util.filesystem
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.bootstrap
import spack.caches import spack.caches
import spack.cmd import spack.cmd.test
import spack.config import spack.config
import spack.repo
import spack.stage import spack.stage
import spack.store import spack.store
import spack.util.path import spack.util.path

View File

@@ -17,7 +17,6 @@
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
import spack.cmd import spack.cmd
import spack.config
import spack.main import spack.main
import spack.paths import spack.paths
import spack.platforms import spack.platforms

View File

@@ -15,6 +15,7 @@
import spack.deptypes as dt import spack.deptypes as dt
import spack.environment as ev import spack.environment as ev
import spack.mirror import spack.mirror
import spack.modules
import spack.reporters import spack.reporters
import spack.spec import spack.spec
import spack.store import spack.store

View File

@@ -9,7 +9,6 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.cmd import spack.cmd
import spack.spec
display_args = {"long": True, "show_flags": False, "variants": False, "indent": 4} display_args = {"long": True, "show_flags": False, "variants": False, "indent": 4}

View File

@@ -10,6 +10,7 @@
import spack.cmd import spack.cmd
import spack.deptypes as dt import spack.deptypes as dt
import spack.error import spack.error
import spack.paths
import spack.spec import spack.spec
import spack.store import spack.store
from spack import build_environment, traverse from spack import build_environment, traverse

View File

@@ -13,9 +13,9 @@
import spack.config import spack.config
import spack.environment as ev import spack.environment as ev
import spack.error import spack.repo
import spack.schema.env import spack.schema.env
import spack.spec import spack.schema.packages
import spack.store import spack.store
import spack.util.spack_yaml as syaml import spack.util.spack_yaml as syaml
from spack.cmd.common import arguments from spack.cmd.common import arguments
@@ -256,7 +256,7 @@ def config_remove(args):
existing.pop(value, None) existing.pop(value, None)
else: else:
# This should be impossible to reach # This should be impossible to reach
raise spack.error.ConfigError("Config has nested non-dict values") raise spack.config.ConfigError("Config has nested non-dict values")
spack.config.set(path, existing, scope) spack.config.set(path, existing, scope)
@@ -340,7 +340,7 @@ def _config_change(config_path, match_spec_str=None):
if not changed: if not changed:
existing_requirements = spack.config.get(key_path) existing_requirements = spack.config.get(key_path)
if isinstance(existing_requirements, str): if isinstance(existing_requirements, str):
raise spack.error.ConfigError( raise spack.config.ConfigError(
"'config change' needs to append a requirement," "'config change' needs to append a requirement,"
" but existing require: config is not a list" " but existing require: config is not a list"
) )
@@ -536,11 +536,11 @@ def config_prefer_upstream(args):
# Get and list all the variants that differ from the default. # Get and list all the variants that differ from the default.
variants = [] variants = []
for var_name, variant in spec.variants.items(): for var_name, variant in spec.variants.items():
if var_name in ["patches"] or not spec.package.has_variant(var_name): if var_name in ["patches"] or var_name not in spec.package.variants:
continue continue
vdef = spec.package.get_variant(var_name) variant_desc, _ = spec.package.variants[var_name]
if variant.value != vdef.default: if variant.value != variant_desc.default:
variants.append(str(variant)) variants.append(str(variant))
variants.sort() variants.sort()
variants = " ".join(variants) variants = " ".join(variants)

View File

@@ -13,6 +13,7 @@
import spack.repo import spack.repo
import spack.stage import spack.stage
import spack.util.web
from spack.spec import Spec from spack.spec import Spec
from spack.url import ( from spack.url import (
UndetectableNameError, UndetectableNameError,

View File

@@ -13,12 +13,11 @@
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.filesystem import working_dir from llnl.util.filesystem import working_dir
import spack import spack.config
import spack.paths import spack.paths
import spack.platforms import spack.platforms
import spack.spec
import spack.store
import spack.util.git import spack.util.git
from spack.main import get_version
from spack.util.executable import which from spack.util.executable import which
description = "debugging commands for troubleshooting Spack" description = "debugging commands for troubleshooting Spack"
@@ -90,7 +89,7 @@ def report(args):
host_os = host_platform.operating_system("frontend") host_os = host_platform.operating_system("frontend")
host_target = host_platform.target("frontend") host_target = host_platform.target("frontend")
architecture = spack.spec.ArchSpec((str(host_platform), str(host_os), str(host_target))) architecture = spack.spec.ArchSpec((str(host_platform), str(host_os), str(host_target)))
print("* **Spack:**", spack.get_version()) print("* **Spack:**", get_version())
print("* **Python:**", platform.python_version()) print("* **Python:**", platform.python_version())
print("* **Platform:**", architecture) print("* **Platform:**", architecture)

View File

@@ -11,6 +11,7 @@
import spack.cmd import spack.cmd
import spack.environment as ev import spack.environment as ev
import spack.package_base import spack.package_base
import spack.repo
import spack.store import spack.store
from spack.cmd.common import arguments from spack.cmd.common import arguments

View File

@@ -8,9 +8,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.build_environment
import spack.cmd import spack.cmd
import spack.cmd.common.arguments
import spack.config import spack.config
import spack.repo import spack.repo
from spack.cmd.common import arguments from spack.cmd.common import arguments

View File

@@ -10,6 +10,7 @@
import spack.cmd import spack.cmd
import spack.config import spack.config
import spack.fetch_strategy import spack.fetch_strategy
import spack.package_base
import spack.repo import spack.repo
import spack.spec import spack.spec
import spack.stage import spack.stage

View File

@@ -12,6 +12,7 @@
import spack.cmd import spack.cmd
import spack.environment as ev import spack.environment as ev
import spack.solver.asp as asp import spack.solver.asp as asp
import spack.util.environment
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
from spack.cmd.common import arguments from spack.cmd.common import arguments

View File

@@ -21,12 +21,15 @@
import spack.cmd import spack.cmd
import spack.cmd.common import spack.cmd.common
import spack.cmd.common.arguments import spack.cmd.common.arguments
import spack.cmd.install
import spack.cmd.modules import spack.cmd.modules
import spack.cmd.uninstall
import spack.config import spack.config
import spack.environment as ev import spack.environment as ev
import spack.environment.depfile as depfile import spack.environment.depfile as depfile
import spack.environment.environment
import spack.environment.shell import spack.environment.shell
import spack.schema.env
import spack.spec
import spack.tengine import spack.tengine
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.util.environment import EnvironmentModifications from spack.util.environment import EnvironmentModifications

View File

@@ -18,9 +18,9 @@
import spack.cray_manifest as cray_manifest import spack.cray_manifest as cray_manifest
import spack.detection import spack.detection
import spack.error import spack.error
import spack.package_base
import spack.repo import spack.repo
import spack.spec import spack.spec
import spack.util.environment
from spack.cmd.common import arguments from spack.cmd.common import arguments
description = "manage external packages in Spack configuration" description = "manage external packages in Spack configuration"

View File

@@ -8,6 +8,7 @@
import spack.cmd import spack.cmd
import spack.config import spack.config
import spack.environment as ev import spack.environment as ev
import spack.repo
import spack.traverse import spack.traverse
from spack.cmd.common import arguments from spack.cmd.common import arguments

View File

@@ -10,11 +10,10 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import llnl.util.tty.color as color import llnl.util.tty.color as color
import spack.bootstrap
import spack.cmd as cmd import spack.cmd as cmd
import spack.config
import spack.environment as ev import spack.environment as ev
import spack.repo import spack.repo
import spack.spec
import spack.store import spack.store
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.database import InstallStatuses from spack.database import InstallStatuses

View File

@@ -16,7 +16,6 @@
import spack.install_test import spack.install_test
import spack.repo import spack.repo
import spack.spec import spack.spec
import spack.variant
import spack.version import spack.version
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.package_base import preferred_version from spack.package_base import preferred_version
@@ -334,6 +333,26 @@ def _fmt_variant(variant, max_name_default_len, indent, when=None, out=None):
out.write("\n") out.write("\n")
def _variants_by_name_when(pkg):
"""Adaptor to get variants keyed by { name: { when: { [Variant...] } }."""
# TODO: replace with pkg.variants_by_name(when=True) when unified directive dicts are merged.
variants = {}
for name, (variant, whens) in sorted(pkg.variants.items()):
for when in whens:
variants.setdefault(name, {}).setdefault(when, []).append(variant)
return variants
def _variants_by_when_name(pkg):
"""Adaptor to get variants keyed by { when: { name: Variant } }"""
# TODO: replace with pkg.variants when unified directive dicts are merged.
variants = {}
for name, (variant, whens) in pkg.variants.items():
for when in whens:
variants.setdefault(when, {})[name] = variant
return variants
def _print_variants_header(pkg): def _print_variants_header(pkg):
"""output variants""" """output variants"""
@@ -344,22 +363,32 @@ def _print_variants_header(pkg):
color.cprint("") color.cprint("")
color.cprint(section_title("Variants:")) color.cprint(section_title("Variants:"))
variants_by_name = _variants_by_name_when(pkg)
# Calculate the max length of the "name [default]" part of the variant display # Calculate the max length of the "name [default]" part of the variant display
# This lets us know where to print variant values. # This lets us know where to print variant values.
max_name_default_len = max( max_name_default_len = max(
color.clen(_fmt_name_and_default(variant)) color.clen(_fmt_name_and_default(variant))
for name in pkg.variant_names() for name, when_variants in variants_by_name.items()
for _, variant in pkg.variant_definitions(name) for variants in when_variants.values()
for variant in variants
) )
return max_name_default_len return max_name_default_len, variants_by_name
def _unconstrained_ver_first(item):
"""sort key that puts specs with open version ranges first"""
spec, _ = item
return (spack.version.any_version not in spec.versions, spec)
def print_variants_grouped_by_when(pkg): def print_variants_grouped_by_when(pkg):
max_name_default_len = _print_variants_header(pkg) max_name_default_len, _ = _print_variants_header(pkg)
indent = 4 indent = 4
for when, variants_by_name in pkg.variant_items(): variants = _variants_by_when_name(pkg)
for when, variants_by_name in sorted(variants.items(), key=_unconstrained_ver_first):
padded_values = max_name_default_len + 4 padded_values = max_name_default_len + 4
start_indent = indent start_indent = indent
@@ -377,14 +406,15 @@ def print_variants_grouped_by_when(pkg):
def print_variants_by_name(pkg): def print_variants_by_name(pkg):
max_name_default_len = _print_variants_header(pkg) max_name_default_len, variants_by_name = _print_variants_header(pkg)
max_name_default_len += 4 max_name_default_len += 4
indent = 4 indent = 4
for name in pkg.variant_names(): for name, when_variants in variants_by_name.items():
for when, variant in pkg.variant_definitions(name): for when, variants in sorted(when_variants.items(), key=_unconstrained_ver_first):
_fmt_variant(variant, max_name_default_len, indent, when, out=sys.stdout) for variant in variants:
sys.stdout.write("\n") _fmt_variant(variant, max_name_default_len, indent, when, out=sys.stdout)
sys.stdout.write("\n")
def print_variants(pkg, args): def print_variants(pkg, args):

View File

@@ -13,15 +13,18 @@
from llnl.string import plural from llnl.string import plural
from llnl.util import lang, tty from llnl.util import lang, tty
import spack.build_environment
import spack.cmd import spack.cmd
import spack.config import spack.config
import spack.environment as ev import spack.environment as ev
import spack.fetch_strategy
import spack.package_base
import spack.paths import spack.paths
import spack.report import spack.report
import spack.spec import spack.spec
import spack.store import spack.store
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.error import InstallError, SpackError from spack.error import SpackError
from spack.installer import PackageInstaller from spack.installer import PackageInstaller
description = "build and install packages" description = "build and install packages"
@@ -284,7 +287,7 @@ def require_user_confirmation_for_overwrite(concrete_specs, args):
tty.die("Reinstallation aborted.") tty.die("Reinstallation aborted.")
def _dump_log_on_error(e: InstallError): def _dump_log_on_error(e: spack.build_environment.InstallError):
e.print_context() e.print_context()
assert e.pkg, "Expected InstallError to include the associated package" assert e.pkg, "Expected InstallError to include the associated package"
if not os.path.exists(e.pkg.log_path): if not os.path.exists(e.pkg.log_path):
@@ -349,7 +352,7 @@ def reporter_factory(specs):
install_with_active_env(env, args, install_kwargs, reporter_factory) install_with_active_env(env, args, install_kwargs, reporter_factory)
else: else:
install_without_active_env(args, install_kwargs, reporter_factory) install_without_active_env(args, install_kwargs, reporter_factory)
except InstallError as e: except spack.build_environment.InstallError as e:
if args.show_log_on_error: if args.show_log_on_error:
_dump_log_on_error(e) _dump_log_on_error(e)
raise raise

View File

@@ -6,10 +6,11 @@
import sys import sys
import spack.cmd import spack.cmd
import spack.cmd.common import spack.cmd.find
import spack.environment as ev import spack.environment as ev
import spack.store import spack.store
import spack.user_environment as uenv import spack.user_environment as uenv
import spack.util.environment
from spack.cmd.common import arguments from spack.cmd.common import arguments
description = "add package to the user environment" description = "add package to the user environment"

View File

@@ -8,6 +8,9 @@
from llnl.util import tty from llnl.util import tty
import spack.cmd import spack.cmd
import spack.error
import spack.package_base
import spack.repo
import spack.store import spack.store
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.database import InstallStatuses from spack.database import InstallStatuses

View File

@@ -17,6 +17,7 @@
import spack.mirror import spack.mirror
import spack.repo import spack.repo
import spack.spec import spack.spec
import spack.util.path
import spack.util.web as web_util import spack.util.web as web_util
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.error import SpackError from spack.error import SpackError

View File

@@ -15,7 +15,6 @@
import spack.cmd import spack.cmd
import spack.config import spack.config
import spack.error
import spack.modules import spack.modules
import spack.modules.common import spack.modules.common
import spack.repo import spack.repo
@@ -125,13 +124,13 @@ def check_module_set_name(name):
names = [k for k in modules if k != "prefix_inspections"] names = [k for k in modules if k != "prefix_inspections"]
if not names: if not names:
raise spack.error.ConfigError( raise spack.config.ConfigError(
f"Module set configuration is missing. Cannot use module set '{name}'" f"Module set configuration is missing. Cannot use module set '{name}'"
) )
pretty_names = "', '".join(names) pretty_names = "', '".join(names)
raise spack.error.ConfigError( raise spack.config.ConfigError(
f"Cannot use invalid module set '{name}'.", f"Cannot use invalid module set '{name}'.",
f"Valid module set names are: '{pretty_names}'.", f"Valid module set names are: '{pretty_names}'.",
) )

View File

@@ -9,6 +9,7 @@
import spack.config import spack.config
import spack.environment as ev import spack.environment as ev
import spack.package_base import spack.package_base
import spack.repo
import spack.traverse import spack.traverse
from spack.cmd.common import arguments from spack.cmd.common import arguments

View File

@@ -12,6 +12,7 @@
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
import spack.cmd import spack.cmd
import spack.paths
import spack.repo import spack.repo
import spack.util.executable as exe import spack.util.executable as exe
import spack.util.package_hash as ph import spack.util.package_hash as ph

View File

@@ -78,8 +78,8 @@ def python(parser, args, unknown_args):
# Run user choice of interpreter # Run user choice of interpreter
if args.python_interpreter == "ipython": if args.python_interpreter == "ipython":
return ipython_interpreter(args) return spack.cmd.python.ipython_interpreter(args)
return python_interpreter(args) return spack.cmd.python.python_interpreter(args)
def ipython_interpreter(args): def ipython_interpreter(args):

View File

@@ -6,6 +6,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.cmd import spack.cmd
import spack.repo
from spack.cmd.common import arguments from spack.cmd.common import arguments
description = "revert checked out package source code" description = "revert checked out package source code"

View File

@@ -12,12 +12,11 @@
import spack import spack
import spack.cmd import spack.cmd
import spack.cmd.common.arguments
import spack.config import spack.config
import spack.environment import spack.environment
import spack.hash_types as ht import spack.hash_types as ht
import spack.package_base
import spack.solver.asp as asp import spack.solver.asp as asp
import spack.spec
from spack.cmd.common import arguments from spack.cmd.common import arguments
description = "concretize a specs using an ASP solver" description = "concretize a specs using an ASP solver"

View File

@@ -14,7 +14,6 @@
import spack.hash_types as ht import spack.hash_types as ht
import spack.spec import spack.spec
import spack.store import spack.store
import spack.traverse
from spack.cmd.common import arguments from spack.cmd.common import arguments
description = "show what would be installed, given a spec" description = "show what would be installed, given a spec"

View File

@@ -11,6 +11,8 @@
import spack.config import spack.config
import spack.environment as ev import spack.environment as ev
import spack.package_base import spack.package_base
import spack.repo
import spack.stage
import spack.traverse import spack.traverse
from spack.cmd.common import arguments from spack.cmd.common import arguments

View File

@@ -9,8 +9,8 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import llnl.util.tty.colify as colify import llnl.util.tty.colify as colify
import spack.environment
import spack.repo import spack.repo
import spack.store
import spack.tag import spack.tag
description = "show package tags and associated packages" description = "show package tags and associated packages"

View File

@@ -15,12 +15,11 @@
from llnl.util.tty import colify from llnl.util.tty import colify
import spack.cmd import spack.cmd
import spack.config
import spack.environment as ev import spack.environment as ev
import spack.install_test import spack.install_test
import spack.package_base
import spack.repo import spack.repo
import spack.report import spack.report
import spack.store
from spack.cmd.common import arguments from spack.cmd.common import arguments
description = "run spack's tests for an install" description = "run spack's tests for an install"

View File

@@ -10,7 +10,6 @@
from llnl.util.filesystem import working_dir from llnl.util.filesystem import working_dir
import spack import spack
import spack.cmd
import spack.config import spack.config
import spack.paths import spack.paths
import spack.util.git import spack.util.git

View File

@@ -6,7 +6,6 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.cmd import spack.cmd
import spack.config
from spack.cmd.common import arguments from spack.cmd.common import arguments
description = "remove specs from an environment" description = "remove specs from an environment"

View File

@@ -10,8 +10,6 @@
import re import re
import sys import sys
import spack.extensions
try: try:
import pytest import pytest
except ImportError: except ImportError:

View File

@@ -7,10 +7,9 @@
import sys import sys
import spack.cmd import spack.cmd
import spack.cmd.common
import spack.error import spack.error
import spack.store
import spack.user_environment as uenv import spack.user_environment as uenv
import spack.util.environment
from spack.cmd.common import arguments from spack.cmd.common import arguments
description = "remove package from the user environment" description = "remove package from the user environment"

View File

@@ -6,7 +6,6 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.cmd
import spack.environment as ev import spack.environment as ev
import spack.store import spack.store
import spack.verify import spack.verify

View File

@@ -25,6 +25,7 @@
import spack.platforms import spack.platforms
import spack.repo import spack.repo
import spack.spec import spack.spec
import spack.version
from spack.operating_systems import windows_os from spack.operating_systems import windows_os
from spack.util.environment import get_path from spack.util.environment import get_path
from spack.util.naming import mod_to_class from spack.util.naming import mod_to_class

View File

@@ -8,6 +8,7 @@
import spack.compiler import spack.compiler
import spack.compilers.clang import spack.compilers.clang
import spack.util.executable
from spack.version import Version from spack.version import Version

View File

@@ -8,8 +8,16 @@
from contextlib import contextmanager from contextlib import contextmanager
from itertools import chain from itertools import chain
import spack.compilers
import spack.config import spack.config
import spack.environment
import spack.error import spack.error
import spack.platforms
import spack.repo
import spack.spec
import spack.target
import spack.tengine
import spack.util.path
CHECK_COMPILER_EXISTENCE = True CHECK_COMPILER_EXISTENCE = True

View File

@@ -39,7 +39,6 @@
from llnl.util import filesystem, lang, tty from llnl.util import filesystem, lang, tty
import spack.error
import spack.paths import spack.paths
import spack.platforms import spack.platforms
import spack.schema import spack.schema
@@ -49,19 +48,17 @@
import spack.schema.compilers import spack.schema.compilers
import spack.schema.concretizer import spack.schema.concretizer
import spack.schema.config import spack.schema.config
import spack.schema.definitions
import spack.schema.develop
import spack.schema.env import spack.schema.env
import spack.schema.mirrors import spack.schema.mirrors
import spack.schema.modules import spack.schema.modules
import spack.schema.packages import spack.schema.packages
import spack.schema.repos import spack.schema.repos
import spack.schema.upstreams import spack.schema.upstreams
import spack.schema.view
# Hacked yaml for configuration files preserves line numbers. # Hacked yaml for configuration files preserves line numbers.
import spack.util.spack_yaml as syaml import spack.util.spack_yaml as syaml
import spack.util.web as web_util import spack.util.web as web_util
from spack.error import SpackError
from spack.util.cpus import cpus_available from spack.util.cpus import cpus_available
#: Dict from section names -> schema for that section #: Dict from section names -> schema for that section
@@ -168,7 +165,7 @@ def get_section(self, section: str) -> Optional[YamlConfigDict]:
def _write_section(self, section: str) -> None: def _write_section(self, section: str) -> None:
if not self.writable: if not self.writable:
raise spack.error.ConfigError(f"Cannot write to immutable scope {self}") raise ConfigError(f"Cannot write to immutable scope {self}")
filename = self.get_section_filename(section) filename = self.get_section_filename(section)
data = self.get_section(section) data = self.get_section(section)
@@ -280,7 +277,7 @@ def get_section(self, section: str) -> Optional[YamlConfigDict]:
def _write_section(self, section: str) -> None: def _write_section(self, section: str) -> None:
if not self.writable: if not self.writable:
raise spack.error.ConfigError(f"Cannot write to immutable scope {self}") raise ConfigError(f"Cannot write to immutable scope {self}")
data_to_write: Optional[YamlConfigDict] = self._raw_data data_to_write: Optional[YamlConfigDict] = self._raw_data
# If there is no existing data, this section SingleFileScope has never # If there is no existing data, this section SingleFileScope has never
@@ -708,7 +705,7 @@ def print_section(self, section: str, blame: bool = False, *, scope=None) -> Non
data[section] = self.get_config(section, scope=scope) data[section] = self.get_config(section, scope=scope)
syaml.dump_config(data, stream=sys.stdout, default_flow_style=False, blame=blame) syaml.dump_config(data, stream=sys.stdout, default_flow_style=False, blame=blame)
except (syaml.SpackYAMLError, OSError) as e: except (syaml.SpackYAMLError, OSError) as e:
raise spack.error.ConfigError(f"cannot read '{section}' configuration") from e raise ConfigError(f"cannot read '{section}' configuration") from e
@contextlib.contextmanager @contextlib.contextmanager
@@ -810,7 +807,7 @@ def _add_command_line_scopes(
_add_platform_scope(cfg, name, path, writable=False) _add_platform_scope(cfg, name, path, writable=False)
continue continue
else: else:
raise spack.error.ConfigError(f"Invalid configuration scope: {path}") raise ConfigError(f"Invalid configuration scope: {path}")
for scope in manifest.env_config_scopes: for scope in manifest.env_config_scopes:
scope.name = f"{name}:{scope.name}" scope.name = f"{name}:{scope.name}"
@@ -1022,7 +1019,7 @@ def change_or_add(
if found: if found:
update_fn(section) update_fn(section)
CONFIG.set(section_name, section, scope=scope) spack.config.set(section_name, section, scope=scope)
return return
# If no scope meets the criteria specified by ``find_fn``, # If no scope meets the criteria specified by ``find_fn``,
@@ -1035,14 +1032,14 @@ def change_or_add(
break break
if found: if found:
CONFIG.set(section_name, section, scope=scope) spack.config.set(section_name, section, scope=scope)
return return
# If no scopes define any config for the named section, then # If no scopes define any config for the named section, then
# modify the highest-priority scope. # modify the highest-priority scope.
scope, section = configs_by_section[0] scope, section = configs_by_section[0]
update_fn(section) update_fn(section)
CONFIG.set(section_name, section, scope=scope) spack.config.set(section_name, section, scope=scope)
def update_all(section_name: str, change_fn: Callable[[str], bool]) -> None: def update_all(section_name: str, change_fn: Callable[[str], bool]) -> None:
@@ -1054,7 +1051,7 @@ def update_all(section_name: str, change_fn: Callable[[str], bool]) -> None:
for scope, section in configs_by_section: for scope, section in configs_by_section:
modified = change_fn(section) modified = change_fn(section)
if modified: if modified:
CONFIG.set(section_name, section, scope=scope) spack.config.set(section_name, section, scope=scope)
def _validate_section_name(section: str) -> None: def _validate_section_name(section: str) -> None:
@@ -1228,7 +1225,7 @@ def get_valid_type(path):
return types[schema_type]() return types[schema_type]()
else: else:
return type(None) return type(None)
raise spack.error.ConfigError(f"Cannot determine valid type for path '{path}'.") raise ConfigError(f"Cannot determine valid type for path '{path}'.")
def remove_yaml(dest, source): def remove_yaml(dest, source):
@@ -1271,7 +1268,7 @@ def they_are(t):
unmerge = sk in dest unmerge = sk in dest
old_dest_value = dest.pop(sk, None) old_dest_value = dest.pop(sk, None)
if unmerge and not _override(sk): if unmerge and not spack.config._override(sk):
dest[sk] = remove_yaml(old_dest_value, sv) dest[sk] = remove_yaml(old_dest_value, sv)
return dest return dest
@@ -1708,48 +1705,40 @@ def get_mark_from_yaml_data(obj):
return mark return mark
def determine_number_of_jobs( def parse_spec_from_yaml_string(string: str) -> "spack.spec.Spec":
*, """Parse a spec from YAML and add file/line info to errors, if it's available.
parallel: bool = False,
max_cpus: int = cpus_available(), Parse a ``Spec`` from the supplied string, but also intercept any syntax errors and
config: Optional[Configuration] = None, add file/line information for debugging using file/line annotations from the string.
) -> int:
Arguments:
string: a string representing a ``Spec`` from config YAML.
""" """
Packages that require sequential builds need 1 job. Otherwise we use the
number of jobs set on the command line. If not set, then we use the config
defaults (which is usually set through the builtin config scope), but we
cap to the number of CPUs available to avoid oversubscription.
Parameters:
parallel: true when package supports parallel builds
max_cpus: maximum number of CPUs to use (defaults to cpus_available())
config: configuration object (defaults to global config)
"""
if not parallel:
return 1
cfg = config or CONFIG
# Command line overrides all
try: try:
command_line = cfg.get("config:build_jobs", default=None, scope="command_line") spec = spack.spec.Spec(string)
if command_line is not None: return spec
return command_line except spack.parser.SpecSyntaxError as e:
except ValueError: mark = spack.config.get_mark_from_yaml_data(string)
pass if mark:
msg = f"{mark.name}:{mark.line + 1}: {str(e)}"
return min(max_cpus, cfg.get("config:build_jobs", 16)) raise spack.parser.SpecSyntaxError(msg) from e
raise e
class ConfigSectionError(spack.error.ConfigError): class ConfigError(SpackError):
"""Superclass for all Spack config related errors."""
class ConfigSectionError(ConfigError):
"""Error for referring to a bad config section name in a configuration.""" """Error for referring to a bad config section name in a configuration."""
class ConfigFileError(spack.error.ConfigError): class ConfigFileError(ConfigError):
"""Issue reading or accessing a configuration file.""" """Issue reading or accessing a configuration file."""
class ConfigFormatError(spack.error.ConfigError): class ConfigFormatError(ConfigError):
"""Raised when a configuration format does not match its schema.""" """Raised when a configuration format does not match its schema."""
def __init__( def __init__(

View File

@@ -6,7 +6,6 @@
convenience functions. convenience functions.
""" """
import copy import copy
import shlex
from collections import namedtuple from collections import namedtuple
from typing import Optional from typing import Optional
@@ -16,7 +15,7 @@
import spack.tengine as tengine import spack.tengine as tengine
import spack.util.spack_yaml as syaml import spack.util.spack_yaml as syaml
from .images import ( from ..images import (
bootstrap_template_for, bootstrap_template_for,
build_info, build_info,
checkout_command, checkout_command,
@@ -309,54 +308,7 @@ def __call__(self):
return t.render(**self.to_dict()) return t.render(**self.to_dict())
@writer("docker") # Import after function definition all the modules in this package,
class DockerContext(PathContext): # so that registration of writers will happen automatically
"""Context used to instantiate a Dockerfile""" from . import docker # noqa: F401 E402
from . import singularity # noqa: F401 E402
#: Name of the template used for Dockerfiles
template_name = "container/Dockerfile"
@tengine.context_property
def manifest(self):
manifest_str = super().manifest
# Docker doesn't support HEREDOC, so we need to resort to
# a horrible echo trick to have the manifest in the Dockerfile
echoed_lines = []
for idx, line in enumerate(manifest_str.split("\n")):
quoted_line = shlex.quote(line)
if idx == 0:
echoed_lines.append("&& (echo " + quoted_line + " \\")
continue
echoed_lines.append("&& echo " + quoted_line + " \\")
echoed_lines[-1] = echoed_lines[-1].replace(" \\", ")")
return "\n".join(echoed_lines)
@writer("singularity")
class SingularityContext(PathContext):
"""Context used to instantiate a Singularity definition file"""
#: Name of the template used for Singularity definition files
template_name = "container/singularity.def"
@property
def singularity_config(self):
return self.container_config.get("singularity", {})
@tengine.context_property
def runscript(self):
return self.singularity_config.get("runscript", "")
@tengine.context_property
def startscript(self):
return self.singularity_config.get("startscript", "")
@tengine.context_property
def test(self):
return self.singularity_config.get("test", "")
@tengine.context_property
def help(self):
return self.singularity_config.get("help", "")

View File

@@ -0,0 +1,34 @@
# 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)
import shlex
import spack.tengine as tengine
from . import PathContext, writer
@writer("docker")
class DockerContext(PathContext):
"""Context used to instantiate a Dockerfile"""
#: Name of the template used for Dockerfiles
template_name = "container/Dockerfile"
@tengine.context_property
def manifest(self):
manifest_str = super().manifest
# Docker doesn't support HEREDOC, so we need to resort to
# a horrible echo trick to have the manifest in the Dockerfile
echoed_lines = []
for idx, line in enumerate(manifest_str.split("\n")):
quoted_line = shlex.quote(line)
if idx == 0:
echoed_lines.append("&& (echo " + quoted_line + " \\")
continue
echoed_lines.append("&& echo " + quoted_line + " \\")
echoed_lines[-1] = echoed_lines[-1].replace(" \\", ")")
return "\n".join(echoed_lines)

View File

@@ -0,0 +1,35 @@
# 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)
import spack.tengine as tengine
from . import PathContext, writer
@writer("singularity")
class SingularityContext(PathContext):
"""Context used to instantiate a Singularity definition file"""
#: Name of the template used for Singularity definition files
template_name = "container/singularity.def"
@property
def singularity_config(self):
return self.container_config.get("singularity", {})
@tengine.context_property
def runscript(self):
return self.singularity_config.get("runscript", "")
@tengine.context_property
def startscript(self):
return self.singularity_config.get("startscript", "")
@tengine.context_property
def test(self):
return self.singularity_config.get("test", "")
@tengine.context_property
def help(self):
return self.singularity_config.get("help", "")

View File

@@ -132,7 +132,7 @@ def spec_from_entry(entry):
variant_strs = list() variant_strs = list()
for name, value in entry["parameters"].items(): for name, value in entry["parameters"].items():
# TODO: also ensure that the variant value is valid? # TODO: also ensure that the variant value is valid?
if not pkg_cls.has_variant(name): if not (name in pkg_cls.variants):
tty.debug( tty.debug(
"Omitting variant {0} for entry {1}/{2}".format( "Omitting variant {0} for entry {1}/{2}".format(
name, entry["name"], entry["hash"][:7] name, entry["name"], entry["hash"][:7]

View File

@@ -25,10 +25,8 @@
import llnl.util.tty import llnl.util.tty
import spack.config import spack.config
import spack.error
import spack.operating_systems.windows_os as winOs import spack.operating_systems.windows_os as winOs
import spack.spec import spack.spec
import spack.util.environment
import spack.util.spack_yaml import spack.util.spack_yaml
import spack.util.windows_registry import spack.util.windows_registry

View File

@@ -18,12 +18,10 @@
import llnl.util.lang import llnl.util.lang
import llnl.util.tty import llnl.util.tty
import spack.spec
import spack.util.elf as elf_utils import spack.util.elf as elf_utils
import spack.util.environment import spack.util.environment
import spack.util.environment as environment import spack.util.environment as environment
import spack.util.ld_so_conf import spack.util.ld_so_conf
import spack.util.parallel
from .common import ( from .common import (
WindowsCompilerExternalPaths, WindowsCompilerExternalPaths,
@@ -408,7 +406,7 @@ def by_path(
result = collections.defaultdict(list) result = collections.defaultdict(list)
repository = spack.repo.PATH.ensure_unwrapped() repository = spack.repo.PATH.ensure_unwrapped()
with spack.util.parallel.make_concurrent_executor(max_workers, require_fork=False) as executor: with concurrent.futures.ProcessPoolExecutor(max_workers=max_workers) as executor:
for pkg in packages_to_search: for pkg in packages_to_search:
executable_future = executor.submit( executable_future = executor.submit(
executables_finder.find, executables_finder.find,

View File

@@ -40,8 +40,10 @@ class OpenMpi(Package):
import llnl.util.tty.color import llnl.util.tty.color
import spack.deptypes as dt import spack.deptypes as dt
import spack.error
import spack.patch import spack.patch
import spack.spec import spack.spec
import spack.url
import spack.util.crypto import spack.util.crypto
import spack.variant import spack.variant
from spack.dependency import Dependency from spack.dependency import Dependency
@@ -78,6 +80,7 @@ class OpenMpi(Package):
"redistribute", "redistribute",
] ]
_patch_order_index = 0 _patch_order_index = 0
@@ -673,25 +676,22 @@ def _raise_default_not_set(pkg):
def _execute_variant(pkg): def _execute_variant(pkg):
when_spec = _make_when_spec(when) when_spec = _make_when_spec(when)
when_specs = [when_spec]
if not re.match(spack.spec.IDENTIFIER_RE, name): if not re.match(spack.spec.IDENTIFIER_RE, name):
directive = "variant" directive = "variant"
msg = "Invalid variant name in {0}: '{1}'" msg = "Invalid variant name in {0}: '{1}'"
raise DirectiveError(directive, msg.format(pkg.name, name)) raise DirectiveError(directive, msg.format(pkg.name, name))
# variants are stored by condition then by name (so only the last variant of a if name in pkg.variants:
# given name takes precedence *per condition*). # We accumulate when specs, but replace the rest of the variant
# NOTE: variant defaults and values can conflict if when conditions overlap. # with the newer values
variants_by_name = pkg.variants.setdefault(when_spec, {}) _, orig_when = pkg.variants[name]
variants_by_name[name] = spack.variant.Variant( when_specs += orig_when
name=name,
default=default, pkg.variants[name] = (
description=description, spack.variant.Variant(name, default, description, values, multi, validator, sticky),
values=values, when_specs,
multi=multi,
validator=validator,
sticky=sticky,
precedence=pkg.num_variant_definitions(),
) )
return _execute_variant return _execute_variant

View File

@@ -16,9 +16,7 @@
import spack.config import spack.config
import spack.hash_types as ht import spack.hash_types as ht
import spack.projections
import spack.spec import spack.spec
import spack.store
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
from spack.error import SpackError from spack.error import SpackError

View File

@@ -24,23 +24,25 @@
from llnl.util.link_tree import ConflictingSpecsError from llnl.util.link_tree import ConflictingSpecsError
from llnl.util.symlink import readlink, symlink from llnl.util.symlink import readlink, symlink
import spack
import spack.caches import spack.caches
import spack.cmd
import spack.compilers import spack.compilers
import spack.concretize import spack.concretize
import spack.config import spack.config
import spack.deptypes as dt import spack.deptypes as dt
import spack.environment
import spack.error import spack.error
import spack.fetch_strategy
import spack.filesystem_view as fsv import spack.filesystem_view as fsv
import spack.hash_types as ht import spack.hash_types as ht
import spack.hooks
import spack.main
import spack.paths import spack.paths
import spack.repo import spack.repo
import spack.schema.env import spack.schema.env
import spack.schema.merged
import spack.spec import spack.spec
import spack.spec_list import spack.stage
import spack.store import spack.store
import spack.subprocess_context
import spack.user_environment as uenv import spack.user_environment as uenv
import spack.util.cpus import spack.util.cpus
import spack.util.environment import spack.util.environment
@@ -51,6 +53,7 @@
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
import spack.util.spack_yaml as syaml import spack.util.spack_yaml as syaml
import spack.util.url import spack.util.url
import spack.version
from spack import traverse from spack import traverse
from spack.installer import PackageInstaller from spack.installer import PackageInstaller
from spack.schema.env import TOP_LEVEL_KEY from spack.schema.env import TOP_LEVEL_KEY
@@ -1648,7 +1651,7 @@ def _concretize_separately(self, tests=False):
# Solve the environment in parallel on Linux # Solve the environment in parallel on Linux
start = time.time() start = time.time()
num_procs = min(len(args), spack.config.determine_number_of_jobs(parallel=True)) num_procs = min(len(args), spack.util.cpus.determine_number_of_jobs(parallel=True))
# TODO: support parallel concretization on macOS and Windows # TODO: support parallel concretization on macOS and Windows
msg = "Starting concretization" msg = "Starting concretization"
@@ -2176,7 +2179,7 @@ def _to_lockfile_dict(self):
root_specs = self._concrete_roots_dict() root_specs = self._concrete_roots_dict()
spack_dict = {"version": spack.spack_version} spack_dict = {"version": spack.spack_version}
spack_commit = spack.get_spack_commit() spack_commit = spack.main.get_spack_commit()
if spack_commit: if spack_commit:
spack_dict["type"] = "git" spack_dict["type"] = "git"
spack_dict["commit"] = spack_commit spack_dict["commit"] = spack_commit

View File

@@ -132,60 +132,3 @@ def __init__(self, provided, required, constraint_type):
class FetchError(SpackError): class FetchError(SpackError):
"""Superclass for fetch-related errors.""" """Superclass for fetch-related errors."""
class NoSuchPatchError(SpackError):
"""Raised when a patch file doesn't exist."""
class PatchDirectiveError(SpackError):
"""Raised when the wrong arguments are suppled to the patch directive."""
class PatchLookupError(NoSuchPatchError):
"""Raised when a patch file cannot be located from sha256."""
class SpecSyntaxError(Exception):
"""Base class for Spec syntax errors"""
class PackageError(SpackError):
"""Raised when something is wrong with a package definition."""
def __init__(self, message, long_msg=None):
super().__init__(message, long_msg)
class NoURLError(PackageError):
"""Raised when someone tries to build a URL for a package with no URLs."""
def __init__(self, cls):
super().__init__("Package %s has no version with a URL." % cls.__name__)
class InstallError(SpackError):
"""Raised when something goes wrong during install or uninstall.
The error can be annotated with a ``pkg`` attribute to allow the
caller to get the package for which the exception was raised.
"""
def __init__(self, message, long_msg=None, pkg=None):
super().__init__(message, long_msg)
self.pkg = pkg
class ConfigError(SpackError):
"""Superclass for all Spack config related errors."""
class StopPhase(SpackError):
"""Pickle-able exception to control stopped builds."""
def __reduce__(self):
return _make_stop_phase, (self.message, self.long_message)
def _make_stop_phase(msg, long_msg):
return StopPhase(msg, long_msg)

View File

@@ -17,7 +17,6 @@
import llnl.util.lang import llnl.util.lang
import spack.cmd
import spack.config import spack.config
import spack.error import spack.error
import spack.util.path import spack.util.path

View File

@@ -46,6 +46,7 @@
import spack.config import spack.config
import spack.error import spack.error
import spack.oci.opener import spack.oci.opener
import spack.url
import spack.util.archive import spack.util.archive
import spack.util.crypto as crypto import spack.util.crypto as crypto
import spack.util.git import spack.util.git
@@ -1541,7 +1542,7 @@ def _extrapolate(pkg, version):
"""Create a fetcher from an extrapolated URL for this version.""" """Create a fetcher from an extrapolated URL for this version."""
try: try:
return URLFetchStrategy(url=pkg.url_for_version(version), fetch_options=pkg.fetch_options) return URLFetchStrategy(url=pkg.url_for_version(version), fetch_options=pkg.fetch_options)
except spack.error.NoURLError: except spack.package_base.NoURLError:
raise ExtrapolationError( raise ExtrapolationError(
f"Can't extrapolate a URL for version {version} because " f"Can't extrapolate a URL for version {version} because "
f"package {pkg.name} defines no URLs" f"package {pkg.name} defines no URLs"

View File

@@ -46,7 +46,6 @@
import spack.repo import spack.repo
import spack.spec import spack.spec
import spack.tengine import spack.tengine
import spack.traverse
def find(seq, predicate): def find(seq, predicate):

View File

@@ -17,23 +17,14 @@
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import llnl.util.tty as tty import llnl.util.tty as tty
import llnl.util.tty.log
from llnl.string import plural from llnl.string import plural
from llnl.util.lang import nullcontext from llnl.util.lang import nullcontext
from llnl.util.tty.color import colorize from llnl.util.tty.color import colorize
import spack.build_environment
import spack.builder
import spack.config
import spack.error import spack.error
import spack.package_base
import spack.paths import spack.paths
import spack.repo
import spack.spec
import spack.util.executable
import spack.util.path
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
from spack.error import InstallError from spack.installer import InstallError
from spack.spec import Spec from spack.spec import Spec
from spack.util.prefix import Prefix from spack.util.prefix import Prefix
@@ -51,7 +42,7 @@
ListOrStringType = Union[str, List[str]] ListOrStringType = Union[str, List[str]]
LogType = Union[llnl.util.tty.log.nixlog, llnl.util.tty.log.winlog] LogType = Union["tty.log.nixlog", "tty.log.winlog"]
Pb = TypeVar("Pb", bound="spack.package_base.PackageBase") Pb = TypeVar("Pb", bound="spack.package_base.PackageBase")
PackageObjectOrClass = Union[Pb, Type[Pb]] PackageObjectOrClass = Union[Pb, Type[Pb]]
@@ -119,7 +110,7 @@ def cache_extra_test_sources(pkg: Pb, srcs: ListOrStringType):
location(s) under the install testing directory. location(s) under the install testing directory.
Raises: Raises:
spack.error.InstallError: if any of the source paths are absolute spack.installer.InstallError: if any of the source paths are absolute
or do not exist or do not exist
under the build stage under the build stage
""" """
@@ -289,7 +280,7 @@ def __init__(self, pkg: Pb):
def logger(self) -> Optional[LogType]: def logger(self) -> Optional[LogType]:
"""The current logger or, if none, sets to one.""" """The current logger or, if none, sets to one."""
if not self._logger: if not self._logger:
self._logger = llnl.util.tty.log.log_output(self.test_log_file) self._logger = tty.log.log_output(self.test_log_file)
return self._logger return self._logger
@@ -306,7 +297,7 @@ def test_logger(self, verbose: bool = False, externals: bool = False):
fs.touch(self.test_log_file) # Otherwise log_parse complains fs.touch(self.test_log_file) # Otherwise log_parse complains
fs.set_install_permissions(self.test_log_file) fs.set_install_permissions(self.test_log_file)
with llnl.util.tty.log.log_output(self.test_log_file, verbose) as self._logger: with tty.log.log_output(self.test_log_file, verbose) as self._logger:
with self.logger.force_echo(): # type: ignore[union-attr] with self.logger.force_echo(): # type: ignore[union-attr]
tty.msg("Testing package " + colorize(r"@*g{" + self.pkg_id + r"}")) tty.msg("Testing package " + colorize(r"@*g{" + self.pkg_id + r"}"))

View File

@@ -48,6 +48,7 @@
import spack.binary_distribution as binary_distribution import spack.binary_distribution as binary_distribution
import spack.build_environment import spack.build_environment
import spack.compilers
import spack.config import spack.config
import spack.database import spack.database
import spack.deptypes as dt import spack.deptypes as dt
@@ -889,7 +890,7 @@ def __init__(
# ensure priority queue invariants when tasks are "removed" from the # ensure priority queue invariants when tasks are "removed" from the
# queue. # queue.
if status == STATUS_REMOVED: if status == STATUS_REMOVED:
raise spack.error.InstallError( raise InstallError(
f"Cannot create a build task for {self.pkg_id} with status '{status}'", pkg=pkg f"Cannot create a build task for {self.pkg_id} with status '{status}'", pkg=pkg
) )
@@ -1160,7 +1161,7 @@ def _check_deps_status(self, request: BuildRequest) -> None:
if spack.store.STORE.failure_tracker.has_failed(dep): if spack.store.STORE.failure_tracker.has_failed(dep):
action = "'spack install' the dependency" action = "'spack install' the dependency"
msg = f"{dep_id} is marked as an install failure: {action}" msg = f"{dep_id} is marked as an install failure: {action}"
raise spack.error.InstallError(err.format(request.pkg_id, msg), pkg=dep_pkg) raise InstallError(err.format(request.pkg_id, msg), pkg=dep_pkg)
# Attempt to get a read lock to ensure another process does not # Attempt to get a read lock to ensure another process does not
# uninstall the dependency while the requested spec is being # uninstall the dependency while the requested spec is being
@@ -1168,7 +1169,7 @@ def _check_deps_status(self, request: BuildRequest) -> None:
ltype, lock = self._ensure_locked("read", dep_pkg) ltype, lock = self._ensure_locked("read", dep_pkg)
if lock is None: if lock is None:
msg = f"{dep_id} is write locked by another process" msg = f"{dep_id} is write locked by another process"
raise spack.error.InstallError(err.format(request.pkg_id, msg), pkg=request.pkg) raise InstallError(err.format(request.pkg_id, msg), pkg=request.pkg)
# Flag external and upstream packages as being installed # Flag external and upstream packages as being installed
if dep_pkg.spec.external or dep_pkg.spec.installed_upstream: if dep_pkg.spec.external or dep_pkg.spec.installed_upstream:
@@ -1220,7 +1221,7 @@ def _prepare_for_install(self, task: BuildTask) -> None:
if not installed_in_db: if not installed_in_db:
# Ensure there is no other installed spec with the same prefix dir # Ensure there is no other installed spec with the same prefix dir
if spack.store.STORE.db.is_occupied_install_prefix(task.pkg.spec.prefix): if spack.store.STORE.db.is_occupied_install_prefix(task.pkg.spec.prefix):
raise spack.error.InstallError( raise InstallError(
f"Install prefix collision for {task.pkg_id}", f"Install prefix collision for {task.pkg_id}",
long_msg=f"Prefix directory {task.pkg.spec.prefix} already " long_msg=f"Prefix directory {task.pkg.spec.prefix} already "
"used by another installed spec.", "used by another installed spec.",
@@ -1488,9 +1489,7 @@ def _install_task(self, task: BuildTask, install_status: InstallStatus) -> None:
self._update_installed(task) self._update_installed(task)
return return
elif cache_only: elif cache_only:
raise spack.error.InstallError( raise InstallError("No binary found when cache-only was specified", pkg=pkg)
"No binary found when cache-only was specified", pkg=pkg
)
else: else:
tty.msg(f"No binary for {pkg_id} found: installing from source") tty.msg(f"No binary for {pkg_id} found: installing from source")
@@ -1517,7 +1516,7 @@ def _install_task(self, task: BuildTask, install_status: InstallStatus) -> None:
# the database, so that we don't need to re-read from file. # the database, so that we don't need to re-read from file.
spack.store.STORE.db.add(pkg.spec, explicit=explicit) spack.store.STORE.db.add(pkg.spec, explicit=explicit)
except spack.error.StopPhase as e: except spack.build_environment.StopPhase as e:
# A StopPhase exception means that do_install was asked to # A StopPhase exception means that do_install was asked to
# stop early from clients, and is not an error at this point # stop early from clients, and is not an error at this point
pid = f"{self.pid}: " if tty.show_pid() else "" pid = f"{self.pid}: " if tty.show_pid() else ""
@@ -1850,7 +1849,7 @@ def install(self) -> None:
tty.warn(f"{pkg_id} does NOT actually have any uninstalled deps left") tty.warn(f"{pkg_id} does NOT actually have any uninstalled deps left")
dep_str = "dependencies" if task.priority > 1 else "dependency" dep_str = "dependencies" if task.priority > 1 else "dependency"
raise spack.error.InstallError( raise InstallError(
f"Cannot proceed with {pkg_id}: {task.priority} uninstalled " f"Cannot proceed with {pkg_id}: {task.priority} uninstalled "
f"{dep_str}: {','.join(task.uninstalled_deps)}", f"{dep_str}: {','.join(task.uninstalled_deps)}",
pkg=pkg, pkg=pkg,
@@ -1872,7 +1871,7 @@ def install(self) -> None:
self._update_failed(task) self._update_failed(task)
if self.fail_fast: if self.fail_fast:
raise spack.error.InstallError(fail_fast_err, pkg=pkg) raise InstallError(fail_fast_err, pkg=pkg)
continue continue
@@ -2001,7 +2000,7 @@ def install(self) -> None:
) )
# Terminate if requested to do so on the first failure. # Terminate if requested to do so on the first failure.
if self.fail_fast: if self.fail_fast:
raise spack.error.InstallError(f"{fail_fast_err}: {str(exc)}", pkg=pkg) raise InstallError(f"{fail_fast_err}: {str(exc)}", pkg=pkg)
# Terminate when a single build request has failed, or summarize errors later. # Terminate when a single build request has failed, or summarize errors later.
if task.is_build_request: if task.is_build_request:
@@ -2053,7 +2052,7 @@ def install(self) -> None:
f"missing package ({ids[0]}) from {', '.join(ids)}" f"missing package ({ids[0]}) from {', '.join(ids)}"
) )
raise spack.error.InstallError( raise InstallError(
"Installation request failed. Refer to reported errors for failing package(s).", "Installation request failed. Refer to reported errors for failing package(s).",
pkg=pkg, pkg=pkg,
) )
@@ -2319,21 +2318,33 @@ def install(self):
raise e.inner_exception raise e.inner_exception
class BadInstallPhase(spack.error.InstallError): class InstallError(spack.error.SpackError):
"""Raised when something goes wrong during install or uninstall.
The error can be annotated with a ``pkg`` attribute to allow the
caller to get the package for which the exception was raised.
"""
def __init__(self, message, long_msg=None, pkg=None):
super().__init__(message, long_msg)
self.pkg = pkg
class BadInstallPhase(InstallError):
"""Raised for an install phase option is not allowed for a package.""" """Raised for an install phase option is not allowed for a package."""
def __init__(self, pkg_name, phase): def __init__(self, pkg_name, phase):
super().__init__(f"'{phase}' is not a valid phase for package {pkg_name}") super().__init__(f"'{phase}' is not a valid phase for package {pkg_name}")
class ExternalPackageError(spack.error.InstallError): class ExternalPackageError(InstallError):
"""Raised by install() when a package is only for external use.""" """Raised by install() when a package is only for external use."""
class InstallLockError(spack.error.InstallError): class InstallLockError(InstallError):
"""Raised during install when something goes wrong with package locking.""" """Raised during install when something goes wrong with package locking."""
class UpstreamPackageError(spack.error.InstallError): class UpstreamPackageError(InstallError):
"""Raised during install when something goes wrong with an upstream """Raised during install when something goes wrong with an upstream
package.""" package."""

View File

@@ -9,8 +9,6 @@
after the system path is set up. after the system path is set up.
""" """
import argparse import argparse
# import spack.modules.common
import inspect import inspect
import io import io
import operator import operator
@@ -34,20 +32,20 @@
import llnl.util.tty.color as color import llnl.util.tty.color as color
from llnl.util.tty.log import log_output from llnl.util.tty.log import log_output
import spack
import spack.cmd import spack.cmd
import spack.config import spack.config
import spack.environment as ev import spack.environment as ev
import spack.error
import spack.modules import spack.modules
import spack.paths import spack.paths
import spack.platforms import spack.platforms
import spack.repo import spack.repo
import spack.solver.asp
import spack.spec import spack.spec
import spack.store import spack.store
import spack.util.debug import spack.util.debug
import spack.util.environment import spack.util.environment
import spack.util.lock import spack.util.git
import spack.util.path
from spack.error import SpackError from spack.error import SpackError
#: names of profile statistics #: names of profile statistics
@@ -100,18 +98,75 @@
#: Properties that commands are required to set. #: Properties that commands are required to set.
required_command_properties = ["level", "section", "description"] required_command_properties = ["level", "section", "description"]
#: Recorded directory where spack command was originally invoked
spack_working_dir = None
spack_ld_library_path = os.environ.get("LD_LIBRARY_PATH", "") spack_ld_library_path = os.environ.get("LD_LIBRARY_PATH", "")
#: Whether to print backtraces on error #: Whether to print backtraces on error
SHOW_BACKTRACE = False SHOW_BACKTRACE = False
def set_working_dir():
"""Change the working directory to getcwd, or spack prefix if no cwd."""
global spack_working_dir
try:
spack_working_dir = os.getcwd()
except OSError:
os.chdir(spack.paths.prefix)
spack_working_dir = spack.paths.prefix
def add_all_commands(parser): def add_all_commands(parser):
"""Add all spack subcommands to the parser.""" """Add all spack subcommands to the parser."""
for cmd in spack.cmd.all_commands(): for cmd in spack.cmd.all_commands():
parser.add_command(cmd) parser.add_command(cmd)
def get_spack_commit():
"""Get the Spack git commit sha.
Returns:
(str or None) the commit sha if available, otherwise None
"""
git_path = os.path.join(spack.paths.prefix, ".git")
if not os.path.exists(git_path):
return None
git = spack.util.git.git()
if not git:
return None
rev = git(
"-C",
spack.paths.prefix,
"rev-parse",
"HEAD",
output=str,
error=os.devnull,
fail_on_error=False,
)
if git.returncode != 0:
return None
match = re.match(r"[a-f\d]{7,}$", rev)
return match.group(0) if match else None
def get_version():
"""Get a descriptive version of this instance of Spack.
Outputs '<PEP440 version> (<git commit sha>)'.
The commit sha is only added when available.
"""
version = spack.spack_version
commit = get_spack_commit()
if commit:
version += " ({0})".format(commit)
return version
def index_commands(): def index_commands():
"""create an index of commands by section for this help level""" """create an index of commands by section for this help level"""
index = {} index = {}
@@ -755,8 +810,6 @@ def print_setup_info(*info):
This is in ``main.py`` to make it fast; the setup scripts need to This is in ``main.py`` to make it fast; the setup scripts need to
invoke spack in login scripts, and it needs to be quick. invoke spack in login scripts, and it needs to be quick.
""" """
import spack.modules.common
shell = "csh" if "csh" in info else "sh" shell = "csh" if "csh" in info else "sh"
def shell_set(var, value): def shell_set(var, value):
@@ -901,7 +954,7 @@ def _main(argv=None):
# version is special as it does not require a command or loading and additional infrastructure # version is special as it does not require a command or loading and additional infrastructure
if args.version: if args.version:
print(spack.get_version()) print(get_version())
return 0 return 0
# ------------------------------------------------------------------------ # ------------------------------------------------------------------------
@@ -986,7 +1039,7 @@ def finish_parse_and_run(parser, cmd_name, main_args, env_format_error):
raise env_format_error raise env_format_error
# many operations will fail without a working directory. # many operations will fail without a working directory.
spack.paths.set_working_dir() set_working_dir()
# now we can actually execute the command. # now we can actually execute the command.
if main_args.spack_profile or main_args.sorted_profile: if main_args.spack_profile or main_args.sorted_profile:

View File

@@ -29,7 +29,6 @@
import spack.config import spack.config
import spack.error import spack.error
import spack.fetch_strategy import spack.fetch_strategy
import spack.mirror
import spack.oci.image import spack.oci.image
import spack.repo import spack.repo
import spack.spec import spack.spec

View File

@@ -46,7 +46,6 @@
import spack.deptypes as dt import spack.deptypes as dt
import spack.environment import spack.environment
import spack.error import spack.error
import spack.modules
import spack.paths import spack.paths
import spack.projections as proj import spack.projections as proj
import spack.repo import spack.repo

View File

@@ -15,10 +15,17 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.binary_distribution
import spack.config
import spack.error
import spack.fetch_strategy import spack.fetch_strategy
import spack.mirror import spack.mirror
import spack.oci.opener import spack.oci.opener
import spack.repo
import spack.spec
import spack.stage import spack.stage
import spack.traverse
import spack.util.crypto
import spack.util.url import spack.util.url
from .image import Digest, ImageReference from .image import Digest, ImageReference
@@ -30,6 +37,11 @@ class Blob(NamedTuple):
size: int size: int
def create_tarball(spec: spack.spec.Spec, tarfile_path):
buildinfo = spack.binary_distribution.get_buildinfo_dict(spec)
return spack.binary_distribution._do_create_tarball(tarfile_path, spec.prefix, buildinfo)
def with_query_param(url: str, param: str, value: str) -> str: def with_query_param(url: str, param: str, value: str) -> str:
"""Add a query parameter to a URL """Add a query parameter to a URL

View File

@@ -22,6 +22,7 @@
import spack.config import spack.config
import spack.mirror import spack.mirror
import spack.parser import spack.parser
import spack.repo
import spack.util.web import spack.util.web
from .image import ImageReference from .image import ImageReference

View File

@@ -11,8 +11,6 @@
from os import chdir, environ, getcwd, makedirs, mkdir, remove, removedirs from os import chdir, environ, getcwd, makedirs, mkdir, remove, removedirs
from shutil import move, rmtree from shutil import move, rmtree
from spack.error import InstallError
# Emulate some shell commands for convenience # Emulate some shell commands for convenience
env = environ env = environ
cd = chdir cd = chdir
@@ -75,7 +73,6 @@
from spack.build_systems.waf import WafPackage from spack.build_systems.waf import WafPackage
from spack.build_systems.xorg import XorgPackage from spack.build_systems.xorg import XorgPackage
from spack.builder import run_after, run_before from spack.builder import run_after, run_before
from spack.config import determine_number_of_jobs
from spack.deptypes import ALL_TYPES as all_deptypes from spack.deptypes import ALL_TYPES as all_deptypes
from spack.directives import * from spack.directives import *
from spack.install_test import ( from spack.install_test import (
@@ -87,7 +84,12 @@
install_test_root, install_test_root,
test_part, test_part,
) )
from spack.installer import ExternalPackageError, InstallLockError, UpstreamPackageError from spack.installer import (
ExternalPackageError,
InstallError,
InstallLockError,
UpstreamPackageError,
)
from spack.mixins import filter_compiler_wrappers from spack.mixins import filter_compiler_wrappers
from spack.multimethod import default_args, when from spack.multimethod import default_args, when
from spack.package_base import ( from spack.package_base import (
@@ -100,6 +102,7 @@
on_package_attributes, on_package_attributes,
) )
from spack.spec import InvalidSpecDetected, Spec from spack.spec import InvalidSpecDetected, Spec
from spack.util.cpus import determine_number_of_jobs
from spack.util.executable import * from spack.util.executable import *
from spack.util.filesystem import file_command, fix_darwin_install_name, mime_type from spack.util.filesystem import file_command, fix_darwin_install_name, mime_type
from spack.variant import ( from spack.variant import (

View File

@@ -33,28 +33,28 @@
from llnl.util.lang import classproperty, memoized from llnl.util.lang import classproperty, memoized
from llnl.util.link_tree import LinkTree from llnl.util.link_tree import LinkTree
import spack.build_environment
import spack.builder
import spack.compilers import spack.compilers
import spack.config import spack.config
import spack.dependency import spack.dependency
import spack.deptypes as dt import spack.deptypes as dt
import spack.directives import spack.directives
import spack.directory_layout
import spack.environment
import spack.error import spack.error
import spack.fetch_strategy as fs import spack.fetch_strategy as fs
import spack.hooks import spack.hooks
import spack.mirror import spack.mirror
import spack.mixins
import spack.multimethod import spack.multimethod
import spack.patch import spack.patch
import spack.paths
import spack.repo import spack.repo
import spack.spec import spack.spec
import spack.store import spack.store
import spack.url import spack.url
import spack.util.environment import spack.util.environment
import spack.util.executable
import spack.util.path import spack.util.path
import spack.util.web import spack.util.web
from spack.error import InstallError, NoURLError, PackageError
from spack.filesystem_view import YamlFilesystemView from spack.filesystem_view import YamlFilesystemView
from spack.install_test import ( from spack.install_test import (
PackageTest, PackageTest,
@@ -64,8 +64,7 @@
cache_extra_test_sources, cache_extra_test_sources,
install_test_root, install_test_root,
) )
from spack.installer import PackageInstaller from spack.installer import InstallError, PackageInstaller
from spack.solver.version_order import concretization_version_order
from spack.stage import DevelopStage, ResourceStage, Stage, StageComposite, compute_stage_name from spack.stage import DevelopStage, ResourceStage, Stage, StageComposite, compute_stage_name
from spack.util.executable import ProcessError, which from spack.util.executable import ProcessError, which
from spack.util.package_hash import package_hash from spack.util.package_hash import package_hash
@@ -117,6 +116,7 @@ def preferred_version(pkg: "PackageBase"):
Arguments: Arguments:
pkg: The package whose versions are to be assessed. pkg: The package whose versions are to be assessed.
""" """
from spack.solver.asp import concretization_version_order
version, _ = max(pkg.versions.items(), key=concretization_version_order) version, _ = max(pkg.versions.items(), key=concretization_version_order)
return version return version
@@ -451,11 +451,10 @@ def _by_name(
else: else:
all_by_name.setdefault(name, []).append(value) all_by_name.setdefault(name, []).append(value)
# this needs to preserve the insertion order of whens
return dict(sorted(all_by_name.items())) return dict(sorted(all_by_name.items()))
def _names(when_indexed_dictionary: WhenDict) -> List[str]: def _names(when_indexed_dictionary):
"""Get sorted names from dicts keyed by when/name.""" """Get sorted names from dicts keyed by when/name."""
all_names = set() all_names = set()
for when, by_name in when_indexed_dictionary.items(): for when, by_name in when_indexed_dictionary.items():
@@ -465,45 +464,6 @@ def _names(when_indexed_dictionary: WhenDict) -> List[str]:
return sorted(all_names) return sorted(all_names)
WhenVariantList = List[Tuple["spack.spec.Spec", "spack.variant.Variant"]]
def _remove_overridden_vdefs(variant_defs: WhenVariantList) -> None:
"""Remove variant defs from the list if their when specs are satisfied by later ones.
Any such variant definitions are *always* overridden by their successor, as it will
match everything the predecessor matches, and the solver will prefer it because of
its higher precedence.
We can just remove these defs from variant definitions and avoid putting them in the
solver. This is also useful for, e.g., `spack info`, where we don't want to show a
variant from a superclass if it is always overridden by a variant defined in a
subclass.
Example::
class ROCmPackage:
variant("amdgpu_target", ..., when="+rocm")
class Hipblas:
variant("amdgpu_target", ...)
The subclass definition *always* overrides the superclass definition here, but they
have different when specs and the subclass def won't just replace the one in the
superclass. In this situation, the subclass should *probably* also have
``when="+rocm"``, but we can't guarantee that will always happen when a vdef is
overridden. So we use this method to remove any overrides we can know statically.
"""
i = 0
while i < len(variant_defs):
when, vdef = variant_defs[i]
if any(when.satisfies(successor) for successor, _ in variant_defs[i + 1 :]):
del variant_defs[i]
else:
i += 1
class RedistributionMixin: class RedistributionMixin:
"""Logic for determining whether a Package is source/binary """Logic for determining whether a Package is source/binary
redistributable. redistributable.
@@ -636,7 +596,7 @@ class PackageBase(WindowsRPath, PackageViewMixin, RedistributionMixin, metaclass
provided: Dict["spack.spec.Spec", Set["spack.spec.Spec"]] provided: Dict["spack.spec.Spec", Set["spack.spec.Spec"]]
provided_together: Dict["spack.spec.Spec", List[Set[str]]] provided_together: Dict["spack.spec.Spec", List[Set[str]]]
patches: Dict["spack.spec.Spec", List["spack.patch.Patch"]] patches: Dict["spack.spec.Spec", List["spack.patch.Patch"]]
variants: Dict["spack.spec.Spec", Dict[str, "spack.variant.Variant"]] variants: Dict[str, Tuple["spack.variant.Variant", "spack.spec.Spec"]]
languages: Dict["spack.spec.Spec", Set[str]] languages: Dict["spack.spec.Spec", Set[str]]
#: By default, packages are not virtual #: By default, packages are not virtual
@@ -790,72 +750,6 @@ def dependency_names(cls):
def dependencies_by_name(cls, when: bool = False): def dependencies_by_name(cls, when: bool = False):
return _by_name(cls.dependencies, when=when) return _by_name(cls.dependencies, when=when)
# Accessors for variants
# External code workingw with Variants should go through the methods below
@classmethod
def variant_names(cls) -> List[str]:
return _names(cls.variants)
@classmethod
def has_variant(cls, name) -> bool:
return any(name in dictionary for dictionary in cls.variants.values())
@classmethod
def num_variant_definitions(cls) -> int:
"""Total number of variant definitions in this class so far."""
return sum(len(variants_by_name) for variants_by_name in cls.variants.values())
@classmethod
def variant_definitions(cls, name: str) -> WhenVariantList:
"""Iterator over (when_spec, Variant) for all variant definitions for a particular name."""
# construct a list of defs sorted by precedence
defs: WhenVariantList = []
for when, variants_by_name in cls.variants.items():
variant_def = variants_by_name.get(name)
if variant_def:
defs.append((when, variant_def))
# With multiple definitions, ensure precedence order and simplify overrides
if len(defs) > 1:
defs.sort(key=lambda v: v[1].precedence)
_remove_overridden_vdefs(defs)
return defs
@classmethod
def variant_items(
cls,
) -> Iterable[Tuple["spack.spec.Spec", Dict[str, "spack.variant.Variant"]]]:
"""Iterate over ``cls.variants.items()`` with overridden definitions removed."""
# Note: This is quadratic in the average number of variant definitions per name.
# That is likely close to linear in practice, as there are few variants with
# multiple definitions (but it matters when they are there).
exclude = {
name: [id(vdef) for _, vdef in cls.variant_definitions(name)]
for name in cls.variant_names()
}
for when, variants_by_name in cls.variants.items():
filtered_variants_by_name = {
name: vdef for name, vdef in variants_by_name.items() if id(vdef) in exclude[name]
}
if filtered_variants_by_name:
yield when, filtered_variants_by_name
def get_variant(self, name: str) -> "spack.variant.Variant":
"""Get the highest precedence variant definition matching this package's spec.
Arguments:
name: name of the variant definition to get
"""
try:
highest_to_lowest = reversed(self.variant_definitions(name))
return next(vdef for when, vdef in highest_to_lowest if self.spec.satisfies(when))
except StopIteration:
raise ValueError(f"No variant '{name}' on spec: {self.spec}")
@classmethod @classmethod
def possible_dependencies( def possible_dependencies(
cls, cls,
@@ -1805,7 +1699,8 @@ def content_hash(self, content=None):
# should this attempt to download the source and set one? This # should this attempt to download the source and set one? This
# probably only happens for source repositories which are # probably only happens for source repositories which are
# referenced by branch name rather than tag or commit ID. # referenced by branch name rather than tag or commit ID.
from_local_sources = "dev_path" in self.spec.variants env = spack.environment.active_environment()
from_local_sources = env and env.is_develop(self.spec)
if self.has_code and not self.spec.external and not from_local_sources: if self.has_code and not self.spec.external and not from_local_sources:
message = "Missing a source id for {s.name}@{s.version}" message = "Missing a source id for {s.name}@{s.version}"
tty.debug(message.format(s=self)) tty.debug(message.format(s=self))
@@ -2689,6 +2584,20 @@ def __init__(self, spec, dependents):
self.dependents = dependents self.dependents = dependents
class PackageError(spack.error.SpackError):
"""Raised when something is wrong with a package definition."""
def __init__(self, message, long_msg=None):
super().__init__(message, long_msg)
class NoURLError(PackageError):
"""Raised when someone tries to build a URL for a package with no URLs."""
def __init__(self, cls):
super().__init__("Package %s has no version with a URL." % cls.__name__)
class InvalidPackageOpError(PackageError): class InvalidPackageOpError(PackageError):
"""Raised when someone tries perform an invalid operation on a package.""" """Raised when someone tries perform an invalid operation on a package."""

View File

@@ -9,7 +9,7 @@
import spack.error import spack.error
import spack.repo import spack.repo
import spack.spec import spack.spec
from spack.error import ConfigError from spack.config import ConfigError
from spack.version import Version from spack.version import Version
_lesser_spec_types = {"compiler": spack.spec.CompilerSpec, "version": Version} _lesser_spec_types = {"compiler": spack.spec.CompilerSpec, "version": Version}
@@ -149,12 +149,10 @@ def preferred_variants(cls, pkg_name):
# Only return variants that are actually supported by the package # Only return variants that are actually supported by the package
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name) pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
spec = spack.spec.Spec(f"{pkg_name} {variants}") spec = spack.spec.Spec("%s %s" % (pkg_name, variants))
return { return dict(
name: variant (name, variant) for name, variant in spec.variants.items() if name in pkg_cls.variants
for name, variant in spec.variants.items() )
if name in pkg_cls.variant_names()
}
def is_spec_buildable(spec): def is_spec_buildable(spec):

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