Compare commits

..

3 Commits

Author SHA1 Message Date
Harmen Stoppels
dd9e28a621 simplify mro stuff 2024-08-30 15:07:33 +02:00
Harmen Stoppels
3d827b0ea5 build_systems: use pkg.module 2024-08-28 14:58:09 +02:00
Harmen Stoppels
45ec04ef7c builtin: remove redundant use of inspec 2024-08-28 14:58:09 +02:00
987 changed files with 7927 additions and 14964 deletions

View File

@@ -1,5 +1,4 @@
{ {
"name": "Ubuntu 20.04",
"image": "ghcr.io/spack/ubuntu20.04-runner-amd64-gcc-11.4:2023.08.01", "image": "ghcr.io/spack/ubuntu20.04-runner-amd64-gcc-11.4:2023.08.01",
"postCreateCommand": "./.devcontainer/postCreateCommand.sh" "postCreateCommand": "./.devcontainer/postCreateCommand.sh"
} }

View File

@@ -1,5 +0,0 @@
{
"name": "Ubuntu 22.04",
"image": "ghcr.io/spack/ubuntu-22.04:v2024-05-07",
"postCreateCommand": "./.devcontainer/postCreateCommand.sh"
}

View File

@@ -28,8 +28,8 @@ jobs:
run: run:
shell: ${{ matrix.system.shell }} shell: ${{ matrix.system.shell }}
steps: steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
with: with:
python-version: ${{inputs.python_version}} python-version: ${{inputs.python_version}}
- name: Install Python packages - name: Install Python packages
@@ -40,8 +40,6 @@ jobs:
run: | run: |
python -m pip install --upgrade pywin32 python -m pip install --upgrade pywin32
- name: Package audits (with coverage) - name: Package audits (with coverage)
env:
COVERAGE_FILE: coverage/.coverage-audits-${{ matrix.system.os }}
if: ${{ inputs.with_coverage == 'true' && runner.os != 'Windows' }} if: ${{ inputs.with_coverage == 'true' && runner.os != 'Windows' }}
run: | run: |
. share/spack/setup-env.sh . share/spack/setup-env.sh
@@ -49,26 +47,27 @@ jobs:
coverage run $(which spack) audit configs coverage run $(which spack) audit configs
coverage run $(which spack) -d audit externals coverage run $(which spack) -d audit externals
coverage combine coverage combine
coverage xml
- name: Package audits (without coverage) - name: Package audits (without coverage)
if: ${{ inputs.with_coverage == 'false' && runner.os != 'Windows' }} if: ${{ inputs.with_coverage == 'false' && runner.os != 'Windows' }}
run: | run: |
. share/spack/setup-env.sh . share/spack/setup-env.sh
spack -d audit packages spack -d audit packages
spack -d audit configs spack -d audit configs
spack -d audit externals spack -d audit externals
- name: Package audits (without coverage) - name: Package audits (without coverage)
if: ${{ runner.os == 'Windows' }} if: ${{ runner.os == 'Windows' }}
run: | run: |
. share/spack/setup-env.sh . share/spack/setup-env.sh
spack -d audit packages spack -d audit packages
./share/spack/qa/validate_last_exit.ps1 ./share/spack/qa/validate_last_exit.ps1
spack -d audit configs spack -d audit configs
./share/spack/qa/validate_last_exit.ps1 ./share/spack/qa/validate_last_exit.ps1
spack -d audit externals spack -d audit externals
./share/spack/qa/validate_last_exit.ps1 ./share/spack/qa/validate_last_exit.ps1
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
if: ${{ inputs.with_coverage == 'true' && runner.os != 'Windows' }} if: ${{ inputs.with_coverage == 'true' }}
with: with:
name: coverage-audits-${{ matrix.system.os }} flags: unittests,audits
path: coverage token: ${{ secrets.CODECOV_TOKEN }}
include-hidden-files: true verbose: true

View File

@@ -37,7 +37,7 @@ jobs:
make patch unzip which xz python3 python3-devel tree \ make patch unzip which xz python3 python3-devel tree \
cmake bison cmake bison
- name: Checkout - name: Checkout
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Bootstrap clingo - name: Bootstrap clingo
@@ -60,10 +60,10 @@ jobs:
run: | run: |
brew install cmake bison tree brew install cmake bison tree
- name: Checkout - name: Checkout
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
with: with:
python-version: "3.12" python-version: "3.12"
- name: Bootstrap clingo - name: Bootstrap clingo
@@ -96,7 +96,7 @@ jobs:
if: ${{ matrix.runner == 'ubuntu-latest' }} if: ${{ matrix.runner == 'ubuntu-latest' }}
run: sudo rm -rf $(command -v gpg gpg2 patchelf) run: sudo rm -rf $(command -v gpg gpg2 patchelf)
- name: Checkout - name: Checkout
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Bootstrap GnuPG - name: Bootstrap GnuPG
@@ -112,10 +112,10 @@ jobs:
runs-on: ${{ matrix.runner }} runs-on: ${{ matrix.runner }}
strategy: strategy:
matrix: matrix:
runner: ['macos-13', 'macos-14', "ubuntu-latest", "windows-latest"] runner: ['macos-13', 'macos-14', "ubuntu-latest"]
steps: steps:
- name: Setup macOS - name: Setup macOS
if: ${{ matrix.runner != 'ubuntu-latest' && matrix.runner != 'windows-latest'}} if: ${{ matrix.runner != 'ubuntu-latest' }}
run: | run: |
brew install tree brew install tree
# Remove GnuPG since we want to bootstrap it # Remove GnuPG since we want to bootstrap it
@@ -124,16 +124,11 @@ jobs:
if: ${{ matrix.runner == 'ubuntu-latest' }} if: ${{ matrix.runner == 'ubuntu-latest' }}
run: | run: |
sudo rm -rf $(which gpg) $(which gpg2) $(which patchelf) 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 - name: Checkout
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
with: with:
python-version: | python-version: |
3.8 3.8
@@ -142,20 +137,11 @@ jobs:
3.11 3.11
3.12 3.12
- name: Set bootstrap sources - 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: | run: |
source share/spack/setup-env.sh source share/spack/setup-env.sh
spack bootstrap disable github-actions-v0.4
spack bootstrap disable spack-install spack bootstrap disable spack-install
- name: Bootstrap clingo - name: Bootstrap clingo
# No binary clingo on Windows yet
if: ${{ matrix.runner != 'windows-latest' }}
run: | run: |
set -e set -e
for ver in '3.8' '3.9' '3.10' '3.11' '3.12' ; do for ver in '3.8' '3.9' '3.10' '3.11' '3.12' ; do
@@ -178,24 +164,7 @@ jobs:
fi fi
done done
- name: Bootstrap GnuPG - 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: | run: |
${{ env.SETUP_SCRIPT_SOURCE }}share/spack/setup-env.${{ env.SETUP_SCRIPT_EXT }} source share/spack/setup-env.sh
spack -d gpg list spack -d gpg list
${{ env.VALIDATE_LAST_EXIT }} tree ~/.spack/bootstrap/store/
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

@@ -55,7 +55,7 @@ jobs:
if: github.repository == 'spack/spack' if: github.repository == 'spack/spack'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81
id: docker_meta id: docker_meta
@@ -87,7 +87,7 @@ jobs:
fi fi
- name: Upload Dockerfile - name: Upload Dockerfile
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a
with: with:
name: dockerfiles_${{ matrix.dockerfile[0] }} name: dockerfiles_${{ matrix.dockerfile[0] }}
path: dockerfiles path: dockerfiles
@@ -113,7 +113,7 @@ jobs:
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build & Deploy ${{ matrix.dockerfile[0] }} - name: Build & Deploy ${{ matrix.dockerfile[0] }}
uses: docker/build-push-action@32945a339266b759abcbdc89316275140b0fc960 uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85
with: with:
context: dockerfiles/${{ matrix.dockerfile[0] }} context: dockerfiles/${{ matrix.dockerfile[0] }}
platforms: ${{ matrix.dockerfile[1] }} platforms: ${{ matrix.dockerfile[1] }}
@@ -126,7 +126,7 @@ jobs:
needs: deploy-images needs: deploy-images
steps: steps:
- name: Merge Artifacts - name: Merge Artifacts
uses: actions/upload-artifact/merge@50769540e7f4bd5e21e526ee35c689e35e0d6874 uses: actions/upload-artifact/merge@834a144ee995460fba8ed112a2fc961b36a5ec5a
with: with:
name: dockerfiles name: dockerfiles
pattern: dockerfiles_* pattern: dockerfiles_*

View File

@@ -15,6 +15,18 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
prechecks:
needs: [ changes ]
uses: ./.github/workflows/valid-style.yml
secrets: inherit
with:
with_coverage: ${{ needs.changes.outputs.core }}
all-prechecks:
needs: [ prechecks ]
runs-on: ubuntu-latest
steps:
- name: Success
run: "true"
# Check which files have been updated by the PR # Check which files have been updated by the PR
changes: changes:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -24,7 +36,7 @@ jobs:
core: ${{ steps.filter.outputs.core }} core: ${{ steps.filter.outputs.core }}
packages: ${{ steps.filter.outputs.packages }} packages: ${{ steps.filter.outputs.packages }}
steps: steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
if: ${{ github.event_name == 'push' }} if: ${{ github.event_name == 'push' }}
with: with:
fetch-depth: 0 fetch-depth: 0
@@ -67,34 +79,13 @@ jobs:
needs: [ prechecks, changes ] needs: [ prechecks, changes ]
uses: ./.github/workflows/bootstrap.yml uses: ./.github/workflows/bootstrap.yml
secrets: inherit secrets: inherit
unit-tests: unit-tests:
if: ${{ github.repository == 'spack/spack' && needs.changes.outputs.core == 'true' }} if: ${{ github.repository == 'spack/spack' && needs.changes.outputs.core == 'true' }}
needs: [ prechecks, changes ] needs: [ prechecks, changes ]
uses: ./.github/workflows/unit_tests.yaml uses: ./.github/workflows/unit_tests.yaml
secrets: inherit secrets: inherit
prechecks:
needs: [ changes ]
uses: ./.github/workflows/valid-style.yml
secrets: inherit
with:
with_coverage: ${{ needs.changes.outputs.core }}
all-prechecks:
needs: [ prechecks ]
runs-on: ubuntu-latest
steps:
- name: Success
run: "true"
coverage:
needs: [ unit-tests, prechecks ]
uses: ./.github/workflows/coverage.yml
secrets: inherit
all: all:
needs: [ coverage, bootstrap ] needs: [ unit-tests, bootstrap ]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Success - name: Success

View File

@@ -1,34 +0,0 @@
name: coverage
on:
workflow_call:
jobs:
# Upload coverage reports to codecov once as a single bundle
upload:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
with:
python-version: '3.11'
cache: 'pip'
- name: Install python dependencies
run: pip install -r .github/workflows/requirements/coverage/requirements.txt
- name: Download coverage artifact files
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16
with:
pattern: coverage-*
path: coverage
merge-multiple: true
- run: ls -la coverage
- run: coverage combine -a coverage/.coverage*
- run: coverage xml
- name: "Upload coverage report to CodeCov"
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
with:
verbose: true

View File

@@ -14,10 +14,10 @@ jobs:
build-paraview-deps: build-paraview-deps:
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
with: with:
python-version: 3.9 python-version: 3.9
- name: Install Python packages - name: Install Python packages

View File

@@ -1 +0,0 @@
coverage==7.6.1

View File

@@ -40,10 +40,10 @@ jobs:
on_develop: false on_develop: false
steps: steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Install System packages - name: Install System packages
@@ -76,23 +76,22 @@ jobs:
SPACK_PYTHON: python SPACK_PYTHON: python
SPACK_TEST_PARALLEL: 2 SPACK_TEST_PARALLEL: 2
COVERAGE: true COVERAGE: true
COVERAGE_FILE: coverage/.coverage-${{ matrix.os }}-python${{ matrix.python-version }}
UNIT_TEST_COVERAGE: ${{ matrix.python-version == '3.11' }} UNIT_TEST_COVERAGE: ${{ matrix.python-version == '3.11' }}
run: | run: |
share/spack/qa/run-unit-tests share/spack/qa/run-unit-tests
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
with: with:
name: coverage-${{ matrix.os }}-python${{ matrix.python-version }} flags: unittests,linux,${{ matrix.concretizer }}
path: coverage token: ${{ secrets.CODECOV_TOKEN }}
include-hidden-files: true verbose: true
# Test shell integration # Test shell integration
shell: shell:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
with: with:
python-version: '3.11' python-version: '3.11'
- name: Install System packages - name: Install System packages
@@ -113,11 +112,11 @@ jobs:
COVERAGE: true COVERAGE: true
run: | run: |
share/spack/qa/run-shell-tests share/spack/qa/run-shell-tests
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
with: with:
name: coverage-shell flags: shelltests,linux
path: coverage token: ${{ secrets.CODECOV_TOKEN }}
include-hidden-files: true verbose: true
# Test RHEL8 UBI with platform Python. This job is run # Test RHEL8 UBI with platform Python. This job is run
# only on PRs modifying core Spack # only on PRs modifying core Spack
@@ -130,7 +129,7 @@ jobs:
dnf install -y \ dnf install -y \
bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \ bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \
make patch tcl unzip which xz make patch tcl unzip which xz
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Setup repo and non-root user - name: Setup repo and non-root user
run: | run: |
git --version git --version
@@ -149,10 +148,10 @@ jobs:
clingo-cffi: clingo-cffi:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
with: with:
python-version: '3.11' python-version: '3.11'
- name: Install System packages - name: Install System packages
@@ -171,14 +170,13 @@ jobs:
- name: Run unit tests (full suite with coverage) - name: Run unit tests (full suite with coverage)
env: env:
COVERAGE: true COVERAGE: true
COVERAGE_FILE: coverage/.coverage-clingo-cffi
run: | run: |
share/spack/qa/run-unit-tests share/spack/qa/run-unit-tests
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
with: with:
name: coverage-clingo-cffi flags: unittests,linux,clingo
path: coverage token: ${{ secrets.CODECOV_TOKEN }}
include-hidden-files: true verbose: true
# Run unit tests on MacOS # Run unit tests on MacOS
macos: macos:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -187,10 +185,10 @@ jobs:
os: [macos-13, macos-14] os: [macos-13, macos-14]
python-version: ["3.11"] python-version: ["3.11"]
steps: steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Install Python packages - name: Install Python packages
@@ -203,7 +201,6 @@ jobs:
- name: Run unit tests - name: Run unit tests
env: env:
SPACK_TEST_PARALLEL: 4 SPACK_TEST_PARALLEL: 4
COVERAGE_FILE: coverage/.coverage-${{ matrix.os }}-python${{ matrix.python-version }}
run: | run: |
git --version git --version
. .github/workflows/bin/setup_git.sh . .github/workflows/bin/setup_git.sh
@@ -212,11 +209,11 @@ jobs:
$(which spack) solve zlib $(which spack) solve zlib
common_args=(--dist loadfile --tx '4*popen//python=./bin/spack-tmpconfig python -u ./bin/spack python' -x) common_args=(--dist loadfile --tx '4*popen//python=./bin/spack-tmpconfig python -u ./bin/spack python' -x)
$(which spack) unit-test --verbose --cov --cov-config=pyproject.toml --cov-report=xml:coverage.xml "${common_args[@]}" $(which spack) unit-test --verbose --cov --cov-config=pyproject.toml --cov-report=xml:coverage.xml "${common_args[@]}"
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
with: with:
name: coverage-${{ matrix.os }}-python${{ matrix.python-version }} flags: unittests,macos
path: coverage token: ${{ secrets.CODECOV_TOKEN }}
include-hidden-files: true verbose: true
# Run unit tests on Windows # Run unit tests on Windows
windows: windows:
defaults: defaults:
@@ -225,10 +222,10 @@ jobs:
powershell Invoke-Expression -Command "./share/spack/qa/windows_test_setup.ps1"; {0} powershell Invoke-Expression -Command "./share/spack/qa/windows_test_setup.ps1"; {0}
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
with: with:
python-version: 3.9 python-version: 3.9
- name: Install Python packages - name: Install Python packages
@@ -238,13 +235,13 @@ jobs:
run: | run: |
./.github/workflows/bin/setup_git.ps1 ./.github/workflows/bin/setup_git.ps1
- name: Unit Test - name: Unit Test
env:
COVERAGE_FILE: coverage/.coverage-windows
run: | run: |
spack unit-test -x --verbose --cov --cov-config=pyproject.toml spack unit-test -x --verbose --cov --cov-config=pyproject.toml
./share/spack/qa/validate_last_exit.ps1 ./share/spack/qa/validate_last_exit.ps1
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 coverage combine -a
coverage xml
- uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
with: with:
name: coverage-windows flags: unittests,windows
path: coverage token: ${{ secrets.CODECOV_TOKEN }}
include-hidden-files: true verbose: true

View File

@@ -18,8 +18,8 @@ jobs:
validate: validate:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
with: with:
python-version: '3.11' python-version: '3.11'
cache: 'pip' cache: 'pip'
@@ -35,10 +35,10 @@ jobs:
style: style:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
with: with:
python-version: '3.11' python-version: '3.11'
cache: 'pip' cache: 'pip'
@@ -70,7 +70,7 @@ jobs:
dnf install -y \ dnf install -y \
bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \ bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \
make patch tcl unzip which xz make patch tcl unzip which xz
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Setup repo and non-root user - name: Setup repo and non-root user
run: | run: |
git --version git --version
@@ -87,62 +87,3 @@ jobs:
spack -d bootstrap now --dev spack -d bootstrap now --dev
spack style -t black spack style -t black
spack unit-test -V 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@d632683dd7b4114ad314bca15554477dd762a938
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@d632683dd7b4114ad314bca15554477dd762a938
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@d632683dd7b4114ad314bca15554477dd762a938
with:
path: new
- name: Install circular import checker
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938
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

@@ -46,18 +46,13 @@ See the
[Feature Overview](https://spack.readthedocs.io/en/latest/features.html) [Feature Overview](https://spack.readthedocs.io/en/latest/features.html)
for examples and highlights. for examples and highlights.
To install spack and your first package, make sure you have Python & Git. To install spack and your first package, make sure you have Python.
Then: Then:
$ git clone -c feature.manyFiles=true --depth=2 https://github.com/spack/spack.git $ git clone -c feature.manyFiles=true https://github.com/spack/spack.git
$ cd spack/bin $ cd spack/bin
$ ./spack install zlib $ ./spack install zlib
> [!TIP]
> `-c feature.manyFiles=true` improves git's performance on repositories with 1,000+ files.
>
> `--depth=2` prunes the git history to reduce the size of the Spack installation.
Documentation Documentation
---------------- ----------------

View File

@@ -115,6 +115,12 @@ config:
suppress_gpg_warnings: false suppress_gpg_warnings: false
# If set to true, Spack will attempt to build any compiler on the spec
# that is not already available. If set to False, Spack will only use
# compilers already configured in compilers.yaml
install_missing_compilers: false
# If set to true, Spack will always check checksums after downloading # If set to true, Spack will always check checksums after downloading
# archives. If false, Spack skips the checksum step. # archives. If false, Spack skips the checksum step.
checksum: true checksum: true

View File

@@ -72,13 +72,3 @@ packages:
permissions: permissions:
read: world read: world
write: user write: user
cray-mpich:
buildable: false
cray-mvapich2:
buildable: false
fujitsu-mpi:
buildable: false
hpcx-mpi:
buildable: false
spectrum-mpi:
buildable: false

View File

@@ -1175,17 +1175,6 @@ unspecified version, but packages can depend on other packages with
could depend on ``mpich@1.2:`` if it can only build with version could depend on ``mpich@1.2:`` if it can only build with version
``1.2`` or higher of ``mpich``. ``1.2`` or higher of ``mpich``.
.. note:: Windows Spec Syntax Caveats
Windows has a few idiosyncrasies when it comes to the Spack spec syntax and the use of certain shells
Spack's spec dependency syntax uses the carat (``^``) character, however this is an escape string in CMD
so it must be escaped with an additional carat (i.e. ``^^``).
CMD also will attempt to interpret strings with ``=`` characters in them. Any spec including this symbol
must double quote the string.
Note: All of these issues are unique to CMD, they can be avoided by using Powershell.
For more context on these caveats see the related issues: `carat <https://github.com/spack/spack/issues/42833>`_ and `equals <https://github.com/spack/spack/issues/43348>`_
Below are more details about the specifiers that you can add to specs. Below are more details about the specifiers that you can add to specs.
.. _version-specifier: .. _version-specifier:

View File

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

View File

@@ -218,8 +218,6 @@ def setup(sphinx):
("py:class", "spack.spec.SpecfileReaderBase"), ("py:class", "spack.spec.SpecfileReaderBase"),
("py:class", "spack.install_test.Pb"), ("py:class", "spack.install_test.Pb"),
("py:class", "spack.filesystem_view.SimpleFilesystemView"), ("py:class", "spack.filesystem_view.SimpleFilesystemView"),
("py:class", "spack.traverse.EdgeAndDepth"),
("py:class", "archspec.cpu.microarchitecture.Microarchitecture"),
] ]
# The reST default role (used for this markup: `text`) to use for all documents. # The reST default role (used for this markup: `text`) to use for all documents.

View File

@@ -316,215 +316,6 @@ documentation tests to make sure there are no errors. Documentation changes can
in some obfuscated warning messages. If you don't understand what they mean, feel free in some obfuscated warning messages. If you don't understand what they mean, feel free
to ask when you submit your PR. to ask when you submit your PR.
.. _spack-builders-and-pipelines:
^^^^^^^^^
GitLab CI
^^^^^^^^^
""""""""""""""""""
Build Cache Stacks
""""""""""""""""""
Spack welcomes the contribution of software stacks of interest to the community. These
stacks are used to test package recipes and generate publicly available build caches.
Spack uses GitLab CI for managing the orchestration of build jobs.
GitLab Entry Point
~~~~~~~~~~~~~~~~~~
Add stack entrypoint to the ``share/spack/gitlab/cloud_pipelines/.gitlab-ci.yml``. There
are two stages required for each new stack, the generation stage and the build stage.
The generate stage is defined using the job template ``.generate`` configured with
environment variables defining the name of the stack in ``SPACK_CI_STACK_NAME`` and the
platform (``SPACK_TARGET_PLATFORM``) and architecture (``SPACK_TARGET_ARCH``) configuration,
and the tags associated with the class of runners to build on.
.. note::
The ``SPACK_CI_STACK_NAME`` must match the name of the directory containing the
stacks ``spack.yaml``.
.. note::
The platform and architecture variables are specified in order to select the
correct configurations from the generic configurations used in Spack CI. The
configurations currently available are:
* ``.cray_rhel_zen4``
* ``.cray_sles_zen4``
* ``.darwin_aarch64``
* ``.darwin_x86_64``
* ``.linux_aarch64``
* ``.linux_icelake``
* ``.linux_neoverse_n1``
* ``.linux_neoverse_v1``
* ``.linux_neoverse_v2``
* ``.linux_power``
* ``.linux_skylake``
* ``.linux_x86_64``
* ``.linux_x86_64_v4``
New configurations can be added to accommodate new platforms and architectures.
The build stage is defined as a trigger job that consumes the GitLab CI pipeline generated in
the generate stage for this stack. Build stage jobs use the ``.build`` job template which
handles the basic configuration.
An example entry point for a new stack called ``my-super-cool-stack``
.. code-block:: yaml
.my-super-cool-stack:
extends: [ ".linux_x86_64_v3" ]
variables:
SPACK_CI_STACK_NAME: my-super-cool-stack
tags: [ "all", "tags", "your", "job", "needs"]
my-super-cool-stack-generate:
extends: [ ".generate", ".my-super-cool-stack" ]
image: my-super-cool-stack-image:0.0.1
my-super-cool-stack-build:
extends: [ ".build", ".my-super-cool-stack" ]
trigger:
include:
- artifact: jobs_scratch_dir/cloud-ci-pipeline.yml
job: my-super-cool-stack-generate
strategy: depend
needs:
- artifacts: True
job: my-super-cool-stack-generate
Stack Configuration
~~~~~~~~~~~~~~~~~~~
The stack configuration is a spack environment file with two additional sections added.
Stack configurations should be located in ``share/spack/gitlab/cloud_pipelines/stacks/<stack_name>/spack.yaml``.
The ``ci`` section is generally used to define stack specific mappings such as image or tags.
For more information on what can go into the ``ci`` section refer to the docs on pipelines.
The ``cdash`` section is used for defining where to upload the results of builds. Spack configures
most of the details for posting pipeline results to
`cdash.spack.io <https://cdash.spack.io/index.php?project=Spack+Testing>`_. The only
requirement in the stack configuration is to define a ``build-group`` that is unique,
this is usually the long name of the stack.
An example stack that builds ``zlib``.
.. code-block:: yaml
spack:
view: false
packages:
all:
require: ["%gcc", "target=x86_64_v3"]
specs:
- zlib
ci:
pipeline-gen
- build-job:
image: my-super-cool-stack-image:0.0.1
cdash:
build-group: My Super Cool Stack
.. note::
The ``image`` used in the ``*-generate`` job must match exactly the ``image`` used in the ``build-job``.
When the images do not match the build job may fail.
"""""""""""""""""""
Registering Runners
"""""""""""""""""""
Contributing computational resources to Spack's CI build farm is one way to help expand the
capabilities and offerings of the public Spack build caches. Currently, Spack utilizes linux runners
from AWS, Google, and the University of Oregon (UO).
Runners require three key peices:
* Runner Registration Token
* Accurate tags
* OIDC Authentication script
* GPG keys
Minimum GitLab Runner Version: ``16.1.0``
`Intallation instructions <https://docs.gitlab.com/runner/install/>`_
Registration Token
~~~~~~~~~~~~~~~~~~
The first step to contribute new runners is to open an issue in the `spack infrastructure <https://github.com/spack/spack-infrastructure/issues/new?assignees=&labels=runner-registration&projects=&template=runner_registration.yml>`_
project. This will be reported to the spack infrastructure team who will guide users through the process
of registering new runners for Spack CI.
The information needed to register a runner is the motivation for the new resources, a semi-detailed description of
the runner, and finallly the point of contact for maintaining the software on the runner.
The point of contact will then work with the infrastruture team to obtain runner registration token(s) for interacting with
with Spack's GitLab instance. Once the runner is active, this point of contact will also be responsible for updating the
GitLab runner software to keep pace with Spack's Gitlab.
Tagging
~~~~~~~
In the initial stages of runner registration it is important to **exclude** the special tag ``spack``. This will prevent
the new runner(s) from being picked up for production CI jobs while it is configured and evaluated. Once it is determined
that the runner is ready for production use the ``spack`` tag will be added.
Because gitlab has no concept of tag exclustion, runners that provide specialized resource also require specialized tags.
For example, a basic CPU only x86_64 runner may have a tag ``x86_64`` associated with it. However, a runner containing an
CUDA capable GPU may have the tag ``x86_64-cuda`` to denote that it should only be used for packages that will benefit from
a CUDA capable resource.
OIDC
~~~~
Spack runners use OIDC authentication for connecting to the appropriate AWS bucket
which is used for coordinating the communication of binaries between build jobs. In
order to configure OIDC authentication, Spack CI runners use a python script with minimal
dependencies. This script can be configured for runners as seen here using the ``pre_build_script``.
.. code-block:: toml
[[runners]]
pre_build_script = """
echo 'Executing Spack pre-build setup script'
for cmd in "${PY3:-}" python3 python; do
if command -v > /dev/null "$cmd"; then
export PY3="$(command -v "$cmd")"
break
fi
done
if [ -z "${PY3:-}" ]; then
echo "Unable to find python3 executable"
exit 1
fi
$PY3 -c "import urllib.request;urllib.request.urlretrieve('https://raw.githubusercontent.com/spack/spack-infrastructure/main/scripts/gitlab_runner_pre_build/pre_build.py', 'pre_build.py')"
$PY3 pre_build.py > envvars
. ./envvars
rm -f envvars
unset GITLAB_OIDC_TOKEN
"""
GPG Keys
~~~~~~~~
Runners that may be utilized for ``protected`` CI require the registration of an intermediate signing key that
can be used to sign packages. For more information on package signing read :ref:`key_architecture`.
-------- --------
Coverage Coverage
-------- --------

View File

@@ -181,6 +181,10 @@ Spec-related modules
:mod:`spack.parser` :mod:`spack.parser`
Contains :class:`~spack.parser.SpecParser` and functions related to parsing specs. Contains :class:`~spack.parser.SpecParser` and functions related to parsing specs.
:mod:`spack.concretize`
Contains :class:`~spack.concretize.Concretizer` implementation,
which allows site administrators to change Spack's :ref:`concretization-policies`.
:mod:`spack.version` :mod:`spack.version`
Implements a simple :class:`~spack.version.Version` class with simple Implements a simple :class:`~spack.version.Version` class with simple
comparison semantics. Also implements :class:`~spack.version.VersionRange` comparison semantics. Also implements :class:`~spack.version.VersionRange`

View File

@@ -414,13 +414,7 @@ default, it will also clone the package to a subdirectory in the
environment. This package will have a special variant ``dev_path`` environment. This package will have a special variant ``dev_path``
set, and Spack will ensure the package and its dependents are rebuilt set, and Spack will ensure the package and its dependents are rebuilt
any time the environment is installed if the package's local source any time the environment is installed if the package's local source
code has been modified. Spack's native implementation to check for modifications code has been modified. Spack ensures that all instances of a
is to check if ``mtime`` is newer than the installation.
A custom check can be created by overriding the ``detect_dev_src_change`` method
in your package class. This is particularly useful for projects using custom spack repo's
to drive development and want to optimize performance.
Spack ensures that all instances of a
developed package in the environment are concretized to match the developed package in the environment are concretized to match the
version (and other constraints) passed as the spec argument to the version (and other constraints) passed as the spec argument to the
``spack develop`` command. ``spack develop`` command.
@@ -869,7 +863,7 @@ named list ``compilers`` is ``['%gcc', '%clang', '%intel']`` on
spack: spack:
definitions: definitions:
- compilers: ['%gcc', '%clang'] - compilers: ['%gcc', '%clang']
- when: arch.satisfies('target=x86_64:') - when: arch.satisfies('x86_64:')
compilers: ['%intel'] compilers: ['%intel']
.. note:: .. note::

View File

@@ -61,15 +61,10 @@ Getting Spack is easy. You can clone it from the `github repository
.. code-block:: console .. code-block:: console
$ git clone -c feature.manyFiles=true --depth=2 https://github.com/spack/spack.git $ git clone -c feature.manyFiles=true https://github.com/spack/spack.git
This will create a directory called ``spack``. This will create a directory called ``spack``.
.. note::
``-c feature.manyFiles=true`` improves git's performance on repositories with 1,000+ files.
``--depth=2`` prunes the git history to reduce the size of the Spack installation.
.. _shell-support: .. _shell-support:
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
@@ -1480,14 +1475,16 @@ in a Windows CMD prompt.
Step 3: Run and configure Spack Step 3: Run and configure Spack
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
On Windows, Spack supports both primary native shells, Powershell and the traditional command prompt. To use Spack, run ``bin\spack_cmd.bat`` (you may need to Run as Administrator) from the top-level spack
To use Spack, pick your favorite shell, and run ``bin\spack_cmd.bat`` or ``share/spack/setup-env.ps1`` directory. This will provide a Windows command prompt with an environment properly set up with Spack
(you may need to Run as Administrator) from the top-level spack and its prerequisites. If you receive a warning message that Python is not in your ``PATH``
directory. This will provide a Spack enabled shell. If you receive a warning message that Python is not in your ``PATH``
(which may happen if you installed Python from the website and not the Windows Store) add the location (which may happen if you installed Python from the website and not the Windows Store) add the location
of the Python executable to your ``PATH`` now. You can permanently add Python to your ``PATH`` variable of the Python executable to your ``PATH`` now. You can permanently add Python to your ``PATH`` variable
by using the ``Edit the system environment variables`` utility in Windows Control Panel. by using the ``Edit the system environment variables`` utility in Windows Control Panel.
.. note::
Alternatively, Powershell can be used in place of CMD
To configure Spack, first run the following command inside the Spack console: To configure Spack, first run the following command inside the Spack console:
.. code-block:: console .. code-block:: console
@@ -1552,7 +1549,7 @@ and not tabs, so ensure that this is the case when editing one directly.
.. note:: Cygwin .. note:: Cygwin
The use of Cygwin is not officially supported by Spack and is not tested. The use of Cygwin is not officially supported by Spack and is not tested.
However Spack will not prevent this, so use if choosing to use Spack However Spack will not throw an error, so use if choosing to use Spack
with Cygwin, know that no functionality is garunteed. with Cygwin, know that no functionality is garunteed.
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
@@ -1566,12 +1563,21 @@ Spack console via:
spack install cpuinfo spack install cpuinfo
If in the previous step, you did not have CMake or Ninja installed, running the command above should install both packages If in the previous step, you did not have CMake or Ninja installed, running the command above should bootstrap both packages
.. note:: Spec Syntax Caveats """""""""""""""""""""""""""
Windows has a few idiosyncrasies when it comes to the Spack spec syntax and the use of certain shells Windows Compatible Packages
See the Spack spec syntax doc for more information """""""""""""""""""""""""""
Not all spack packages currently have Windows support. Some are inherently incompatible with the
platform, and others simply have yet to be ported. To view the current set of packages with Windows
support, the list command should be used via `spack list -t windows`. If there's a package you'd like
to install on Windows but is not in that list, feel free to reach out to request the port or contribute
the port yourself.
.. note::
This is by no means a comprehensive list, some packages may have ports that were not tagged
while others may just work out of the box on Windows and have not been tagged as such.
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
For developers For developers
@@ -1581,3 +1587,6 @@ The intent is to provide a Windows installer that will automatically set up
Python, Git, and Spack, instead of requiring the user to do so manually. Python, Git, and Spack, instead of requiring the user to do so manually.
Instructions for creating the installer are at Instructions for creating the installer are at
https://github.com/spack/spack/blob/develop/lib/spack/spack/cmd/installer/README.md https://github.com/spack/spack/blob/develop/lib/spack/spack/cmd/installer/README.md
Alternatively a pre-built copy of the Windows installer is available as an artifact of Spack's Windows CI
available at each run of the CI on develop or any PR.

View File

@@ -39,15 +39,10 @@ package:
.. code-block:: console .. code-block:: console
$ git clone -c feature.manyFiles=true --depth=2 https://github.com/spack/spack.git $ git clone -c feature.manyFiles=true https://github.com/spack/spack.git
$ cd spack/bin $ cd spack/bin
$ ./spack install libelf $ ./spack install libelf
.. note::
``-c feature.manyFiles=true`` improves git's performance on repositories with 1,000+ files.
``--depth=2`` prunes the git history to reduce the size of the Spack installation.
If you're new to spack and want to start using it, see :doc:`getting_started`, If you're new to spack and want to start using it, see :doc:`getting_started`,
or refer to the full manual below. or refer to the full manual below.

View File

@@ -663,7 +663,11 @@ build the package.
When including a bootstrapping phase as in the example above, the result is that When including a bootstrapping phase as in the example above, the result is that
the bootstrapped compiler packages will be pushed to the binary mirror (and the the bootstrapped compiler packages will be pushed to the binary mirror (and the
local artifacts mirror) before the actual release specs are built. local artifacts mirror) before the actual release specs are built. In this case,
the jobs corresponding to subsequent release specs are configured to
``install_missing_compilers``, so that if spack is asked to install a package
with a compiler it doesn't know about, it can be quickly installed from the
binary mirror first.
Since bootstrapping compilers is optional, those items can be left out of the Since bootstrapping compilers is optional, those items can be left out of the
environment/stack file, and in that case no bootstrapping will be done (only the environment/stack file, and in that case no bootstrapping will be done (only the

View File

@@ -5,8 +5,8 @@ sphinx-rtd-theme==2.0.0
python-levenshtein==0.25.1 python-levenshtein==0.25.1
docutils==0.20.1 docutils==0.20.1
pygments==2.18.0 pygments==2.18.0
urllib3==2.2.3 urllib3==2.2.2
pytest==8.3.3 pytest==8.3.2
isort==5.13.2 isort==5.13.2
black==24.8.0 black==24.8.0
flake8==7.1.1 flake8==7.1.1

276
lib/spack/env/cc vendored
View File

@@ -101,9 +101,10 @@ setsep() {
esac esac
} }
# prepend LISTNAME ELEMENT # prepend LISTNAME ELEMENT [SEP]
# #
# Prepend ELEMENT to the list stored in the variable LISTNAME. # Prepend ELEMENT to the list stored in the variable LISTNAME,
# assuming the list is separated by SEP.
# Handles empty lists and single-element lists. # Handles empty lists and single-element lists.
prepend() { prepend() {
varname="$1" varname="$1"
@@ -118,39 +119,18 @@ prepend() {
fi fi
} }
# contains LISTNAME ELEMENT # append LISTNAME ELEMENT [SEP]
# #
# Test whether LISTNAME contains ELEMENT. # Append ELEMENT to the list stored in the variable LISTNAME,
# Set $? to 1 if LISTNAME does not contain ELEMENT. # assuming the list is separated by SEP.
# Set $? to 0 if LISTNAME does not contain ELEMENT.
contains() {
varname="$1"
elt="$2"
setsep "$varname"
# the list may: 1) only contain the element, 2) start with the element,
# 3) contain the element in the middle, or 4) end wtih the element.
eval "[ \"\${$varname}\" = \"$elt\" ]" \
|| eval "[ \"\${$varname#${elt}${sep}}\" != \"\${$varname}\" ]" \
|| eval "[ \"\${$varname#*${sep}${elt}${sep}}\" != \"\${$varname}\" ]" \
|| eval "[ \"\${$varname%${sep}${elt}}\" != \"\${$varname}\" ]"
}
# append LISTNAME ELEMENT [unique]
#
# Append ELEMENT to the list stored in the variable LISTNAME.
# Handles empty lists and single-element lists. # Handles empty lists and single-element lists.
#
# If the third argument is provided and if it is the string 'unique',
# this will not append if ELEMENT is already in the list LISTNAME.
append() { append() {
varname="$1" varname="$1"
elt="$2" elt="$2"
if empty "$varname"; then if empty "$varname"; then
eval "$varname=\"\${elt}\"" eval "$varname=\"\${elt}\""
elif [ "$3" != "unique" ] || ! contains "$varname" "$elt" ; then else
# Get the appropriate separator for the list we're appending to. # Get the appropriate separator for the list we're appending to.
setsep "$varname" setsep "$varname"
eval "$varname=\"\${$varname}${sep}\${elt}\"" eval "$varname=\"\${$varname}${sep}\${elt}\""
@@ -168,21 +148,10 @@ extend() {
if [ "$sep" != " " ]; then if [ "$sep" != " " ]; then
IFS="$sep" IFS="$sep"
fi fi
eval "for elt in \${$2}; do append $1 \"$3\${elt}\" ${_append_args}; done" eval "for elt in \${$2}; do append $1 \"$3\${elt}\"; done"
unset IFS unset IFS
} }
# extend_unique LISTNAME1 LISTNAME2 [PREFIX]
#
# Append the elements stored in the variable LISTNAME2 to the list
# stored in LISTNAME1, if they are not already present.
# If PREFIX is provided, prepend it to each element.
extend_unique() {
_append_args="unique"
extend "$@"
unset _append_args
}
# preextend LISTNAME1 LISTNAME2 [PREFIX] # preextend LISTNAME1 LISTNAME2 [PREFIX]
# #
# Prepend the elements stored in the list at LISTNAME2 # Prepend the elements stored in the list at LISTNAME2
@@ -269,36 +238,6 @@ esac
} }
" "
# path_list functions. Path_lists have 3 parts: spack_store_<list>, <list> and system_<list>,
# which are used to prioritize paths when assembling the final command line.
# init_path_lists LISTNAME
# Set <LISTNAME>, spack_store_<LISTNAME>, and system_<LISTNAME> to "".
init_path_lists() {
eval "spack_store_$1=\"\""
eval "$1=\"\""
eval "system_$1=\"\""
}
# assign_path_lists LISTNAME1 LISTNAME2
# Copy contents of LISTNAME2 into LISTNAME1, for each path_list prefix.
assign_path_lists() {
eval "spack_store_$1=\"\${spack_store_$2}\""
eval "$1=\"\${$2}\""
eval "system_$1=\"\${system_$2}\""
}
# append_path_lists LISTNAME ELT
# Append the provided ELT to the appropriate list, based on the result of path_order().
append_path_lists() {
path_order "$2"
case $? in
0) eval "append spack_store_$1 \"\$2\"" ;;
1) eval "append $1 \"\$2\"" ;;
2) eval "append system_$1 \"\$2\"" ;;
esac
}
# Check if optional parameters are defined # Check if optional parameters are defined
# If we aren't asking for debug flags, don't add them # If we aren't asking for debug flags, don't add them
if [ -z "${SPACK_ADD_DEBUG_FLAGS:-}" ]; then if [ -z "${SPACK_ADD_DEBUG_FLAGS:-}" ]; then
@@ -531,7 +470,12 @@ input_command="$*"
parse_Wl() { parse_Wl() {
while [ $# -ne 0 ]; do while [ $# -ne 0 ]; do
if [ "$wl_expect_rpath" = yes ]; then if [ "$wl_expect_rpath" = yes ]; then
append_path_lists return_rpath_dirs_list "$1" path_order "$1"
case $? in
0) append return_spack_store_rpath_dirs_list "$1" ;;
1) append return_rpath_dirs_list "$1" ;;
2) append return_system_rpath_dirs_list "$1" ;;
esac
wl_expect_rpath=no wl_expect_rpath=no
else else
case "$1" in case "$1" in
@@ -540,14 +484,24 @@ parse_Wl() {
if [ -z "$arg" ]; then if [ -z "$arg" ]; then
shift; continue shift; continue
fi fi
append_path_lists return_rpath_dirs_list "$arg" path_order "$arg"
case $? in
0) append return_spack_store_rpath_dirs_list "$arg" ;;
1) append return_rpath_dirs_list "$arg" ;;
2) append return_system_rpath_dirs_list "$arg" ;;
esac
;; ;;
--rpath=*) --rpath=*)
arg="${1#--rpath=}" arg="${1#--rpath=}"
if [ -z "$arg" ]; then if [ -z "$arg" ]; then
shift; continue shift; continue
fi fi
append_path_lists return_rpath_dirs_list "$arg" path_order "$arg"
case $? in
0) append return_spack_store_rpath_dirs_list "$arg" ;;
1) append return_rpath_dirs_list "$arg" ;;
2) append return_system_rpath_dirs_list "$arg" ;;
esac
;; ;;
-rpath|--rpath) -rpath|--rpath)
wl_expect_rpath=yes wl_expect_rpath=yes
@@ -555,7 +509,8 @@ parse_Wl() {
"$dtags_to_strip") "$dtags_to_strip")
;; ;;
-Wl) -Wl)
# Nested -Wl,-Wl means we're in NAG compiler territory. We don't support it. # Nested -Wl,-Wl means we're in NAG compiler territory, we don't support
# it.
return 1 return 1
;; ;;
*) *)
@@ -574,10 +529,21 @@ categorize_arguments() {
return_other_args_list="" return_other_args_list=""
return_isystem_was_used="" return_isystem_was_used=""
init_path_lists return_isystem_include_dirs_list return_isystem_spack_store_include_dirs_list=""
init_path_lists return_include_dirs_list return_isystem_system_include_dirs_list=""
init_path_lists return_lib_dirs_list return_isystem_include_dirs_list=""
init_path_lists return_rpath_dirs_list
return_spack_store_include_dirs_list=""
return_system_include_dirs_list=""
return_include_dirs_list=""
return_spack_store_lib_dirs_list=""
return_system_lib_dirs_list=""
return_lib_dirs_list=""
return_spack_store_rpath_dirs_list=""
return_system_rpath_dirs_list=""
return_rpath_dirs_list=""
# Global state for keeping track of -Wl,-rpath -Wl,/path # Global state for keeping track of -Wl,-rpath -Wl,/path
wl_expect_rpath=no wl_expect_rpath=no
@@ -643,17 +609,32 @@ categorize_arguments() {
arg="${1#-isystem}" arg="${1#-isystem}"
return_isystem_was_used=true return_isystem_was_used=true
if [ -z "$arg" ]; then shift; arg="$1"; fi if [ -z "$arg" ]; then shift; arg="$1"; fi
append_path_lists return_isystem_include_dirs_list "$arg" path_order "$arg"
case $? in
0) append return_isystem_spack_store_include_dirs_list "$arg" ;;
1) append return_isystem_include_dirs_list "$arg" ;;
2) append return_isystem_system_include_dirs_list "$arg" ;;
esac
;; ;;
-I*) -I*)
arg="${1#-I}" arg="${1#-I}"
if [ -z "$arg" ]; then shift; arg="$1"; fi if [ -z "$arg" ]; then shift; arg="$1"; fi
append_path_lists return_include_dirs_list "$arg" path_order "$arg"
case $? in
0) append return_spack_store_include_dirs_list "$arg" ;;
1) append return_include_dirs_list "$arg" ;;
2) append return_system_include_dirs_list "$arg" ;;
esac
;; ;;
-L*) -L*)
arg="${1#-L}" arg="${1#-L}"
if [ -z "$arg" ]; then shift; arg="$1"; fi if [ -z "$arg" ]; then shift; arg="$1"; fi
append_path_lists return_lib_dirs_list "$arg" path_order "$arg"
case $? in
0) append return_spack_store_lib_dirs_list "$arg" ;;
1) append return_lib_dirs_list "$arg" ;;
2) append return_system_lib_dirs_list "$arg" ;;
esac
;; ;;
-l*) -l*)
# -loopopt=0 is generated erroneously in autoconf <= 2.69, # -loopopt=0 is generated erroneously in autoconf <= 2.69,
@@ -686,17 +667,32 @@ categorize_arguments() {
break break
elif [ "$xlinker_expect_rpath" = yes ]; then elif [ "$xlinker_expect_rpath" = yes ]; then
# Register the path of -Xlinker -rpath <other args> -Xlinker <path> # Register the path of -Xlinker -rpath <other args> -Xlinker <path>
append_path_lists return_rpath_dirs_list "$1" path_order "$1"
case $? in
0) append return_spack_store_rpath_dirs_list "$1" ;;
1) append return_rpath_dirs_list "$1" ;;
2) append return_system_rpath_dirs_list "$1" ;;
esac
xlinker_expect_rpath=no xlinker_expect_rpath=no
else else
case "$1" in case "$1" in
-rpath=*) -rpath=*)
arg="${1#-rpath=}" arg="${1#-rpath=}"
append_path_lists return_rpath_dirs_list "$arg" path_order "$arg"
case $? in
0) append return_spack_store_rpath_dirs_list "$arg" ;;
1) append return_rpath_dirs_list "$arg" ;;
2) append return_system_rpath_dirs_list "$arg" ;;
esac
;; ;;
--rpath=*) --rpath=*)
arg="${1#--rpath=}" arg="${1#--rpath=}"
append_path_lists return_rpath_dirs_list "$arg" path_order "$arg"
case $? in
0) append return_spack_store_rpath_dirs_list "$arg" ;;
1) append return_rpath_dirs_list "$arg" ;;
2) append return_system_rpath_dirs_list "$arg" ;;
esac
;; ;;
-rpath|--rpath) -rpath|--rpath)
xlinker_expect_rpath=yes xlinker_expect_rpath=yes
@@ -713,32 +709,7 @@ categorize_arguments() {
"$dtags_to_strip") "$dtags_to_strip")
;; ;;
*) *)
# if mode is not ld, we can just add to other args append return_other_args_list "$1"
if [ "$mode" != "ld" ]; then
append return_other_args_list "$1"
shift
continue
fi
# if we're in linker mode, we need to parse raw RPATH args
case "$1" in
-rpath=*)
arg="${1#-rpath=}"
append_path_lists return_rpath_dirs_list "$arg"
;;
--rpath=*)
arg="${1#--rpath=}"
append_path_lists return_rpath_dirs_list "$arg"
;;
-rpath|--rpath)
shift
[ $# -eq 0 ] && break # ignore -rpath without value
append_path_lists return_rpath_dirs_list "$1"
;;
*)
append return_other_args_list "$1"
;;
esac
;; ;;
esac esac
shift shift
@@ -760,10 +731,21 @@ categorize_arguments() {
categorize_arguments "$@" categorize_arguments "$@"
assign_path_lists isystem_include_dirs_list return_isystem_include_dirs_list spack_store_include_dirs_list="$return_spack_store_include_dirs_list"
assign_path_lists include_dirs_list return_include_dirs_list system_include_dirs_list="$return_system_include_dirs_list"
assign_path_lists lib_dirs_list return_lib_dirs_list include_dirs_list="$return_include_dirs_list"
assign_path_lists rpath_dirs_list return_rpath_dirs_list
spack_store_lib_dirs_list="$return_spack_store_lib_dirs_list"
system_lib_dirs_list="$return_system_lib_dirs_list"
lib_dirs_list="$return_lib_dirs_list"
spack_store_rpath_dirs_list="$return_spack_store_rpath_dirs_list"
system_rpath_dirs_list="$return_system_rpath_dirs_list"
rpath_dirs_list="$return_rpath_dirs_list"
isystem_spack_store_include_dirs_list="$return_isystem_spack_store_include_dirs_list"
isystem_system_include_dirs_list="$return_isystem_system_include_dirs_list"
isystem_include_dirs_list="$return_isystem_include_dirs_list"
isystem_was_used="$return_isystem_was_used" isystem_was_used="$return_isystem_was_used"
other_args_list="$return_other_args_list" other_args_list="$return_other_args_list"
@@ -839,10 +821,21 @@ IFS="$lsep"
categorize_arguments $spack_flags_list categorize_arguments $spack_flags_list
unset IFS unset IFS
assign_path_lists spack_flags_isystem_include_dirs_list return_isystem_include_dirs_list spack_flags_isystem_spack_store_include_dirs_list="$return_isystem_spack_store_include_dirs_list"
assign_path_lists spack_flags_include_dirs_list return_include_dirs_list spack_flags_isystem_system_include_dirs_list="$return_isystem_system_include_dirs_list"
assign_path_lists spack_flags_lib_dirs_list return_lib_dirs_list spack_flags_isystem_include_dirs_list="$return_isystem_include_dirs_list"
assign_path_lists spack_flags_rpath_dirs_list return_rpath_dirs_list
spack_flags_spack_store_include_dirs_list="$return_spack_store_include_dirs_list"
spack_flags_system_include_dirs_list="$return_system_include_dirs_list"
spack_flags_include_dirs_list="$return_include_dirs_list"
spack_flags_spack_store_lib_dirs_list="$return_spack_store_lib_dirs_list"
spack_flags_system_lib_dirs_list="$return_system_lib_dirs_list"
spack_flags_lib_dirs_list="$return_lib_dirs_list"
spack_flags_spack_store_rpath_dirs_list="$return_spack_store_rpath_dirs_list"
spack_flags_system_rpath_dirs_list="$return_system_rpath_dirs_list"
spack_flags_rpath_dirs_list="$return_rpath_dirs_list"
spack_flags_isystem_was_used="$return_isystem_was_used" spack_flags_isystem_was_used="$return_isystem_was_used"
spack_flags_other_args_list="$return_other_args_list" spack_flags_other_args_list="$return_other_args_list"
@@ -901,7 +894,7 @@ esac
case "$mode" in case "$mode" in
cpp|cc|as|ccld) cpp|cc|as|ccld)
if [ "$spack_flags_isystem_was_used" = "true" ] || [ "$isystem_was_used" = "true" ]; then if [ "$spack_flags_isystem_was_used" = "true" ] || [ "$isystem_was_used" = "true" ]; then
extend spack_store_isystem_include_dirs_list SPACK_STORE_INCLUDE_DIRS extend isystem_spack_store_include_dirs_list SPACK_STORE_INCLUDE_DIRS
extend isystem_include_dirs_list SPACK_INCLUDE_DIRS extend isystem_include_dirs_list SPACK_INCLUDE_DIRS
else else
extend spack_store_include_dirs_list SPACK_STORE_INCLUDE_DIRS extend spack_store_include_dirs_list SPACK_STORE_INCLUDE_DIRS
@@ -917,63 +910,64 @@ args_list="$flags_list"
# Include search paths partitioned by (in store, non-sytem, system) # Include search paths partitioned by (in store, non-sytem, system)
# NOTE: adding ${lsep} to the prefix here turns every added element into two # NOTE: adding ${lsep} to the prefix here turns every added element into two
extend args_list spack_store_spack_flags_include_dirs_list -I extend args_list spack_flags_spack_store_include_dirs_list -I
extend args_list spack_store_include_dirs_list -I extend args_list spack_store_include_dirs_list -I
extend args_list spack_flags_include_dirs_list -I extend args_list spack_flags_include_dirs_list -I
extend args_list include_dirs_list -I extend args_list include_dirs_list -I
extend args_list spack_store_spack_flags_isystem_include_dirs_list "-isystem${lsep}" extend args_list spack_flags_isystem_spack_store_include_dirs_list "-isystem${lsep}"
extend args_list spack_store_isystem_include_dirs_list "-isystem${lsep}" extend args_list isystem_spack_store_include_dirs_list "-isystem${lsep}"
extend args_list spack_flags_isystem_include_dirs_list "-isystem${lsep}" extend args_list spack_flags_isystem_include_dirs_list "-isystem${lsep}"
extend args_list isystem_include_dirs_list "-isystem${lsep}" extend args_list isystem_include_dirs_list "-isystem${lsep}"
extend args_list system_spack_flags_include_dirs_list -I extend args_list spack_flags_system_include_dirs_list -I
extend args_list system_include_dirs_list -I extend args_list system_include_dirs_list -I
extend args_list system_spack_flags_isystem_include_dirs_list "-isystem${lsep}" extend args_list spack_flags_isystem_system_include_dirs_list "-isystem${lsep}"
extend args_list system_isystem_include_dirs_list "-isystem${lsep}" extend args_list isystem_system_include_dirs_list "-isystem${lsep}"
# Library search paths partitioned by (in store, non-sytem, system) # Library search paths partitioned by (in store, non-sytem, system)
extend args_list spack_store_spack_flags_lib_dirs_list "-L" extend args_list spack_flags_spack_store_lib_dirs_list "-L"
extend args_list spack_store_lib_dirs_list "-L" extend args_list spack_store_lib_dirs_list "-L"
extend args_list spack_flags_lib_dirs_list "-L" extend args_list spack_flags_lib_dirs_list "-L"
extend args_list lib_dirs_list "-L" extend args_list lib_dirs_list "-L"
extend args_list system_spack_flags_lib_dirs_list "-L" extend args_list spack_flags_system_lib_dirs_list "-L"
extend args_list system_lib_dirs_list "-L" extend args_list system_lib_dirs_list "-L"
# RPATHs arguments # RPATHs arguments
rpath_prefix=""
case "$mode" in case "$mode" in
ccld) ccld)
if [ -n "$dtags_to_add" ] ; then if [ -n "$dtags_to_add" ] ; then
append args_list "$linker_arg$dtags_to_add" append args_list "$linker_arg$dtags_to_add"
fi fi
rpath_prefix="$rpath" extend args_list spack_flags_spack_store_rpath_dirs_list "$rpath"
extend args_list spack_store_rpath_dirs_list "$rpath"
extend args_list spack_flags_rpath_dirs_list "$rpath"
extend args_list rpath_dirs_list "$rpath"
extend args_list spack_flags_system_rpath_dirs_list "$rpath"
extend args_list system_rpath_dirs_list "$rpath"
;; ;;
ld) ld)
if [ -n "$dtags_to_add" ] ; then if [ -n "$dtags_to_add" ] ; then
append args_list "$dtags_to_add" append args_list "$dtags_to_add"
fi fi
rpath_prefix="-rpath${lsep}" extend args_list spack_flags_spack_store_rpath_dirs_list "-rpath${lsep}"
extend args_list spack_store_rpath_dirs_list "-rpath${lsep}"
extend args_list spack_flags_rpath_dirs_list "-rpath${lsep}"
extend args_list rpath_dirs_list "-rpath${lsep}"
extend args_list spack_flags_system_rpath_dirs_list "-rpath${lsep}"
extend args_list system_rpath_dirs_list "-rpath${lsep}"
;; ;;
esac esac
# if mode is ccld or ld, extend RPATH lists with the prefix determined above
if [ -n "$rpath_prefix" ]; then
extend_unique args_list spack_store_spack_flags_rpath_dirs_list "$rpath_prefix"
extend_unique args_list spack_store_rpath_dirs_list "$rpath_prefix"
extend_unique args_list spack_flags_rpath_dirs_list "$rpath_prefix"
extend_unique args_list rpath_dirs_list "$rpath_prefix"
extend_unique args_list system_spack_flags_rpath_dirs_list "$rpath_prefix"
extend_unique args_list system_rpath_dirs_list "$rpath_prefix"
fi
# Other arguments from the input command # Other arguments from the input command
extend args_list other_args_list extend args_list other_args_list
extend args_list spack_flags_other_args_list extend args_list spack_flags_other_args_list

View File

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

View File

@@ -115,9 +115,6 @@ def __eq__(self, other):
and self.cpu_part == other.cpu_part and self.cpu_part == other.cpu_part
) )
def __hash__(self):
return hash(self.name)
@coerce_target_names @coerce_target_names
def __ne__(self, other): def __ne__(self, other):
return not self == other return not self == other

View File

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

View File

@@ -27,6 +27,8 @@
from llnl.util.lang import dedupe, memoized from llnl.util.lang import dedupe, memoized
from llnl.util.symlink import islink, readlink, resolve_link_target_relative_to_the_link, symlink from llnl.util.symlink import islink, readlink, resolve_link_target_relative_to_the_link, symlink
from spack.util.executable import Executable, which
from ..path import path_to_os_path, system_path_filter from ..path import path_to_os_path, system_path_filter
if sys.platform != "win32": if sys.platform != "win32":
@@ -51,6 +53,7 @@
"find_all_headers", "find_all_headers",
"find_libraries", "find_libraries",
"find_system_libraries", "find_system_libraries",
"fix_darwin_install_name",
"force_remove", "force_remove",
"force_symlink", "force_symlink",
"getuid", "getuid",
@@ -245,6 +248,42 @@ def path_contains_subdirectory(path, root):
return norm_path.startswith(norm_root) return norm_path.startswith(norm_root)
@memoized
def file_command(*args):
"""Creates entry point to `file` system command with provided arguments"""
file_cmd = which("file", required=True)
for arg in args:
file_cmd.add_default_arg(arg)
return file_cmd
@memoized
def _get_mime_type():
"""Generate method to call `file` system command to aquire mime type
for a specified path
"""
if sys.platform == "win32":
# -h option (no-dereference) does not exist in Windows
return file_command("-b", "--mime-type")
else:
return file_command("-b", "-h", "--mime-type")
def mime_type(filename):
"""Returns the mime type and subtype of a file.
Args:
filename: file to be analyzed
Returns:
Tuple containing the MIME type and subtype
"""
output = _get_mime_type()(filename, output=str, error=str).strip()
tty.debug("==> " + output)
type, _, subtype = output.partition("/")
return type, subtype
#: This generates the library filenames that may appear on any OS. #: This generates the library filenames that may appear on any OS.
library_extensions = ["a", "la", "so", "tbd", "dylib"] library_extensions = ["a", "la", "so", "tbd", "dylib"]
@@ -1640,6 +1679,41 @@ def safe_remove(*files_or_dirs):
raise raise
@system_path_filter
def fix_darwin_install_name(path):
"""Fix install name of dynamic libraries on Darwin to have full path.
There are two parts of this task:
1. Use ``install_name('-id', ...)`` to change install name of a single lib
2. Use ``install_name('-change', ...)`` to change the cross linking between
libs. The function assumes that all libraries are in one folder and
currently won't follow subfolders.
Parameters:
path (str): directory in which .dylib files are located
"""
libs = glob.glob(join_path(path, "*.dylib"))
for lib in libs:
# fix install name first:
install_name_tool = Executable("install_name_tool")
install_name_tool("-id", lib, lib)
otool = Executable("otool")
long_deps = otool("-L", lib, output=str).split("\n")
deps = [dep.partition(" ")[0][1::] for dep in long_deps[2:-1]]
# fix all dependencies:
for dep in deps:
for loc in libs:
# We really want to check for either
# dep == os.path.basename(loc) or
# dep == join_path(builddir, os.path.basename(loc)),
# but we don't know builddir (nor how symbolic links look
# in builddir). We thus only compare the basenames.
if os.path.basename(dep) == os.path.basename(loc):
install_name_tool("-change", dep, loc, lib)
break
def find_first(root: str, files: Union[Iterable[str], str], bfs_depth: int = 2) -> Optional[str]: def find_first(root: str, files: Union[Iterable[str], str], bfs_depth: int = 2) -> Optional[str]:
"""Find the first file matching a pattern. """Find the first file matching a pattern.

View File

@@ -843,19 +843,20 @@ def uniq(sequence):
return uniq_list return uniq_list
def elide_list(line_list: List[str], max_num: int = 10) -> List[str]: def elide_list(line_list, max_num=10):
"""Takes a long list and limits it to a smaller number of elements, """Takes a long list and limits it to a smaller number of elements,
replacing intervening elements with '...'. For example:: replacing intervening elements with '...'. For example::
elide_list(["1", "2", "3", "4", "5", "6"], 4) elide_list([1,2,3,4,5,6], 4)
gives:: gives::
["1", "2", "3", "...", "6"] [1, 2, 3, '...', 6]
""" """
if len(line_list) > max_num: if len(line_list) > max_num:
return [*line_list[: max_num - 1], "...", line_list[-1]] return line_list[: max_num - 1] + ["..."] + line_list[-1:]
return line_list else:
return line_list
@contextlib.contextmanager @contextlib.contextmanager

View File

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

View File

@@ -46,14 +46,11 @@ def _search_duplicate_compilers(error_cls):
import pickle import pickle
import re import re
import warnings import warnings
from typing import Iterable, List, Set, Tuple
from urllib.request import urlopen from urllib.request import urlopen
import llnl.util.lang import llnl.util.lang
import spack.builder
import spack.config import spack.config
import spack.fetch_strategy
import spack.patch import spack.patch
import spack.repo import spack.repo
import spack.spec import spack.spec
@@ -76,9 +73,7 @@ def __init__(self, summary, details):
self.details = tuple(details) self.details = tuple(details)
def __str__(self): def __str__(self):
if self.details: return self.summary + "\n" + "\n".join([" " + detail for detail in self.details])
return f"{self.summary}\n" + "\n".join(f" {detail}" for detail in self.details)
return self.summary
def __eq__(self, other): def __eq__(self, other):
if self.summary != other.summary or self.details != other.details: if self.summary != other.summary or self.details != other.details:
@@ -262,6 +257,40 @@ def _search_duplicate_specs_in_externals(error_cls):
return errors return errors
@config_packages
def _deprecated_preferences(error_cls):
"""Search package preferences deprecated in v0.21 (and slated for removal in v0.23)"""
# TODO (v0.23): remove this audit as the attributes will not be allowed in config
errors = []
packages_yaml = spack.config.CONFIG.get_config("packages")
def make_error(attribute_name, config_data, summary):
s = io.StringIO()
s.write("Occurring in the following file:\n")
dict_view = syaml.syaml_dict((k, v) for k, v in config_data.items() if k == attribute_name)
syaml.dump_config(dict_view, stream=s, blame=True)
return error_cls(summary=summary, details=[s.getvalue()])
if "all" in packages_yaml and "version" in packages_yaml["all"]:
summary = "Using the deprecated 'version' attribute under 'packages:all'"
errors.append(make_error("version", packages_yaml["all"], summary))
for package_name in packages_yaml:
if package_name == "all":
continue
package_conf = packages_yaml[package_name]
for attribute in ("compiler", "providers", "target"):
if attribute not in package_conf:
continue
summary = (
f"Using the deprecated '{attribute}' attribute " f"under 'packages:{package_name}'"
)
errors.append(make_error(attribute, package_conf, summary))
return errors
@config_packages @config_packages
def _avoid_mismatched_variants(error_cls): def _avoid_mismatched_variants(error_cls):
"""Warns if variant preferences have mismatched types or names.""" """Warns if variant preferences have mismatched types or names."""
@@ -282,7 +311,7 @@ def _avoid_mismatched_variants(error_cls):
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name) pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
for variant in current_spec.variants.values(): for variant in current_spec.variants.values():
# Variant does not exist at all # Variant does not exist at all
if variant.name not in pkg_cls.variant_names(): if variant.name not in pkg_cls.variants:
summary = ( summary = (
f"Setting a preference for the '{pkg_name}' package to the " f"Setting a preference for the '{pkg_name}' package to the "
f"non-existing variant '{variant.name}'" f"non-existing variant '{variant.name}'"
@@ -291,8 +320,9 @@ def _avoid_mismatched_variants(error_cls):
continue continue
# Variant cannot accept this value # Variant cannot accept this value
s = spack.spec.Spec(pkg_name)
try: try:
spack.variant.prevalidate_variant_value(pkg_cls, variant, strict=True) s.update_variant_validate(variant.name, variant.value)
except Exception: except Exception:
summary = ( summary = (
f"Setting the variant '{variant.name}' of the '{pkg_name}' package " f"Setting the variant '{variant.name}' of the '{pkg_name}' package "
@@ -662,15 +692,9 @@ def _ensure_env_methods_are_ported_to_builders(pkgs, error_cls):
errors = [] errors = []
for pkg_name in pkgs: for pkg_name in pkgs:
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name) pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
buildsystem_variant, _ = pkg_cls.variants["build_system"]
# values are either Value objects (for conditional values) or the values themselves buildsystem_names = [getattr(x, "value", x) for x in buildsystem_variant.values]
build_system_names = set( builder_cls_names = [spack.builder.BUILDER_CLS[x].__name__ for x in buildsystem_names]
v.value if isinstance(v, spack.variant.Value) else v
for _, variant in pkg_cls.variant_definitions("build_system")
for v in variant.values
)
builder_cls_names = [spack.builder.BUILDER_CLS[x].__name__ for x in build_system_names]
module = pkg_cls.module module = pkg_cls.module
has_builders_in_package_py = any( has_builders_in_package_py = any(
getattr(module, name, False) for name in builder_cls_names getattr(module, name, False) for name in builder_cls_names
@@ -689,88 +713,6 @@ def _ensure_env_methods_are_ported_to_builders(pkgs, error_cls):
return errors return errors
class DeprecatedMagicGlobals(ast.NodeVisitor):
def __init__(self, magic_globals: Iterable[str]):
super().__init__()
self.magic_globals: Set[str] = set(magic_globals)
# State to track whether we're in a class function
self.depth: int = 0
self.in_function: bool = False
self.path = (ast.Module, ast.ClassDef, ast.FunctionDef)
# Defined locals in the current function (heuristically at least)
self.locals: Set[str] = set()
# List of (name, lineno) tuples for references to magic globals
self.references_to_globals: List[Tuple[str, int]] = []
def descend_in_function_def(self, node: ast.AST) -> None:
if not isinstance(node, self.path[self.depth]):
return
self.depth += 1
if self.depth == len(self.path):
self.in_function = True
super().generic_visit(node)
if self.depth == len(self.path):
self.in_function = False
self.locals.clear()
self.depth -= 1
def generic_visit(self, node: ast.AST) -> None:
# Recurse into function definitions
if self.depth < len(self.path):
return self.descend_in_function_def(node)
elif not self.in_function:
return
elif isinstance(node, ast.Global):
for name in node.names:
if name in self.magic_globals:
self.references_to_globals.append((name, node.lineno))
elif isinstance(node, ast.Assign):
# visit the rhs before lhs
super().visit(node.value)
for target in node.targets:
super().visit(target)
elif isinstance(node, ast.Name) and node.id in self.magic_globals:
if isinstance(node.ctx, ast.Load) and node.id not in self.locals:
self.references_to_globals.append((node.id, node.lineno))
elif isinstance(node.ctx, ast.Store):
self.locals.add(node.id)
else:
super().generic_visit(node)
@package_properties
def _uses_deprecated_globals(pkgs, error_cls):
"""Ensure that packages do not use deprecated globals"""
errors = []
for pkg_name in pkgs:
# some packages scheduled to be removed in v0.23 are not worth fixing.
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
if all(v.get("deprecated", False) for v in pkg_cls.versions.values()):
continue
file = spack.repo.PATH.filename_for_package_name(pkg_name)
tree = ast.parse(open(file).read())
visitor = DeprecatedMagicGlobals(("std_cmake_args",))
visitor.visit(tree)
if visitor.references_to_globals:
errors.append(
error_cls(
f"Package '{pkg_name}' uses deprecated globals",
[
f"{file}:{line} references '{name}'"
for name, line in visitor.references_to_globals
],
)
)
return errors
@package_https_directives @package_https_directives
def _linting_package_file(pkgs, error_cls): def _linting_package_file(pkgs, error_cls):
"""Check for correctness of links""" """Check for correctness of links"""
@@ -937,22 +879,20 @@ def check_virtual_with_variants(spec, msg):
# check variants # check variants
dependency_variants = dep.spec.variants dependency_variants = dep.spec.variants
for name, variant in dependency_variants.items(): for name, value in dependency_variants.items():
try: try:
spack.variant.prevalidate_variant_value( v, _ = dependency_pkg_cls.variants[name]
dependency_pkg_cls, variant, dep.spec, strict=True v.validate_or_raise(value, pkg_cls=dependency_pkg_cls)
)
except Exception as e: except Exception as e:
summary = ( summary = (
f"{pkg_name}: wrong variant used for dependency in 'depends_on()'" f"{pkg_name}: wrong variant used for dependency in 'depends_on()'"
) )
error_msg = str(e)
if isinstance(e, KeyError): if isinstance(e, KeyError):
error_msg = ( error_msg = (
f"variant {str(e).strip()} does not exist in package {dep_name}" f"variant {str(e).strip()} does not exist in package {dep_name}"
f" in package '{dep_name}'"
) )
error_msg += f" in package '{dep_name}'"
errors.append( errors.append(
error_cls(summary=summary, details=[error_msg, f"in {filename}"]) error_cls(summary=summary, details=[error_msg, f"in {filename}"])
@@ -964,38 +904,39 @@ def check_virtual_with_variants(spec, msg):
@package_directives @package_directives
def _ensure_variant_defaults_are_parsable(pkgs, error_cls): def _ensure_variant_defaults_are_parsable(pkgs, error_cls):
"""Ensures that variant defaults are present and parsable from cli""" """Ensures that variant defaults are present and parsable from cli"""
def check_variant(pkg_cls, variant, vname):
# bool is a subclass of int in python. Permitting a default that is an instance
# of 'int' means both foo=false and foo=0 are accepted. Other falsish values are
# not allowed, since they can't be parsed from CLI ('foo=')
default_is_parsable = isinstance(variant.default, int) or variant.default
if not default_is_parsable:
msg = f"Variant '{vname}' of package '{pkg_cls.name}' has an unparsable default value"
return [error_cls(msg, [])]
try:
vspec = variant.make_default()
except spack.variant.MultipleValuesInExclusiveVariantError:
msg = f"Can't create default value for variant '{vname}' in package '{pkg_cls.name}'"
return [error_cls(msg, [])]
try:
variant.validate_or_raise(vspec, pkg_cls.name)
except spack.variant.InvalidVariantValueError:
msg = "Default value of variant '{vname}' in package '{pkg.name}' is invalid"
question = "Is it among the allowed values?"
return [error_cls(msg, [question])]
return []
errors = [] errors = []
for pkg_name in pkgs: for pkg_name in pkgs:
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name) pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
for vname in pkg_cls.variant_names(): for variant_name, entry in pkg_cls.variants.items():
for _, variant_def in pkg_cls.variant_definitions(vname): variant, _ = entry
errors.extend(check_variant(pkg_cls, variant_def, vname)) default_is_parsable = (
# Permitting a default that is an instance on 'int' permits
# to have foo=false or foo=0. Other falsish values are
# not allowed, since they can't be parsed from cli ('foo=')
isinstance(variant.default, int)
or variant.default
)
if not default_is_parsable:
error_msg = "Variant '{}' of package '{}' has a bad default value"
errors.append(error_cls(error_msg.format(variant_name, pkg_name), []))
continue
try:
vspec = variant.make_default()
except spack.variant.MultipleValuesInExclusiveVariantError:
error_msg = "Cannot create a default value for the variant '{}' in package '{}'"
errors.append(error_cls(error_msg.format(variant_name, pkg_name), []))
continue
try:
variant.validate_or_raise(vspec, pkg_cls=pkg_cls)
except spack.variant.InvalidVariantValueError:
error_msg = (
"The default value of the variant '{}' in package '{}' failed validation"
)
question = "Is it among the allowed values?"
errors.append(error_cls(error_msg.format(variant_name, pkg_name), [question]))
return errors return errors
@@ -1005,11 +946,11 @@ def _ensure_variants_have_descriptions(pkgs, error_cls):
errors = [] errors = []
for pkg_name in pkgs: for pkg_name in pkgs:
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name) pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
for name in pkg_cls.variant_names(): for variant_name, entry in pkg_cls.variants.items():
for when, variant in pkg_cls.variant_definitions(name): variant, _ = entry
if not variant.description: if not variant.description:
msg = f"Variant '{name}' in package '{pkg_name}' is missing a description" error_msg = "Variant '{}' in package '{}' is missing a description"
errors.append(error_cls(msg, [])) errors.append(error_cls(error_msg.format(variant_name, pkg_name), []))
return errors return errors
@@ -1066,26 +1007,29 @@ def _version_constraints_are_satisfiable_by_some_version_in_repo(pkgs, error_cls
def _analyze_variants_in_directive(pkg, constraint, directive, error_cls): def _analyze_variants_in_directive(pkg, constraint, directive, error_cls):
variant_exceptions = (
spack.variant.InconsistentValidationError,
spack.variant.MultipleValuesInExclusiveVariantError,
spack.variant.InvalidVariantValueError,
KeyError,
)
errors = [] errors = []
variant_names = pkg.variant_names()
summary = f"{pkg.name}: wrong variant in '{directive}' directive"
filename = spack.repo.PATH.filename_for_package_name(pkg.name)
for name, v in constraint.variants.items(): for name, v in constraint.variants.items():
if name not in variant_names:
msg = f"variant {name} does not exist in {pkg.name}"
errors.append(error_cls(summary=summary, details=[msg, f"in {filename}"]))
continue
try: try:
spack.variant.prevalidate_variant_value(pkg, v, constraint, strict=True) variant, _ = pkg.variants[name]
except ( variant.validate_or_raise(v, pkg_cls=pkg)
spack.variant.InconsistentValidationError, except variant_exceptions as e:
spack.variant.MultipleValuesInExclusiveVariantError, summary = pkg.name + ': wrong variant in "{0}" directive'
spack.variant.InvalidVariantValueError, summary = summary.format(directive)
) as e: filename = spack.repo.PATH.filename_for_package_name(pkg.name)
msg = str(e).strip()
errors.append(error_cls(summary=summary, details=[msg, f"in {filename}"])) error_msg = str(e).strip()
if isinstance(e, KeyError):
error_msg = "the variant {0} does not exist".format(error_msg)
err = error_cls(summary=summary, details=[error_msg, "in " + filename])
errors.append(err)
return errors return errors
@@ -1123,10 +1067,9 @@ def _extracts_errors(triggers, summary):
for dname in dnames for dname in dnames
) )
for when, variants_by_name in pkg_cls.variants.items(): for vname, (variant, triggers) in pkg_cls.variants.items():
for vname, variant in variants_by_name.items(): summary = f"{pkg_name}: wrong 'when=' condition for the '{vname}' variant"
summary = f"{pkg_name}: wrong 'when=' condition for the '{vname}' variant" errors.extend(_extracts_errors(triggers, summary))
errors.extend(_extracts_errors([when], summary))
for when, providers, details in _error_items(pkg_cls.provided): for when, providers, details in _error_items(pkg_cls.provided):
errors.extend( errors.extend(

View File

@@ -33,6 +33,7 @@
from llnl.util.symlink import readlink from llnl.util.symlink import readlink
import spack.caches import spack.caches
import spack.cmd
import spack.config as config import spack.config as config
import spack.database as spack_db import spack.database as spack_db
import spack.error import spack.error
@@ -43,9 +44,9 @@
import spack.oci.image import spack.oci.image
import spack.oci.oci import spack.oci.oci
import spack.oci.opener import spack.oci.opener
import spack.paths
import spack.platforms import spack.platforms
import spack.relocate as relocate import spack.relocate as relocate
import spack.repo
import spack.spec import spack.spec
import spack.stage import spack.stage
import spack.store import spack.store
@@ -53,7 +54,6 @@
import spack.util.archive import spack.util.archive
import spack.util.crypto import spack.util.crypto
import spack.util.file_cache as file_cache import spack.util.file_cache as file_cache
import spack.util.filesystem as ssys
import spack.util.gpg import spack.util.gpg
import spack.util.parallel import spack.util.parallel
import spack.util.path import spack.util.path
@@ -105,7 +105,7 @@ class BuildCacheDatabase(spack_db.Database):
record_fields = ("spec", "ref_count", "in_buildcache") record_fields = ("spec", "ref_count", "in_buildcache")
def __init__(self, root): def __init__(self, root):
super().__init__(root, lock_cfg=spack_db.NO_LOCK, layout=None) super().__init__(root, lock_cfg=spack_db.NO_LOCK)
self._write_transaction_impl = llnl.util.lang.nullcontext self._write_transaction_impl = llnl.util.lang.nullcontext
self._read_transaction_impl = llnl.util.lang.nullcontext self._read_transaction_impl = llnl.util.lang.nullcontext
@@ -687,7 +687,7 @@ def get_buildfile_manifest(spec):
# Non-symlinks. # Non-symlinks.
for rel_path in visitor.files: for rel_path in visitor.files:
abs_path = os.path.join(root, rel_path) abs_path = os.path.join(root, rel_path)
m_type, m_subtype = ssys.mime_type(abs_path) m_type, m_subtype = fsys.mime_type(abs_path)
if relocate.needs_binary_relocation(m_type, m_subtype): if relocate.needs_binary_relocation(m_type, m_subtype):
# Why is this branch not part of needs_binary_relocation? :( # Why is this branch not part of needs_binary_relocation? :(
@@ -788,9 +788,7 @@ def sign_specfile(key: str, specfile_path: str) -> str:
return signed_specfile_path return signed_specfile_path
def _read_specs_and_push_index( def _read_specs_and_push_index(file_list, read_method, cache_prefix, db, temp_dir, concurrency):
file_list, read_method, cache_prefix, db: BuildCacheDatabase, temp_dir, concurrency
):
"""Read all the specs listed in the provided list, using thread given thread parallelism, """Read all the specs listed in the provided list, using thread given thread parallelism,
generate the index, and push it to the mirror. generate the index, and push it to the mirror.
@@ -814,7 +812,7 @@ def _read_specs_and_push_index(
else: else:
continue continue
db.add(fetched_spec) db.add(fetched_spec, None)
db.mark(fetched_spec, "in_buildcache", True) db.mark(fetched_spec, "in_buildcache", True)
# Now generate the index, compute its hash, and push the two files to # Now generate the index, compute its hash, and push the two files to
@@ -1446,9 +1444,7 @@ def _oci_push_pkg_blob(
filename = os.path.join(tmpdir, f"{spec.dag_hash()}.tar.gz") filename = os.path.join(tmpdir, f"{spec.dag_hash()}.tar.gz")
# Create an oci.image.layer aka tarball of the package # Create an oci.image.layer aka tarball of the package
compressed_tarfile_checksum, tarfile_checksum = _do_create_tarball( compressed_tarfile_checksum, tarfile_checksum = spack.oci.oci.create_tarball(spec, filename)
filename, spec.prefix, get_buildinfo_dict(spec)
)
blob = spack.oci.oci.Blob( blob = spack.oci.oci.Blob(
Digest.from_sha256(compressed_tarfile_checksum), Digest.from_sha256(compressed_tarfile_checksum),
@@ -1769,7 +1765,7 @@ def _oci_update_index(
for spec_dict in spec_dicts: for spec_dict in spec_dicts:
spec = Spec.from_dict(spec_dict) spec = Spec.from_dict(spec_dict)
db.add(spec) db.add(spec, directory_layout=None)
db.mark(spec, "in_buildcache", True) db.mark(spec, "in_buildcache", True)
# Create the index.json file # Create the index.json file
@@ -2565,8 +2561,9 @@ def install_root_node(spec, unsigned=False, force=False, sha256=None):
with spack.util.path.filter_padding(): with spack.util.path.filter_padding():
tty.msg('Installing "{0}" from a buildcache'.format(spec.format())) tty.msg('Installing "{0}" from a buildcache'.format(spec.format()))
extract_tarball(spec, download_result, force) extract_tarball(spec, download_result, force)
spec.package.windows_establish_runtime_linkage()
spack.hooks.post_install(spec, False) spack.hooks.post_install(spec, False)
spack.store.STORE.db.add(spec) spack.store.STORE.db.add(spec, spack.store.STORE.layout)
def install_single_spec(spec, unsigned=False, force=False): def install_single_spec(spec, unsigned=False, force=False):
@@ -2698,9 +2695,6 @@ def get_keys(install=False, trust=False, force=False, mirrors=None):
for mirror in mirror_collection.values(): for mirror in mirror_collection.values():
fetch_url = mirror.fetch_url fetch_url = mirror.fetch_url
# TODO: oci:// does not support signing.
if fetch_url.startswith("oci://"):
continue
keys_url = url_util.join( keys_url = url_util.join(
fetch_url, BUILD_CACHE_RELATIVE_PATH, BUILD_CACHE_KEYS_RELATIVE_PATH fetch_url, BUILD_CACHE_RELATIVE_PATH, BUILD_CACHE_KEYS_RELATIVE_PATH
) )

View File

@@ -9,7 +9,6 @@
all_core_root_specs, all_core_root_specs,
ensure_clingo_importable_or_raise, ensure_clingo_importable_or_raise,
ensure_core_dependencies, ensure_core_dependencies,
ensure_file_in_path_or_raise,
ensure_gpg_in_path_or_raise, ensure_gpg_in_path_or_raise,
ensure_patchelf_in_path_or_raise, ensure_patchelf_in_path_or_raise,
) )
@@ -20,7 +19,6 @@
"is_bootstrapping", "is_bootstrapping",
"ensure_bootstrap_configuration", "ensure_bootstrap_configuration",
"ensure_core_dependencies", "ensure_core_dependencies",
"ensure_file_in_path_or_raise",
"ensure_gpg_in_path_or_raise", "ensure_gpg_in_path_or_raise",
"ensure_clingo_importable_or_raise", "ensure_clingo_importable_or_raise",
"ensure_patchelf_in_path_or_raise", "ensure_patchelf_in_path_or_raise",

View File

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

View File

@@ -37,16 +37,21 @@
import spack.binary_distribution import spack.binary_distribution
import spack.config import spack.config
import spack.detection import spack.detection
import spack.environment
import spack.modules
import spack.paths
import spack.platforms import spack.platforms
import spack.platforms.linux
import spack.repo
import spack.spec import spack.spec
import spack.store import spack.store
import spack.user_environment import spack.user_environment
import spack.util.environment
import spack.util.executable import spack.util.executable
import spack.util.path import spack.util.path
import spack.util.spack_yaml import spack.util.spack_yaml
import spack.util.url import spack.util.url
import spack.version import spack.version
from spack.installer import PackageInstaller
from ._common import _executables_in_store, _python_import, _root_spec, _try_import_from_store from ._common import _executables_in_store, _python_import, _root_spec, _try_import_from_store
from .clingo import ClingoBootstrapConcretizer from .clingo import ClingoBootstrapConcretizer
@@ -278,7 +283,7 @@ def try_import(self, module: str, abstract_spec_str: str) -> bool:
# Install the spec that should make the module importable # Install the spec that should make the module importable
with spack.config.override(self.mirror_scope): with spack.config.override(self.mirror_scope):
PackageInstaller([concrete_spec.package], fail_fast=True).install() concrete_spec.package.do_install(fail_fast=True)
if _try_import_from_store(module, query_spec=concrete_spec, query_info=info): if _try_import_from_store(module, query_spec=concrete_spec, query_info=info):
self.last_search = info self.last_search = info
@@ -301,7 +306,7 @@ def try_search_path(self, executables: Tuple[str], abstract_spec_str: str) -> bo
msg = "[BOOTSTRAP] Try installing '{0}' from sources" msg = "[BOOTSTRAP] Try installing '{0}' from sources"
tty.debug(msg.format(abstract_spec_str)) tty.debug(msg.format(abstract_spec_str))
with spack.config.override(self.mirror_scope): with spack.config.override(self.mirror_scope):
PackageInstaller([concrete_spec.package], fail_fast=True).install() concrete_spec.package.do_install()
if _executables_in_store(executables, concrete_spec, query_info=info): if _executables_in_store(executables, concrete_spec, query_info=info):
self.last_search = info self.last_search = info
return True return True
@@ -467,8 +472,7 @@ def ensure_clingo_importable_or_raise() -> None:
def gnupg_root_spec() -> str: def gnupg_root_spec() -> str:
"""Return the root spec used to bootstrap GnuPG""" """Return the root spec used to bootstrap GnuPG"""
root_spec_name = "win-gpg" if IS_WINDOWS else "gnupg" return _root_spec("gnupg@2.3:")
return _root_spec(f"{root_spec_name}@2.3:")
def ensure_gpg_in_path_or_raise() -> None: def ensure_gpg_in_path_or_raise() -> None:
@@ -478,19 +482,6 @@ def ensure_gpg_in_path_or_raise() -> None:
) )
def file_root_spec() -> str:
"""Return the root spec used to bootstrap file"""
root_spec_name = "win-file" if IS_WINDOWS else "file"
return _root_spec(root_spec_name)
def ensure_file_in_path_or_raise() -> None:
"""Ensure file is in the PATH or raise"""
return ensure_executables_in_path_or_raise(
executables=["file"], abstract_spec=file_root_spec()
)
def patchelf_root_spec() -> str: def patchelf_root_spec() -> str:
"""Return the root spec used to bootstrap patchelf""" """Return the root spec used to bootstrap patchelf"""
# 0.13.1 is the last version not to require C++17. # 0.13.1 is the last version not to require C++17.
@@ -574,15 +565,14 @@ def ensure_core_dependencies() -> None:
"""Ensure the presence of all the core dependencies.""" """Ensure the presence of all the core dependencies."""
if sys.platform.lower() == "linux": if sys.platform.lower() == "linux":
ensure_patchelf_in_path_or_raise() ensure_patchelf_in_path_or_raise()
elif sys.platform == "win32": if not IS_WINDOWS:
ensure_file_in_path_or_raise() ensure_gpg_in_path_or_raise()
ensure_gpg_in_path_or_raise()
ensure_clingo_importable_or_raise() ensure_clingo_importable_or_raise()
def all_core_root_specs() -> List[str]: def all_core_root_specs() -> List[str]:
"""Return a list of all the core root specs that may be used to bootstrap Spack""" """Return a list of all the core root specs that may be used to bootstrap Spack"""
return [clingo_root_spec(), gnupg_root_spec(), patchelf_root_spec(), file_root_spec()] return [clingo_root_spec(), gnupg_root_spec(), patchelf_root_spec()]
def bootstrapping_sources(scope: Optional[str] = None): def bootstrapping_sources(scope: Optional[str] = None):

View File

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

View File

@@ -88,7 +88,7 @@ def _core_requirements() -> List[RequiredResponseType]:
def _buildcache_requirements() -> List[RequiredResponseType]: def _buildcache_requirements() -> List[RequiredResponseType]:
_buildcache_exes = { _buildcache_exes = {
"file": _missing("file", "required to analyze files for buildcaches", system_only=False), "file": _missing("file", "required to analyze files for buildcaches"),
("gpg2", "gpg"): _missing("gpg2", "required to sign/verify buildcaches", False), ("gpg2", "gpg"): _missing("gpg2", "required to sign/verify buildcaches", False),
} }
if platform.system().lower() == "darwin": if platform.system().lower() == "darwin":

View File

@@ -45,8 +45,6 @@
from itertools import chain from itertools import chain
from typing import Dict, List, Set, Tuple from typing import Dict, List, Set, Tuple
import archspec.cpu
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.string import plural from llnl.string import plural
from llnl.util.filesystem import join_path from llnl.util.filesystem import join_path
@@ -55,7 +53,6 @@
from llnl.util.tty.color import cescape, colorize from llnl.util.tty.color import cescape, colorize
from llnl.util.tty.log import MultiProcessFd from llnl.util.tty.log import MultiProcessFd
import spack.build_systems._checks
import spack.build_systems.cmake import spack.build_systems.cmake
import spack.build_systems.meson import spack.build_systems.meson
import spack.build_systems.python import spack.build_systems.python
@@ -64,20 +61,26 @@
import spack.config import spack.config
import spack.deptypes as dt import spack.deptypes as dt
import spack.error import spack.error
import spack.multimethod import spack.main
import spack.package_base import spack.package_base
import spack.paths import spack.paths
import spack.platforms import spack.platforms
import spack.repo
import spack.schema.environment import spack.schema.environment
import spack.spec import spack.spec
import spack.stage import spack.stage
import spack.store import spack.store
import spack.subprocess_context import spack.subprocess_context
import spack.user_environment
import spack.util.executable import spack.util.executable
import spack.util.path
import spack.util.pattern
from spack import traverse from spack import traverse
from spack.context import Context from spack.context import Context
from spack.error import InstallError, NoHeadersError, NoLibrariesError from spack.error import NoHeadersError, NoLibrariesError
from spack.install_test import spack_install_test_log from spack.install_test import spack_install_test_log
from spack.installer import InstallError
from spack.util.cpus import determine_number_of_jobs
from spack.util.environment import ( from spack.util.environment import (
SYSTEM_DIR_CASE_ENTRY, SYSTEM_DIR_CASE_ENTRY,
EnvironmentModifications, EnvironmentModifications,
@@ -360,7 +363,7 @@ def set_compiler_environment_variables(pkg, env):
_add_werror_handling(keep_werror, env) _add_werror_handling(keep_werror, env)
# Set the target parameters that the compiler will add # Set the target parameters that the compiler will add
isa_arg = optimization_flags(compiler, spec.target) isa_arg = spec.architecture.target.optimization_flags(compiler)
env.set("SPACK_TARGET_ARGS", isa_arg) env.set("SPACK_TARGET_ARGS", isa_arg)
# Trap spack-tracked compiler flags as appropriate. # Trap spack-tracked compiler flags as appropriate.
@@ -405,36 +408,6 @@ def set_compiler_environment_variables(pkg, env):
return env return env
def optimization_flags(compiler, target):
if spack.compilers.is_mixed_toolchain(compiler):
msg = (
"microarchitecture specific optimizations are not "
"supported yet on mixed compiler toolchains [check"
f" {compiler.name}@{compiler.version} for further details]"
)
tty.debug(msg)
return ""
# Try to check if the current compiler comes with a version number or
# has an unexpected suffix. If so, treat it as a compiler with a
# custom spec.
compiler_version = compiler.version
version_number, suffix = archspec.cpu.version_components(compiler.version)
if not version_number or suffix:
try:
compiler_version = compiler.real_version
except spack.util.executable.ProcessError as e:
# log this and just return compiler.version instead
tty.debug(str(e))
try:
result = target.optimization_flags(compiler.name, compiler_version.dotted_numeric_string)
except (ValueError, archspec.cpu.UnsupportedMicroarchitecture):
result = ""
return result
def set_wrapper_variables(pkg, env): def set_wrapper_variables(pkg, env):
"""Set environment variables used by the Spack compiler wrapper (which have the prefix """Set environment variables used by the Spack compiler wrapper (which have the prefix
`SPACK_`) and also add the compiler wrappers to PATH. `SPACK_`) and also add the compiler wrappers to PATH.
@@ -482,7 +455,7 @@ def set_wrapper_variables(pkg, env):
env.set(SPACK_DEBUG, "TRUE") env.set(SPACK_DEBUG, "TRUE")
env.set(SPACK_SHORT_SPEC, pkg.spec.short_spec) env.set(SPACK_SHORT_SPEC, pkg.spec.short_spec)
env.set(SPACK_DEBUG_LOG_ID, pkg.spec.format("{name}-{hash:7}")) env.set(SPACK_DEBUG_LOG_ID, pkg.spec.format("{name}-{hash:7}"))
env.set(SPACK_DEBUG_LOG_DIR, spack.paths.spack_working_dir) env.set(SPACK_DEBUG_LOG_DIR, spack.main.spack_working_dir)
if spack.config.get("config:ccache"): if spack.config.get("config:ccache"):
# Enable ccache in the compiler wrapper # Enable ccache in the compiler wrapper
@@ -582,14 +555,14 @@ def set_package_py_globals(pkg, context: Context = Context.BUILD):
"""Populate the Python module of a package with some useful global names. """Populate the Python module of a package with some useful global names.
This makes things easier for package writers. This makes things easier for package writers.
""" """
module = ModuleChangePropagator(pkg) module = SetPackageGlobals(pkg)
if context == Context.BUILD: if context == Context.BUILD:
module.std_cmake_args = spack.build_systems.cmake.CMakeBuilder.std_args(pkg) module.std_cmake_args = spack.build_systems.cmake.CMakeBuilder.std_args(pkg)
module.std_meson_args = spack.build_systems.meson.MesonBuilder.std_args(pkg) module.std_meson_args = spack.build_systems.meson.MesonBuilder.std_args(pkg)
module.std_pip_args = spack.build_systems.python.PythonPipBuilder.std_args(pkg) module.std_pip_args = spack.build_systems.python.PythonPipBuilder.std_args(pkg)
jobs = spack.config.determine_number_of_jobs(parallel=pkg.parallel) jobs = determine_number_of_jobs(parallel=pkg.parallel)
module.make_jobs = jobs module.make_jobs = jobs
# TODO: make these build deps that can be installed if not found. # TODO: make these build deps that can be installed if not found.
@@ -815,6 +788,7 @@ def setup_package(pkg, dirty, context: Context = Context.BUILD):
# Platform specific setup goes before package specific setup. This is for setting # Platform specific setup goes before package specific setup. This is for setting
# defaults like MACOSX_DEPLOYMENT_TARGET on macOS. # defaults like MACOSX_DEPLOYMENT_TARGET on macOS.
platform = spack.platforms.by_name(pkg.spec.architecture.platform) platform = spack.platforms.by_name(pkg.spec.architecture.platform)
target = platform.target(pkg.spec.architecture.target)
platform.setup_platform_environment(pkg, env_mods) platform.setup_platform_environment(pkg, env_mods)
tty.debug("setup_package: grabbing modifications from dependencies") tty.debug("setup_package: grabbing modifications from dependencies")
@@ -839,6 +813,9 @@ def setup_package(pkg, dirty, context: Context = Context.BUILD):
for mod in pkg.compiler.modules: for mod in pkg.compiler.modules:
load_module(mod) load_module(mod)
if target and target.module_name:
load_module(target.module_name)
load_external_modules(pkg) load_external_modules(pkg)
implicit_rpaths = pkg.compiler.implicit_rpaths() implicit_rpaths = pkg.compiler.implicit_rpaths()
@@ -1039,7 +1016,7 @@ def set_all_package_py_globals(self):
# setting globals for those. # setting globals for those.
if id(spec) not in self.nodes_in_subdag: if id(spec) not in self.nodes_in_subdag:
continue continue
dependent_module = ModuleChangePropagator(spec.package) dependent_module = SetPackageGlobals(spec.package)
pkg.setup_dependent_package(dependent_module, spec) pkg.setup_dependent_package(dependent_module, spec)
dependent_module.propagate_changes_to_mro() dependent_module.propagate_changes_to_mro()
@@ -1162,7 +1139,7 @@ def _setup_pkg_and_run(
return_value = function(pkg, kwargs) return_value = function(pkg, kwargs)
write_pipe.send(return_value) write_pipe.send(return_value)
except spack.error.StopPhase as e: except StopPhase as e:
# Do not create a full ChildError from this, it's not an error # Do not create a full ChildError from this, it's not an error
# it's a control statement. # it's a control statement.
write_pipe.send(e) write_pipe.send(e)
@@ -1323,7 +1300,7 @@ def exitcode_msg(p):
p.join() p.join()
# If returns a StopPhase, raise it # If returns a StopPhase, raise it
if isinstance(child_result, spack.error.StopPhase): if isinstance(child_result, StopPhase):
# do not print # do not print
raise child_result raise child_result
@@ -1532,6 +1509,17 @@ def _make_child_error(msg, module, name, traceback, log, log_type, context):
return ChildError(msg, module, name, traceback, log, log_type, context) return ChildError(msg, module, name, traceback, log, log_type, context)
class StopPhase(spack.error.SpackError):
"""Pickle-able exception to control stopped builds."""
def __reduce__(self):
return _make_stop_phase, (self.message, self.long_message)
def _make_stop_phase(msg, long_msg):
return StopPhase(msg, long_msg)
def write_log_summary(out, log_type, log, last=None): def write_log_summary(out, log_type, log, last=None):
errors, warnings = parse_log_events(log) errors, warnings = parse_log_events(log)
nerr = len(errors) nerr = len(errors)
@@ -1555,7 +1543,7 @@ def write_log_summary(out, log_type, log, last=None):
out.write(make_log_context(warnings)) out.write(make_log_context(warnings))
class ModuleChangePropagator: class SetPackageGlobals:
"""Wrapper class to accept changes to a package.py Python module, and propagate them in the """Wrapper class to accept changes to a package.py Python module, and propagate them in the
MRO of the package. MRO of the package.
@@ -1563,41 +1551,22 @@ class ModuleChangePropagator:
"setup_dependent_package" function during build environment setup. "setup_dependent_package" function during build environment setup.
""" """
_PROTECTED_NAMES = ("package", "current_module", "modules_in_mro", "_set_attributes")
def __init__(self, package: spack.package_base.PackageBase) -> None: def __init__(self, package: spack.package_base.PackageBase) -> None:
self._set_self_attributes("package", package)
self._set_self_attributes("current_module", package.module)
#: Modules for the classes in the MRO up to PackageBase #: Modules for the classes in the MRO up to PackageBase
modules_in_mro = [] modules_in_mro = []
for cls in package.__class__.__mro__: for cls in package.__class__.__mro__:
module = getattr(cls, "module", None) module = getattr(cls, "module", None)
if module is None or module is spack.package_base: if module is None or module is spack.package_base:
break break
if module is self.current_module:
continue
modules_in_mro.append(module) modules_in_mro.append(module)
self._set_self_attributes("modules_in_mro", modules_in_mro)
self._set_self_attributes("_set_attributes", {})
def _set_self_attributes(self, key, value): super().__setattr__("modules_in_mro", modules_in_mro)
super().__setattr__(key, value)
def __getattr__(self, item): def __getattr__(self, item):
return getattr(self.current_module, item) return getattr(self.modules_in_mro[0], item)
def __setattr__(self, key, value): def __setattr__(self, key, value):
if key in ModuleChangePropagator._PROTECTED_NAMES: if key == "modules_in_mro":
msg = f'Cannot set attribute "{key}" in ModuleMonkeyPatcher' raise AttributeError(f'Cannot set attribute "{key}" in ModuleMonkeyPatcher')
return AttributeError(msg) for module in self.modules_in_mro:
setattr(module, key, value)
setattr(self.current_module, key, value)
self._set_attributes[key] = value
def propagate_changes_to_mro(self):
for module_in_mro in self.modules_in_mro:
module_in_mro.__dict__.update(self._set_attributes)

View File

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

View File

@@ -2,8 +2,6 @@
# Spack Project Developers. See the top-level COPYRIGHT file for details. # Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import spack.directives import spack.directives
@@ -48,12 +46,18 @@ class AspellDictPackage(AutotoolsPackage):
#: Override the default autotools builder #: Override the default autotools builder
AutotoolsBuilder = AspellBuilder AutotoolsBuilder = AspellBuilder
def patch(self): def view_destination(self, view):
aspell_spec = self.spec["aspell"] aspell_spec = self.spec["aspell"]
if view.get_projection_for_spec(aspell_spec) != aspell_spec.prefix:
raise spack.package_base.ExtensionError(
"aspell does not support non-global extensions"
)
aspell = aspell_spec.command aspell = aspell_spec.command
dictdir = aspell("dump", "config", "dict-dir", output=str).strip() return aspell("dump", "config", "dict-dir", output=str).strip()
datadir = aspell("dump", "config", "data-dir", output=str).strip()
dictdir = os.path.relpath(dictdir, aspell_spec.prefix) def view_source(self):
datadir = os.path.relpath(datadir, aspell_spec.prefix) return self.prefix.lib
fs.filter_file(r"^dictdir=.*$", f"dictdir=/{dictdir}", "configure")
fs.filter_file(r"^datadir=.*$", f"datadir=/{datadir}", "configure") def patch(self):
fs.filter_file(r"^dictdir=.*$", "dictdir=/lib", "configure")
fs.filter_file(r"^datadir=.*$", "datadir=/lib", "configure")

View File

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

View File

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

View File

@@ -15,7 +15,6 @@
import spack.build_environment import spack.build_environment
import spack.builder import spack.builder
import spack.deptypes as dt import spack.deptypes as dt
import spack.error
import spack.package_base import spack.package_base
from spack.directives import build_system, conflicts, depends_on, variant from spack.directives import build_system, conflicts, depends_on, variant
from spack.multimethod import when from spack.multimethod import when
@@ -108,11 +107,6 @@ def _conditional_cmake_defaults(pkg: spack.package_base.PackageBase, args: List[
if _supports_compilation_databases(pkg): if _supports_compilation_databases(pkg):
args.append(CMakeBuilder.define("CMAKE_EXPORT_COMPILE_COMMANDS", True)) args.append(CMakeBuilder.define("CMAKE_EXPORT_COMPILE_COMMANDS", True))
# Enable MACOSX_RPATH by default when cmake_minimum_required < 3
# https://cmake.org/cmake/help/latest/policy/CMP0042.html
if pkg.spec.satisfies("platform=darwin") and cmake.satisfies("@3:"):
args.append(CMakeBuilder.define("CMAKE_POLICY_DEFAULT_CMP0042", "NEW"))
def generator(*names: str, default: Optional[str] = None): def generator(*names: str, default: Optional[str] = None):
"""The build system generator to use. """The build system generator to use.
@@ -146,7 +140,6 @@ def _values(x):
default=default, default=default,
values=_values, values=_values,
description="the build system generator to use", description="the build system generator to use",
when="build_system=cmake",
) )
for x in not_used: for x in not_used:
conflicts(f"generator={x}") conflicts(f"generator={x}")
@@ -346,7 +339,7 @@ def std_args(pkg, generator=None):
msg = "Invalid CMake generator: '{0}'\n".format(generator) msg = "Invalid CMake generator: '{0}'\n".format(generator)
msg += "CMakePackage currently supports the following " msg += "CMakePackage currently supports the following "
msg += "primary generators: '{0}'".format("', '".join(valid_primary_generators)) msg += "primary generators: '{0}'".format("', '".join(valid_primary_generators))
raise spack.error.InstallError(msg) raise spack.package_base.InstallError(msg)
try: try:
build_type = pkg.spec.variants["build_type"].value build_type = pkg.spec.variants["build_type"].value
@@ -506,7 +499,7 @@ def define_from_variant(self, cmake_var, variant=None):
if variant is None: if variant is None:
variant = cmake_var.lower() variant = cmake_var.lower()
if not self.pkg.has_variant(variant): if variant not in self.pkg.variants:
raise KeyError('"{0}" is not a variant of "{1}"'.format(variant, self.pkg.name)) raise KeyError('"{0}" is not a variant of "{1}"'.format(variant, self.pkg.name))
if variant not in self.pkg.spec.variants: if variant not in self.pkg.spec.variants:

View File

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

View File

@@ -3,9 +3,6 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import re
from typing import Iterable, List
import spack.variant import spack.variant
from spack.directives import conflicts, depends_on, variant from spack.directives import conflicts, depends_on, variant
from spack.multimethod import when from spack.multimethod import when
@@ -47,7 +44,6 @@ class CudaPackage(PackageBase):
"87", "87",
"89", "89",
"90", "90",
"90a",
) )
# FIXME: keep cuda and cuda_arch separate to make usage easier until # FIXME: keep cuda and cuda_arch separate to make usage easier until
@@ -74,27 +70,6 @@ def cuda_flags(arch_list):
for s in arch_list for s in arch_list
] ]
@staticmethod
def compute_capabilities(arch_list: Iterable[str]) -> List[str]:
"""Adds a decimal place to each CUDA arch.
>>> compute_capabilities(['90', '90a'])
['9.0', '9.0a']
Args:
arch_list: A list of integer strings, optionally followed by a suffix.
Returns:
A list of float strings, optionally followed by a suffix
"""
pattern = re.compile(r"(\d+)")
capabilities = []
for arch in arch_list:
_, number, letter = re.split(pattern, arch)
number = "{0:.1f}".format(float(number) / 10.0)
capabilities.append(number + letter)
return capabilities
depends_on("cuda", when="+cuda") depends_on("cuda", when="+cuda")
# CUDA version vs Architecture # CUDA version vs Architecture
@@ -170,8 +145,7 @@ def compute_capabilities(arch_list: Iterable[str]) -> List[str]:
conflicts("%clang@15:", when="+cuda ^cuda@:12.0") conflicts("%clang@15:", when="+cuda ^cuda@:12.0")
conflicts("%clang@16:", when="+cuda ^cuda@:12.1") conflicts("%clang@16:", when="+cuda ^cuda@:12.1")
conflicts("%clang@17:", when="+cuda ^cuda@:12.3") conflicts("%clang@17:", when="+cuda ^cuda@:12.3")
conflicts("%clang@18:", when="+cuda ^cuda@:12.5") conflicts("%clang@18:", when="+cuda ^cuda@:12.6")
conflicts("%clang@19:", when="+cuda ^cuda@:12.6")
# https://gist.github.com/ax3l/9489132#gistcomment-3860114 # https://gist.github.com/ax3l/9489132#gistcomment-3860114
conflicts("%gcc@10", when="+cuda ^cuda@:11.4.0") conflicts("%gcc@10", when="+cuda ^cuda@:11.4.0")

View File

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

View File

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

View File

@@ -24,8 +24,6 @@
import spack.detection import spack.detection
import spack.multimethod import spack.multimethod
import spack.package_base import spack.package_base
import spack.platforms
import spack.repo
import spack.spec import spack.spec
import spack.store import spack.store
from spack.directives import build_system, depends_on, extends from spack.directives import build_system, depends_on, extends
@@ -316,9 +314,9 @@ def get_external_python_for_prefix(self):
) )
python_externals_detected = [ python_externals_detected = [
spec d.spec
for spec in python_externals_detection.get("python", []) for d in python_externals_detection.get("python", [])
if spec.external_path == self.spec.external_path if d.prefix == self.spec.external_path
] ]
if python_externals_detected: if python_externals_detected:
return python_externals_detected[0] return python_externals_detected[0]

View File

@@ -5,7 +5,6 @@
from typing import Optional, Tuple from typing import Optional, Tuple
import llnl.util.lang as lang import llnl.util.lang as lang
from llnl.util.filesystem import mkdirp
from spack.directives import extends from spack.directives import extends
@@ -37,7 +36,6 @@ def configure_vars(self):
def install(self, pkg, spec, prefix): def install(self, pkg, spec, prefix):
"""Installs an R package.""" """Installs an R package."""
mkdirp(pkg.module.r_lib_dir)
config_args = self.configure_args() config_args = self.configure_args()
config_vars = self.configure_vars() config_vars = self.configure_vars()
@@ -45,12 +43,12 @@ def install(self, pkg, spec, prefix):
args = ["--vanilla", "CMD", "INSTALL"] args = ["--vanilla", "CMD", "INSTALL"]
if config_args: if config_args:
args.append(f"--configure-args={' '.join(config_args)}") args.append("--configure-args={0}".format(" ".join(config_args)))
if config_vars: if config_vars:
args.append(f"--configure-vars={' '.join(config_vars)}") args.append("--configure-vars={0}".format(" ".join(config_vars)))
args.extend([f"--library={pkg.module.r_lib_dir}", self.stage.source_path]) args.extend(["--library={0}".format(self.pkg.module.r_lib_dir), self.stage.source_path])
pkg.module.R(*args) pkg.module.R(*args)
@@ -81,21 +79,27 @@ class RPackage(Package):
@lang.classproperty @lang.classproperty
def homepage(cls): def homepage(cls):
if cls.cran: if cls.cran:
return f"https://cloud.r-project.org/package={cls.cran}" return "https://cloud.r-project.org/package=" + cls.cran
elif cls.bioc: elif cls.bioc:
return f"https://bioconductor.org/packages/{cls.bioc}" return "https://bioconductor.org/packages/" + cls.bioc
@lang.classproperty @lang.classproperty
def url(cls): def url(cls):
if cls.cran: if cls.cran:
return f"https://cloud.r-project.org/src/contrib/{cls.cran}_{str(list(cls.versions)[0])}.tar.gz" return (
"https://cloud.r-project.org/src/contrib/"
+ cls.cran
+ "_"
+ str(list(cls.versions)[0])
+ ".tar.gz"
)
@lang.classproperty @lang.classproperty
def list_url(cls): def list_url(cls):
if cls.cran: if cls.cran:
return f"https://cloud.r-project.org/src/contrib/Archive/{cls.cran}/" return "https://cloud.r-project.org/src/contrib/Archive/" + cls.cran + "/"
@property @property
def git(self): def git(self):
if self.bioc: if self.bioc:
return f"https://git.bioconductor.org/packages/{self.bioc}" return "https://git.bioconductor.org/packages/" + self.bioc

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -115,11 +115,15 @@ def audit(parser, args):
def _process_reports(reports): def _process_reports(reports):
for check, errors in reports: for check, errors in reports:
if errors: if errors:
status = f"{len(errors)} issue{'' if len(errors) == 1 else 's'} found" msg = "{0}: {1} issue{2} found".format(
print(cl.colorize(f"{check}: @*r{{{status}}}")) check, len(errors), "" if len(errors) == 1 else "s"
numdigits = len(str(len(errors))) )
header = "@*b{" + msg + "}"
print(cl.colorize(header))
for idx, error in enumerate(errors): for idx, error in enumerate(errors):
print(f"{idx + 1:>{numdigits}}. {error}") print(str(idx + 1) + ". " + str(error))
raise SystemExit(1) raise SystemExit(1)
else: else:
print(cl.colorize(f"{check}: @*g{{passed}}")) msg = "{0}: 0 issues found.".format(check)
header = "@*b{" + msg + "}"
print(cl.colorize(header))

View File

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

View File

@@ -23,9 +23,14 @@
import spack.error import spack.error
import spack.mirror import spack.mirror
import spack.oci.oci import spack.oci.oci
import spack.oci.opener
import spack.relocate
import spack.repo
import spack.spec import spack.spec
import spack.stage import spack.stage
import spack.store import spack.store
import spack.user_environment
import spack.util.crypto
import spack.util.parallel import spack.util.parallel
import spack.util.url as url_util import spack.util.url as url_util
import spack.util.web as web_util import spack.util.web as web_util
@@ -455,7 +460,7 @@ def push_fn(args):
"The following {} specs were skipped as they already exist in the buildcache:\n" "The following {} specs were skipped as they already exist in the buildcache:\n"
" {}\n" " {}\n"
" Use --force to overwrite them.".format( " Use --force to overwrite them.".format(
len(skipped), ", ".join(elide_list([_format_spec(s) for s in skipped], 5)) len(skipped), ", ".join(elide_list(skipped, 5))
) )
) )

View File

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

View File

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

View File

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

View File

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

View File

@@ -7,7 +7,6 @@
import copy import copy
import os import os
import re import re
import shlex
import sys import sys
from argparse import ArgumentParser, Namespace from argparse import ArgumentParser, Namespace
from typing import IO, Any, Callable, Dict, Iterable, List, Optional, Sequence, Set, Tuple, Union from typing import IO, Any, Callable, Dict, Iterable, List, Optional, Sequence, Set, Tuple, Union
@@ -17,10 +16,8 @@
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
import spack.cmd import spack.cmd
import spack.config
import spack.main import spack.main
import spack.paths import spack.paths
import spack.platforms
from spack.main import section_descriptions from spack.main import section_descriptions
description = "list available spack commands" description = "list available spack commands"
@@ -142,7 +139,7 @@ def usage(self, usage: str) -> str:
cmd = self.parser.prog.replace(" ", "-") cmd = self.parser.prog.replace(" ", "-")
if cmd in self.documented: if cmd in self.documented:
string = f"{string}\n:ref:`More documentation <cmd-{cmd}>`\n" string += "\n:ref:`More documentation <cmd-{0}>`\n".format(cmd)
return string return string
@@ -252,27 +249,33 @@ def body(
Function body. Function body.
""" """
if positionals: if positionals:
return f""" return """
if $list_options if $list_options
then then
{self.optionals(optionals)} {0}
else else
{self.positionals(positionals)} {1}
fi fi
""" """.format(
self.optionals(optionals), self.positionals(positionals)
)
elif subcommands: elif subcommands:
return f""" return """
if $list_options if $list_options
then then
{self.optionals(optionals)} {0}
else else
{self.subcommands(subcommands)} {1}
fi fi
""" """.format(
self.optionals(optionals), self.subcommands(subcommands)
)
else: else:
return f""" return """
{self.optionals(optionals)} {0}
""" """.format(
self.optionals(optionals)
)
def positionals(self, positionals: Sequence[str]) -> str: def positionals(self, positionals: Sequence[str]) -> str:
"""Return the syntax for reporting positional arguments. """Return the syntax for reporting positional arguments.
@@ -301,7 +304,7 @@ def optionals(self, optionals: Sequence[str]) -> str:
Returns: Returns:
Syntax for optional flags. Syntax for optional flags.
""" """
return f'SPACK_COMPREPLY="{" ".join(optionals)}"' return 'SPACK_COMPREPLY="{0}"'.format(" ".join(optionals))
def subcommands(self, subcommands: Sequence[str]) -> str: def subcommands(self, subcommands: Sequence[str]) -> str:
"""Return the syntax for reporting subcommands. """Return the syntax for reporting subcommands.
@@ -312,7 +315,7 @@ def subcommands(self, subcommands: Sequence[str]) -> str:
Returns: Returns:
Syntax for subcommand parsers Syntax for subcommand parsers
""" """
return f'SPACK_COMPREPLY="{" ".join(subcommands)}"' return 'SPACK_COMPREPLY="{0}"'.format(" ".join(subcommands))
# Map argument destination names to their complete commands # Map argument destination names to their complete commands
@@ -392,7 +395,7 @@ def _fish_dest_get_complete(prog: str, dest: str) -> Optional[str]:
subcmd = s[1] if len(s) == 2 else "" subcmd = s[1] if len(s) == 2 else ""
for (prog_key, pos_key), value in _dest_to_fish_complete.items(): for (prog_key, pos_key), value in _dest_to_fish_complete.items():
if subcmd.startswith(prog_key) and re.match(f"^{pos_key}$", dest): if subcmd.startswith(prog_key) and re.match("^" + pos_key + "$", dest):
return value return value
return None return None
@@ -424,6 +427,24 @@ def format(self, cmd: Command) -> str:
+ self.complete(cmd.prog, positionals, optionals, subcommands) + self.complete(cmd.prog, positionals, optionals, subcommands)
) )
def _quote(self, string: str) -> str:
"""Quote string and escape special characters if necessary.
Args:
string: Input string.
Returns:
Quoted string.
"""
# Goal here is to match fish_indent behavior
# Strings without spaces (or other special characters) do not need to be escaped
if not any([sub in string for sub in [" ", "'", '"']]):
return string
string = string.replace("'", r"\'")
return f"'{string}'"
def optspecs( def optspecs(
self, self,
prog: str, prog: str,
@@ -442,7 +463,7 @@ def optspecs(
optspec_var = "__fish_spack_optspecs_" + prog.replace(" ", "_").replace("-", "_") optspec_var = "__fish_spack_optspecs_" + prog.replace(" ", "_").replace("-", "_")
if optionals is None: if optionals is None:
return f"set -g {optspec_var}\n" return "set -g %s\n" % optspec_var
# Build optspec by iterating over options # Build optspec by iterating over options
args = [] args = []
@@ -469,11 +490,11 @@ def optspecs(
long = [f[2:] for f in flags if f.startswith("--")] long = [f[2:] for f in flags if f.startswith("--")]
while len(short) > 0 and len(long) > 0: while len(short) > 0 and len(long) > 0:
arg = f"{short.pop()}/{long.pop()}{required}" arg = "%s/%s%s" % (short.pop(), long.pop(), required)
while len(short) > 0: while len(short) > 0:
arg = f"{short.pop()}/{required}" arg = "%s/%s" % (short.pop(), required)
while len(long) > 0: while len(long) > 0:
arg = f"{long.pop()}{required}" arg = "%s%s" % (long.pop(), required)
args.append(arg) args.append(arg)
@@ -482,7 +503,7 @@ def optspecs(
# indicate that such subcommand exists. # indicate that such subcommand exists.
args = " ".join(args) args = " ".join(args)
return f"set -g {optspec_var} {args}\n" return "set -g %s %s\n" % (optspec_var, args)
@staticmethod @staticmethod
def complete_head( def complete_head(
@@ -503,14 +524,12 @@ def complete_head(
subcmd = s[1] if len(s) == 2 else "" subcmd = s[1] if len(s) == 2 else ""
if index is None: if index is None:
return f"complete -c {s[0]} -n '__fish_spack_using_command {subcmd}'" return "complete -c %s -n '__fish_spack_using_command %s'" % (s[0], subcmd)
elif nargs in [argparse.ZERO_OR_MORE, argparse.ONE_OR_MORE, argparse.REMAINDER]: elif nargs in [argparse.ZERO_OR_MORE, argparse.ONE_OR_MORE, argparse.REMAINDER]:
return ( head = "complete -c %s -n '__fish_spack_using_command_pos_remainder %d %s'"
f"complete -c {s[0]} -n '__fish_spack_using_command_pos_remainder "
f"{index} {subcmd}'"
)
else: else:
return f"complete -c {s[0]} -n '__fish_spack_using_command_pos {index} {subcmd}'" head = "complete -c %s -n '__fish_spack_using_command_pos %d %s'"
return head % (s[0], index, subcmd)
def complete( def complete(
self, self,
@@ -578,18 +597,25 @@ def positionals(
if choices is not None: if choices is not None:
# If there are choices, we provide a completion for all possible values. # If there are choices, we provide a completion for all possible values.
commands.append(f"{head} -f -a {shlex.quote(' '.join(choices))}") commands.append(head + " -f -a %s" % self._quote(" ".join(choices)))
else: else:
# Otherwise, we try to find a predefined completion for it # Otherwise, we try to find a predefined completion for it
value = _fish_dest_get_complete(prog, args) value = _fish_dest_get_complete(prog, args)
if value is not None: if value is not None:
commands.append(f"{head} {value}") commands.append(head + " " + value)
return "\n".join(commands) + "\n" return "\n".join(commands) + "\n"
def prog_comment(self, prog: str) -> str: def prog_comment(self, prog: str) -> str:
"""Return a comment line for the command.""" """Return a comment line for the command.
return f"\n# {prog}\n"
Args:
prog: Program name.
Returns:
Comment line.
"""
return "\n# %s\n" % prog
def optionals( def optionals(
self, self,
@@ -632,28 +658,28 @@ def optionals(
for f in flags: for f in flags:
if f.startswith("--"): if f.startswith("--"):
long = f[2:] long = f[2:]
prefix = f"{prefix} -l {long}" prefix += " -l %s" % long
elif f.startswith("-"): elif f.startswith("-"):
short = f[1:] short = f[1:]
assert len(short) == 1 assert len(short) == 1
prefix = f"{prefix} -s {short}" prefix += " -s %s" % short
# Check if option require argument. # Check if option require argument.
# Currently multi-argument options are not supported, so we treat it like one argument. # Currently multi-argument options are not supported, so we treat it like one argument.
if nargs != 0: if nargs != 0:
prefix = f"{prefix} -r" prefix += " -r"
if dest is not None: if dest is not None:
# If there are choices, we provide a completion for all possible values. # If there are choices, we provide a completion for all possible values.
commands.append(f"{prefix} -f -a {shlex.quote(' '.join(dest))}") commands.append(prefix + " -f -a %s" % self._quote(" ".join(dest)))
else: else:
# Otherwise, we try to find a predefined completion for it # Otherwise, we try to find a predefined completion for it
value = _fish_dest_get_complete(prog, dest) value = _fish_dest_get_complete(prog, dest)
if value is not None: if value is not None:
commands.append(f"{prefix} {value}") commands.append(prefix + " " + value)
if help: if help:
commands.append(f"{prefix} -d {shlex.quote(help)}") commands.append(prefix + " -d %s" % self._quote(help))
return "\n".join(commands) + "\n" return "\n".join(commands) + "\n"
@@ -671,11 +697,11 @@ def subcommands(self, prog: str, subcommands: List[Tuple[ArgumentParser, str, st
head = self.complete_head(prog, 0) head = self.complete_head(prog, 0)
for _, subcommand, help in subcommands: for _, subcommand, help in subcommands:
command = f"{head} -f -a {shlex.quote(subcommand)}" command = head + " -f -a %s" % self._quote(subcommand)
if help is not None and len(help) > 0: if help is not None and len(help) > 0:
help = help.split("\n")[0] help = help.split("\n")[0]
command = f"{command} -d {shlex.quote(help)}" command += " -d %s" % self._quote(help)
commands.append(command) commands.append(command)
@@ -721,7 +747,7 @@ def rst_index(out: IO) -> None:
for i, cmd in enumerate(sorted(commands)): for i, cmd in enumerate(sorted(commands)):
description = description.capitalize() if i == 0 else "" description = description.capitalize() if i == 0 else ""
ref = f":ref:`{cmd} <spack-{cmd}>`" ref = ":ref:`%s <spack-%s>`" % (cmd, cmd)
comma = "," if i != len(commands) - 1 else "" comma = "," if i != len(commands) - 1 else ""
bar = "| " if i % 8 == 0 else " " bar = "| " if i % 8 == 0 else " "
out.write(line % (description, bar + ref + comma)) out.write(line % (description, bar + ref + comma))
@@ -832,10 +858,10 @@ def _commands(parser: ArgumentParser, args: Namespace) -> None:
# check header first so we don't open out files unnecessarily # check header first so we don't open out files unnecessarily
if args.header and not os.path.exists(args.header): if args.header and not os.path.exists(args.header):
tty.die(f"No such file: '{args.header}'") tty.die("No such file: '%s'" % args.header)
if args.update: if args.update:
tty.msg(f"Updating file: {args.update}") tty.msg("Updating file: %s" % args.update)
with open(args.update, "w") as f: with open(args.update, "w") as f:
prepend_header(args, f) prepend_header(args, f)
formatter(args, f) formatter(args, f)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,13 +14,13 @@
installation and its deprecator. installation and its deprecator.
""" """
import argparse import argparse
import os
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.symlink import symlink from llnl.util.symlink import symlink
import spack.cmd import spack.cmd
import spack.environment as ev import spack.environment as ev
import spack.installer
import spack.store import spack.store
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.database import InstallStatuses from spack.database import InstallStatuses
@@ -76,7 +76,12 @@ def setup_parser(sp):
) )
sp.add_argument( sp.add_argument(
"-l", "--link-type", type=str, default=None, choices=["soft", "hard"], help="(deprecated)" "-l",
"--link-type",
type=str,
default="soft",
choices=["soft", "hard"],
help="type of filesystem link to use for deprecation (default soft)",
) )
sp.add_argument( sp.add_argument(
@@ -86,9 +91,6 @@ def setup_parser(sp):
def deprecate(parser, args): def deprecate(parser, args):
"""Deprecate one spec in favor of another""" """Deprecate one spec in favor of another"""
if args.link_type is not None:
tty.warn("The --link-type option is deprecated and will be removed in a future release.")
env = ev.active_environment() env = ev.active_environment()
specs = spack.cmd.parse_specs(args.specs) specs = spack.cmd.parse_specs(args.specs)
@@ -142,5 +144,7 @@ def deprecate(parser, args):
if not answer: if not answer:
tty.die("Will not deprecate any packages.") tty.die("Will not deprecate any packages.")
link_fn = os.link if args.link_type == "hard" else symlink
for dcate, dcator in zip(all_deprecate, all_deprecators): for dcate, dcator in zip(all_deprecate, all_deprecators):
spack.installer.deprecate(dcate, dcator, symlink) dcate.package.do_deprecate(dcator, link_fn)

View File

@@ -8,13 +8,10 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.build_environment
import spack.cmd import spack.cmd
import spack.cmd.common.arguments
import spack.config import spack.config
import spack.repo import spack.repo
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.installer import PackageInstaller
description = "developer build: build from code in current working directory" description = "developer build: build from code in current working directory"
section = "build" section = "build"
@@ -132,9 +129,9 @@ def dev_build(self, args):
elif args.test == "root": elif args.test == "root":
tests = [spec.name for spec in specs] tests = [spec.name for spec in specs]
PackageInstaller( spec.package.do_install(
[spec.package],
tests=tests, tests=tests,
make_jobs=args.jobs,
keep_prefix=args.keep_prefix, keep_prefix=args.keep_prefix,
install_deps=not args.ignore_deps, install_deps=not args.ignore_deps,
verbose=not args.quiet, verbose=not args.quiet,
@@ -142,7 +139,7 @@ def dev_build(self, args):
stop_before=args.before, stop_before=args.before,
skip_patch=args.skip_patch, skip_patch=args.skip_patch,
stop_at=args.until, stop_at=args.until,
).install() )
# drop into the build environment of the package? # drop into the build environment of the package?
if args.shell is not None: if args.shell is not None:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,7 +16,7 @@
import spack.install_test import spack.install_test
import spack.repo import spack.repo
import spack.spec import spack.spec
import spack.variant import spack.version
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.package_base import preferred_version from spack.package_base import preferred_version
@@ -48,7 +48,6 @@ def setup_parser(subparser):
options = [ options = [
("--detectable", print_detectable.__doc__), ("--detectable", print_detectable.__doc__),
("--maintainers", print_maintainers.__doc__), ("--maintainers", print_maintainers.__doc__),
("--namespace", print_namespace.__doc__),
("--no-dependencies", "do not " + print_dependencies.__doc__), ("--no-dependencies", "do not " + print_dependencies.__doc__),
("--no-variants", "do not " + print_variants.__doc__), ("--no-variants", "do not " + print_variants.__doc__),
("--no-versions", "do not " + print_versions.__doc__), ("--no-versions", "do not " + print_versions.__doc__),
@@ -190,15 +189,6 @@ def print_maintainers(pkg, args):
color.cprint(section_title("Maintainers: ") + mnt) color.cprint(section_title("Maintainers: ") + mnt)
def print_namespace(pkg, args):
"""output package namespace"""
repo = spack.repo.PATH.get_repo(pkg.namespace)
color.cprint("")
color.cprint(section_title("Namespace:"))
color.cprint(f" @c{{{repo.namespace}}} at {repo.root}")
def print_phases(pkg, args): def print_phases(pkg, args):
"""output installation phases""" """output installation phases"""
@@ -333,6 +323,26 @@ def _fmt_variant(variant, max_name_default_len, indent, when=None, out=None):
out.write("\n") out.write("\n")
def _variants_by_name_when(pkg):
"""Adaptor to get variants keyed by { name: { when: { [Variant...] } }."""
# TODO: replace with pkg.variants_by_name(when=True) when unified directive dicts are merged.
variants = {}
for name, (variant, whens) in sorted(pkg.variants.items()):
for when in whens:
variants.setdefault(name, {}).setdefault(when, []).append(variant)
return variants
def _variants_by_when_name(pkg):
"""Adaptor to get variants keyed by { when: { name: Variant } }"""
# TODO: replace with pkg.variants when unified directive dicts are merged.
variants = {}
for name, (variant, whens) in pkg.variants.items():
for when in whens:
variants.setdefault(when, {})[name] = variant
return variants
def _print_variants_header(pkg): def _print_variants_header(pkg):
"""output variants""" """output variants"""
@@ -343,22 +353,32 @@ def _print_variants_header(pkg):
color.cprint("") color.cprint("")
color.cprint(section_title("Variants:")) color.cprint(section_title("Variants:"))
variants_by_name = _variants_by_name_when(pkg)
# Calculate the max length of the "name [default]" part of the variant display # Calculate the max length of the "name [default]" part of the variant display
# This lets us know where to print variant values. # This lets us know where to print variant values.
max_name_default_len = max( max_name_default_len = max(
color.clen(_fmt_name_and_default(variant)) color.clen(_fmt_name_and_default(variant))
for name in pkg.variant_names() for name, when_variants in variants_by_name.items()
for _, variant in pkg.variant_definitions(name) for variants in when_variants.values()
for variant in variants
) )
return max_name_default_len return max_name_default_len, variants_by_name
def _unconstrained_ver_first(item):
"""sort key that puts specs with open version ranges first"""
spec, _ = item
return (spack.version.any_version not in spec.versions, spec)
def print_variants_grouped_by_when(pkg): def print_variants_grouped_by_when(pkg):
max_name_default_len = _print_variants_header(pkg) max_name_default_len, _ = _print_variants_header(pkg)
indent = 4 indent = 4
for when, variants_by_name in pkg.variant_items(): variants = _variants_by_when_name(pkg)
for when, variants_by_name in sorted(variants.items(), key=_unconstrained_ver_first):
padded_values = max_name_default_len + 4 padded_values = max_name_default_len + 4
start_indent = indent start_indent = indent
@@ -376,14 +396,15 @@ def print_variants_grouped_by_when(pkg):
def print_variants_by_name(pkg): def print_variants_by_name(pkg):
max_name_default_len = _print_variants_header(pkg) max_name_default_len, variants_by_name = _print_variants_header(pkg)
max_name_default_len += 4 max_name_default_len += 4
indent = 4 indent = 4
for name in pkg.variant_names(): for name, when_variants in variants_by_name.items():
for when, variant in pkg.variant_definitions(name): for when, variants in sorted(when_variants.items(), key=_unconstrained_ver_first):
_fmt_variant(variant, max_name_default_len, indent, when, out=sys.stdout) for variant in variants:
sys.stdout.write("\n") _fmt_variant(variant, max_name_default_len, indent, when, out=sys.stdout)
sys.stdout.write("\n")
def print_variants(pkg, args): def print_variants(pkg, args):
@@ -501,7 +522,6 @@ def info(parser, args):
# Now output optional information in expected order # Now output optional information in expected order
sections = [ sections = [
(args.all or args.maintainers, print_maintainers), (args.all or args.maintainers, print_maintainers),
(args.all or args.namespace, print_namespace),
(args.all or args.detectable, print_detectable), (args.all or args.detectable, print_detectable),
(args.all or args.tags, print_tags), (args.all or args.tags, print_tags),
(args.all or not args.no_versions, print_versions), (args.all or not args.no_versions, print_versions),

View File

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

View File

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

View File

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

View File

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

View File

@@ -15,7 +15,6 @@
import spack.cmd import spack.cmd
import spack.config import spack.config
import spack.error
import spack.modules import spack.modules
import spack.modules.common import spack.modules.common
import spack.repo import spack.repo
@@ -125,13 +124,13 @@ def check_module_set_name(name):
names = [k for k in modules if k != "prefix_inspections"] names = [k for k in modules if k != "prefix_inspections"]
if not names: if not names:
raise spack.error.ConfigError( raise spack.config.ConfigError(
f"Module set configuration is missing. Cannot use module set '{name}'" f"Module set configuration is missing. Cannot use module set '{name}'"
) )
pretty_names = "', '".join(names) pretty_names = "', '".join(names)
raise spack.error.ConfigError( raise spack.config.ConfigError(
f"Cannot use invalid module set '{name}'.", f"Cannot use invalid module set '{name}'.",
f"Valid module set names are: '{pretty_names}'.", f"Valid module set names are: '{pretty_names}'.",
) )
@@ -173,7 +172,7 @@ def loads(module_type, specs, args, out=None):
modules = list( modules = list(
( (
spec, spec,
spack.modules.get_module( spack.modules.common.get_module(
module_type, module_type,
spec, spec,
get_full_path=False, get_full_path=False,
@@ -222,7 +221,7 @@ def find(module_type, specs, args):
try: try:
modules = [ modules = [
spack.modules.get_module( spack.modules.common.get_module(
module_type, module_type,
spec, spec,
args.full_path, args.full_path,
@@ -233,7 +232,7 @@ def find(module_type, specs, args):
] ]
modules.append( modules.append(
spack.modules.get_module( spack.modules.common.get_module(
module_type, module_type,
single_spec, single_spec,
args.full_path, args.full_path,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -202,6 +202,18 @@ class Compiler:
support for specific compilers, their possible names, arguments, support for specific compilers, their possible names, arguments,
and how to identify the particular type of compiler.""" and how to identify the particular type of compiler."""
# Subclasses use possible names of C compiler
cc_names: List[str] = []
# Subclasses use possible names of C++ compiler
cxx_names: List[str] = []
# Subclasses use possible names of Fortran 77 compiler
f77_names: List[str] = []
# Subclasses use possible names of Fortran 90 compiler
fc_names: List[str] = []
# Optional prefix regexes for searching for this type of compiler. # Optional prefix regexes for searching for this type of compiler.
# Prefixes are sometimes used for toolchains # Prefixes are sometimes used for toolchains
prefixes: List[str] = [] prefixes: List[str] = []
@@ -607,6 +619,18 @@ def extract_version_from_output(cls, output):
def cc_version(cls, cc): def cc_version(cls, cc):
return cls.default_version(cc) return cls.default_version(cc)
@classmethod
def cxx_version(cls, cxx):
return cls.default_version(cxx)
@classmethod
def f77_version(cls, f77):
return cls.default_version(f77)
@classmethod
def fc_version(cls, fc):
return cls.default_version(fc)
@classmethod @classmethod
def search_regexps(cls, language): def search_regexps(cls, language):
# Compile all the regular expressions used for files beforehand. # Compile all the regular expressions used for files beforehand.

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