-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
PEP 730: Adding iOS as a supported platform #3473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
41aeadb
Add first draft of an iOS support PEP.
freakboy3742 bb77455
Remove Discussions-To metadata to pass linting.
freakboy3742 433d97c
Restore Discussions-To link.
freakboy3742 9093f7e
Apply suggestions from code review
freakboy3742 cbc4c2c
Additional updates following review.
freakboy3742 5a12632
Correct markup error.
freakboy3742 9d537a9
Grammar correction.
freakboy3742 65f8c1a
Merge branch 'main' into iOS-support
freakboy3742 a32d0ae
Correct word wrap line length, and apply various edits picked up in c…
freakboy3742 9335024
Add a note about being embedded only.
freakboy3742 23fd044
Apply suggestions from code review
freakboy3742 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,309 @@ | ||
PEP: 730 | ||
Title: Adding iOS as a supported platform | ||
Author: Russell Keith-Magee <russell@keith-magee.com> | ||
Sponsor: Ned Deily <nad@python.org> | ||
Discussions-To: https://discuss.python.org/t/pep730-adding-ios-as-a-supported-platform/35854 | ||
Status: Draft | ||
Type: Standards Track | ||
Content-Type: text/x-rst | ||
Created: 09-Oct-2023 | ||
Python-Version: 3.13 | ||
|
||
Abstract | ||
======== | ||
|
||
This PEP proposes adding iOS as a supported platform in CPython. The initial goal is to | ||
achieve Tier 3 support for Python 3.13. This PEP describes the technical aspects of the | ||
changes that are required to support iOS. It also describes the project management | ||
concerns related to adoption of iOS as a Tier 3 platform. | ||
|
||
Motivation | ||
========== | ||
|
||
Over the last 15 years, mobile platforms have become increasingly important parts of the | ||
computing landscape. iOS is one of two operating systems that control the vast majority | ||
of these devices. However, there is no official support for iOS in CPython. | ||
|
||
The BeeWare Project [1]_ and Kivy [2]_ have both supported iOS for almost 10 years. | ||
This support has been able to generate applications that have been accepted for | ||
publication in the iOS App Store. This demonstrates the technical feasibility of iOS | ||
support. | ||
|
||
It is important for the future of Python as a language that it is able to be used on any | ||
hardware or OS that has widespread adoption. If Python cannot be used a on a platform | ||
that has widespread use, adoption of the language will be impacted as potential users | ||
will adopt other languages that *do* provide support for these platforms. | ||
|
||
Rationale | ||
========= | ||
|
||
Development landscape | ||
--------------------- | ||
|
||
iOS provides a single API, but 2 distinct ABIs - ``iphoneos`` (physical devices), and | ||
``iphonesimulator``. Each of these ABIs can be provided on multiple CPU architectures. | ||
At time of writing, Apple officially supports ``arm64`` on the device ABI, and ``arm64`` | ||
and ``x86_64`` are supported on the simulator ABI. | ||
|
||
As with macOS, iOS supports the creation of "fat" binaries that contains multiple CPU | ||
architectures. However, fat binaries *cannot* span ABIs. That is, it is possible to have | ||
a fat *simulator* binary, and a fat *device* binary, but it is not possible to create a | ||
single fat "iOS" binary that covers both simulator and device needs. To support | ||
distribution of a single development artefact, Apple uses an "XCframework" structure - a | ||
wrapper around multiple ABIs that implement a common API. | ||
|
||
iOS runs on a Darwin kernel, similar to macOS. However, there is a need to differentiate | ||
between macOS and iOS at an implementation level, as there are significant platform | ||
differences between iOS and macOS. | ||
|
||
iOS code is compiled for compatibility against a minimum iOS version. | ||
|
||
POSIX compliance | ||
---------------- | ||
|
||
iOS is broadly a POSIX platform. However, similar to WASI/Emscripten, there are POSIX | ||
APIs that exist on iOS, but cannot be used; and POSIX APIs that don't exist at all. | ||
|
||
Most notable of these is the fact that iOS does not provide any form of multiprocess | ||
support. ``fork`` and ``spawn`` both *exist* in the iOS API; however, if they are invoked, | ||
the invoking iOS process stops, and the new process doesn't start. | ||
|
||
Unlike WASI/Emscripten, threading *is* supported on iOS. | ||
|
||
There are also significant limits to socket handling. Due to process sandboxing, there | ||
is no availability of interprocess communication via socket. However, sockets for | ||
network communication *are* available. | ||
|
||
Dynamic libraries | ||
----------------- | ||
|
||
The iOS App Store guidelines [3]_ allow apps to be written in languages other than | ||
Objective C or Swift. However, they have very strict guidelines about the structure of | ||
apps that are submitted for distribution. | ||
|
||
iOS apps can use dynamically loaded libraries; however, there are very strict | ||
requirements on how dynamically loaded content is packaged for use on iOS: | ||
|
||
* Dynamic binary content must be compiled as dynamic libraries, not shared objects or | ||
binary bundles. | ||
|
||
* They must be packaged in the app bundle as Frameworks. | ||
|
||
* Each Framework can only contain a single dynamic library. | ||
|
||
* The Framework *must* be contained in the iOS App's ``Frameworks`` folder. | ||
|
||
* A Framework may not contain any non-library content. | ||
|
||
This imposes some constraints on the operation of CPython. It is not possible store | ||
binary modules in the ``lib-dynload`` and/or ``site-packages`` folders; they must be | ||
stored in the app's Frameworks folder, with each module wrapped in a Framework. This | ||
also means that the common assumption that a Python module can construct the location of | ||
a binary module by using the ``__file__`` attribute of the Python module no longer | ||
holds. | ||
|
||
As with macOS, compiling a dynamic library requires the use of the ``--undefined | ||
dynamic_lookup`` option to avoid linking libPython into every binary module. This option | ||
currently raises a deprecation warning when it is used. This warning *was* previously | ||
raised on macOS builds as well; however, responses from Apple staff suggests this was | ||
unintentional, and they did not intend to break the CPython ecosystem by removing this | ||
option [4]_. It is difficult to judge whether iOS support would fall under the same | ||
umbrella. | ||
|
||
Distribution | ||
------------ | ||
|
||
Adding iOS as a Tier 3 platform only requires adding support for compiling an | ||
iOS-compatibile code with an unpatched CPython code checkout. It does not require | ||
production of officially distributed iOS artefacts for use by end-users. | ||
|
||
If/when iOS is updated to Tier 2 or 1 support, this should be include a proposal for | ||
JelleZijlstra marked this conversation as resolved.
Show resolved
Hide resolved
|
||
producing iOS distriution artefacts. This could be in the form of an "embedded | ||
distribution" analogous to the Windows embedded distribution, or as a Cocoapod or Swift | ||
Package that could be added to an Xcode project. | ||
|
||
Specification | ||
============= | ||
|
||
Platform identification | ||
----------------------- | ||
|
||
``sys`` | ||
''''''' | ||
|
||
``sys.platform`` will identify as ``ios`` on both simulator and physical devices. | ||
|
||
``sys.implementation._multiarch`` will describe the ABI and CPU architecture: | ||
|
||
* ``iphoneos-arm64`` for ARM64 devices | ||
* ``iphonesimulator-arm64`` for ARM64 simulators | ||
* ``iphonesimulator-x86_64`` for x86_64 simulators | ||
|
||
``sys.implementation`` will also have an additional attribute - ``_simulator`` - storing | ||
a Boolean that is ``True`` if the device running the app is a simulator. This attribute | ||
would not exist on non-iOS platforms. | ||
|
||
``platform`` | ||
'''''''''''' | ||
|
||
Platform will be used as the primary mechanism for retrieving OS and device details. | ||
|
||
* ``platform.system()`` - ``iOS`` | ||
hugovk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
* ``platform.node()`` - the user-provided name of the device, as returned by the | ||
``[[UIDevice currentDevice] systemName]`` system call. (e.g., ``Janes-iPhone``). For | ||
hugovk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
simulated devices, this will be the name of the development computer running the | ||
simulator. | ||
|
||
* ``platform.release()`` - the iOS version number, as a string (e.g., "16.6.1") | ||
|
||
* ``platform.machine()`` - The device model returned by ``[[UIDevice currentDevice] | ||
model]`` (e.g., ``iPhone13,2``); or ``iPhoneSimulator`` for simulated devices. | ||
hugovk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
All other values will be as returned by ``os.uname()``. | ||
hugovk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
``os`` | ||
'''''' | ||
|
||
``os.uname()`` will return the raw result of a POSIX ``uname()`` call. This will result | ||
in the following values: | ||
|
||
* ``sysname`` - ``Darwin`` | ||
hugovk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
* ``release`` - The Darwin kernel version (e.g., ``"22.6.0"``) | ||
|
||
``sysconfig`` | ||
''''''''''''' | ||
|
||
The ``sysconfig`` module will use the minimum iOS version as part of ``sysconfig.get_platform()`` identifier (e.g., ``iOS-12.0-iphoneos-arm64``). The ``sysconfigdata_name`` and Config makefile will follow the same patterns as existing platforms (using ``sys.platform``, ``sys.implementation._multiarch`` etc) to construct identifiers. | ||
hugovk marked this conversation as resolved.
Show resolved
Hide resolved
hugovk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Subprocess support | ||
------------------ | ||
|
||
iOS will leverage the pattern for disabling subprocesses established by WASI/Emscripten. The ``subprocess`` module will raise an exception if an attempt is made to start a subprocess ``os.fork`` and ``os.spawn`` calls will raise an ``OSError``. | ||
freakboy3742 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Dynamic module loading | ||
---------------------- | ||
|
||
To accommodate iOS dynamic loading, the ``importlib`` bootstrap will be extended to add a metapath finder that can convert a request for a Python binary module into a Framework location. This finder will only be installed if ``sys.platform == "ios"``. | ||
|
||
This finder will convert a Python module name (e.g., ``foo.bar._whiz``) into a unique Framework name by replacing the dots with underscores (i.e., ``foo_bar__whiz.framework``). A framework is a directory; the finder will look for ``_whiz.dylib`` in that directory. | ||
|
||
CI resources | ||
------------ | ||
|
||
Github Actions is able to host iOS simulators on their macOS machines, and the iOS simulator can be controlled by scripting environments. The free tier currently only provides x86_64 macOS machines; however ARM64 runners have recently become available on paid plans [5]_. | ||
|
||
If Github Actions resources are insufficient or not viable for cost reasons, Anaconda has offered to provide resources to support CI requirements. | ||
freakboy3742 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Packaging | ||
--------- | ||
|
||
iOS will not provide a "universal" wheel format. Instead, wheels will be provided on a for each ABI-arch combination. At present, no binary merging is required. There is only 1 on-device architecture; and simulator binaries are not considered to be distributable artefacts, so only 1 architecture is needed to build a simulator. | ||
freakboy3742 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
iOS wheels will use tags: | ||
|
||
* ``iOS_12_0_iphoneos_arm64`` | ||
* ``iOS_12_0_iphonesimulator_arm64`` | ||
* ``iOS_12_0_iphonesimulator_x86_64`` | ||
|
||
In these tags, "12.0" is the minimum supported iOS version. The choice of minimum supported iOS version is a decision of whoever compiles CPython for iOS. At time of writing, iOS 12.0 exposes most significant iOS features, while reaching near 100% of devices. | ||
|
||
These wheels can include binaries modules in-situ (i.e., co-located with the Python source, in the same way as wheels for a desktop platform); however, they will need to be post-processed as part of inin the samewill need to be post-processed into the "Frameworks" location required for distribution. This can be automated with an Xcode build step. | ||
freakboy3742 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
PEP11 Update | ||
freakboy3742 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
------------ | ||
|
||
:pep:`11` will be updated to include the 3 iOS ABIs: | ||
hugovk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
* ``aarch64-apple-ios`` | ||
* ``aarch64-apple-ios-simulator`` | ||
* ``x86_64-apple-ios-simulator`` | ||
|
||
Ned Deily will serve as the initial Core Team contact for these ABIs. | ||
hugovk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Backwards Compatibility | ||
======================= | ||
|
||
Adding a new platform does not introduce any backwards compatibility concerns to CPython | ||
itself. | ||
|
||
There may be some backwards compatibility implications on the projects that have | ||
historically provided CPython support (i.e., BeeWare and Kivy) if the final form of any | ||
CPython patches don't align with the patches they have historically used. | ||
|
||
Although not strictly a backwards compatibility issue, there *is* a platform adoption | ||
consideration. Although CPython itself may support iOS, if it is unclear how to produce | ||
iOS-compatibile wheels, and prominent libraries like cryptography, Pillow, and numpy | ||
freakboy3742 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
don't provide iOS wheels, the ability of the community to adopt Python on iOS will be | ||
limited. Therefore, it will be necessary to clearly document how projects can add iOS | ||
builds to their CI and release tooling. | ||
JelleZijlstra marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Security Implications | ||
===================== | ||
|
||
Adding iOS as a new platform does not add any security implications. | ||
|
||
How to Teach This | ||
================= | ||
|
||
The education needs related to this PEP mostly relate to how end-users can add iOS support to their own Xcode projects. This can be accomplished with documentation and tutorials on that process. The need for this documentation will increase if/when support raises from Tier 3 to Tier 2 or 1; however, this transition should also be accompanied with simplified deployment artefacts (such as a Cocoapod or Swift ) that are integrated with Xcode development. | ||
JelleZijlstra marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Reference Implementation | ||
======================== | ||
|
||
The BeeWare Python-Apple-support [6]_ repository contains a reference patch and build tooling to compile a distributable artefact. | ||
|
||
Briefcase [7]_ provides a reference implementation of code to execute test suites on iOS simulators. The Toga Testbed [8]_ is an example of a test suite that is executed on the iOS simulator using Github Actions. | ||
|
||
Rejected Ideas | ||
============== | ||
|
||
``sys.implementation._simulator`` availability | ||
---------------------------------------------- | ||
|
||
The ``_simulator`` attribute could be provided on *all* platforms, returning ``False``. However, the attribute has no use outside of an iOS context. | ||
|
||
Open Issues | ||
=========== | ||
|
||
On-device testing | ||
----------------- | ||
|
||
CI testing on simulators can be accommodated reasonly easily; however, on-device testing | ||
freakboy3742 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
is much harder. | ||
|
||
However, on device testing may not be necessary. As a data point - Apple's Xcode Cloud solution doesn't provide on-device testing. They rely on the fact that the API is consistent between device and simulator, and ARM64 simulator testing is sufficient to reveal CPU-specific issues. | ||
|
||
Footnotes | ||
========= | ||
|
||
.. [1] BeeWare Project | ||
(https://beeware.org) | ||
|
||
.. [2] Kivy | ||
(https://kivy.org) | ||
|
||
.. [3] Apple App Store Review Guidelines | ||
(https://developer.apple.com/app-store/review/guidelines) | ||
|
||
.. [4] Warning about chained fixups when using ``-undefined dynamic_lookup`` | ||
(https://developer.apple.com/forums/thread/719961) | ||
|
||
.. [5] Introducing the new, Apple silicon powered M1 macOS larger runner for GitHub Actions | ||
(https://github.blog/ 2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/) | ||
hugovk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
.. [6] Python-Apple-support | ||
(https://github.com/beeware/Python-Apple-support) | ||
|
||
.. [7] Briefcase | ||
(https://briefcase.readthedocs.org) | ||
|
||
.. [8] Toga Testbed | ||
(https://github.com/beeware/toga/tree/main/testbed) | ||
|
||
Copyright | ||
========= | ||
|
||
This document is placed in the public domain or under the CC0-1.0-Universal license, | ||
whichever is more permissive. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.