@@ -90,8 +90,13 @@ Python build for a single framework, the following options are available.
9090 installed. If ` DIR ` is not specified, the framework will be installed into
9191 a subdirectory of the ` iOS/Frameworks ` folder.
9292
93- This argument * must* be provided when configuring iOS builds. iOS does not
94- support non-framework builds.
93+ This argument is required for any iOS build that will be distributed, and
94+ for any build that needs to load binary extension modules.
95+
96+ Omitting it builds a static ` libpython ` for embedding directly in an app
97+ binary, instead of a ` Python.framework ` . That configuration comes with
98+ significant restrictions; see [ Building a static
99+ Python] ( #building-a-static-python ) below.
95100
96101* ` --with-framework-name=NAME `
97102
@@ -113,9 +118,11 @@ framework to contain non-library content, so the iOS build will produce a
113118The ` lib ` folder will be needed at runtime to support the Python library.
114119
115120If you want to use Python in a real iOS project, you need to produce multiple
116- ` Python.framework ` builds, one for each ABI and architecture. iOS builds of
117- Python * must* be constructed as framework builds. To support this, you must
118- provide the ` --enable-framework ` flag when configuring the build. The build
121+ ` Python.framework ` builds, one for each ABI and architecture. Unless you are
122+ statically linking Python into your app (see [ Building a static
123+ Python] ( #building-a-static-python ) below), iOS builds of Python * must* be
124+ constructed as framework builds. To support this, you must provide the
125+ ` --enable-framework ` flag when configuring the build. The build
119126also requires the use of cross-compilation. The minimal commands for building
120127Python for the ARM64 iOS simulator will look something like:
121128```
@@ -216,6 +223,68 @@ target, provide the version number as part of the `--host` argument - for
216223example, ` --host=arm64-apple-ios15.4-simulator ` would compile an ARM64
217224simulator build with a deployment target of 15.4.
218225
226+ ### Building a static Python
227+
228+ The official iOS release artefact is a framework build. However, if you are
229+ embedding Python in an app that links ` libpython ` at compile time, you can
230+ instead build a static ` libpython3.x.a ` , and link that archive directly into
231+ your app binary.
232+
233+ The App Store requirement that binary modules be packaged as signed frameworks
234+ does not apply to a static build, because a static build loads nothing at
235+ runtime; but for the same reason, this configuration cannot use * any* binary
236+ module that isn't compiled into the app binary. The restrictions that follow
237+ from that must be opted into explicitly at configure time:
238+
239+ * ` MODULE_BUILDTYPE=static ` is required. There is no framework for a shared
240+ extension module to link against, so every extension module, including the
241+ ones in the standard library, must be linked into ` libpython ` .
242+
243+ * ` --disable-test-modules ` is required. Some test modules must be compiled as
244+ shared libraries (see ` Modules/Setup.stdlib.in ` ), so they cannot be built in
245+ this configuration at all.
246+
247+ A non-framework build is selected by omitting ` --enable-framework ` ;
248+ ` --disable-framework ` is accepted as an explicit spelling of the same thing.
249+
250+ The minimal commands for a static build targeting ARM64 iOS devices are then:
251+ ```
252+ export PATH="$(pwd)/Platforms/Apple/iOS/Resources/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin"
253+ ./configure \
254+ --prefix=/path/to/install/dir \
255+ --disable-test-modules \
256+ MODULE_BUILDTYPE=static \
257+ --host=arm64-apple-ios \
258+ --build=arm64-apple-darwin \
259+ --with-build-python=/path/to/python.exe
260+ make
261+ make install
262+ ```
263+ This produces a ` libpython3.x.a ` containing the interpreter and the standard
264+ library's extension modules; ` make install ` installs that archive, along with
265+ the standard library's Python source, into the location given by ` --prefix ` .
266+ Unlike a framework build, ` --prefix ` is not set for you, so specify it
267+ explicitly - otherwise ` libpython ` will be installed into ` /usr/local ` .
268+
269+ #### Limitations of a static build
270+
271+ * ** Binary wheels cannot be used.** There is no ` libpython ` dylib for a
272+ third-party extension module to link against, and a static Python has nothing
273+ to ` dlopen ` in any case. Pure Python wheels work as normal; any package with a
274+ C extension must be compiled into the app binary alongside ` libpython ` .
275+
276+ * ** The standard library's extension modules are not loadable modules.** They
277+ live in the archive, not in ` .framework ` bundles in the app's ` Frameworks `
278+ folder, so the packaging described in
279+ [ Using Python on iOS] ( https://docs.python.org/3/using/ios.html ) does not apply
280+ to them.
281+
282+ * ** The test suite cannot be run as-is** , as the test modules are not built.
283+
284+ * This configuration is not covered by the ` Platforms/Apple ` build script, nor
285+ by CPython's CI. It is not the configuration used to produce official
286+ releases.
287+
219288## Testing Python on iOS
220289
221290### Testing a multi-architecture framework
0 commit comments