Skip to content

BLD: Add support for building iOS wheels#28759

Open
freakboy3742 wants to merge 33 commits intonumpy:mainfrom
freakboy3742:ios-support
Open

BLD: Add support for building iOS wheels#28759
freakboy3742 wants to merge 33 commits intonumpy:mainfrom
freakboy3742:ios-support

Conversation

@freakboy3742
Copy link
Copy Markdown
Contributor

@freakboy3742 freakboy3742 commented Apr 18, 2025

Adds iOS as a test and release target for NumPy.

UPDATE: 12 Nov 2025 This PR is almost ready for review. PR body reflects current status.

In an environment where:

  • Xcode and the iOS SDK is installed, with all licences accepted.
  • cibuildwheel 3.2.1 is installed
  • ninja is available on the path

This branch will build and test accelerated iOS device and simulator wheels:

CIBW_PLATFORM=ios CIBW_ENVIRONMENT="INSTALL_OPENBLAS=false RUNNER_OS=iOS IPHONEOS_DEPLOYMENT_TARGET=17.0" cibuildwheel 

The build will also work without the IPHONEOS_DEPLOYMENT_TARGET definition, but with an unaccelerated version of blas (this is the analog of the MACOSX_DEPLOYMENT_TARGET=14.0 configuration, except that there isn't a pre-compiled openBLAS for iOS to fall back on).

Other notable details of this PR:

@rgommers
Copy link
Copy Markdown
Member

Thanks @freakboy3742. This looks pretty clean. The vendored-meson changes are integrated in the main branch of this repo now that gh-28860 is merged. I'd be fine with merging the npy_cblas.h and numpy/meson.build changes in this PR separate if that helps you, those changes look good to go.

@freakboy3742
Copy link
Copy Markdown
Contributor Author

And update; after discussions on the mesonbuild/meson-python#731, some additional changes to meson (mesonbuild/meson#14541) and CPython (python/cpython#133184) were identified. I'm working on getting those changes upstreamed.

@henryiii
Copy link
Copy Markdown
Contributor

cibuildwheel 3.0 out. :)

@freakboy3742
Copy link
Copy Markdown
Contributor Author

cibuildwheel 3.0 out. :)

Awesome! A new meson-python release is only remaining blocker.

@freakboy3742
Copy link
Copy Markdown
Contributor Author

freakboy3742 commented Jul 29, 2025

Status update: With the current main branch of meson-python, numpy/meson#22 applied to the meson-python branch, and the current main branch of cibuildwheel, this passes the full test suite on iOS under both Python 3.13 and 3.14.

The changes to the test suite changes involve:

  1. making test skips that were WASM-specific into a more generic test skip when subprocess isn't available, or
  2. making known macOS-specific test skips generic to all Apple platforms.

On top of those changes, there's one specific change to ctypes handling to account for the odd way that iOS handles dynamic loading, and one workaround for a pytest issue (related to getuser() and the creation of temporary files).

Comment thread numpy/testing/_private/utils.py Outdated
@rgommers
Copy link
Copy Markdown
Member

The test changes seem fine to me.

@freakboy3742
Copy link
Copy Markdown
Contributor Author

I've added CI workflows, and updated cibuildwheel and vendored-meson versions; the meson-python release is the only outstanding TODO.

I've updated the description of the PR to reflect current status, and a couple of notable design decisions.

@freakboy3742
Copy link
Copy Markdown
Contributor Author

I've just pushed an update; This is still waiting on a meson-python release, plus a fix for python/cpython#141443 (which then needs to work its way through the cibuildwheel release process. The latter problem causes a test failure because the not slow pytest argument is interpreted as 2 arguments, even though it's quoted.

The current complexity in the iOS workflow is caused by what appears to be a bug in the meson - if a single build tries to compile both arm64_iphoneos and arm64_iphonesimulator, the build.ninja file for the second architecture built is not clean - the C and C++ compiler rules aren't updated for the second architecture target. The linker commands are updated, though. Splitting the workflows out so that there's a single architecture per cibuildwheel invocation avoids the problem; I'm not even sure how to start diagnosing the underlying cause...

Comment thread numpy/_core/meson.build
Comment thread .github/workflows/wheels.yml Outdated
Comment thread .github/workflows/wheels.yml Outdated
Comment on lines +102 to +104
if [[ "${{ matrix.buildplat[3] }}" == 'accelerate' ]]; then
# Accelerate with ILP64 requires iOS 16.4 or higher
CIBW="IPHONEOS_DEPLOYMENT_TARGET=17.0 INSTALL_OPENBLAS=false RUNNER_OS=iOS"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iOS 17 is only 2 years old, so this means most apps, including the default Briefcase configuration, will end up using the unaccelerated build, which may be "100x slower".

Could we avoid this by building in non-ILP64 mode? As I understand it, the only advantage of ILP64 is that it allows arrays with more than 2 billion elements, which, on a phone, is far less likely to be a problem than a 100x slowdown. In that case, there probably isn't even any need for a separate iOS 17.0 build, and the workflows can all be simplified.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only using LP64 (32-bit) BLAS seems fine to me. That said, the LP64 Accelerate comes in two flavors as well - the improved one (with the $NEWLAPACK symbol names) was introduced at the same time as the ILP64 support. The old Accelerate may work, but I'm not sure since we don't use it for anything else and it's not tested in CI. If it does build and passes the test suite, then it should be safe to use it. Some fiddling may be required to avoid defining ACCELERATE_NEW_LAPACK; see notes under AccelerateSystemDependency in vendored-meson/meson/mesonbuild/dependencies/blas_lapack.py

Copy link
Copy Markdown
Contributor Author

@freakboy3742 freakboy3742 Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be "only" 2 years old, but a feature of the iOS ecosystem is mass and near-immediate adoption of OS updates. Based on this chart, as of today, 97.5% of devices are on iOS 17 or newer. I included the "non accelerate" wheels mostly as a convenience so that a default iOS install will have access to something.

I can take a look to see if it's possible to pick up the older accelerate implementation on iOS13+.

@github-actions

This comment has been minimized.

Comment thread numpy/testing/_private/utils.py Outdated
@rgommers
Copy link
Copy Markdown
Member

A new meson-python release is only remaining blocker.

Sorry that that took so long 🙄. meson-python 0.19.0 is up on PyPI now, conda-forge will follow shortly.

@freakboy3742
Copy link
Copy Markdown
Contributor Author

A new meson-python release is only remaining blocker.

Sorry that that took so long 🙄. meson-python 0.19.0 is up on PyPI now, conda-forge will follow shortly.

No worries - thanks for letting me know. I've done the immediate merge; I should have a chance to address the remaining issues (and revert some of the overenthusiastic Ruff handling...) early next week.

@freakboy3742
Copy link
Copy Markdown
Contributor Author

I've got this passing tests locally; but it is failing in CI because it requires an updates iOS support package in cibuildwheel. I'll be working on that over the next couple of days.

@mhsmith
Copy link
Copy Markdown
Contributor

mhsmith commented Apr 14, 2026

@freakboy3742: What's the status of this PR?

@freakboy3742 freakboy3742 marked this pull request as ready for review April 15, 2026 01:10
@freakboy3742
Copy link
Copy Markdown
Contributor Author

My apologies - this fell off my radar for a bit; I was waiting for a cibuildwheel release for some patches. Those changes have now landed, and I've merged this PR with the current main.

The PR could be reviewed (and potentially merged) as is as of 11c74b7 (the most recent-but-one commit).

That build removes x86-64 simulator wheels from the build. In the most recent CI passes, the wheels build and pass almost all the tests, but here were failing some tests verifying the print format of floating point and complex types. I'm guessing they're related to the odd float sizeI couldn't find an immediately obvious cause for these problems (they're likely related to the odd float size, so I came to the conclusion that it wasn't worth the effort.

The x86-64 simulator platform is on borrowed time at this point. Apple no longer produced x86-64 hardware; Tahoe (macOS 26, released last year) is the last macOS that will include x86-64 support; Circle CI dropped x86-64 simulators 2 years ago, and Github has indicated that they're dropping support in Fall of next year. So - I'd need to do a bunch of debugging for a hardware platform that we'd need to deprecate in just over 12 months.

The most recent commit is failing CI on older iOS versions. There was a discussion above about whether we should be using "non-accelerated" iOS wheels, or using the older Accelerate interface; I've done some tinkering, and with the inclusion of numpy/meson#25 in the vendored meson, I can generate "pre-NEW_LAPACK" wheels for iOS 13.0.

@rgommers
Copy link
Copy Markdown
Member

so I came to the conclusion that it wasn't worth the effort.

That sounds right to me.

with the inclusion of numpy/meson#25 in the vendored meson, I can generate "pre-NEW_LAPACK" wheels for iOS 13.0.

That looks pretty clean, I'd be fine with merging that if it's needed. I'll have a look at that tomorrow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

36 - Build Build related PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants