8000 PEP 730: Adding iOS as a supported platform by freakboy3742 · Pull Request #3473 · python/peps · GitHub
[go: up one dir, main page]

Skip to content

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 11 commits into from
Oct 11, 2023
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ peps/pep-0725.rst @pradyunsg
peps/pep-0726.rst @AA-Turner
peps/pep-0727.rst @JelleZijlstra
peps/pep-0729.rst @JelleZijlstra @hauntsaninja
peps/pep-0730.rst @ned-deily
# ...
# peps/pep-0754.rst
# ...
Expand Down
309 changes: 309 additions & 0 deletions peps/pep-0730.rst
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
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``

* ``platform.node()`` - the user-provided name of the device, as returned by the
``[[UIDevice currentDevice] systemName]`` system call. (e.g., ``Janes-iPhone``). For
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.

All other values will be as returned by ``os.uname()``.

``os``
''''''

``os.uname()`` will return the raw result of a POSIX ``uname()`` call. This will result
in the following values:

* ``sysname`` - ``Darwin``

* ``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.

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``.

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.

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.

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.

PEP11 Update
------------

:pep:`11` will be updated to include the 3 iOS ABIs:

* ``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.

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
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.

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.

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
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/)

.. [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.
0