gh-156109: Allow static, non-framework iOS builds - #156110
Conversation
82788a4 to
e710088
Compare
CPython appends -mios-version-min - the device flag - to every iOS build. Against the simulator SDK the linker rejects the dylibs it resolves there, and the first configure check that links one fails, taking the depends build with it. The local patch faked ac_sys_system=iOS by deleting CPython's host parsing, because config.site.in pinned every package to the tree's darwin triplet. Python now configures against its own iOS triplet, so CPython derives ac_sys_system, the deployment target and the device/simulator split itself, and the 76 lines that deleted that logic are gone. What is left matches three patches under review upstream, so all three can be dropped when python is next bumped: python/cpython#156110 python/cpython#156116 python/cpython#156113 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CPython appends -mios-version-min - the device flag - to every iOS build. Against the simulator SDK the linker rejects the dylibs it resolves there, and the first configure check that links one fails, taking the depends build with it. The local patch faked ac_sys_system=iOS by deleting CPython's host parsing, because config.site.in pinned every package to the tree's darwin triplet. Python now configures against its own iOS triplet, so CPython derives ac_sys_system, the deployment target and the device/simulator split itself, and the 76 lines that deleted that logic are gone. What is left matches three patches under review upstream, so all three can be dropped when python is next bumped: python/cpython#156110 python/cpython#156116 python/cpython#156113 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CPython appends -mios-version-min - the device flag - to every iOS build. Against the simulator SDK the linker rejects the dylibs it resolves there, and the first configure check that links one fails, taking the depends build with it. The local patch faked ac_sys_system=iOS by deleting CPython's host parsing, because config.site.in pinned every package to the tree's darwin triplet. Python now configures against its own iOS triplet, so CPython derives ac_sys_system, the deployment target and the device/simulator split itself, and the 76 lines that deleted that logic are gone. What is left matches three patches under review upstream, so all three can be dropped when python is next bumped: python/cpython#156110 python/cpython#156116 python/cpython#156113 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
From a pure configuration perspective, this seems a fairly straightforward. My concern is the impact on wheels (and, for that matter, the binaries in the standard library). iOS wheels are linked against libpython because What (if any) testing have you done of this code with the standard library and/or third party libraries? |
|
Context first: Kodi embeds Python in a single signed app binary. It has built The stdlib is built static ( Testing, honestly: I built Your point about wheels stands: with no libpython dylib there is nothing for a
Happy to build the stdlib statically for iOS and report back if that helps. |
995aa88 to
fccc461
Compare
|
Ran the stdlib build — you were right, this is broken as it stands.
configure.ac:3687 links iOS extensions against the framework unconditionally:
So a static libpython needs static modules — Kodi passes I'll make configure require |
|
Follow-up: with So my proposed requirement isn't sufficient alone: Either require |
I feel like I'm having a conversation with an agent rather than a human, except without the ability to actually drive the conversation... What exactly are you proposing as the options here? |
|
@freakboy3742 yes, there is an AI agent in the loop. I use it to dig through the build system, and I read and approve everything before it gets posted. 3 propositions:
|
My inclination is to go with this - the fully explicit option. A static build is clearly useful, but there will be restrictions on use - I think there is value in requiring the prospective user to explicitly opt into all those options. These limitations will also need to be documented; a section on static builds (describing both the build process and limitations) to Platforms/Apple/iOS/README.md will be required. It may also be worth mentioning in Doc/using/iOS.rst that the official iOS release artefact is a framework build, but "static builds are also possible with limitations, see the README for details". |
fccc461 to
d89c672
Compare
Documentation build overview
9 files changed ·
|
|
Done - pushed the explicit version.
Tested here on an Docs as you asked: a "Building a static Python" section in |
d89c672 to
14b7fc3
Compare
freakboy3742
left a comment
There was a problem hiding this comment.
I'm currently at PyCon AU; a full review for this will need to wait until I'm back next week.
However, my first impression looking at the patch - is --disable-framework actually doing anything? --enable-framework is clearly needed, but AFAICT --disable-framework is the default value. It won't hurt to include it, but it doesn't appear to actually be necessary either, essentially falling back on autoconf's default --enable/--disable behavior for flags.
If that's the case - is there any point explicitly calling it out as an option? Wouldn't it make more sense to just say "if --enable-framework is not enabled, --disable-shared must be enabled", and do error handling on that basis?
14b7fc3 to
87205e3
Compare
A shared Python on iOS has to be packaged as a framework for App Store Connect to accept it. A static libpython is linked into the app binary and loads nothing at runtime, so the requirement does not apply to it, but configure refused that configuration outright. Refuse it only where it cannot work: a shared build with no framework. The LINKFORSHARED and MODULE_DEPS_SHARED framework references are gated on enable_framework, as the Darwin arm above already does, since a build without a framework has nothing to link against. Omitting the framework option behaves as --disable-framework, as it does on every other platform. A static build does come with restrictions - it cannot load extension modules at runtime, and so cannot use binary wheels - so require the user to opt into them explicitly. A non-framework iOS build now errors unless MODULE_BUILDTYPE=static is set (there is no framework for a shared extension module to link against) and --disable-test-modules is given (some test modules must be built as shared libraries; see Modules/Setup.stdlib.in). Those two options have defaults that point the other way, so they must be typed; the errors lead with --enable-framework, so that a forgotten framework option does not read as an invitation to build static. Document the build process and its limitations in a new section of Platforms/Apple/iOS/README.md, and note in Doc/using/ios.rst that the official iOS release artefact is a framework build.
87205e3 to
abfa4b2
Compare
|
Well noted and thanks for the first feeback. I have pushed a new version without the --disable-framework, it was a bit overprotective, to be sure that the user want explicity to build without the framework. New version is simpler. Configure decision table:
|
configurerefuses any non-framework iOS build. That is correct for a shared Python — an iOS app can only load a signed framework, never a bare dylib — but a--disable-sharedbuild produces alibpython3.x.athat is linked into the app binary and loads nothing at runtime, so the requirement does not apply to it.This narrows the refusal to the combination that genuinely cannot work, and stops two Makefile variables referencing a framework that a non-framework build never produces.
--disable-frameworkpath no longer errors on iOS; it falls through to the existing non-framework setup.PY_ENABLE_SHAREDis known, rejects a shared build with no framework.LINKFORSHAREDandMODULE_DEPS_SHAREDgate their$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)appends onenable_framework, as the Darwin arm directly above the first one already does.--disable-framework.Verified on macOS/arm64 against
main:--host=arm64-apple-ios12.0)--disable-framework --disable-sharedmake libpython3.16.asucceeds — arm64,LC_BUILD_VERSION platform 2,minos 12.0--disable-framework --enable-shared--enable-frameworkMakefileandpyconfig.hbyte-identical to unpatchedmainconfigurewas regenerated withTools/build/regen-configure.sh;autoreconf -ivf -Werroris clean and the generated diff contains no unrelated churn.