Skip to content

Free-Threaded Wheel Builder #7

Free-Threaded Wheel Builder

Free-Threaded Wheel Builder #7

# Workflow to build and test wheels for the free-threaded Python build.
#
# This should be merged back into wheels.yml when free-threaded wheel
# builds can be uploaded to pypi along with the rest of numpy's release
# artifacts.
#
# 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/
name: Free-Threaded 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/**
# we don't want to upload free-threaded wheels to pypi yet
# so we don't build on tags
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
# To enable this job and subsequent jobs on a fork, comment out:
if: github.repository == 'numpy/numpy'
outputs:
message: ${{ steps.commit_message.outputs.message }}
steps:
- name: Checkout numpy
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
# Gets the correct commit message for pull request
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Get commit message
id: commit_message
run: |
set -xe
COMMIT_MSG=$(git log --no-merges -1 --oneline)
echo "message=$COMMIT_MSG" >> $GITHUB_OUTPUT
echo github.ref ${{ github.ref }}
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'
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-20.04, manylinux_x86_64, ""]
- [ubuntu-20.04, musllinux_x86_64, ""]
- [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
# TODO: set up Windows wheels windows is supported on cibuildwheel but
# numpy doesn't build on the image yet
python: ["cp313t"]
env:
IS_32_BIT: ${{ matrix.buildplat[1] == 'win32' }}
IS_SCHEDULE_DISPATCH: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
steps:
- name: Checkout numpy
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Setup MSVC (32-bit)
if: ${{ matrix.buildplat[1] == 'win32' }}
uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d # v1
with:
architecture: 'x86'
- 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@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
with:
python-version: "3.x"
- name: Setup macOS
if: matrix.buildplat[0] == 'macos-13' || matrix.buildplat[0] == 'macos-14'
run: |
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@932529cab190fafca8c735a551657247fa8f8eaf # v2.19.1
env:
CIBW_PRERELEASE_PYTHONS: True
CIBW_FREE_THREADED_SUPPORT: True
CIBW_BUILD: ${{ matrix.python }}-${{ matrix.buildplat[1] }}
# TODO: remove along with installing build deps in
# cibw_before_build.sh when a released cython can build numpy
CIBW_BUILD_FRONTEND: "pip; args: --no-build-isolation"
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: ${{ matrix.python }}-${{ matrix.buildplat[1] }}-${{ matrix.buildplat[2] }}
path: ./wheelhouse/*.whl
- uses: mamba-org/setup-micromamba@f8b8a1e23a26f60a44c853292711bacfd3eac822
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: Upload wheels
if: success()
shell: bash -el {0}
# see https://github.com/marketplace/actions/setup-miniconda for why
# `-el {0}` is required.
env:
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).
# The tokens were originally generated at anaconda.org
upload_wheels