Skip to content

Pass the app's bundle id to serious_python's darwin packaging - #6731

Merged
FeodorFitsner merged 1 commit into
mainfrom
feat/serious-python-bundle-id
Jul 27, 2026
Merged

Pass the app's bundle id to serious_python's darwin packaging#6731
FeodorFitsner merged 1 commit into
mainfrom
feat/serious-python-bundle-id

Conversation

@FeodorFitsner

@FeodorFitsner FeodorFitsner commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Exports SERIOUS_PYTHON_BUNDLE_ID to serious_python's darwin packaging, from both the package step 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> CFBundleIdentifierorg.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 the codesign -f Xcode applies at embed and again at exportArchive.

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 in Platforms/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 signature rejection in #6724, where Apple flags _ssl.framework and _hashlib.framework as 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 package step stages the frameworks, but the CocoaPods prepare_command re-runs the darwin sync at flutter build time. 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 before package_python_app() in all three entry points (build.py:77-79, debug.py:114-116, test.py:42-44), so self.template_data is 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:

  • Propagate the app bundle identifier into the serious_python packaging environment during the main package step.
  • Ensure the same bundle identifier is exported in the CocoaPods-driven serious_python build environment to keep framework identifiers consistent across build paths.

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.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying flet-website-v2 with  Cloudflare Pages  Cloudflare Pages

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

View logs

@FeodorFitsner
FeodorFitsner merged commit fa2ed21 into main Jul 27, 2026
16 of 173 checks passed
@FeodorFitsner
FeodorFitsner deleted the feat/serious-python-bundle-id branch July 27, 2026 18:31
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant