Skip to content

Commit 1d63ec7

Browse files
authored
add CI job updates too (#32)
1 parent 131eac0 commit 1d63ec7

4 files changed

Lines changed: 175 additions & 6 deletions

File tree

‎.github/workflows/dry-run-testpypi.yml‎

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,83 @@ jobs:
115115
path: dist/*.whl
116116
if-no-files-found: error
117117

118+
build-wheel-macos:
119+
name: Build macOS arm64 wheel (cp${{ matrix.python-version }})
120+
needs: [resolve]
121+
runs-on: macos-15
122+
timeout-minutes: 120
123+
124+
strategy:
125+
fail-fast: false
126+
matrix: ${{ fromJSON(needs.resolve.outputs.matrix) }}
127+
128+
steps:
129+
- name: Check out source
130+
uses: actions/checkout@v7
131+
with:
132+
ref: ${{ inputs.ref }}
133+
134+
- name: Set up Python
135+
uses: actions/setup-python@v7
136+
with:
137+
python-version: ${{ matrix.python-version }}
138+
cache: pip
139+
140+
# The wheel bundles Homebrew's libomp, so it can only claim the macOS
141+
# version that libomp was built for.
142+
- name: Install libomp and set deployment target
143+
run: |
144+
brew install libomp
145+
prefix="$(brew --prefix libomp)"
146+
minos="$(otool -l "$prefix/lib/libomp.dylib" | awk '/LC_BUILD_VERSION/{f=1} f&&/minos/{print $2; exit}')"
147+
echo "LIBOMP_PREFIX=$prefix" >> "$GITHUB_ENV"
148+
echo "MACOSX_DEPLOYMENT_TARGET=$minos" >> "$GITHUB_ENV"
149+
echo "libomp at $prefix, macOS deployment target $minos"
150+
151+
- name: Install build tooling
152+
run: |
153+
python -m pip install --upgrade pip
154+
python -m pip install build wheel delocate
155+
156+
- name: Build wheel
157+
run: python -m build --wheel --outdir ../dist
158+
working-directory: senpy
159+
160+
- name: Bundle native libraries into wheel
161+
run: |
162+
cd dist
163+
for whl in *.whl; do
164+
delocate-wheel --require-archs arm64 -w repaired -v "$whl"
165+
rm "$whl"
166+
done
167+
mv repaired/*.whl .
168+
rmdir repaired
169+
delocate-listdeps --all *.whl
170+
cd ..
171+
172+
- name: List wheel
173+
run: ls -lh dist
174+
175+
# Remove Homebrew's libomp so the smoke test proves the wheel is self-contained.
176+
- name: Smoke test wheel
177+
run: |
178+
brew uninstall --ignore-dependencies libomp
179+
python -m pip install dist/*.whl
180+
cp senpy/example.py "$RUNNER_TEMP/example.py"
181+
cd "$RUNNER_TEMP"
182+
python -c "import pathlib, senpy; assert pathlib.Path(senpy.__file__).resolve().is_relative_to(pathlib.Path('${{ github.workspace }}').resolve()) is False; print('senpy imported successfully')"
183+
python example.py
184+
185+
- name: Upload wheel artifact
186+
uses: actions/upload-artifact@v7
187+
with:
188+
name: testpypi-wheel-macos-${{ matrix.python-version }}
189+
path: dist/*.whl
190+
if-no-files-found: error
191+
118192
publish-testpypi:
119193
name: Publish to TestPyPI
120-
needs: [resolve, build-wheel]
194+
needs: [resolve, build-wheel, build-wheel-macos]
121195
runs-on: ubuntu-latest
122196
environment:
123197
name: testpypi

‎.github/workflows/release-wheel.yml‎

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,97 @@ jobs:
167167
path: dist/*.whl
168168
if-no-files-found: error
169169

170+
build-wheel-macos:
171+
name: Build macOS arm64 wheel (cp${{ matrix.python-version }})
172+
needs: [resolve]
173+
runs-on: macos-15
174+
timeout-minutes: 120
175+
permissions:
176+
contents: write
177+
178+
strategy:
179+
fail-fast: false
180+
matrix: ${{ fromJSON(needs.resolve.outputs.matrix) }}
181+
182+
steps:
183+
- name: Check out release source
184+
uses: actions/checkout@v7
185+
with:
186+
ref: ${{ needs.resolve.outputs.tag }}
187+
188+
- name: Set up Python
189+
uses: actions/setup-python@v7
190+
with:
191+
python-version: ${{ matrix.python-version }}
192+
cache: pip
193+
194+
# The wheel bundles Homebrew's libomp, so it can only claim the macOS
195+
# version that libomp was built for.
196+
- name: Install libomp and set deployment target
197+
run: |
198+
brew install libomp
199+
prefix="$(brew --prefix libomp)"
200+
minos="$(otool -l "$prefix/lib/libomp.dylib" | awk '/LC_BUILD_VERSION/{f=1} f&&/minos/{print $2; exit}')"
201+
echo "LIBOMP_PREFIX=$prefix" >> "$GITHUB_ENV"
202+
echo "MACOSX_DEPLOYMENT_TARGET=$minos" >> "$GITHUB_ENV"
203+
echo "libomp at $prefix, macOS deployment target $minos"
204+
205+
- name: Install build tooling
206+
run: |
207+
python -m pip install --upgrade pip
208+
python -m pip install build wheel delocate
209+
210+
- name: Build wheel
211+
run: python -m build --wheel --outdir ../dist
212+
working-directory: senpy
213+
214+
- name: Bundle native libraries into wheel
215+
run: |
216+
cd dist
217+
for whl in *.whl; do
218+
delocate-wheel --require-archs arm64 -w repaired -v "$whl"
219+
rm "$whl"
220+
done
221+
mv repaired/*.whl .
222+
rmdir repaired
223+
delocate-listdeps --all *.whl
224+
cd ..
225+
226+
- name: List wheel
227+
run: ls -lh dist
228+
229+
# Remove Homebrew's libomp so the smoke test proves the wheel is self-contained.
230+
- name: Smoke test wheel
231+
run: |
232+
brew uninstall --ignore-dependencies libomp
233+
python -m pip install dist/*.whl
234+
cp senpy/example.py "$RUNNER_TEMP/example.py"
235+
cd "$RUNNER_TEMP"
236+
python -c "import pathlib, senpy; assert pathlib.Path(senpy.__file__).resolve().is_relative_to(pathlib.Path('${{ github.workspace }}').resolve()) is False; print('senpy imported successfully')"
237+
python example.py
238+
239+
- name: Verify release exists
240+
env:
241+
GH_TOKEN: ${{ github.token }}
242+
TAG: ${{ needs.resolve.outputs.tag }}
243+
run: gh release view "$TAG"
244+
245+
- name: Upload wheel to release
246+
env:
247+
GH_TOKEN: ${{ github.token }}
248+
TAG: ${{ needs.resolve.outputs.tag }}
249+
run: gh release upload "$TAG" dist/*.whl --clobber
250+
251+
- name: Upload wheel artifact
252+
uses: actions/upload-artifact@v7
253+
with:
254+
name: pypi-wheel-macos-${{ matrix.python-version }}
255+
path: dist/*.whl
256+
if-no-files-found: error
257+
170258
publish-pypi:
171259
name: Publish to PyPI
172-
needs: [resolve, build-wheel]
260+
needs: [resolve, build-wheel, build-wheel-macos]
173261
# On release events always publish; on manual runs only when requested.
174262
if: github.event_name == 'release' || inputs.publish-to-pypi
175263
runs-on: ubuntu-latest

‎CMakeLists.txt‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,21 @@ endif()
1212

1313
# Compiler-specific optimizations
1414
# Note: -ffast-math is intentionally omitted — it breaks FINUFFT (IEEE-754 violations)
15-
# CI runners use x86-64-v3 (AVX2) for portability; local builds use native.
15+
# CI runners use a portable baseline -- x86-64-v3 (AVX2) on x86, the Apple M1
16+
# on Apple Silicon -- so release wheels run on any CPU of that family; local
17+
# builds use native.
1618
if(DEFINED ENV{CI} AND "$ENV{CI}" STREQUAL "true")
17-
set(MARCH_FLAG "-march=x86-64-v3")
19+
if(APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")
20+
set(MARCH_FLAG "-mcpu=apple-m1")
21+
else()
22+
set(MARCH_FLAG "-march=x86-64-v3")
23+
endif()
1824
# FINUFFT defaults FINUFFT_ARCH_FLAGS to "native" (-march=native), which bakes
1925
# the build machine's ISA (e.g. AVX-512) into libfinufft.so. Release wheels
2026
# must be portable, so pin the dependency to the same baseline as the rest of
2127
# the build. This must be a CACHE variable: FINUFFT's own CMakeLists declares
2228
# it with `CACHE`, and normal variables do not propagate into its scope.
23-
set(FINUFFT_ARCH_FLAGS "-march=x86-64-v3" CACHE STRING "" FORCE)
29+
set(FINUFFT_ARCH_FLAGS "${MARCH_FLAG}" CACHE STRING "" FORCE)
2430
else()
2531
set(MARCH_FLAG "-march=native -mtune=native")
2632
set(FINUFFT_ARCH_FLAGS "-march=native" CACHE STRING "" FORCE)

‎README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ python -m pip install arcascope-senpy
1313
python -m pip install 'arcascope-senpy[jax]'
1414
```
1515

16-
Prebuilt manylinux wheels are published for CPython 3.12, 3.13, and 3.14. Python 3.11 and other
16+
Prebuilt wheels are published for CPython 3.12, 3.13, and 3.14 on manylinux x86_64 and macOS
17+
arm64 (Apple Silicon; the macOS wheels bundle their OpenMP runtime). Python 3.11 and other
1718
platforms build from source on install.
1819

1920
To install a specific precompiled wheel from a GitHub release instead:

0 commit comments

Comments
 (0)