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
# 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
run: |
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:
=============================================
Chaining Spack Installations (upstreams.yaml)
=============================================
============================
Chaining Spack Installations
============================
You can point your Spack installation to another installation to use any
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).
#. ``hostname``. The hostname of the system (if ``hostname`` is an
executable in the user's PATH).
#. ``hostname``. The hostname of the system.
#. ``full_hostname``. The fully qualified hostname of the system.
^^^^^^^^^^^^^^^^^^^^^^^^
SpecLists as Constraints

View File

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

View File

@@ -2844,7 +2844,8 @@
"asimdrdm",
"lrcpc",
"dcpop",
"asimddp"
"asimddp",
"ssbs"
],
"compilers" : {
"gcc": [
@@ -2941,6 +2942,7 @@
"uscat",
"ilrcpc",
"flagm",
"ssbs",
"dcpodp",
"svei8mm",
"svebf16",
@@ -3008,7 +3010,7 @@
},
{
"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:",
@@ -3064,6 +3066,7 @@
"uscat",
"ilrcpc",
"flagm",
"ssbs",
"sb",
"dcpodp",
"sve2",
@@ -3176,6 +3179,7 @@
"uscat",
"ilrcpc",
"flagm",
"ssbs",
"sb",
"dcpodp",
"sve2",

View File

@@ -3,13 +3,6 @@
#
# 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
__version__ = "0.23.0.dev0"
spack_version = __version__
@@ -26,47 +19,4 @@ def __try_int(v):
spack_version_info = tuple([__try_int(v) for v in __version__.split(".")])
def get_spack_commit() -> Optional[str]:
"""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"]
__all__ = ["spack_version_info", "spack_version"]

View File

@@ -51,10 +51,9 @@ def _search_duplicate_compilers(error_cls):
import llnl.util.lang
import spack.builder
import spack.config
import spack.fetch_strategy
import spack.patch
import spack.paths
import spack.repo
import spack.spec
import spack.util.crypto
@@ -282,7 +281,7 @@ def _avoid_mismatched_variants(error_cls):
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
for variant in current_spec.variants.values():
# Variant does not exist at all
if variant.name not in pkg_cls.variant_names():
if variant.name not in pkg_cls.variants:
summary = (
f"Setting a preference for the '{pkg_name}' package to the "
f"non-existing variant '{variant.name}'"
@@ -291,8 +290,9 @@ def _avoid_mismatched_variants(error_cls):
continue
# Variant cannot accept this value
s = spack.spec.Spec(pkg_name)
try:
spack.variant.prevalidate_variant_value(pkg_cls, variant, strict=True)
s.update_variant_validate(variant.name, variant.value)
except Exception:
summary = (
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 = []
for pkg_name in pkgs:
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
# values are either Value objects (for conditional values) or the values themselves
build_system_names = set(
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]
buildsystem_variant, _ = pkg_cls.variants["build_system"]
buildsystem_names = [getattr(x, "value", x) for x in buildsystem_variant.values]
builder_cls_names = [spack.builder.BUILDER_CLS[x].__name__ for x in buildsystem_names]
module = pkg_cls.module
has_builders_in_package_py = any(
getattr(module, name, False) for name in builder_cls_names
@@ -937,22 +931,20 @@ def check_virtual_with_variants(spec, msg):
# check variants
dependency_variants = dep.spec.variants
for name, variant in dependency_variants.items():
for name, value in dependency_variants.items():
try:
spack.variant.prevalidate_variant_value(
dependency_pkg_cls, variant, dep.spec, strict=True
)
v, _ = dependency_pkg_cls.variants[name]
v.validate_or_raise(value, pkg_cls=dependency_pkg_cls)
except Exception as e:
summary = (
f"{pkg_name}: wrong variant used for dependency in 'depends_on()'"
)
error_msg = str(e)
if isinstance(e, KeyError):
error_msg = (
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(
error_cls(summary=summary, details=[error_msg, f"in {filename}"])
@@ -964,38 +956,39 @@ def check_virtual_with_variants(spec, msg):
@package_directives
def _ensure_variant_defaults_are_parsable(pkgs, error_cls):
"""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 = []
for pkg_name in pkgs:
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
for vname in pkg_cls.variant_names():
for _, variant_def in pkg_cls.variant_definitions(vname):
errors.extend(check_variant(pkg_cls, variant_def, vname))
for variant_name, entry in pkg_cls.variants.items():
variant, _ = entry
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
@@ -1005,11 +998,11 @@ def _ensure_variants_have_descriptions(pkgs, error_cls):
errors = []
for pkg_name in pkgs:
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
for name in pkg_cls.variant_names():
for when, variant in pkg_cls.variant_definitions(name):
if not variant.description:
msg = f"Variant '{name}' in package '{pkg_name}' is missing a description"
errors.append(error_cls(msg, []))
for variant_name, entry in pkg_cls.variants.items():
variant, _ = entry
if not variant.description:
error_msg = "Variant '{}' in package '{}' is missing a description"
errors.append(error_cls(error_msg.format(variant_name, pkg_name), []))
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):
variant_exceptions = (
spack.variant.InconsistentValidationError,
spack.variant.MultipleValuesInExclusiveVariantError,
spack.variant.InvalidVariantValueError,
KeyError,
)
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():
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:
spack.variant.prevalidate_variant_value(pkg, v, constraint, strict=True)
except (
spack.variant.InconsistentValidationError,
spack.variant.MultipleValuesInExclusiveVariantError,
spack.variant.InvalidVariantValueError,
) as e:
msg = str(e).strip()
errors.append(error_cls(summary=summary, details=[msg, f"in {filename}"]))
variant, _ = pkg.variants[name]
variant.validate_or_raise(v, pkg_cls=pkg)
except variant_exceptions as e:
summary = pkg.name + ': wrong variant in "{0}" directive'
summary = summary.format(directive)
filename = spack.repo.PATH.filename_for_package_name(pkg.name)
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
@@ -1123,10 +1119,9 @@ def _extracts_errors(triggers, summary):
for dname in dnames
)
for when, variants_by_name in pkg_cls.variants.items():
for vname, variant in variants_by_name.items():
summary = f"{pkg_name}: wrong 'when=' condition for the '{vname}' variant"
errors.extend(_extracts_errors([when], summary))
for vname, (variant, triggers) in pkg_cls.variants.items():
summary = f"{pkg_name}: wrong 'when=' condition for the '{vname}' variant"
errors.extend(_extracts_errors(triggers, summary))
for when, providers, details in _error_items(pkg_cls.provided):
errors.extend(

View File

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

View File

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

View File

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

View File

@@ -14,9 +14,9 @@
from llnl.util import tty
import spack.environment
import spack.spec
import spack.tengine
import spack.util.path
import spack.util.cpus
import spack.util.executable
from ._common import _root_spec
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.log import MultiProcessFd
import spack.build_systems._checks
import spack.build_systems.cmake
import spack.build_systems.meson
import spack.build_systems.python
@@ -62,20 +61,26 @@
import spack.config
import spack.deptypes as dt
import spack.error
import spack.multimethod
import spack.main
import spack.package_base
import spack.paths
import spack.platforms
import spack.repo
import spack.schema.environment
import spack.spec
import spack.stage
import spack.store
import spack.subprocess_context
import spack.user_environment
import spack.util.executable
import spack.util.path
import spack.util.pattern
from spack import traverse
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.installer import InstallError
from spack.util.cpus import determine_number_of_jobs
from spack.util.environment import (
SYSTEM_DIR_CASE_ENTRY,
EnvironmentModifications,
@@ -450,7 +455,7 @@ def set_wrapper_variables(pkg, env):
env.set(SPACK_DEBUG, "TRUE")
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_DIR, spack.paths.spack_working_dir)
env.set(SPACK_DEBUG_LOG_DIR, spack.main.spack_working_dir)
if spack.config.get("config:ccache"):
# 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_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
# 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)
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
# it's a control statement.
write_pipe.send(e)
@@ -1295,7 +1300,7 @@ def exitcode_msg(p):
p.join()
# If returns a StopPhase, raise it
if isinstance(child_result, spack.error.StopPhase):
if isinstance(child_result, StopPhase):
# do not print
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)
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):
errors, warnings = parse_log_events(log)
nerr = len(errors)

View File

@@ -8,7 +8,7 @@
import llnl.util.lang
import spack.builder
import spack.error
import spack.installer
import spack.relocate
import spack.spec
import spack.store
@@ -34,7 +34,7 @@ def check_paths(path_list, filetype, predicate):
if not predicate(abs_path):
msg = "Install failed for {0}. No such {1} in prefix: {2}"
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_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)
if all(map(ignore_file, os.listdir(pkg.prefix))):
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):

View File

@@ -13,7 +13,6 @@
import spack.build_environment
import spack.builder
import spack.error
import spack.package_base
from spack.directives import build_system, conflicts, depends_on
from spack.multimethod import when
@@ -249,7 +248,7 @@ def runs_ok(script_abs_path):
# An external gnuconfig may not not have a prefix.
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 "
"prefix is available for the `gnuconfig` package. Make sure you set a "
"prefix path instead of modules for external `gnuconfig`."
@@ -269,7 +268,7 @@ def runs_ok(script_abs_path):
msg += (
" 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
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
`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
for abs_path in to_be_patched:
@@ -687,8 +688,9 @@ def _activate_or_not(
variant = variant or name
# Defensively look that the name passed as argument is among variants
if not self.pkg.has_variant(variant):
# Defensively look that the name passed as argument is among
# variants
if variant not in self.pkg.variants:
msg = '"{0}" is not a variant of "{1}"'
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
# option and whether or not that option is activated
vdef = self.pkg.get_variant(variant)
if set(vdef.values) == set((True, False)):
variant_desc, _ = self.pkg.variants[variant]
if set(variant_desc.values) == set((True, False)):
# BoolValuedVariant carry information about a single option.
# Nonetheless, for uniformity of treatment we'll package them
# in an iterable of one element.
options = [(name, f"+{variant}" in spec)]
condition = "+{name}".format(name=variant)
options = [(name, condition in spec)]
else:
condition = "{variant}={value}"
# "feature_values" is used to track values which correspond to
# features which can be enabled or disabled as understood by the
# package's build system. It excludes values which have special
# meanings and do not correspond to features (e.g. "none")
feature_values = getattr(vdef.values, "feature_values", None) or vdef.values
options = [(value, f"{variant}={value}" in spec) for value in feature_values]
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 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:
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))
if variant not in self.pkg.spec.variants:

View File

@@ -15,7 +15,6 @@
import spack.build_environment
import spack.builder
import spack.deptypes as dt
import spack.error
import spack.package_base
from spack.directives import build_system, conflicts, depends_on, variant
from spack.multimethod import when
@@ -146,7 +145,6 @@ def _values(x):
default=default,
values=_values,
description="the build system generator to use",
when="build_system=cmake",
)
for x in not_used:
conflicts(f"generator={x}")
@@ -346,7 +344,7 @@ def std_args(pkg, generator=None):
msg = "Invalid CMake generator: '{0}'\n".format(generator)
msg += "CMakePackage currently supports the following "
msg += "primary generators: '{0}'".format("', '".join(valid_primary_generators))
raise spack.error.InstallError(msg)
raise spack.package_base.InstallError(msg)
try:
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:
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))
if variant not in self.pkg.spec.variants:

View File

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

View File

@@ -22,10 +22,9 @@
install,
)
import spack.builder
import spack.error
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.executable import Executable
from spack.util.prefix import Prefix

View File

@@ -15,7 +15,7 @@
import spack.util.path
from spack.build_environment import dso_suffix
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.executable import Executable

View File

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

View File

@@ -11,9 +11,9 @@
import spack.builder
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.package_base import PackageBase
from spack.util.cpus import determine_number_of_jobs
from spack.util.environment import env_flag
from spack.util.executable import Executable, ProcessError

View File

@@ -10,7 +10,7 @@
from llnl.util import lang
import spack.error
import spack.build_environment
import spack.multimethod
#: 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,
# stop the installation process raising a StopPhase
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):
# If a phase has a matching last_phase attribute,
# stop the installation process raising a StopPhase
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):
return copy.deepcopy(self)

View File

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

View File

@@ -31,7 +31,6 @@
import spack
import spack.binary_distribution as bindist
import spack.concretize
import spack.config as cfg
import spack.environment as ev
import spack.main
@@ -39,6 +38,7 @@
import spack.paths
import spack.repo
import spack.spec
import spack.stage
import spack.util.git
import spack.util.gpg as gpg_util
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
# 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.
spack_version = spack.get_version()
version_to_clone = spack.get_spack_commit() or f"v{spack.spack_version}"
spack_version = spack.main.get_version()
version_to_clone = spack.main.get_spack_commit() or f"v{spack.spack_version}"
output_object["variables"] = {
"SPACK_ARTIFACTS_ROOT": rel_artifacts_root,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -13,9 +13,9 @@
import spack.config
import spack.environment as ev
import spack.error
import spack.repo
import spack.schema.env
import spack.spec
import spack.schema.packages
import spack.store
import spack.util.spack_yaml as syaml
from spack.cmd.common import arguments
@@ -256,7 +256,7 @@ def config_remove(args):
existing.pop(value, None)
else:
# 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)
@@ -340,7 +340,7 @@ def _config_change(config_path, match_spec_str=None):
if not changed:
existing_requirements = spack.config.get(key_path)
if isinstance(existing_requirements, str):
raise spack.error.ConfigError(
raise spack.config.ConfigError(
"'config change' needs to append a requirement,"
" 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.
variants = []
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
vdef = spec.package.get_variant(var_name)
if variant.value != vdef.default:
variant_desc, _ = spec.package.variants[var_name]
if variant.value != variant_desc.default:
variants.append(str(variant))
variants.sort()
variants = " ".join(variants)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,7 +16,6 @@
import spack.install_test
import spack.repo
import spack.spec
import spack.variant
import spack.version
from spack.cmd.common import arguments
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")
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):
"""output variants"""
@@ -344,22 +363,32 @@ def _print_variants_header(pkg):
color.cprint("")
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
# This lets us know where to print variant values.
max_name_default_len = max(
color.clen(_fmt_name_and_default(variant))
for name in pkg.variant_names()
for _, variant in pkg.variant_definitions(name)
for name, when_variants in variants_by_name.items()
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):
max_name_default_len = _print_variants_header(pkg)
max_name_default_len, _ = _print_variants_header(pkg)
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
start_indent = indent
@@ -377,14 +406,15 @@ def print_variants_grouped_by_when(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
indent = 4
for name in pkg.variant_names():
for when, variant in pkg.variant_definitions(name):
_fmt_variant(variant, max_name_default_len, indent, when, out=sys.stdout)
sys.stdout.write("\n")
for name, when_variants in variants_by_name.items():
for when, variants in sorted(when_variants.items(), key=_unconstrained_ver_first):
for variant in variants:
_fmt_variant(variant, max_name_default_len, indent, when, out=sys.stdout)
sys.stdout.write("\n")
def print_variants(pkg, args):

View File

@@ -13,15 +13,18 @@
from llnl.string import plural
from llnl.util import lang, tty
import spack.build_environment
import spack.cmd
import spack.config
import spack.environment as ev
import spack.fetch_strategy
import spack.package_base
import spack.paths
import spack.report
import spack.spec
import spack.store
from spack.cmd.common import arguments
from spack.error import InstallError, SpackError
from spack.error import SpackError
from spack.installer import PackageInstaller
description = "build and install packages"
@@ -284,7 +287,7 @@ def require_user_confirmation_for_overwrite(concrete_specs, args):
tty.die("Reinstallation aborted.")
def _dump_log_on_error(e: InstallError):
def _dump_log_on_error(e: spack.build_environment.InstallError):
e.print_context()
assert e.pkg, "Expected InstallError to include the associated package"
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)
else:
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:
_dump_log_on_error(e)
raise

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -8,8 +8,16 @@
from contextlib import contextmanager
from itertools import chain
import spack.compilers
import spack.config
import spack.environment
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

View File

@@ -39,7 +39,6 @@
from llnl.util import filesystem, lang, tty
import spack.error
import spack.paths
import spack.platforms
import spack.schema
@@ -49,19 +48,17 @@
import spack.schema.compilers
import spack.schema.concretizer
import spack.schema.config
import spack.schema.definitions
import spack.schema.develop
import spack.schema.env
import spack.schema.mirrors
import spack.schema.modules
import spack.schema.packages
import spack.schema.repos
import spack.schema.upstreams
import spack.schema.view
# Hacked yaml for configuration files preserves line numbers.
import spack.util.spack_yaml as syaml
import spack.util.web as web_util
from spack.error import SpackError
from spack.util.cpus import cpus_available
#: 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:
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)
data = self.get_section(section)
@@ -280,7 +277,7 @@ def get_section(self, section: str) -> Optional[YamlConfigDict]:
def _write_section(self, section: str) -> None:
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
# 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)
syaml.dump_config(data, stream=sys.stdout, default_flow_style=False, blame=blame)
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
@@ -810,7 +807,7 @@ def _add_command_line_scopes(
_add_platform_scope(cfg, name, path, writable=False)
continue
else:
raise spack.error.ConfigError(f"Invalid configuration scope: {path}")
raise ConfigError(f"Invalid configuration scope: {path}")
for scope in manifest.env_config_scopes:
scope.name = f"{name}:{scope.name}"
@@ -1022,7 +1019,7 @@ def change_or_add(
if found:
update_fn(section)
CONFIG.set(section_name, section, scope=scope)
spack.config.set(section_name, section, scope=scope)
return
# If no scope meets the criteria specified by ``find_fn``,
@@ -1035,14 +1032,14 @@ def change_or_add(
break
if found:
CONFIG.set(section_name, section, scope=scope)
spack.config.set(section_name, section, scope=scope)
return
# If no scopes define any config for the named section, then
# modify the highest-priority scope.
scope, section = configs_by_section[0]
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:
@@ -1054,7 +1051,7 @@ def update_all(section_name: str, change_fn: Callable[[str], bool]) -> None:
for scope, section in configs_by_section:
modified = change_fn(section)
if modified:
CONFIG.set(section_name, section, scope=scope)
spack.config.set(section_name, section, scope=scope)
def _validate_section_name(section: str) -> None:
@@ -1228,7 +1225,7 @@ def get_valid_type(path):
return types[schema_type]()
else:
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):
@@ -1271,7 +1268,7 @@ def they_are(t):
unmerge = sk in dest
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)
return dest
@@ -1708,48 +1705,40 @@ def get_mark_from_yaml_data(obj):
return mark
def determine_number_of_jobs(
*,
parallel: bool = False,
max_cpus: int = cpus_available(),
config: Optional[Configuration] = None,
) -> int:
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.
Parse a ``Spec`` from the supplied string, but also intercept any syntax errors and
add file/line information for debugging using file/line annotations from the string.
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:
command_line = cfg.get("config:build_jobs", default=None, scope="command_line")
if command_line is not None:
return command_line
except ValueError:
pass
return min(max_cpus, cfg.get("config:build_jobs", 16))
spec = spack.spec.Spec(string)
return spec
except spack.parser.SpecSyntaxError as e:
mark = spack.config.get_mark_from_yaml_data(string)
if mark:
msg = f"{mark.name}:{mark.line + 1}: {str(e)}"
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."""
class ConfigFileError(spack.error.ConfigError):
class ConfigFileError(ConfigError):
"""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."""
def __init__(

View File

@@ -6,7 +6,6 @@
convenience functions.
"""
import copy
import shlex
from collections import namedtuple
from typing import Optional
@@ -16,7 +15,7 @@
import spack.tengine as tengine
import spack.util.spack_yaml as syaml
from .images import (
from ..images import (
bootstrap_template_for,
build_info,
checkout_command,
@@ -309,54 +308,7 @@ def __call__(self):
return t.render(**self.to_dict())
@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)
@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", "")
# Import after function definition all the modules in this package,
# so that registration of writers will happen automatically
from . import docker # noqa: F401 E402
from . import singularity # noqa: F401 E402

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()
for name, value in entry["parameters"].items():
# 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(
"Omitting variant {0} for entry {1}/{2}".format(
name, entry["name"], entry["hash"][:7]

View File

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

View File

@@ -18,12 +18,10 @@
import llnl.util.lang
import llnl.util.tty
import spack.spec
import spack.util.elf as elf_utils
import spack.util.environment
import spack.util.environment as environment
import spack.util.ld_so_conf
import spack.util.parallel
from .common import (
WindowsCompilerExternalPaths,
@@ -408,7 +406,7 @@ def by_path(
result = collections.defaultdict(list)
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:
executable_future = executor.submit(
executables_finder.find,

View File

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

View File

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

View File

@@ -24,23 +24,25 @@
from llnl.util.link_tree import ConflictingSpecsError
from llnl.util.symlink import readlink, symlink
import spack
import spack.caches
import spack.cmd
import spack.compilers
import spack.concretize
import spack.config
import spack.deptypes as dt
import spack.environment
import spack.error
import spack.fetch_strategy
import spack.filesystem_view as fsv
import spack.hash_types as ht
import spack.hooks
import spack.main
import spack.paths
import spack.repo
import spack.schema.env
import spack.schema.merged
import spack.spec
import spack.spec_list
import spack.stage
import spack.store
import spack.subprocess_context
import spack.user_environment as uenv
import spack.util.cpus
import spack.util.environment
@@ -51,6 +53,7 @@
import spack.util.spack_json as sjson
import spack.util.spack_yaml as syaml
import spack.util.url
import spack.version
from spack import traverse
from spack.installer import PackageInstaller
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
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
msg = "Starting concretization"
@@ -2176,7 +2179,7 @@ def _to_lockfile_dict(self):
root_specs = self._concrete_roots_dict()
spack_dict = {"version": spack.spack_version}
spack_commit = spack.get_spack_commit()
spack_commit = spack.main.get_spack_commit()
if spack_commit:
spack_dict["type"] = "git"
spack_dict["commit"] = spack_commit

View File

@@ -132,60 +132,3 @@ def __init__(self, provided, required, constraint_type):
class FetchError(SpackError):
"""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 spack.cmd
import spack.config
import spack.error
import spack.util.path

View File

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

View File

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

View File

@@ -17,23 +17,14 @@
import llnl.util.filesystem as fs
import llnl.util.tty as tty
import llnl.util.tty.log
from llnl.string import plural
from llnl.util.lang import nullcontext
from llnl.util.tty.color import colorize
import spack.build_environment
import spack.builder
import spack.config
import spack.error
import spack.package_base
import spack.paths
import spack.repo
import spack.spec
import spack.util.executable
import spack.util.path
import spack.util.spack_json as sjson
from spack.error import InstallError
from spack.installer import InstallError
from spack.spec import Spec
from spack.util.prefix import Prefix
@@ -51,7 +42,7 @@
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")
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.
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
under the build stage
"""
@@ -289,7 +280,7 @@ def __init__(self, pkg: Pb):
def logger(self) -> Optional[LogType]:
"""The current logger or, if none, sets to one."""
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
@@ -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.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]
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.build_environment
import spack.compilers
import spack.config
import spack.database
import spack.deptypes as dt
@@ -889,7 +890,7 @@ def __init__(
# ensure priority queue invariants when tasks are "removed" from the
# queue.
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
)
@@ -1160,7 +1161,7 @@ def _check_deps_status(self, request: BuildRequest) -> None:
if spack.store.STORE.failure_tracker.has_failed(dep):
action = "'spack install' the dependency"
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
# 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)
if lock is None:
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
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:
# Ensure there is no other installed spec with the same prefix dir
if spack.store.STORE.db.is_occupied_install_prefix(task.pkg.spec.prefix):
raise spack.error.InstallError(
raise InstallError(
f"Install prefix collision for {task.pkg_id}",
long_msg=f"Prefix directory {task.pkg.spec.prefix} already "
"used by another installed spec.",
@@ -1488,9 +1489,7 @@ def _install_task(self, task: BuildTask, install_status: InstallStatus) -> None:
self._update_installed(task)
return
elif cache_only:
raise spack.error.InstallError(
"No binary found when cache-only was specified", pkg=pkg
)
raise InstallError("No binary found when cache-only was specified", pkg=pkg)
else:
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.
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
# stop early from clients, and is not an error at this point
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")
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"{dep_str}: {','.join(task.uninstalled_deps)}",
pkg=pkg,
@@ -1872,7 +1871,7 @@ def install(self) -> None:
self._update_failed(task)
if self.fail_fast:
raise spack.error.InstallError(fail_fast_err, pkg=pkg)
raise InstallError(fail_fast_err, pkg=pkg)
continue
@@ -2001,7 +2000,7 @@ def install(self) -> None:
)
# Terminate if requested to do so on the first failure.
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.
if task.is_build_request:
@@ -2053,7 +2052,7 @@ def install(self) -> None:
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).",
pkg=pkg,
)
@@ -2319,21 +2318,33 @@ def install(self):
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."""
def __init__(self, pkg_name, phase):
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."""
class InstallLockError(spack.error.InstallError):
class InstallLockError(InstallError):
"""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
package."""

View File

@@ -9,8 +9,6 @@
after the system path is set up.
"""
import argparse
# import spack.modules.common
import inspect
import io
import operator
@@ -34,20 +32,20 @@
import llnl.util.tty.color as color
from llnl.util.tty.log import log_output
import spack
import spack.cmd
import spack.config
import spack.environment as ev
import spack.error
import spack.modules
import spack.paths
import spack.platforms
import spack.repo
import spack.solver.asp
import spack.spec
import spack.store
import spack.util.debug
import spack.util.environment
import spack.util.lock
import spack.util.git
import spack.util.path
from spack.error import SpackError
#: names of profile statistics
@@ -100,18 +98,75 @@
#: Properties that commands are required to set.
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", "")
#: Whether to print backtraces on error
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):
"""Add all spack subcommands to the parser."""
for cmd in spack.cmd.all_commands():
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():
"""create an index of commands by section for this help level"""
index = {}
@@ -755,8 +810,6 @@ def print_setup_info(*info):
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.
"""
import spack.modules.common
shell = "csh" if "csh" in info else "sh"
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
if args.version:
print(spack.get_version())
print(get_version())
return 0
# ------------------------------------------------------------------------
@@ -986,7 +1039,7 @@ def finish_parse_and_run(parser, cmd_name, main_args, env_format_error):
raise env_format_error
# many operations will fail without a working directory.
spack.paths.set_working_dir()
set_working_dir()
# now we can actually execute the command.
if main_args.spack_profile or main_args.sorted_profile:

View File

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

View File

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

View File

@@ -15,10 +15,17 @@
import llnl.util.tty as tty
import spack.binary_distribution
import spack.config
import spack.error
import spack.fetch_strategy
import spack.mirror
import spack.oci.opener
import spack.repo
import spack.spec
import spack.stage
import spack.traverse
import spack.util.crypto
import spack.util.url
from .image import Digest, ImageReference
@@ -30,6 +37,11 @@ class Blob(NamedTuple):
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:
"""Add a query parameter to a URL

View File

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

View File

@@ -11,8 +11,6 @@
from os import chdir, environ, getcwd, makedirs, mkdir, remove, removedirs
from shutil import move, rmtree
from spack.error import InstallError
# Emulate some shell commands for convenience
env = environ
cd = chdir
@@ -75,7 +73,6 @@
from spack.build_systems.waf import WafPackage
from spack.build_systems.xorg import XorgPackage
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.directives import *
from spack.install_test import (
@@ -87,7 +84,12 @@
install_test_root,
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.multimethod import default_args, when
from spack.package_base import (
@@ -100,6 +102,7 @@
on_package_attributes,
)
from spack.spec import InvalidSpecDetected, Spec
from spack.util.cpus import determine_number_of_jobs
from spack.util.executable import *
from spack.util.filesystem import file_command, fix_darwin_install_name, mime_type
from spack.variant import (

View File

@@ -33,28 +33,28 @@
from llnl.util.lang import classproperty, memoized
from llnl.util.link_tree import LinkTree
import spack.build_environment
import spack.builder
import spack.compilers
import spack.config
import spack.dependency
import spack.deptypes as dt
import spack.directives
import spack.directory_layout
import spack.environment
import spack.error
import spack.fetch_strategy as fs
import spack.hooks
import spack.mirror
import spack.mixins
import spack.multimethod
import spack.patch
import spack.paths
import spack.repo
import spack.spec
import spack.store
import spack.url
import spack.util.environment
import spack.util.executable
import spack.util.path
import spack.util.web
from spack.error import InstallError, NoURLError, PackageError
from spack.filesystem_view import YamlFilesystemView
from spack.install_test import (
PackageTest,
@@ -64,8 +64,7 @@
cache_extra_test_sources,
install_test_root,
)
from spack.installer import PackageInstaller
from spack.solver.version_order import concretization_version_order
from spack.installer import InstallError, PackageInstaller
from spack.stage import DevelopStage, ResourceStage, Stage, StageComposite, compute_stage_name
from spack.util.executable import ProcessError, which
from spack.util.package_hash import package_hash
@@ -117,6 +116,7 @@ def preferred_version(pkg: "PackageBase"):
Arguments:
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)
return version
@@ -451,11 +451,10 @@ def _by_name(
else:
all_by_name.setdefault(name, []).append(value)
# this needs to preserve the insertion order of whens
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."""
all_names = set()
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)
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:
"""Logic for determining whether a Package is source/binary
redistributable.
@@ -636,7 +596,7 @@ class PackageBase(WindowsRPath, PackageViewMixin, RedistributionMixin, metaclass
provided: Dict["spack.spec.Spec", Set["spack.spec.Spec"]]
provided_together: Dict["spack.spec.Spec", List[Set[str]]]
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]]
#: By default, packages are not virtual
@@ -790,72 +750,6 @@ def dependency_names(cls):
def dependencies_by_name(cls, when: bool = False):
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
def possible_dependencies(
cls,
@@ -1805,7 +1699,8 @@ def content_hash(self, content=None):
# should this attempt to download the source and set one? This
# probably only happens for source repositories which are
# referenced by branch name rather than tag or commit ID.
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:
message = "Missing a source id for {s.name}@{s.version}"
tty.debug(message.format(s=self))
@@ -2689,6 +2584,20 @@ def __init__(self, spec, 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):
"""Raised when someone tries perform an invalid operation on a package."""

View File

@@ -9,7 +9,7 @@
import spack.error
import spack.repo
import spack.spec
from spack.error import ConfigError
from spack.config import ConfigError
from spack.version import 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
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
spec = spack.spec.Spec(f"{pkg_name} {variants}")
return {
name: variant
for name, variant in spec.variants.items()
if name in pkg_cls.variant_names()
}
spec = spack.spec.Spec("%s %s" % (pkg_name, variants))
return dict(
(name, variant) for name, variant in spec.variants.items() if name in pkg_cls.variants
)
def is_spec_buildable(spec):

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