From 5b3635aa63fddb6c22d8bde45f8c6cdf88d64145 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 6 Nov 2025 09:12:04 -0500 Subject: [PATCH 01/11] MAINT: Build abi3 wheels and use native arm64 Linux --- .github/workflows/wheels.yml | 11 ++----- pyproject.toml | 24 ++++++++++++++-- setup.py | 56 ++++++++++++++++++++++++------------ tools/audit_wheel.sh | 9 ++++++ 4 files changed, 70 insertions(+), 30 deletions(-) create mode 100755 tools/audit_wheel.sh diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index d8c4686a..39e38f91 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -59,10 +59,10 @@ jobs: matrix: buildplat: - [ubuntu-latest, musllinux_x86_64] - - [ubuntu-latest, manylinux_aarch64] + - [ubuntu-24.04-arm64, manylinux_aarch64] - [macos-15-intel, macosx_x86_64] # native Intel hardware - [windows-latest, win_amd64] - python: ["cp310", "cp311", "cp312", "cp313", "cp314"] + python: ["cp310", "cp311"] include: # Manylinux and arm64 builds (on native hardware) are cheap, do all in one - { buildplat: ["ubuntu-latest", "manylinux_x86_64"], python: "*" } @@ -76,13 +76,6 @@ jobs: - name: Install the latest version of uv uses: astral-sh/setup-uv@v6 - # For aarch64 support - # https://cibuildwheel.pypa.io/en/stable/faq/#emulation - - uses: docker/setup-qemu-action@v3 - with: - platforms: all - if: runner.os == 'Linux' && endsWith(matrix.buildplat[1], 'aarch64') - - name: Build wheel(s) run: uvx cibuildwheel env: diff --git a/pyproject.toml b/pyproject.toml index 3141e3ab..049a63e0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,11 +64,12 @@ test = [ [tool.cibuildwheel] # Disable PyPy skip = "pp*" - +# 3.11 is abi3 +build = "cp310-* cp311-*" # 64-bit builds only; 32-bit builds seem pretty niche these days, so # don't bother unless someone asks archs = ["native"] - +before-build = "pip install auditwheel" test-requires = [ "pytest", "nitime[full]", # Enable all optional behavior @@ -76,7 +77,24 @@ test-requires = [ test-command = "pytest -rsx --pyargs nitime" [tool.cibuildwheel.linux] -archs = ["x86_64", "aarch64"] +repair-wheel-command = [ + "auditwheel repair -w {dest_dir} {wheel}", + "bash tools/audit_wheel.sh {wheel}", +] + +[tool.cibuildwheel.macos] +archs = ["native"] +repair-wheel-command = [ + "delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}", + "bash tools/audit_wheel.sh {wheel}", +] + +[tool.cibuildwheel.windows] +before-build = "pip install delvewheel abi3audit" +repair-wheel-command = [ + "delvewheel repair -w {dest_dir} {wheel}", + "bash tools/audit_wheel.sh {wheel}", +] [tool.pytest.ini_options] minversion = "8" diff --git a/setup.py b/setup.py index 3974b51f..56bf4bee 100755 --- a/setup.py +++ b/setup.py @@ -4,26 +4,46 @@ This file only contains cython components. See pyproject.toml for the remaining configuration. """ +import platform +import sys + from setuptools import setup +from setuptools import Extension +from Cython.Build import cythonize +from numpy import get_include + +# add Cython extensions to the setup options + + +# https://github.com/joerick/python-abi3-package-sample/blob/main/setup.py +class bdist_wheel_abi3(bdist_wheel): # noqa: D101 + def get_tag(self): # noqa: D102 + python, abi, plat = super().get_tag() + + if python.startswith("cp"): + return "cp311", "abi3", plat + + return python, abi, plat + +macros = [('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION')] +ext_kwargs = {} +setup_kwargs = {} +if sys.version_info.minor >= 11 and platform.python_implementation() == "CPython": + # Can create an abi3 wheel (typed memoryviews first available in 3.11)! + macros.append(("Py_LIMITED_API", "0x030B0000")) + ext_kwargs["py_limited_api"] = True + setup_kwargs["cmdclass"] = {"bdist_wheel": bdist_wheel_abi3} + -try: - from setuptools import Extension - from Cython.Build import cythonize - from numpy import get_include - - # add Cython extensions to the setup options - exts = [ - Extension( - 'nitime._utils', - ['nitime/_utils.pyx'], - include_dirs=[get_include()], - define_macros=[('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION')], - ) - ] - opts = {'ext_modules': cythonize(exts, language_level='3')} -except ImportError: - # no loop for you! - opts = {} +exts = [ + Extension( + 'nitime._utils', + ['nitime/_utils.pyx'], + include_dirs=[get_include()], + define_macros=macros, + ) +] +opts = {'ext_modules': cythonize(exts, language_level='3'), **setup_kwargs} # Now call the actual setup function if __name__ == '__main__': diff --git a/tools/audit_wheel.sh b/tools/audit_wheel.sh new file mode 100755 index 00000000..dcd80bef --- /dev/null +++ b/tools/audit_wheel.sh @@ -0,0 +1,9 @@ +#!/bin/bash -eo pipefail +set -x + +PY_MINOR=$(python -c "import sys; print(sys.version_info.minor)") +if [ "$PY_MINOR" -lt 11 ]; then + echo "Not checking abi3audit for Python $PY_MINOR < 3.11" + exit 0 +fi +abi3audit --strict --report --verbose "$1" From c6c7d0b5a76866a834902ae6818f5f01f045571e Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 6 Nov 2025 09:14:36 -0500 Subject: [PATCH 02/11] FIX: Missing --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 56bf4bee..77f433a4 100755 --- a/setup.py +++ b/setup.py @@ -7,10 +7,10 @@ import platform import sys -from setuptools import setup -from setuptools import Extension from Cython.Build import cythonize from numpy import get_include +from setuptools import setup, Extension +from wheel.bdist_wheel import bdist_wheel # add Cython extensions to the setup options From 3c336435d18dcf3c04b42ca0c5ebf92925c9fded Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 6 Nov 2025 09:14:50 -0500 Subject: [PATCH 03/11] FIX: Spacing --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 77f433a4..300dcb10 100755 --- a/setup.py +++ b/setup.py @@ -25,6 +25,7 @@ def get_tag(self): # noqa: D102 return python, abi, plat + macros = [('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION')] ext_kwargs = {} setup_kwargs = {} From d6bc040f9bf2d40adc2dd0a40536de2065f15a5b Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 6 Nov 2025 09:16:10 -0500 Subject: [PATCH 04/11] TST: Wheels [build wheels] From 3bcc84e135e9e78649fc0da8283a2a44b458b0bb Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 6 Nov 2025 09:27:06 -0500 Subject: [PATCH 05/11] FIX: Wrong --- .github/workflows/wheels.yml | 22 +++++++++------------- pyproject.toml | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 39e38f91..635e0536 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -59,31 +59,27 @@ jobs: matrix: buildplat: - [ubuntu-latest, musllinux_x86_64] + - [ubuntu-latest, manylinux_x86_64] - [ubuntu-24.04-arm64, manylinux_aarch64] - - [macos-15-intel, macosx_x86_64] # native Intel hardware + - [macos-latest, macosx_arm64] + - [macos-15-intel, macosx_x86_64] - [windows-latest, win_amd64] - python: ["cp310", "cp311"] - include: - # Manylinux and arm64 builds (on native hardware) are cheap, do all in one - - { buildplat: ["ubuntu-latest", "manylinux_x86_64"], python: "*" } - - { buildplat: ["macos-14", "macosx_arm64"], python: "*" } steps: - uses: actions/checkout@v5 with: fetch-depth: 0 - - name: Install the latest version of uv - uses: astral-sh/setup-uv@v6 - - name: Build wheel(s) - run: uvx cibuildwheel - env: - CIBW_BUILD: ${{ matrix.python }}-${{ matrix.buildplat[1] }} + uses: pypa/cibuildwheel@v3.2.1 + with: + env: + CIBW_BUILD: "cp*-${{ matrix.buildplat[1] }}" + CIBW_SKIP: "cp312-* cp313-* cp314-*" - uses: actions/upload-artifact@v5 with: - name: ${{ matrix.python == '*' && 'all' || matrix.python }}-${{ startsWith(matrix.buildplat[1], 'macosx') && 'macosx' || matrix.buildplat[1] }}-dist + name: ${{ startsWith(matrix.buildplat[1], 'macosx') && 'macosx' || matrix.buildplat[1] }}-dist path: ./wheelhouse/*.whl test-sdist: diff --git a/pyproject.toml b/pyproject.toml index 049a63e0..e1d4365a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,7 @@ build = "cp310-* cp311-*" # 64-bit builds only; 32-bit builds seem pretty niche these days, so # don't bother unless someone asks archs = ["native"] -before-build = "pip install auditwheel" +before-build = "pip install abi3audit" test-requires = [ "pytest", "nitime[full]", # Enable all optional behavior From d8d23f1819413dbf6c35088c3e01bed6b1fe7878 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 6 Nov 2025 09:27:41 -0500 Subject: [PATCH 06/11] FIX: Fast enough now --- .github/workflows/wheels.yml | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 635e0536..dd3e0d41 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -15,26 +15,6 @@ concurrency: cancel-in-progress: true jobs: - job_metadata: - runs-on: ubuntu-latest - outputs: - commit_message: ${{ steps.get_commit_message.outputs.commit_message }} - steps: - - name: Checkout - uses: actions/checkout@v5 - with: - fetch-depth: 2 - - name: Print head git commit message - id: get_commit_message - run: | - if [[ -z "$COMMIT_MSG" ]]; then - COMMIT_MSG=$(git show -s --format=%s $REF) - fi - echo commit_message=$COMMIT_MSG | tee -a $GITHUB_OUTPUT - env: - COMMIT_MSG: ${{ github.event.head_commit.message }} - REF: ${{ github.event.pull_request.head.sha }} - build-sdist: name: Build sdist runs-on: ubuntu-latest @@ -51,9 +31,7 @@ jobs: build-wheel: name: Build wheel for ${{ matrix.python }}-${{ matrix.buildplat[1] }} - needs: [job_metadata] runs-on: ${{ matrix.buildplat[0] }} - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') || contains(needs.job_metadata.outputs.commit_message, '[build wheels]') strategy: fail-fast: false matrix: From ebb55d0943440baa30ed6a36dd1ffc968d24f293 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 6 Nov 2025 09:29:19 -0500 Subject: [PATCH 07/11] FIX: Name --- .github/workflows/wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index dd3e0d41..3800d2ae 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -30,7 +30,7 @@ jobs: path: ./dist/*.tar.gz build-wheel: - name: Build wheel for ${{ matrix.python }}-${{ matrix.buildplat[1] }} + name: Build wheel for ${{ matrix.buildplat[1] }} runs-on: ${{ matrix.buildplat[0] }} strategy: fail-fast: false From fec414767a2fed590fb643f3a166135aa93d1dcc Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 6 Nov 2025 09:31:30 -0500 Subject: [PATCH 08/11] FIX: Mpping --- .github/workflows/wheels.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 3800d2ae..46edd05c 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -50,10 +50,9 @@ jobs: - name: Build wheel(s) uses: pypa/cibuildwheel@v3.2.1 - with: - env: - CIBW_BUILD: "cp*-${{ matrix.buildplat[1] }}" - CIBW_SKIP: "cp312-* cp313-* cp314-*" + env: + CIBW_BUILD: "cp*-${{ matrix.buildplat[1] }}" + CIBW_SKIP: "cp312-* cp313-* cp314-*" - uses: actions/upload-artifact@v5 with: From 716491efc07f2f0e0bf5b283643e3266f73a3033 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 6 Nov 2025 09:32:27 -0500 Subject: [PATCH 09/11] FIX: One line --- .github/workflows/wheels.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 46edd05c..17560b67 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -51,8 +51,7 @@ jobs: - name: Build wheel(s) uses: pypa/cibuildwheel@v3.2.1 env: - CIBW_BUILD: "cp*-${{ matrix.buildplat[1] }}" - CIBW_SKIP: "cp312-* cp313-* cp314-*" + CIBW_BUILD: "cp310-${{ matrix.buildplat[1] }} cp311-${{ matrix.buildplat[1] }} " - uses: actions/upload-artifact@v5 with: From 519defa710ba5a1425efc7226007ee5d759b0ec2 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 6 Nov 2025 09:36:41 -0500 Subject: [PATCH 10/11] FIX: Name --- .github/workflows/wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 17560b67..9d6e0b73 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -38,7 +38,7 @@ jobs: buildplat: - [ubuntu-latest, musllinux_x86_64] - [ubuntu-latest, manylinux_x86_64] - - [ubuntu-24.04-arm64, manylinux_aarch64] + - [ubuntu-24.04-arm, manylinux_aarch64] - [macos-latest, macosx_arm64] - [macos-15-intel, macosx_x86_64] - [windows-latest, win_amd64] From 8dee24e146b572ea28527274601e965ae0810e1a Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 6 Nov 2025 09:38:47 -0500 Subject: [PATCH 11/11] FIX: Name --- .github/workflows/wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 9d6e0b73..1afd8300 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -55,7 +55,7 @@ jobs: - uses: actions/upload-artifact@v5 with: - name: ${{ startsWith(matrix.buildplat[1], 'macosx') && 'macosx' || matrix.buildplat[1] }}-dist + name: ${{ matrix.buildplat[1] }}-dist path: ./wheelhouse/*.whl test-sdist: