Hi there. First attempt at embedding Python and have hit a wall, and not really sure how to get around it. Hoping for some tips from the community. Apologies for the long post.
Environment: Ventura13.0.1, Xcode 14.2, MBP Pro M1 Max.
Process:
-
cloned the PythonKit repo, and downloaded the pre-built binary of Python_Apple_Support for macOS
-
dragged python-stdlib and Python.xcframework into my Xcode project
-
added the PythonKit package
-
Added SystemConfiguration.framework to the Frameworks in Build Phases
-
Added PythonKit to Target Dependencies in Build Phases
-
Verified that Python.xcframework, and SystemConfiguration.framework are Do Not Embed, and that python-stdlib is Copied as a Bundle Resource
-
Created a file in Python.xcframework/macos-arm64_x86_64/Headers/module.modulemap and pasted in
module Python {
umbrella header "Python.h"
export *
link "Python"
}
- Added Run Script phase, pasted in the following script
set -e
echo "Signing as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)"
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 {} \;
- Modified the default app source
class EmbeddedPython {
init() {
guard let stdLibPath = Bundle.main.path(forResource: "python-stdlib", ofType: nil) else { return }
guard let libDynloadPath = Bundle.main.path(forResource: "python-stdlib/lib-dynload", ofType: nil) else { return }
setenv("PYTHONHOME", stdLibPath, 1)
setenv("PYTHONPATH", "\(stdLibPath):\(libDynloadPath)", 1)
Py_Initialize()
let sys = Python.import("sys")
print("Python Version: \(sys.version_info.major).\(sys.version_info.minor)")
print("Python Encoding: \(sys.getdefaultencoding().upper())")
print("Python Path: \(sys.path)")
_ = Python.import("math") // verifies `lib-dynload` is found and signed successfully
}
}
@main
struct EmbeddedPythonApp: App {
@State var embeddedPython = EmbeddedPython()
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
This does not link, generating a warning "Could not find or use auto-linked library 'Python', and a smattering of Undefined symbol errors which all look like the arm64 binaries are missing. But using otool -D to examine libPython3.11.a shows both architectures are present. I can't seem to find the PythonKit library so haven't checked if it includes the arm64 architecture. Does anyone know where this library is?
Have I missed a step, or am I not correctly configuring my Xcode project. Some help would be deeply appreciated.