Pass the app's bundle id to serious_python's darwin packaging - #6731
Merged
Conversation
serious_python builds each Python C-extension into its own iOS framework, and those frameworks carried a fixed `org.python.<module>` CFBundleIdentifier -- byte-identical in every Flet app ever shipped. That value also becomes the framework's code signing identifier, which is the one field that survives the `codesign -f` Xcode applies at embed and again at exportArchive. serious_python 4.4.2 namespaces the identifiers under the host app's bundle id (`com.example.app.-ssl`), matching what CPython's own iOS support does, but it needs the value passed in. Export SERIOUS_PYTHON_BUNDLE_ID from both the `package` step and the native-build env -- the CocoaPods prepare_command re-runs the darwin sync at `flutter build` time and needs the same value, or the identifiers fall back to the old defaults. Both reads are defensive: an unset or empty bundle id simply leaves the defaults in place. Context: #6724.
FeodorFitsner
added a commit
to flet-dev/serious-python
that referenced
this pull request
Jul 27, 2026
Every Python C-extension ships as its own embedded framework, and each carried a fixed `org.python.<module>` CFBundleIdentifier -- org.python.ssl, org.python.hashlib, ... -- byte-identical in every app ever built with serious_python. A framework's bundle identifier also becomes its CODE SIGNING identifier, and that is the one field that survives the `codesign -f` Xcode applies at embed and again at exportArchive (everything else -- certificate chain, team identifier, secure timestamp -- is destroyed). A globally-shared identifier on a framework Apple fingerprints as a listed third-party SDK is the leading explanation for the ITMS-91065 rejection in flet-dev/flet#6724. Setting SERIOUS_PYTHON_BUNDLE_ID rewrites them to `<app id>.<module>` with underscores mapped to hyphens, matching CPython's own iOS support (Platforms/Apple/testbed/Python.xcframework/build/utils.sh). The leading hyphen for underscore-prefixed modules (`_ssl` -> `<app>.-ssl`) is deliberate: it is what keeps `_ssl` distinct from `ssl`, and it is the form CPython ships. The rewrite runs before reconcile_framework_install_names, whose ad-hoc re-sign reseals the modified plists; the stdlib xcframeworks are unsigned at that point so editing them invalidates nothing. Module names come from arbitrary wheels, so anything outside CFBundleIdentifier's [A-Za-z0-9.-] is mapped to a hyphen, and an invalid SERIOUS_PYTHON_BUNDLE_ID leaves the defaults in place with a warning rather than emitting a plist that fails late at export. flet passes the value from flet-dev/flet#6731.
Deploying flet-website-v2 with
|
| Latest commit: |
b0ceb87
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://04dd9086.flet-website-v2.pages.dev |
| Branch Preview URL: | https://feat-serious-python-bundle-i.flet-website-v2.pages.dev |
FeodorFitsner
added a commit
to flet-dev/serious-python
that referenced
this pull request
Jul 27, 2026
…ts (#242) * Bump to 4.4.2: Xcode build-provenance keys in iOS framework Info.plists Re-pins the bundled python-build snapshot to 20260727, which stamps the DT* build-provenance keys Xcode writes into a real framework's Info.plist into every framework generated from a lib-dynload .so, and labels the simulator slice as iPhoneSimulator instead of iPhoneOS (flet-dev/python-build#36). No versions moved: Python 3.12.13 / 3.13.14 / 3.14.6, Pyodide, and dart_bridge 1.6.1 are all unchanged from 20260726. This is the next hypothesis under test for the ITMS-91065 rejection in flet-dev/flet#6724, not a confirmed fix — see the serious_python_darwin 4.4.2 entry for what was ruled out experimentally and what remains open. * iOS: namespace framework bundle identifiers under the host app Every Python C-extension ships as its own embedded framework, and each carried a fixed `org.python.<module>` CFBundleIdentifier -- org.python.ssl, org.python.hashlib, ... -- byte-identical in every app ever built with serious_python. A framework's bundle identifier also becomes its CODE SIGNING identifier, and that is the one field that survives the `codesign -f` Xcode applies at embed and again at exportArchive (everything else -- certificate chain, team identifier, secure timestamp -- is destroyed). A globally-shared identifier on a framework Apple fingerprints as a listed third-party SDK is the leading explanation for the ITMS-91065 rejection in flet-dev/flet#6724. Setting SERIOUS_PYTHON_BUNDLE_ID rewrites them to `<app id>.<module>` with underscores mapped to hyphens, matching CPython's own iOS support (Platforms/Apple/testbed/Python.xcframework/build/utils.sh). The leading hyphen for underscore-prefixed modules (`_ssl` -> `<app>.-ssl`) is deliberate: it is what keeps `_ssl` distinct from `ssl`, and it is the form CPython ships. The rewrite runs before reconcile_framework_install_names, whose ad-hoc re-sign reseals the modified plists; the stdlib xcframeworks are unsigned at that point so editing them invalidates nothing. Module names come from arbitrary wheels, so anything outside CFBundleIdentifier's [A-Za-z0-9.-] is mapped to a hyphen, and an invalid SERIOUS_PYTHON_BUNDLE_ID leaves the defaults in place with a warning rather than emitting a plist that fails late at export. flet passes the value from flet-dev/flet#6731. * iOS: namespace Python.framework's bundle id too Python.xcframework is staged straight out of dist/xcframeworks by stage_spm.sh and vendored from there by the podspec, so it never passes through site-xcframeworks and kept a shared `org.python.python` -- identical in every app, the same class of identifier the previous commit fixed for the extension frameworks. Verified inert at runtime before renaming: `org.python.python` appears in no shipped binary, and neither Python.framework nor App.framework contains a CFBundleGetBundleWithIdentifier / bundleWithIdentifier lookup. serious_python sets PYTHONHOME explicitly and resolves extensions through the .fwork/.origin path mechanism, not bundle identifiers. rewrite_framework_bundle_ids takes an optional skip list so dart_bridge keeps `dev.flet.dartbridge` -- a vendor-owned reverse-DNS identifier is the shape we're aiming for, not the problem we're fixing. Confirmed against a real build (flet playground abc1.xcarchive): 93 of 98 frameworks were already namespaced, no duplicate identifiers; this covers Python.framework, leaving only Flutter's own three (App, Flutter, objective_c) and dart_bridge. * examples: pin jni to 1.0.0 (1.0.1 breaks aarch64 Linux builds) jni 1.0.1, published 2026-07-27T01:10Z, added global_jni_env.c, which passes a `va_list` where a `void *` is expected. On x86_64 va_list is an array type that decays to a pointer so it compiles; on aarch64 it is a struct, so it is a hard error and `flutter build linux` fails with 19 of them. Tracked upstream at dart-lang/native#3498. This surfaced on the release PR rather than as a scheduled failure because the examples depend on the serious_python packages by path: bumping their version invalidates the committed pubspec.lock, pub re-resolves the whole graph, and picks up the newest transitive versions. Any PR touching package versions after 2026-07-27T01:10Z would have hit it. jni itself arrives via path_provider -> path_provider_android -> jni_flutter -> jni. jni_flutter 1.0.1 declares `jni: ^1.0.0`, so 1.0.0 satisfies it -- the override narrows within the allowed range rather than overriding a constraint. Applied to all three examples; only bridge_example runs in CI, but the other two break identically for anyone building them on an ARM64 Linux host. The flask_example / run_example locks also pick up the current path-dependency version (4.0.0 -> 4.4.1); they were simply stale.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Exports
SERIOUS_PYTHON_BUNDLE_IDto serious_python's darwin packaging, from both thepackagestep and_serious_python_build_env.Why
serious_python builds every Python C-extension into its own iOS framework. Those frameworks carry a fixed
org.python.<module>CFBundleIdentifier—org.python.ssl,org.python.hashlib, … — byte-identical in every Flet app ever shipped. That value also becomes the framework's code signing identifier, which is the one field that survives thecodesign -fXcode applies at embed and again atexportArchive.serious_python 4.4.2 namespaces them under the host app's bundle id instead (
com.example.app.-ssl), mirroring what CPython's own iOS support does inPlatforms/Apple/testbed/Python.xcframework/build/utils.sh. It needs the value passed in — python-build and serious_python have no idea which app their frameworks will end up in.This is the leading hypothesis for the
ITMS-91065: Missing signaturerejection in #6724, where Apple flags_ssl.frameworkand_hashlib.frameworkas containing BoringSSL / openssl_grpc on new App Store submissions. Not a confirmed fix — confirming it needs a new-app submission, since the check doesn't fire for updates to already-published apps.Why two call sites
The
packagestep stages the frameworks, but the CocoaPodsprepare_commandre-runs the darwin sync atflutter buildtime. Both need the same value or the identifiers silently fall back to the old defaults on the CocoaPods path.Safety
Both reads go through
(… or {}).get("bundle_id"), and the serious_python side skips the rewrite entirely when the variable is unset or fails bundle-identifier validation. An app without a configured bundle id builds exactly as before.setup_template_data()is invoked immediately beforepackage_python_app()in all three entry points (build.py:77-79,debug.py:114-116,test.py:42-44), soself.template_datais populated by the time either site reads it.Requires serious_python >= 4.4.2 to have any effect; older versions ignore the variable.
Summary by Sourcery
Export the app bundle identifier to serious_python’s Darwin packaging so its generated iOS frameworks can be namespaced per host app rather than using shared defaults.
Enhancements: