# Workflow to build and test wheels. # To work on the wheel building infrastructure on a fork, comment out: # # if: github.repository == 'numpy/numpy' # # in the get_commit_message job. Be sure to include [wheel build] in your commit # message to trigger the build. All files related to wheel building are located # at tools/wheels/ # Alternatively, you can add labels to the pull request in order to trigger wheel # builds. # The labels that trigger builds are: # 36 - Build(for changes to the building process, # 14 - Release(ensure wheels build before release) name: Wheel builder on: schedule: # ┌───────────── minute (0 - 59) # │ ┌───────────── hour (0 - 23) # │ │ ┌───────────── day of the month (1 - 31) # │ │ │ ┌───────────── month (1 - 12 or JAN-DEC) # │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT) # │ │ │ │ │ - cron: "42 2 * * SUN,WED" pull_request: branches: - main - maintenance/** push: tags: - v* workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true permissions: contents: read # to fetch code (actions/checkout) jobs: get_commit_message: name: Get commit message runs-on: ubuntu-latest # Only workflow_dispatch is enabled on forks. # To enable this job and subsequent jobs on a fork for other events, comment out: if: github.repository == 'numpy/numpy' || github.event_name == 'workflow_dispatch' outputs: message: ${{ steps.commit_message.outputs.message }} steps: - name: Checkout numpy uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # Gets the correct commit message for pull request with: ref: ${{ github.event.pull_request.head.sha }} persist-credentials: false - name: Get commit message id: commit_message env: HEAD: ${{ github.ref }} run: | set -xe COMMIT_MSG=$(git log --no-merges -1 --oneline) echo "message=$COMMIT_MSG" >> $GITHUB_OUTPUT echo github.ref "$HEAD" build_wheels: name: Build wheel ${{ matrix.python }}-${{ matrix.buildplat[1] }}-${{ matrix.buildplat[2] }} needs: get_commit_message if: >- contains(needs.get_commit_message.outputs.message, '[wheel build]') || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && ( ! endsWith(github.ref, 'dev0'))) runs-on: ${{ matrix.buildplat[0] }} strategy: # Ensure that a wheel builder finishes even if another fails fail-fast: false matrix: # Github Actions doesn't support pairing matrix values together, let's improvise # https://github.com/github/feedback/discussions/7835#discussioncomment-1769026 buildplat: - [ubuntu-22.04, manylinux_x86_64, ""] - [ubuntu-22.04, musllinux_x86_64, ""] - [ubuntu-22.04-arm, manylinux_aarch64, ""] - [ubuntu-22.04-arm, musllinux_aarch64, ""] - [macos-13, macosx_x86_64, openblas] # targeting macos >= 14. Could probably build on macos-14, but it would be a cross-compile - [macos-13, macosx_x86_64, accelerate] - [macos-14, macosx_arm64, accelerate] # always use accelerate - [windows-2022, win_amd64, ""] - [windows-2022, win32, ""] - [windows-11-arm, win_arm64, ""] python: ["cp311", "cp312", "cp313", "cp313t", "cp314", "cp314t", "pp311"] exclude: # Don't build PyPy 32-bit windows - buildplat: [windows-2022, win32, ""] python: "pp311" # Don't build PyPy arm64 windows - buildplat: [windows-11-arm, win_arm64, ""] python: "pp311" # No PyPy on musllinux images - buildplat: [ ubuntu-22.04, musllinux_x86_64, "" ] python: "pp311" - buildplat: [ ubuntu-22.04-arm, musllinux_aarch64, "" ] python: "pp311" - buildplat: [ macos13, macosx_x86_64, openblas ] python: "cp313t" - buildplat: [ macos13, macosx_x86_64, openblas ] python: "cp314t" env: IS_32_BIT: ${{ matrix.buildplat[1] == 'win32' }} IS_PUSH: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }} IS_SCHEDULE_DISPATCH: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} steps: - name: Checkout numpy uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: submodules: true persist-credentials: false - name: Setup MSVC (32-bit) if: ${{ matrix.buildplat[1] == 'win32' }} uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d # v1 with: architecture: 'x86' - name: Setup LLVM for Windows ARM64 if: ${{ matrix.buildplat[1] == 'win_arm64' }} uses: ./.github/windows_arm64_steps - name: pkg-config-for-win run: | choco install -y --no-progress --stoponfirstfailure --checksum 6004DF17818F5A6DBF19CB335CC92702 pkgconfiglite $CIBW = "${{ github.workspace }}/.openblas" # pkgconfig needs a complete path, and not just "./openblas since the # build is run in a tmp dir (?) # It seems somewhere in the env passing, `\` is not # passed through, so convert it to '/' $CIBW = $CIBW.replace("\","/") echo "CIBW_ENVIRONMENT_WINDOWS=PKG_CONFIG_PATH=$CIBW" >> $env:GITHUB_ENV if: runner.os == 'windows' # Used to push the built wheels - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.x" - name: Setup macOS if: matrix.buildplat[0] == 'macos-13' || matrix.buildplat[0] == 'macos-14' run: | # Needed due to https://github.com/actions/runner-images/issues/3371 # Supported versions: https://github.com/actions/runner-images/blob/main/images/macos/macos-14-arm64-Readme.md echo "FC=gfortran-13" >> "$GITHUB_ENV" echo "F77=gfortran-13" >> "$GITHUB_ENV" echo "F90=gfortran-13" >> "$GITHUB_ENV" if [[ ${{ matrix.buildplat[2] }} == 'accelerate' ]]; then # macosx_arm64 and macosx_x86_64 with accelerate # only target Sonoma onwards CIBW="MACOSX_DEPLOYMENT_TARGET=14.0 INSTALL_OPENBLAS=false RUNNER_OS=macOS" echo "CIBW_ENVIRONMENT_MACOS=$CIBW" >> "$GITHUB_ENV" # the macos-13 image that's used for building the x86_64 wheel can't test # a wheel with deployment target >= 14 without further work echo "CIBW_TEST_SKIP=*-macosx_x86_64" >> "$GITHUB_ENV" else # macosx_x86_64 with OpenBLAS # if INSTALL_OPENBLAS isn't specified then scipy-openblas is automatically installed CIBW="RUNNER_OS=macOS" PKG_CONFIG_PATH="$PWD/.openblas" DYLD="$DYLD_LIBRARY_PATH:/$PWD/.openblas/lib" echo "CIBW_ENVIRONMENT_MACOS=$CIBW PKG_CONFIG_PATH=$PKG_CONFIG_PATH DYLD_LIBRARY_PATH=$DYLD" >> "$GITHUB_ENV" fi - name: Build wheels uses: pypa/cibuildwheel@95d2f3a92fbf80abe066b09418bbf128a8923df2 # v3.0.1 env: CIBW_BUILD: ${{ matrix.python }}-${{ matrix.buildplat[1] }} - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: ${{ matrix.python }}-${{ matrix.buildplat[1] }}-${{ matrix.buildplat[2] }} path: ./wheelhouse/*.whl - name: install micromamba uses: mamba-org/setup-micromamba@b09ef9b599704322748535812ca03efb2625677b if: ${{ matrix.buildplat[1] != 'win_arm64' }} # unsupported platform at the moment with: # for installation of anaconda-client, required for upload to # anaconda.org # Note that this step is *after* specific pythons have been used to # build and test the wheel # for installation of anaconda-client, for upload to anaconda.org # environment will be activated after creation, and in future bash steps init-shell: bash environment-name: upload-env create-args: >- anaconda-client - name: win-arm64 install anaconda client if: ${{ matrix.buildplat[1] == 'win_arm64' }} run: | # Rust installation needed for rpds-py. Invoke-WebRequest https://static.rust-lang.org/rustup/dist/aarch64-pc-windows-msvc/rustup-init.exe -UseBasicParsing -Outfile rustup-init.exe .\rustup-init.exe -y $env:PATH="$env:PATH;$env:USERPROFILE\.cargo\bin" pip install anaconda-client - name: Upload wheels if: success() && github.repository == 'numpy/numpy' shell: bash -el {0} # see https://github.com/marketplace/actions/setup-miniconda for why # `-el {0}` is required. env: NUMPY_STAGING_UPLOAD_TOKEN: ${{ secrets.NUMPY_STAGING_UPLOAD_TOKEN }} NUMPY_NIGHTLY_UPLOAD_TOKEN: ${{ secrets.NUMPY_NIGHTLY_UPLOAD_TOKEN }} run: | source tools/wheels/upload_wheels.sh set_upload_vars # trigger an upload to # https://anaconda.org/scientific-python-nightly-wheels/numpy # for cron jobs or "Run workflow" (restricted to main branch). # Tags will upload to # https://anaconda.org/multibuild-wheels-staging/numpy # The tokens were originally generated at anaconda.org upload_wheels build_sdist: name: Build sdist needs: get_commit_message if: >- contains(needs.get_commit_message.outputs.message, '[wheel build]') || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && (contains(github.event.pull_request.labels.*.name, '36 - Build') || contains(github.event.pull_request.labels.*.name, '14 - Release'))) || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && ( ! endsWith(github.ref, 'dev0'))) runs-on: ubuntu-latest env: IS_PUSH: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }} # commented out so the sdist doesn't upload to nightly # IS_SCHEDULE_DISPATCH: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} steps: - name: Checkout numpy uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: submodules: true persist-credentials: false # Used to push the built wheels - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: # Build sdist on lowest supported Python python-version: "3.11" - name: Build sdist run: | python -m pip install -U pip build python -m build --sdist -Csetup-args=-Dallow-noblas=true - name: Test the sdist run: | # TODO: Don't run test suite, and instead build wheels from sdist # Depends on pypa/cibuildwheel#1020 python -m pip install dist/*.gz -Csetup-args=-Dallow-noblas=true pip install -r requirements/test_requirements.txt cd .. # Can't import numpy within numpy src directory python -c "import numpy, sys; print(numpy.__version__); sys.exit(numpy.test() is False)" - name: Check README rendering for PyPI run: | python -mpip install twine twine check dist/* - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: sdist path: ./dist/* - uses: conda-incubator/setup-miniconda@835234971496cad1653abb28a638a281cf32541f # v3.2.0 with: # for installation of anaconda-client, required for upload to # anaconda.org # default (and activated) environment name is test # Note that this step is *after* specific pythons have been used to # build and test auto-update-conda: true python-version: "3.11" - name: Upload sdist if: success() && github.repository == 'numpy/numpy' shell: bash -el {0} env: NUMPY_STAGING_UPLOAD_TOKEN: ${{ secrets.NUMPY_STAGING_UPLOAD_TOKEN }} # commented out so the sdist doesn't upload to nightly # NUMPY_NIGHTLY_UPLOAD_TOKEN: ${{ secrets.NUMPY_NIGHTLY_UPLOAD_TOKEN }} run: | conda install -y anaconda-client source tools/wheels/upload_wheels.sh set_upload_vars # trigger an upload to # https://anaconda.org/scientific-python-nightly-wheels/numpy # for cron jobs or "Run workflow" (restricted to main branch). # Tags will upload to # https://anaconda.org/multibuild-wheels-staging/numpy # The tokens were originally generated at anaconda.org upload_wheels