From f83423b01d0e9cc9854eebe2926fe4a716262550 Mon Sep 17 00:00:00 2001 From: zacharyburnett Date: Fri, 10 Apr 2026 09:54:16 -0400 Subject: [PATCH 1/7] build Python wheels with `cibuildwheel` and add to build workflow --- .github/workflows/build.yml | 48 +++++++++++++++++++++++++++++++++++++ pyproject.toml | 7 ++++-- setup.py | 4 +++- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 801c39c13..907d49880 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -94,3 +94,51 @@ jobs: --test_verbose_timeout_warnings \ //... working-directory: src + python: + strategy: + matrix: + runs-on: + - ubuntu-latest + # `large` is x86-64 and `xlarge` is AArch64. + - macos-latest-large + # macos-latest-xlarge may timeout. + # https://github.com/google/s2geometry/issues/409 + - macos-latest-xlarge + fail-fast: false + runs-on: ${{ matrix.runs-on }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-tags: true + persist-credentials: false + - uses: pypa/cibuildwheel@8d2b08b68458a16aeb24b64e68a09ab1c8e82084 # v3.4.1 + with: + package-dir: ./ + output-dir: dist/ + - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: dist-${{ runner.os }}-${{ runner.arch }} + path: ./dist/ + python-publish: + if: (github.event_name == 'release') && (github.event.action == 'released') + needs: [python] + runs-on: ubuntu-latest + permissions: + id-token: write + attestations: write + # Requires environment protection rules in GitHub Settings: + # Settings > Environments > pypi > Add required reviewers + environment: + name: pypi + url: https://pypi.org/p/s2geometry + steps: + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + pattern: dist* + path: dist/ + merge-multiple: true + - uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3.2.0 + with: + subject-path: "dist/*" + # To upload to PyPI without a token, add this workflow file as a Trusted Publisher in the project settings on the PyPI website + - uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 diff --git a/pyproject.toml b/pyproject.toml index 5e019ca2a..d8506b88a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,10 +36,10 @@ test = [ [build-system] requires = [ - "wheel", + "cmake_build_extension", "setuptools", "setuptools_scm[toml]", - "cmake_build_extension", + "swig", ] build-backend = "setuptools.build_meta" @@ -60,3 +60,6 @@ namespaces = false # The same as the default. See #450. # https://setuptools-scm.readthedocs.io/en/latest/config/#setuptools_scm._config.DEFAULT_TAG_REGEX tag_regex = "^(?:[\\w-]+-)?(?P[vV]?\\d+(?:\\.\\d+){0,2}[^\\+]*)(?:\\+.*)?$" + +[tool.cibuildwheel] +test-command = "python -c 'import s2geometry'" diff --git a/setup.py b/setup.py index 242882ab3..2682d1fbf 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,9 @@ '-DCALL_FROM_SETUP_PY:BOOL=ON', '-DBUILD_SHARED_LIBS:BOOL=OFF', '-DCMAKE_POSITION_INDEPENDENT_CODE=ON', - '-DWITH_PYTHON=ON' + '-DWITH_PYTHON=ON', + '-DBUILD_TESTS=OFF', + '-DFETCH_ABSEIL=ON', ] ) ], From 62de1290b628520959229c7033913fb4aa1184c5 Mon Sep 17 00:00:00 2001 From: zacharyburnett Date: Mon, 20 Apr 2026 09:45:34 -0400 Subject: [PATCH 2/7] add minimum macOS version add comment for min macOS pin --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f8120cb6..b6a0e117b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,9 @@ cmake_minimum_required(VERSION 3.18) +# avoids error: aligned allocation function of type 'void *(std::size_t, std::align_val_t)' is only available on macOS 10.13 or newer +# see https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md#macos +set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "Minimum macOS version") + project(s2-geometry VERSION 0.12.0) From 1edc6beed4b26a1dafd5e5b7af8e407935cf8d46 Mon Sep 17 00:00:00 2001 From: zacharyburnett Date: Mon, 20 Apr 2026 12:30:18 -0400 Subject: [PATCH 3/7] skip macOS wheel delocation add comment for skipping wheel delocation on macOS --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index d8506b88a..d5abcddaa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,3 +63,7 @@ tag_regex = "^(?:[\\w-]+-)?(?P[vV]?\\d+(?:\\.\\d+){0,2}[^\\+]*)(?:\\+.* [tool.cibuildwheel] test-command = "python -c 'import s2geometry'" + +[tool.cibuildwheel.macos] +# skip wheel delocation (command can't find the binary) +repair-wheel-command = "" From e2311d5dc2b8a48a5ea92fc06a6b5ede243ff2af Mon Sep 17 00:00:00 2001 From: zacharyburnett Date: Tue, 21 Apr 2026 14:04:58 -0400 Subject: [PATCH 4/7] run pytest in cibuildwheel --- pyproject.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d5abcddaa..c1ed25cb3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ content-type = "text/plain" [project.urls] Source = "https://github.com/google/s2geometry" -[project.optional-dependencies] +[dependency-groups] test = [ "pytest", ] @@ -62,7 +62,8 @@ namespaces = false tag_regex = "^(?:[\\w-]+-)?(?P[vV]?\\d+(?:\\.\\d+){0,2}[^\\+]*)(?:\\+.*)?$" [tool.cibuildwheel] -test-command = "python -c 'import s2geometry'" +test-groups = ["test"] +test-command = "pytest {project}/src/python/s2geometry_test.py" [tool.cibuildwheel.macos] # skip wheel delocation (command can't find the binary) From 9dd13901bc481f1f8253356e49416eca4ca5cf1b Mon Sep 17 00:00:00 2001 From: zacharyburnett Date: Tue, 21 Apr 2026 16:12:04 -0400 Subject: [PATCH 5/7] enable py_limited_api via cmake args and setuptools option --- setup.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/setup.py b/setup.py index 2682d1fbf..e19ce643b 100644 --- a/setup.py +++ b/setup.py @@ -16,18 +16,20 @@ # (it could be a subfolder) source_dir=str(Path(__file__).parent.absolute()), cmake_configure_options=[ - # This option points CMake to the right Python interpreter, and helps - # the logic of FindPython3.cmake to find the active version - f"-DPython3_ROOT_DIR={Path(sys.prefix)}", - '-DCALL_FROM_SETUP_PY:BOOL=ON', - '-DBUILD_SHARED_LIBS:BOOL=OFF', - '-DCMAKE_POSITION_INDEPENDENT_CODE=ON', - '-DWITH_PYTHON=ON', - '-DBUILD_TESTS=OFF', - '-DFETCH_ABSEIL=ON', - ] - ) + # This option points CMake to the right Python interpreter, and helps + # the logic of FindPython3.cmake to find the active version + f"-DPython3_ROOT_DIR={Path(sys.prefix)}", + "-DCALL_FROM_SETUP_PY:BOOL=ON", + "-DBUILD_SHARED_LIBS:BOOL=OFF", + "-DCMAKE_POSITION_INDEPENDENT_CODE=ON", + "-DWITH_PYTHON=ON", + "-DBUILD_TESTS=OFF", + "-DFETCH_ABSEIL=ON", + "-DWITH_PYTHON_LIMITED_API=ON", + ] + ), ], + options={"bdist_wheel": {"py_limited_api": "cp310"}}, cmdclass=dict( # Enable the CMakeExtension entries defined above build_ext=cmake_build_extension.BuildExtension, From efe3f4952c70765dfa26cf969172aa13c47d9724 Mon Sep 17 00:00:00 2001 From: zacharyburnett Date: Tue, 21 Apr 2026 16:19:47 -0400 Subject: [PATCH 6/7] run abi3audit on wheel --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c1ed25cb3..8d091158c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ Source = "https://github.com/google/s2geometry" [dependency-groups] test = [ "pytest", + "abi3audit" ] [build-system] @@ -63,7 +64,7 @@ tag_regex = "^(?:[\\w-]+-)?(?P[vV]?\\d+(?:\\.\\d+){0,2}[^\\+]*)(?:\\+.* [tool.cibuildwheel] test-groups = ["test"] -test-command = "pytest {project}/src/python/s2geometry_test.py" +test-command = "pytest {project}/src/python/s2geometry_test.py && abi3audit --strict --report {project}/dist/*.whl" [tool.cibuildwheel.macos] # skip wheel delocation (command can't find the binary) From 9260a5ed5c797e0b152fed06f4d04608fb46f446 Mon Sep 17 00:00:00 2001 From: zacharyburnett Date: Tue, 21 Apr 2026 16:24:44 -0400 Subject: [PATCH 7/7] tell cibuildwheel to only try cp310 --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 8d091158c..36278aa7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,6 +63,8 @@ namespaces = false tag_regex = "^(?:[\\w-]+-)?(?P[vV]?\\d+(?:\\.\\d+){0,2}[^\\+]*)(?:\\+.*)?$" [tool.cibuildwheel] +# we only need to build with CPython 3.10 (because of the limited API / stable ABI) +build = "cp310-*" test-groups = ["test"] test-command = "pytest {project}/src/python/s2geometry_test.py && abi3audit --strict --report {project}/dist/*.whl"