Skip to content

Commit b8fcfd7

Browse files
committed
Update docs describing the framework build and usage.
1 parent 9ef6e91 commit b8fcfd7

File tree

2 files changed

+62
-38
lines changed

2 files changed

+62
-38
lines changed

README.rst

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,24 @@ pre-requisites, and packaging them as static libraries that can be incorporated
1919
XCode project. The binary modules in the Python standard library are statically
2020
compiled, but are distributed as objects that can be dynamically loaded at runtime.
2121

22-
It exposes *almost* all the modules in the Python standard library except for:
22+
The macOS package is a re-bundling of the official macOS binary, modified so that
23+
it is relocatable.
2324

24-
* ``dbm.gnu``
25-
* ``tkinter``
26-
* ``readline``
27-
* ``nis`` (Deprecated by PEP594)
28-
* ``ossaudiodev`` (Deprecated by PEP594)
29-
* ``spwd`` (Deprecated by PEP594)
30-
31-
The following standard library modules are available on macOS, but not the other
32-
Apple platforms:
25+
The iOS, tvOS and watchOS packages are compiled by this project. They expose
26+
*almost* all the modules in the Python standard library except for:
3327

3428
* ``curses``
29+
* ``dbm.gnu``
3530
* ``grp``
3631
* ``multiprocessing``
32+
* ``nis`` (Deprecated by PEP594)
33+
* ``ossaudiodev`` (Deprecated by PEP594)
3734
* ``posixshmem``
3835
* ``posixsubprocess``
36+
* ``readline``
37+
* ``spwd`` (Deprecated by PEP594)
3938
* ``syslog``
39+
* ``tkinter``
4040

4141
The binaries support x86_64 and arm64 for macOS; arm64 for iOS and appleTV
4242
devices; and arm64_32 for watchOS. It also supports device simulators on both
@@ -93,10 +93,6 @@ Each support package contains:
9393

9494
* ``VERSIONS``, a text file describing the specific versions of code used to build the
9595
support package;
96-
* ``bin``, a folder containing shell aliases for the compilers that are needed
97-
to build packages. This is required because Xcode uses the ``xcrun`` alias to
98-
dynamically generate the name of binaries, but a lot of C tooling expects that ``CC``
99-
will not contain spaces.
10096
* ``platform-site``, a folder that contains site customization scripts that can be used
10197
to make your local Python install look like it is an on-device install for each of the
10298
underlying target architectures supported by the platform. This is needed because when
@@ -107,10 +103,17 @@ Each support package contains:
107103
return ``platform`` and ``sysconfig`` responses consistent with on-device behavior,
108104
which will cause ``pip`` to install platform-appropriate packages.
109105
* ``Python.xcframework``, a multi-architecture build of the Python runtime library
110-
* ``python-stdlib``, the code and binary modules comprising the Python standard library.
111-
On iOS, tvOS and watchOS, there are 2 copies of every binary module - one for physical
112-
devices, and one for the simulator. The simulator binaries are "fat", containing code
113-
for both x86_64 and arm64.
106+
107+
On iOS/tvOS/watchOS, the ``Python.xcframework`` contains a
108+
slice for each supported ABI (device and simulator). The folder containing the
109+
slice can also be used as a ``PYTHONHOME``, as it contains a ``bin``, ``include``
110+
and ``lib`` directory.
111+
112+
The ``bin`` folder does not contain Python executables (as they can't be
113+
invoked). However, it *does* contain shell aliases for the compilers that are
114+
needed to build packages. This is required because Xcode uses the ``xcrun``
115+
alias to dynamically generate the name of binaries, but a lot of C tooling
116+
expects that ``CC`` will not contain spaces.
114117

115118
For a detailed instructions on using the support package in your own project,
116119
see the `usage guide <./USAGE.md>`__

USAGE.md

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,42 @@ To add this support package to your own project:
2323
1. [Download a release tarball for your desired Python version and Apple
2424
platform](https://github.com/beeware/Python-Apple-support/releases)
2525

26-
2. Add the `python-stdlib` and `Python.xcframework` to your Xcode project. Both
27-
the `python-stdlib` folder and the `Python.xcframework` should be members of
28-
any target that needs to use Python.
26+
2. Add `Python.xcframework` to your Xcode project. You can put it anywhere in your
27+
project that you want; the following instructions assume it has been put in a
28+
folder named "Support".
2929

3030
3. In Xcode, select the root node of the project tree, and select the target you
3131
want to build.
3232

3333
4. Select "General" -> "Frameworks, Libraries and Embedded Content", and ensure
3434
that `Python.xcframework` is on the list of frameworks. It should be marked
35-
"Do not embed".
35+
"Embed and sign".
3636

37-
5. Select "General" -> "Build Phases", and ensure that the `python-stdlib` folder
38-
is listed in the "Copy Bundle Resources" step.
37+
5. Select "General" -> "Build Settings", and set the following values:
38+
- Linking - General:
39+
- `@executable_path/Frameworks`
40+
- Search paths:
41+
- Framework Search paths: `"$(PROJECT_DIR)/Support"`
42+
- Header Search paths: `"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers"`
3943

40-
6. If you're on iOS, Add a new "Run script" build phase named "Purge Python Binary
41-
Modules for Non-Target Platforms". This script will purge any dynamic module for the
42-
platform you are *not* targeting. The script should have the following content:
44+
6. Add a new "Run script" build phase named "Install target specific Python
45+
Modules". This script will install the standard library for your target. The
46+
script should have the following content:
4347

4448
```bash
49+
set -e
50+
51+
mkdir -p "$CODESIGNING_FOLDER_PATH/python/lib"
4552
if [ "$EFFECTIVE_PLATFORM_NAME" = "-iphonesimulator" ]; then
46-
echo "Purging Python modules for iOS Device"
47-
find "$CODESIGNING_FOLDER_PATH/python-stdlib" -name "*.*-iphoneos.dylib" -exec rm -f "{}" \;
53+
echo "Installing Python modules for iOS Simulator"
54+
rsync -au --delete "$PROJECT_DIR/Support/Python.xcframework/iphonesimulator/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/"
55+
# Also install any user-provided modules
56+
# rsync -au --delete "$PROJECT_DIR/Testbed/app_packages.iphonesimulator/" "$CODESIGNING_FOLDER_PATH/app_packages"
4857
else
49-
echo "Purging Python modules for iOS Simulator"
50-
find "$CODESIGNING_FOLDER_PATH" -name "*.*-iphonesimulator.dylib" -exec rm -f "{}" \;
58+
echo "Installing Python modules for iOS Device"
59+
rsync -au --delete "$PROJECT_DIR/Support/Python.xcframework/iphoneos/lib/" "$CODESIGNING_FOLDER_PATH/python/lib"
60+
# Also install any user-provided modules
61+
# rsync -au --delete "$PROJECT_DIR/Testbed/app_packages.iphoneos/" "$CODESIGNING_FOLDER_PATH/app_packages"
5162
fi
5263
```
5364

@@ -69,13 +80,12 @@ install_dylib () {
6980
DYLIB=$(basename "$FULL_DYLIB")
7081
# The name of the .dylib file, relative to the install base
7182
RELATIVE_DYLIB=${FULL_DYLIB#$CODESIGNING_FOLDER_PATH/$INSTALL_BASE/}
72-
# The (hopefully unique) name of the framework, constructed by replacing path
73-
# separators in the relative name with underscores.
74-
FRAMEWORK_NAME=$(echo $RELATIVE_DYLIB | cut -d "." -f 1 | tr "/" "_");
83+
# The full dotted name of the binary module, constructed from the file path.
84+
FULL_MODULE_NAME=$(echo $RELATIVE_DYLIB | cut -d "." -f 1 | tr "/" ".");
7585
# A bundle identifier; not actually used, but required by Xcode framework packaging
76-
FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FRAMEWORK_NAME | tr "_" "-")
86+
FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr "_" "-")
7787
# The name of the framework folder.
78-
FRAMEWORK_FOLDER="Frameworks/$FRAMEWORK_NAME.framework"
88+
FRAMEWORK_FOLDER="Frameworks/$FULL_MODULE_NAME.framework"
7989

8090
# If the framework folder doesn't exist, create it.
8191
if [ ! -d "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER" ]; then
@@ -91,10 +101,16 @@ install_dylib () {
91101
mv "$FULL_DYLIB" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER"
92102
}
93103

104+
# Make sure to update the Python version version reference here
94105
echo "Install standard library dylibs..."
95-
find "$CODESIGNING_FOLDER_PATH/python-stdlib/lib-dynload" -name "*.dylib" | while read FULL_DYLIB; do
96-
install_dylib python-stdlib/lib-dynload "$FULL_DYLIB"
106+
find "$CODESIGNING_FOLDER_PATH/python/lib/python3.13/lib-dynload" -name "*.dylib" | while read FULL_DYLIB; do
107+
install_dylib python/lib/python3.13/lib-dynload "$FULL_DYLIB"
97108
done
109+
# Also install any user-provided dynamic modules; e.g.,
110+
# echo "Install app package dylibs..."
111+
# find "$CODESIGNING_FOLDER_PATH/app_packages" -name "*.dylib" | while read FULL_DYLIB; do
112+
# install_dylib app_packages "$FULL_DYLIB"
113+
# done
98114

99115
# Clean up dylib template
100116
rm -f "$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist"
@@ -103,6 +119,11 @@ echo "Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SI
103119
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 "{}" \;
104120
```
105121

122+
Make sure that you update these scripts to update the references to the
123+
Python version, and include any user-provided code that you want to bundle.
124+
If you use the ``rsync`` approach above, user-provided code should *not* be
125+
included as part of the "Copy Bundle Resources" step.
126+
106127
You'll also need to add a file named `dylib-Info-template.plist` to your Xcode
107128
project, and make it a member of any target that needs to use Python. The template
108129
should have the following content:

0 commit comments

Comments
 (0)