Skip to content

Conversation

freakboy3742
Copy link
Contributor

@freakboy3742 freakboy3742 commented Aug 27, 2025

This script simplifies the process of configuring, compiling and packaging an XCframework for an Apple platform. This is an analog of the scripts used to build Android and Emscripten artefacts. It is a precursor to adding GitHub Action builds for iOS, and producing iOS build artefacts.

At present, it only supports iOS, but it has been constructed so that it could be used on any Apple platform (including, potentially, a redistributable macOS XCframework).

The simplest usage of this script is:

  $ python Apple ci iOS

which will:

  • Clean any pre-existing build artefacts
  • Configure and make a Python that can be used for the build
  • Configure and make a Python for each supported iOS architecture and ABI
  • Combine the outputs of the builds from the previous step into a single
    XCframework, merging binaries into a "fat" binary if necessary
  • Clone a copy of the testbed, configured to use the XCframework
  • Construct a tarball containing the release artefacts
  • Run the test suite using the generated XCframework.

This is the complete sequence that would be needed in CI to build and test a candidate release artefact. The output of the command will detect if it's running in a GitHub Actions and use output groups to make the log output easier to digest.

Each individual step can be invoked individually - there are commands to clean, configure-build, make-build, configure-host, make-host, package, and test.

There is also a build command that can be used to combine the configure and make steps for the build Python, an individual host, all hosts, or all builds.

One of the steps is to manage the download of binary artefacts; these artefacts are downloaded to the cross-build/downloads folder by default, but an alternate cache location can be provided.

There are three potentially controversial parts to this PR:

Moving iOS to Apple/iOS

As part of recognising that iOS is one of (potentially) many Apple platforms, and to prevent future proliferation of top-level directories for other Apple platforms, it migrates the iOS folder into a top level Apple folder. This change isn't strictly required, but if we don't make this change now, there is potential for a proliferation of directories if/when we add support for tvOS, watchOS, visionOS, macCatalyst. It also provides a convenient home for "cross platform" apple concerns, like the testbed script and the build script itself, as well as place for the existing content in the Mac directory to migrate to as part of a cleanup of macOS builds - something that @ned-deily has expressed an interest in doing 1

Universal simulator binaries

This PR generates a build that includes x86_64 simulator binaries. The iOS simulator slice of the XCframework is effectively a "universal" build covering both x86_64 and ARM64; although it has to be compiled in 2 passes and binaries merged after the fact. It's possible to both compile and test x86_64 binaries on ARM64 machines (pass --simulator "iPhone 16e,arch=x86_64" to the ci or test target, or to the testbed script), although running the test suite in emulator mode currently causes some test failure related to build-details.json not being fully cross-platform aware.

x86_64 isn't a Tier 3 platform for Python due to the difficulties of commissioning a buildbot; but x86_64 is still a supported platform for Apple. If we're going to produce official binaries, it seems to me like we should still support x86_64.

If we choose not to support x86_64, then there will be some changes required to the build script and testbed, as the name of the simulator slice will change from ios_arm64_x86_64_simulator to ios_arm64_simulator. It would also allow removing the most complicated part of this script - the part that does the merging of binaries.

Backporting to 3.13 and 3.14

I've proposed this for backport to 3.13 and 3.14. This is primarily so that the buildbots can be migrated to use this script, and CI jobs can be added for iOS. The directory reorganization is a significant change to make in a backport, especially in the year-old 3.13 release; however, when I floated this idea at the CPython core team summit, @Yhg1s suggested 1 that while it is a big change, the set of affected iOS users would be small, so the impact wasn't a huge concern.


NOTE: This PR currently contains a duplicate of the iOS/Resources/bin directory; this is needed because the location is hard-coded into the buildbots. Once the location change is confirmed, I can add the new path to the buildbot configuration, and remove the duplicate bin scripts.


📚 Documentation preview 📚: https://cpython-previews--138176.org.readthedocs.build/

Footnotes

  1. https://pyfound.blogspot.com/2025/06/python-language-summit-2025-python-on-mobile.html 2

@freakboy3742

This comment was marked as resolved.

@bedevere-bot

This comment was marked as outdated.

@freakboy3742
Copy link
Contributor Author

The buildbot initially failed because the buildbot configuration references the older iOS/Resource/bin location. As an immediate workaround, I've restored the shims to their old location; if the directory move is accepted as a change, then I can modify the buildbot and remove the duplicate.

@freakboy3742

This comment was marked as outdated.

@bedevere-bot

This comment was marked as outdated.

@freakboy3742
Copy link
Contributor Author

!buildbot iOS

@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @freakboy3742 for commit 68d671b 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F138176%2Fmerge

The command will test the builders whose names match following regular expression: iOS

The builders matched are:

  • iOS ARM64 Simulator PR

@AA-Turner
Copy link
Member

@freakboy3742 I imagine the CODEOWNERS entries will need updating in this PR?

.gitignore Outdated
Comment on lines 77 to 80
Apple/testbed/Python.xcframework/*-*/bin
Apple/testbed/Python.xcframework/*-*/include
Apple/testbed/Python.xcframework/*-*/lib
Apple/testbed/Python.xcframework/*-*/Python.framework
Copy link
Member

Choose a reason for hiding this comment

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

Do we need *-* or would a simpler * pattern work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hrm - you may be right. I used the *-* pattern because there are files in that folder that need to be version controlled (most notably, Info.plist), but when combined with the suffixes, they should be unique.

Copy link
Member

Choose a reason for hiding this comment

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

If this is to be a runnable Python package, we should probably have a blank __init__.py file.

Copy link
Contributor Author

@freakboy3742 freakboy3742 Aug 27, 2025

Choose a reason for hiding this comment

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

The __init__.py is only necessary if you want the directory to be importable as a module. The __main__.py-only approach is already used by Tools/wasm/emscripten,Tools/wasm/wasi and the existing iOS/testbed (now Apple/testbed) folders so that those folders are runnable entry points.

@freakboy3742 freakboy3742 requested a review from ned-deily August 27, 2025 22:09
Copy link
Member

@hugovk hugovk left a comment

Choose a reason for hiding this comment

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

+1 to moving these under Apple.

Or should we go a step further and have a build, platform or $bikeshed dir for all of Apple, Android and PC, and whatever comes next (Linux?)



def unpack_deps(host, prefix_dir, cache_dir=None):
deps_url = "https://github.com/beeware/cpython-apple-source-deps/releases/download"
Copy link
Member

Choose a reason for hiding this comment

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

Are there plans to move this under https://github.com/python/?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. @emmatyping started a pre-PEP discussion recently about consolidating the various repos we have into a single "binary dependency management repo", so that we have a single source for all (or as many as possible) of the build systems as possible. iOS and Android binaries (which are both currently BeeWare hosted) are part of those discussions.

If there's a more pressing interest for an interim solution, I'm happy to transfer ownership of both the iOS and Android repos to the Python org, or to give maintainer access to the existing repos any core team member who wants it.

@freakboy3742
Copy link
Contributor Author

Or should we go a step further and have a build, platform or $bikeshed dir for all of Apple, Android and PC, and whatever comes next (Linux?)

I guess we could - but that feels like slight overkill to me. There aren't that many platforms - and other than Linux/Unix, they're already represented in the existing tree structure without being overwhelming.

If we were only talking about iOS and macOS, even the Apple rename might not be worth it. However, since there's at least 4 other possible Apple platforms (tvOS, watchOS, visionOS and Catalyst), and they all share a lot in common with iOS (and to a lesser extent, macOS), avoiding another 4 top-level directories seemed worthwhile.

@ned-deily
Copy link
Member

Thanks for all the work on this. I will have a chance to review it in the next day or so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants