Skip to content

Commit 4d56ad0

Browse files
committed
README - add MACOS_USAGE_GUIDE.md with a details step-by-step on how to embed in a MacOS app
1 parent d20cf5c commit 4d56ad0

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

MACOS_USAGE_GUIDE.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Usage Guide
2+
3+
A Step-by-Step guide on how to embed a Python interpreter in a MacOS app (The process for an iOS app should be quite similar).
4+
No need to delete the Sandbox (you need it to be able to submit your MacOS App to the App Store).
5+
No need to `Disable Library Validation`.
6+
7+
1. Add PythonKit SPM:
8+
https://github.com/pvieito/PythonKit
9+
10+
2. Download Released framework for the desired Python version (for MacOS platform):
11+
https://github.com/beeware/Python-Apple-support
12+
13+
3. Extract the `python-stdlib` and `Python.xcframework` from the `tag.gz` archive.
14+
15+
4. Copy `python-stdlib` and `Python.xcframework` to the root of the MacOS App, preferably via Xcode.
16+
17+
5. Xcode General -> Frameworks:
18+
5.1. Should already be there:
19+
- `Python.xcframework` is set as `Do Not Embed`
20+
- `PythonKit`
21+
5.2. Add additional required framework:
22+
- `SystemConfiguration.framework` set as `Do Not Embed`
23+
24+
6. Xcode `Build Phases`:
25+
6.1. Verify `Copy Bundle Resources` contains `python-stdlib`.
26+
6.2. Add bash script to Sign `.so` binaries in `python-stdlib/lib-dynload/`:
27+
IMPORTANT NOTE: `.so` binaries must be signed with your TeamID, if you need to use `Sign and Run Locally` it will be signed as ad-hoc, and you will need to `Disable Library Validation`.
28+
```bash
29+
set -e
30+
echo "Signing as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)"
31+
find "$CODESIGNING_FOLDER_PATH/Contents/Resources/python-stdlib/lib-dynload" -name "*.so" -exec /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \;
32+
```
33+
34+
7. Create a file called `module.modulemap` with the following code:
35+
```
36+
module Python {
37+
umbrella header "Python.h"
38+
export *
39+
link "Python"
40+
}
41+
```
42+
43+
8. Place the `module.modulemap` file inside the `Python.xcframework/macos-arm64_x86_64/Headers/`.
44+
This will allow us to do `import Python`
45+
46+
9. Init Python at runtime, as early as possible:
47+
```swift
48+
import Python
49+
50+
guard let stdLibPath = Bundle.main.path(forResource: "python-stdlib", ofType: nil) else { return }
51+
guard let libDynloadPath = Bundle.main.path(forResource: "python-stdlib/lib-dynload", ofType: nil) else { return }
52+
setenv("PYTHONHOME", stdLibPath, 1)
53+
setenv("PYTHONPATH", "\(stdLibPath):\(libDynloadPath)", 1)
54+
Py_Initialize()
55+
// we now have a Python interpreter ready to be used
56+
```
57+
58+
10. Run test code:
59+
```swift
60+
import PythonKit
61+
62+
let sys = Python.import("sys")
63+
print("Python Version: \(sys.version_info.major).\(sys.version_info.minor)")
64+
print("Python Encoding: \(sys.getdefaultencoding().upper())")
65+
print("Python Path: \(sys.path)")
66+
67+
_ = Python.import("math") // verifies `lib-dynload` is found and signed successfully
68+
```
69+
70+
11. To integrate 3rd party python code and dependencies, you will need to make sure `PYTHONPATH` contains their paths;
71+
And then you can just do `Python.import(" <SOME LIB> ")`.
72+
73+
You're in business.

README.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ On macOS, you must also either:
130130
It is not possible to use an ad-hoc signing certificate with the "Disable
131131
Library Validation" entitlement disabled.
132132

133+
For a detailed step-by-step on how to embed a Python interpreter in a MacOS app, see [Usage Guide](./MACOS_USAGE_GUIDE.md)
134+
133135
On iOS/tvOS/watchOS, you can use the default developer certificate for deploying
134136
to a device simulator. However, to deploy to a physical device (including your
135137
own), you will require a Development or Distribution certificate, which requires

0 commit comments

Comments
 (0)