@@ -170,7 +170,7 @@ helpful.
170
170
To add Python to an iOS Xcode project:
171
171
172
172
1. Build or obtain a Python ``XCFramework ``. See the instructions in
173
- :source: `iOS/README.rst ` (in the CPython source distribution) for details on
173
+ :source: `Apple/ iOS/README.md ` (in the CPython source distribution) for details on
174
174
how to build a Python ``XCFramework ``. At a minimum, you will need a build
175
175
that supports ``arm64-apple-ios ``, plus one of either
176
176
``arm64-apple-ios-simulator `` or ``x86_64-apple-ios-simulator ``.
@@ -180,22 +180,19 @@ To add Python to an iOS Xcode project:
180
180
of your project; however, you can use any other location that you want by
181
181
adjusting paths as needed.
182
182
183
- 3. Drag the ``iOS/Resources/dylib-Info-template.plist `` file into your project,
184
- and ensure it is associated with the app target.
185
-
186
- 4. Add your application code as a folder in your Xcode project. In the
183
+ 3. Add your application code as a folder in your Xcode project. In the
187
184
following instructions, we'll assume that your user code is in a folder
188
185
named ``app `` in the root of your project; you can use any other location by
189
186
adjusting paths as needed. Ensure that this folder is associated with your
190
187
app target.
191
188
192
- 5 . Select the app target by selecting the root node of your Xcode project, then
189
+ 4 . Select the app target by selecting the root node of your Xcode project, then
193
190
the target name in the sidebar that appears.
194
191
195
- 6 . In the "General" settings, under "Frameworks, Libraries and Embedded
192
+ 5 . In the "General" settings, under "Frameworks, Libraries and Embedded
196
193
Content", add ``Python.xcframework ``, with "Embed & Sign" selected.
197
194
198
- 7 . In the "Build Settings" tab, modify the following:
195
+ 6 . In the "Build Settings" tab, modify the following:
199
196
200
197
- Build Options
201
198
@@ -211,86 +208,24 @@ To add Python to an iOS Xcode project:
211
208
212
209
* Quoted Include In Framework Header: No
213
210
214
- 8. Add a build step that copies the Python standard library into your app. In
215
- the "Build Phases" tab, add a new "Run Script" build step *before * the
216
- "Embed Frameworks" step, but *after * the "Copy Bundle Resources" step. Name
217
- the step "Install Target Specific Python Standard Library", disable the
218
- "Based on dependency analysis" checkbox, and set the script content to:
211
+ 7. Add a build step that processes the Python standard library, and your own
212
+ Python binary dependencies. In the "Build Phases" tab, add a new "Run
213
+ Script" build step *before * the "Embed Frameworks" step, but *after * the
214
+ "Copy Bundle Resources" step. Name the step "Process Python libraries",
215
+ disable the "Based on dependency analysis" checkbox, and set the script
216
+ content to:
219
217
220
218
.. code-block :: bash
221
219
222
- set -e
223
-
224
- mkdir -p " $CODESIGNING_FOLDER_PATH /python/lib"
225
- if [ " $EFFECTIVE_PLATFORM_NAME " = " -iphonesimulator" ]; then
226
- echo " Installing Python modules for iOS Simulator"
227
- rsync -au --delete " $PROJECT_DIR /Python.xcframework/ios-arm64_x86_64-simulator/lib/" " $CODESIGNING_FOLDER_PATH /python/lib/"
228
- else
229
- echo " Installing Python modules for iOS Device"
230
- rsync -au --delete " $PROJECT_DIR /Python.xcframework/ios-arm64/lib/" " $CODESIGNING_FOLDER_PATH /python/lib/"
231
- fi
232
-
233
- Note that the name of the simulator "slice" in the XCframework may be
234
- different, depending the CPU architectures your ``XCFramework `` supports.
220
+ set -e
221
+ source $PROJECT_DIR /Python.xcframework/build/build_utils.sh
222
+ install_python Python.xcframework app
235
223
236
- 9. Add a second build step that processes the binary extension modules in the
237
- standard library into "Framework" format. Add a "Run Script" build step
238
- *directly after * the one you added in step 8, named "Prepare Python Binary
239
- Modules". It should also have "Based on dependency analysis" unchecked, with
240
- the following script content:
241
-
242
- .. code-block :: bash
224
+ If you have placed your XCframework somewhere other than the root of your
225
+ project, modify the path to the first argument.
243
226
244
- set -e
245
-
246
- install_dylib () {
247
- INSTALL_BASE=$1
248
- FULL_EXT=$2
249
-
250
- # The name of the extension file
251
- EXT=$( basename " $FULL_EXT " )
252
- # The location of the extension file, relative to the bundle
253
- RELATIVE_EXT=${FULL_EXT# $CODESIGNING_FOLDER_PATH / }
254
- # The path to the extension file, relative to the install base
255
- PYTHON_EXT=${RELATIVE_EXT/ $INSTALL_BASE / }
256
- # The full dotted name of the extension module, constructed from the file path.
257
- FULL_MODULE_NAME=$( echo $PYTHON_EXT | cut -d " ." -f 1 | tr " /" " ." ) ;
258
- # A bundle identifier; not actually used, but required by Xcode framework packaging
259
- FRAMEWORK_BUNDLE_ID=$( echo $PRODUCT_BUNDLE_IDENTIFIER .$FULL_MODULE_NAME | tr " _" " -" )
260
- # The name of the framework folder.
261
- FRAMEWORK_FOLDER=" Frameworks/$FULL_MODULE_NAME .framework"
262
-
263
- # If the framework folder doesn't exist, create it.
264
- if [ ! -d " $CODESIGNING_FOLDER_PATH /$FRAMEWORK_FOLDER " ]; then
265
- echo " Creating framework for $RELATIVE_EXT "
266
- mkdir -p " $CODESIGNING_FOLDER_PATH /$FRAMEWORK_FOLDER "
267
- cp " $CODESIGNING_FOLDER_PATH /dylib-Info-template.plist" " $CODESIGNING_FOLDER_PATH /$FRAMEWORK_FOLDER /Info.plist"
268
- plutil -replace CFBundleExecutable -string " $FULL_MODULE_NAME " " $CODESIGNING_FOLDER_PATH /$FRAMEWORK_FOLDER /Info.plist"
269
- plutil -replace CFBundleIdentifier -string " $FRAMEWORK_BUNDLE_ID " " $CODESIGNING_FOLDER_PATH /$FRAMEWORK_FOLDER /Info.plist"
270
- fi
271
-
272
- echo " Installing binary for $FRAMEWORK_FOLDER /$FULL_MODULE_NAME "
273
- mv " $FULL_EXT " " $CODESIGNING_FOLDER_PATH /$FRAMEWORK_FOLDER /$FULL_MODULE_NAME "
274
- # Create a placeholder .fwork file where the .so was
275
- echo " $FRAMEWORK_FOLDER /$FULL_MODULE_NAME " > ${FULL_EXT% .so} .fwork
276
- # Create a back reference to the .so file location in the framework
277
- echo " ${RELATIVE_EXT% .so} .fwork" > " $CODESIGNING_FOLDER_PATH /$FRAMEWORK_FOLDER /$FULL_MODULE_NAME .origin"
278
- }
279
-
280
- PYTHON_VER=$( ls -1 " $CODESIGNING_FOLDER_PATH /python/lib" )
281
- echo " Install Python $PYTHON_VER standard library extension modules..."
282
- find " $CODESIGNING_FOLDER_PATH /python/lib/$PYTHON_VER /lib-dynload" -name " *.so" | while read FULL_EXT; do
283
- install_dylib python/lib/$PYTHON_VER /lib-dynload/ " $FULL_EXT "
284
- done
285
-
286
- # Clean up dylib template
287
- rm -f " $CODESIGNING_FOLDER_PATH /dylib-Info-template.plist"
288
-
289
- echo " Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY )..."
290
- find " $CODESIGNING_FOLDER_PATH /Frameworks" -name " *.framework" -exec /usr/bin/codesign --force --sign " $EXPANDED_CODE_SIGN_IDENTITY " ${OTHER_CODE_SIGN_FLAGS:- } -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der " {}" \;
291
-
292
- 10. Add Objective C code to initialize and use a Python interpreter in embedded
293
- mode. You should ensure that:
227
+ 8. Add Objective C code to initialize and use a Python interpreter in embedded
228
+ mode. You should ensure that:
294
229
295
230
* UTF-8 mode (:c:member: `PyPreConfig.utf8_mode `) is *enabled *;
296
231
* Buffered stdio (:c:member: `PyConfig.buffered_stdio `) is *disabled *;
@@ -309,22 +244,19 @@ To add Python to an iOS Xcode project:
309
244
Your app's bundle location can be determined using ``[[NSBundle mainBundle]
310
245
resourcePath] ``.
311
246
312
- Steps 8, 9 and 10 of these instructions assume that you have a single folder of
247
+ Steps 7 and 8 of these instructions assume that you have a single folder of
313
248
pure Python application code, named ``app ``. If you have third-party binary
314
249
modules in your app, some additional steps will be required:
315
250
316
251
* You need to ensure that any folders containing third-party binaries are
317
- either associated with the app target, or copied in as part of step 8. Step 8
318
- should also purge any binaries that are not appropriate for the platform a
319
- specific build is targeting (i.e., delete any device binaries if you're
320
- building an app targeting the simulator).
252
+ either associated with the app target, or are explicitly copied as part of
253
+ step 7. Step 7 should also purge any binaries that are not appropriate for
254
+ the platform a specific build is targeting (i.e., delete any device binaries
255
+ if you're building an app targeting the simulator).
321
256
322
- * Any folders that contain third-party binaries must be processed into
323
- framework form by step 9. The invocation of ``install_dylib `` that processes
324
- the ``lib-dynload `` folder can be copied and adapted for this purpose.
325
-
326
- * If you're using a separate folder for third-party packages, ensure that folder
327
- is included as part of the :envvar: `PYTHONPATH ` configuration in step 10.
257
+ * If you're using a separate folder for third-party packages, ensure that
258
+ folder is added to the end of the call to ``install_python `` in step 7, and
259
+ as part of the :envvar: `PYTHONPATH ` configuration in step 8.
328
260
329
261
* If any of the folders that contain third-party packages will contain ``.pth ``
330
262
files, you should add that folder as a *site directory * (using
@@ -334,25 +266,30 @@ modules in your app, some additional steps will be required:
334
266
Testing a Python package
335
267
------------------------
336
268
337
- The CPython source tree contains :source: `a testbed project <iOS/testbed> ` that
269
+ The CPython source tree contains :source: `a testbed project <Apple/ iOS/testbed> ` that
338
270
is used to run the CPython test suite on the iOS simulator. This testbed can also
339
271
be used as a testbed project for running your Python library's test suite on iOS.
340
272
341
- After building or obtaining an iOS XCFramework (See :source: `iOS/README.rst `
342
- for details), create a clone of the Python iOS testbed project by running:
273
+ After building or obtaining an iOS XCFramework (see :source: `Apple/iOS/README.md `
274
+ for details), create a clone of the Python iOS testbed project. If you used the
275
+ ``Apple `` build script to build the XCframework, you can run:
276
+
277
+ .. code-block :: bash
278
+
279
+ $ python cross-build/iOS/testbed clone --app < path/to/module1> --app < path/to/module2> app-testbed
280
+
281
+ Or, if you've sourced your own XCframework, by running:
343
282
344
283
.. code-block :: bash
345
284
346
- $ python iOS /testbed clone --framework < path/to/Python.xcframework> --app < path/to/module1> --app < path/to/module2> app-testbed
285
+ $ python Apple /testbed clone --platform iOS --framework < path/to/Python.xcframework> --app < path/to/module1> --app < path/to/module2> app-testbed
347
286
348
- You will need to modify the ``iOS/testbed `` reference to point to that
349
- directory in the CPython source tree; any folders specified with the ``--app ``
350
- flag will be copied into the cloned testbed project. The resulting testbed will
351
- be created in the ``app-testbed `` folder. In this example, the ``module1 `` and
352
- ``module2 `` would be importable modules at runtime. If your project has
353
- additional dependencies, they can be installed into the
354
- ``app-testbed/iOSTestbed/app_packages `` folder (using ``pip install --target
355
- app-testbed/iOSTestbed/app_packages `` or similar).
287
+ Any folders specified with the ``--app `` flag will be copied into the cloned
288
+ testbed project. The resulting testbed will be created in the ``app-testbed ``
289
+ folder. In this example, the ``module1 `` and ``module2 `` would be importable
290
+ modules at runtime. If your project has additional dependencies, they can be
291
+ installed into the ``app-testbed/Testbed/app_packages `` folder (using ``pip
292
+ install --target app-testbed/Testbed/app_packages `` or similar).
356
293
357
294
You can then use the ``app-testbed `` folder to run the test suite for your app,
358
295
For example, if ``module1.tests `` was the entry point to your test suite, you
@@ -381,7 +318,7 @@ tab. Modify the "Arguments Passed On Launch" value to change the testing
381
318
arguments.
382
319
383
320
The test plan also disables parallel testing, and specifies the use of the
384
- ``iOSTestbed .lldbinit `` file for providing configuration of the debugger. The
321
+ ``Testbed .lldbinit `` file for providing configuration of the debugger. The
385
322
default debugger configuration disables automatic breakpoints on the
386
323
``SIGINT ``, ``SIGUSR1 ``, ``SIGUSR2 ``, and ``SIGXFSZ `` signals.
387
324
0 commit comments