From 22f8b6d1a827e36cebf499ca5f519bffa2330464 Mon Sep 17 00:00:00 2001 From: John Zhou Date: Sat, 3 May 2025 18:33:13 -0500 Subject: [PATCH 01/11] let's go... this builds --- Makefile | 52 +- patch/Python/Python.patch | 1527 ++++++++++++++++++++++++++++++++----- 2 files changed, 1375 insertions(+), 204 deletions(-) diff --git a/Makefile b/Makefile index 72994c0..f45af32 100644 --- a/Makefile +++ b/Makefile @@ -44,9 +44,11 @@ TRIPLE_OS-macOS=macos VERSION_MIN-macOS=11.0 # iOS targets -TARGETS-iOS=iphonesimulator.x86_64 iphonesimulator.arm64 iphoneos.arm64 +TARGETS-iOS=iphonesimulator.x86_64 iphonesimulator.arm64 iphoneos.arm64 macabi.x86_64 macabi.arm64 TRIPLE_OS-iOS=ios VERSION_MIN-iOS=13.0 +VERSION_MIN_OVERRIDE-macabi=14.2 +CONFIGFLAGS-macabi=--with-catalyst-macos-version=11.2 # tvOS targets TARGETS-tvOS=appletvsimulator.x86_64 appletvsimulator.arm64 appletvos.arm64 @@ -132,15 +134,34 @@ os=$2 OS_LOWER-$(target)=$(shell echo $(os) | tr '[:upper:]' '[:lower:]') # $(target) can be broken up into is composed of $(SDK).$(ARCH) -SDK-$(target)=$$(basename $(target)) +BASE-$(target)=$$(basename $(target)) +SDK-$(target)=$$(subst macabi,macosx,$$(BASE-$(target))) ARCH-$(target)=$$(subst .,,$$(suffix $(target))) +# Compute version minimum for the target +VERSION_MIN-$(target)=$$(VERSION_MIN-$(os)) +ifdef VERSION_MIN_OVERRIDE-$$(BASE-$(target)) +VERSION_MIN-$(target)=$$(VERSION_MIN_OVERRIDE-$$(BASE-$(target))) +endif + +# Inherit the basename for the configure flags. +ifdef CONFIGFLAGS-$$(BASE-$(target)) +CONFIGFLAGS-$(target)=$$(CONFIGFLAGS-$$(BASE-$(target)) +else +CONFIGFLAGS-$(target)= +endif + ifneq ($(os),macOS) - ifeq ($$(findstring simulator,$$(SDK-$(target))),) -TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(os)) + ifeq ($$(findstring simulator,$$(BASE-$(target))),) + ifeq ($$(findstring macabi,$$(BASE-$(target))),) +TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(target)) IS_SIMULATOR-$(target)=False + else +TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(target))-macabi +IS_SIMULATOR-$(target)=False + endif else -TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(os))-simulator +TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(target))-simulator IS_SIMULATOR-$(target)=True endif endif @@ -274,6 +295,13 @@ PYTHON_PLATFORM_CONFIG-$(target)=$$(PYTHON_INSTALL-$(target))/platform-config/$$ PYTHON_PLATFORM_SITECUSTOMIZE-$(target)=$$(PYTHON_PLATFORM_CONFIG-$(target))/sitecustomize.py + +ifneq ($$(BASE-$(target)),macabi) +RESCDIR-$(target)=$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources +else +RESCDIR-$(target)=$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/MacCatalyst/Resources +endif + $$(PYTHON_SRCDIR-$(target))/configure: \ downloads/Python-$(PYTHON_VERSION).tar.gz \ $$(BZIP2_LIB-$(target)) \ @@ -287,7 +315,7 @@ $$(PYTHON_SRCDIR-$(target))/configure: \ # Apply target Python patches cd $$(PYTHON_SRCDIR-$(target)) && patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch # Make sure the binary scripts are executable - chmod 755 $$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin/* + chmod 755 $$(RESCDIR-$(target))/bin/* # Touch the configure script to ensure that Make identifies it as up to date. touch $$(PYTHON_SRCDIR-$(target))/configure @@ -295,7 +323,7 @@ $$(PYTHON_SRCDIR-$(target))/Makefile: \ $$(PYTHON_SRCDIR-$(target))/configure # Configure target Python cd $$(PYTHON_SRCDIR-$(target)) && \ - PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin:$(PATH)" \ + PATH="$$(RESCDIR-$(target))/bin:$(PATH)" \ ./configure \ LIBLZMA_CFLAGS="-I$$(XZ_INSTALL-$(target))/include" \ LIBLZMA_LIBS="-L$$(XZ_INSTALL-$(target))/lib -llzma" \ @@ -312,19 +340,21 @@ $$(PYTHON_SRCDIR-$(target))/Makefile: \ --with-openssl="$$(OPENSSL_INSTALL-$(target))" \ --enable-framework="$$(PYTHON_INSTALL-$(target))" \ --with-system-libmpdec \ + $$(CONFIGFLAGS-$(target)) \ 2>&1 | tee -a ../python-$(PYTHON_VERSION).config.log $$(PYTHON_SRCDIR-$(target))/python.exe: $$(PYTHON_SRCDIR-$(target))/Makefile @echo ">>> Build Python for $(target)" + cd $$(PYTHON_SRCDIR-$(target)) && \ - PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin:$(PATH)" \ + PATH="$$(RESCDIR-$(target))/bin:$(PATH)" \ make -j8 all \ 2>&1 | tee -a ../python-$(PYTHON_VERSION).build.log $$(PYTHON_LIB-$(target)): $$(PYTHON_SRCDIR-$(target))/python.exe @echo ">>> Install Python for $(target)" cd $$(PYTHON_SRCDIR-$(target)) && \ - PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin:$(PATH)" \ + PATH="$$(RESCDIR-$(target))/bin:$(PATH)" \ make install \ 2>&1 | tee -a ../python-$(PYTHON_VERSION).install.log @@ -349,7 +379,7 @@ $$(PYTHON_PLATFORM_SITECUSTOMIZE-$(target)): | sed -e "s/{{platform}}/$$(OS_LOWER-$(target))/g" \ | sed -e "s/{{arch}}/$$(ARCH-$(target))/g" \ | sed -e "s/{{sdk}}/$$(SDK-$(target))/g" \ - | sed -e "s/{{version_min}}/$$(VERSION_MIN-$(os))/g" \ + | sed -e "s/{{version_min}}/$$(VERSION_MIN-$(target))/g" \ | sed -e "s/{{is_simulator}}/$$(IS_SIMULATOR-$(target))/g" \ > $$(PYTHON_PLATFORM_CONFIG-$(target))/_cross_$$(ARCH-$(target))_$$(SDK-$(target)).py cat $(PROJECT_DIR)/patch/Python/sitecustomize.py.tmpl \ @@ -495,7 +525,7 @@ else $$(foreach target,$$(SDK_TARGETS-$(sdk)),cp $$(PYTHON_INCLUDE-$$(target))/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig-$$(ARCH-$$(target)).h; ) # Copy the cross-target header from the source folder of the first target in the $(sdk) SDK - cp $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$(sdk))))/$(os)/Resources/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h + cp $$(RESCDIR-$$(firstword $$(SDK_TARGETS-$(sdk))))/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h endif diff --git a/patch/Python/Python.patch b/patch/Python/Python.patch index 4c59f84..c19a626 100644 --- a/patch/Python/Python.patch +++ b/patch/Python/Python.patch @@ -1,3 +1,21 @@ +diff --git a/Lib/_ios_support.py b/Lib/_ios_support.py +index 20467a7c2bc..deefacaf8c5 100644 +--- a/Lib/_ios_support.py ++++ b/Lib/_ios_support.py +@@ -25,6 +25,7 @@ + def get_platform_ios(): + # Determine if this is a simulator using the multiarch value + is_simulator = sys.implementation._multiarch.endswith("simulator") ++ is_catalyst = sys.implementation._multiarch.endswith("macabi") + + # We can't use ctypes; abort + if not objc: +@@ -68,4 +69,4 @@ + release = objc.objc_msgSend(device_systemVersion, SEL_UTF8String).decode() + model = objc.objc_msgSend(device_model, SEL_UTF8String).decode() + +- return system, release, model, is_simulator ++ return system, release, model, is_simulator, is_catalyst diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index bba08b99b95..8d03017c223 100644 --- a/Lib/ctypes/__init__.py @@ -34,7 +52,7 @@ index 99504911a3d..527c2f36dd0 100644 if hasattr((_libc := ctypes.CDLL(None)), "dl_iterate_phdr"): diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py -index 8bcd741c446..d8a6f28edba 100644 +index 8bcd741c446..58642d961d6 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -52,7 +52,7 @@ @@ -46,23 +64,42 @@ index 8bcd741c446..d8a6f28edba 100644 _CASE_INSENSITIVE_PLATFORMS = (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY + _CASE_INSENSITIVE_PLATFORMS_STR_KEY) -@@ -1535,7 +1535,7 @@ +@@ -1535,7 +1535,8 @@ """ extension_loaders = [] if hasattr(_imp, 'create_dynamic'): - if sys.platform in {"ios", "tvos", "watchos"}: -+ if sys.platform in {"ios", "tvos", "watchos", "visionos"}: ++ # Mac Catalyst does NOT use the AppleFrameworkLoader. ++ if sys.platform in {"ios", "tvos", "watchos", "visionos"} and not sys.implementation._multiarch.endswith("macabi"): extension_loaders = [(AppleFrameworkLoader, [ suffix.replace(".so", ".fwork") for suffix in _imp.extension_suffixes() diff --git a/Lib/platform.py b/Lib/platform.py -index a62192589af..31f18b026b7 100644 +index a62192589af..d071cd00b86 100644 --- a/Lib/platform.py +++ b/Lib/platform.py -@@ -528,6 +528,78 @@ - return IOSVersionInfo(system, release, model, is_simulator) +@@ -508,11 +508,11 @@ + # A namedtuple for iOS version information. + IOSVersionInfo = collections.namedtuple( + "IOSVersionInfo", +- ["system", "release", "model", "is_simulator"] ++ ["system", "release", "model", "is_simulator", "is_catalyst"] + ) +-def ios_ver(system="", release="", model="", is_simulator=False): ++def ios_ver(system="", release="", model="", is_simulator=False, is_catalyst=False): + """Get iOS version information, and return it as a namedtuple: + (system, release, model, is_simulator). + +@@ -525,7 +525,79 @@ + if result is not None: + return IOSVersionInfo(*result) + +- return IOSVersionInfo(system, release, model, is_simulator) ++ return IOSVersionInfo(system, release, model, is_simulator, is_catalyst) ++ ++ +# A namedtuple for tvOS version information. +TVOSVersionInfo = collections.namedtuple( + "TVOSVersionInfo", @@ -133,11 +170,9 @@ index a62192589af..31f18b026b7 100644 + return VisionOSVersionInfo(*result) + + return VisionOSVersionInfo(system, release, model, is_simulator) -+ -+ + + def _java_getprop(name, default): - """This private helper is deprecated in 3.13 and will be removed in 3.15""" - from java.lang import System @@ -727,7 +799,7 @@ default in case the command should fail. @@ -147,7 +182,7 @@ index a62192589af..31f18b026b7 100644 # XXX Others too ? return default -@@ -891,14 +963,30 @@ +@@ -891,10 +963,26 @@ csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0) return 'Alpha' if cpu_number >= 128 else 'VAX' @@ -159,10 +194,10 @@ index a62192589af..31f18b026b7 100644 + # there's only one CPU architecture for devices, so we know the right + # answer. def get_ios(): - if sys.implementation._multiarch.endswith("simulator"): - return os.uname().machine - return 'arm64' - ++ if sys.implementation._multiarch.endswith("simulator") or sys.implementation._multiarch.endswith("macabi"): ++ return os.uname().machine ++ return 'arm64' ++ + def get_tvos(): + if sys.implementation._multiarch.endswith("simulator"): + return os.uname().machine @@ -174,13 +209,9 @@ index a62192589af..31f18b026b7 100644 + return 'arm64_32' + + def get_visionos(): -+ if sys.implementation._multiarch.endswith("simulator"): -+ return os.uname().machine -+ return 'arm64' -+ - def from_subprocess(): - """ - Fall back to `uname -p` + if sys.implementation._multiarch.endswith("simulator"): + return os.uname().machine + return 'arm64' @@ -1058,9 +1146,15 @@ system = 'Android' release = android_ver().release @@ -188,7 +219,8 @@ index a62192589af..31f18b026b7 100644 - # Normalize responses on iOS + # Normalize responses on Apple mobile platforms if sys.platform == 'ios': - system, release, _, _ = ios_ver() +- system, release, _, _ = ios_ver() ++ system, release, _, _, _ = ios_ver() + if sys.platform == 'tvos': + system, release, _, _ = tvos_ver() + if sys.platform == 'watchos': @@ -198,10 +230,12 @@ index a62192589af..31f18b026b7 100644 vals = system, node, release, version, machine # Replace 'unknown' values with the more portable '' -@@ -1350,6 +1444,12 @@ +@@ -1349,7 +1443,13 @@ + if system == 'Darwin': # macOS and iOS both report as a "Darwin" kernel if sys.platform == "ios": - system, release, _, _ = ios_ver() +- system, release, _, _ = ios_ver() ++ system, release, _, _, _ = ios_ver() + elif sys.platform == "tvos": + system, release, _, _ = tvos_ver() + elif sys.platform == "watchos": @@ -227,15 +261,18 @@ index 9da8b6724e1..345f55a5bde 100644 def joinuser(*args): diff --git a/Lib/subprocess.py b/Lib/subprocess.py -index da5f5729e09..7401ffbc987 100644 +index da5f5729e09..a7427c4cecf 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py -@@ -75,7 +75,7 @@ +@@ -75,7 +75,10 @@ _mswindows = True # some platforms do not support subprocesses -_can_fork_exec = sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos"} -+_can_fork_exec = sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos", "visionos"} ++_can_fork_exec = ( ++ sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos", "visionos"} ++ or sys.implementation._multiarch.endswith("macabi") ++) if _mswindows: import _winapi @@ -282,7 +319,7 @@ index 18e6b8d25e5..64603fb1bb1 100644 import _osx_support osname, release, machine = _osx_support.get_platform_osx( diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py -index ecb37250ceb..67d04491072 100644 +index ecb37250ceb..33770a0ac0d 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -7155,9 +7155,9 @@ @@ -290,18 +327,27 @@ index ecb37250ceb..67d04491072 100644 def test_type_check_in_subinterp(self): - # iOS requires the use of the custom framework loader, -+ # Apple mobile platforms require the use of the custom framework loader, - # not the ExtensionFileLoader. +- # not the ExtensionFileLoader. - if sys.platform == "ios": -+ if support.is_apple_mobile: ++ # Apple mobile platforms EXCEPT Mac Catalyst require the use of the ++ # custom framework loader, not the ExtensionFileLoader. ++ if support.needs_apple_fworks: extension_loader = "AppleFrameworkLoader" else: extension_loader = "ExtensionFileLoader" diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py -index 6d670a575b0..8d7d68d1ee1 100644 +index 6d670a575b0..b3c03088f37 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py -@@ -551,7 +551,7 @@ +@@ -46,6 +46,7 @@ + # sys + "MS_WINDOWS", "is_jython", "is_android", "is_emscripten", "is_wasi", + "is_apple_mobile", "check_impl_detail", "unix_shell", "setswitchinterval", ++ "is_mac_catalyst", "needs_apple_fworks", + # os + "get_pagesize", + # network +@@ -551,7 +552,7 @@ sys.platform == "android", f"Android blocks {name} with SELinux" ) @@ -310,15 +356,38 @@ index 6d670a575b0..8d7d68d1ee1 100644 unix_shell = '/system/bin/sh' if is_android else '/bin/sh' else: unix_shell = None -@@ -567,7 +567,7 @@ +@@ -567,8 +568,10 @@ def skip_wasi_stack_overflow(): return unittest.skipIf(is_wasi, "Exhausts stack on WASI") -is_apple_mobile = sys.platform in {"ios", "tvos", "watchos"} +is_apple_mobile = sys.platform in {"ios", "tvos", "watchos", "visionos"} is_apple = is_apple_mobile or sys.platform == "darwin" ++is_mac_catalyst = sys.implementation._multiarch.endswith("macabi") ++needs_apple_fworks = is_apple_mobile and not is_mac_catalyst has_fork_support = hasattr(os, "fork") and not ( + # WASM and Apple mobile platforms do not support subprocesses. +@@ -579,6 +582,9 @@ + # Although Android supports fork, it's unsafe to call it from Python because + # all Android apps are multi-threaded. + or is_android ++ ++ # Mac Catalyst supports subprocesses. ++ and not is_mac_catalyst + ) + + def requires_fork(): +@@ -594,6 +600,9 @@ + # practice (see PEP 738). And most of the tests that use them are calling + # sys.executable, which won't work when Python is embedded in an Android app. + or is_android ++ ++ # Mac Catalyst supports subprocesses. ++ and not is_mac_catalyst + ) + + def requires_subprocess(): diff --git a/Lib/test/support/os_helper.py b/Lib/test/support/os_helper.py index d82093e375c..2c45fe2369e 100644 --- a/Lib/test/support/os_helper.py @@ -332,6 +401,28 @@ index d82093e375c..2c45fe2369e 100644 fd_path = "/dev/fd" else: fd_path = None +diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py +index 98dc3b42ef0..63385632201 100644 +--- a/Lib/test/test_capi/test_misc.py ++++ b/Lib/test/test_capi/test_misc.py +@@ -1918,7 +1918,7 @@ + + # Apple extensions must be distributed as frameworks. This requires + # a specialist loader. +- if support.is_apple_mobile: ++ if support.needs_apple_fworks: + loader = "AppleFrameworkLoader" + else: + loader = "ExtensionFileLoader" +@@ -2602,7 +2602,7 @@ + origin = importlib.util.find_spec('_testmultiphase').origin + # Apple extensions must be distributed as frameworks. This requires + # a specialist loader. +- if support.is_apple_mobile: ++ if support.needs_apple_fworks: + loader = importlib.machinery.AppleFrameworkLoader(fullname, origin) + else: + loader = importlib.machinery.ExtensionFileLoader(fullname, origin) diff --git a/Lib/test/test_ctypes/test_dllist.py b/Lib/test/test_ctypes/test_dllist.py index 15603dc3d77..bff6c0fb95f 100644 --- a/Lib/test/test_ctypes/test_dllist.py @@ -345,8 +436,126 @@ index 15603dc3d77..bff6c0fb95f 100644 if WINDOWS: KNOWN_LIBRARIES = ["KERNEL32.DLL"] +diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py +index 33df4fef0b2..bc8f6a783ec 100644 +--- a/Lib/test/test_import/__init__.py ++++ b/Lib/test/test_import/__init__.py +@@ -33,7 +33,7 @@ + swap_attr, + swap_item, + cpython_only, +- is_apple_mobile, ++ needs_apple_fworks, + is_emscripten, + is_wasi, + run_in_subinterp, +@@ -111,7 +111,7 @@ + def require_extension(module, *, skip=False): + # Apple extensions must be distributed as frameworks. This requires + # a specialist loader. +- if is_apple_mobile: ++ if needs_apple_fworks: + _require_loader(module, AppleFrameworkLoader, skip) + else: + _require_loader(module, ExtensionFileLoader, skip) +@@ -126,7 +126,7 @@ + def create_extension_loader(modname, filename): + # Apple extensions must be distributed as frameworks. This requires + # a specialist loader. +- if is_apple_mobile: ++ if needs_apple_fworks: + return AppleFrameworkLoader(modname, filename) + else: + return ExtensionFileLoader(modname, filename) +@@ -2217,7 +2217,7 @@ + if filename: + # Apple extensions must be distributed as frameworks. This requires + # a specialist loader. +- if is_apple_mobile: ++ if needs_apple_fworks: + loader = "AppleFrameworkLoader" + else: + loader = "ExtensionFileLoader" +@@ -2692,7 +2692,7 @@ + # Apple extensions must be distributed as frameworks. This requires + # a specialist loader, and we need to differentiate between the + # spec.origin and the original file location. +- if is_apple_mobile: ++ if needs_apple_fworks: + assert cls.LOADER is AppleFrameworkLoader + + cls.ORIGIN = spec.origin +diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py +index cdc8884d668..d1b525f6419 100644 +--- a/Lib/test/test_importlib/extension/test_finder.py ++++ b/Lib/test/test_importlib/extension/test_finder.py +@@ -1,4 +1,4 @@ +-from test.support import is_apple_mobile ++from test.support import needs_apple_fworks + from test.test_importlib import abc, util + + machinery = util.import_importlib('importlib.machinery') +@@ -20,7 +20,7 @@ + ) + + def find_spec(self, fullname): +- if is_apple_mobile: ++ if needs_apple_fworks: + # Apple mobile platforms require a specialist loader that uses + # .fwork files as placeholders for the true `.so` files. + loaders = [ +diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py +index 0dd21e079eb..efae18d4bbd 100644 +--- a/Lib/test/test_importlib/extension/test_loader.py ++++ b/Lib/test/test_importlib/extension/test_loader.py +@@ -1,4 +1,4 @@ +-from test.support import is_apple_mobile ++from test.support import needs_apple_fworks + from test.test_importlib import abc, util + + machinery = util.import_importlib('importlib.machinery') +@@ -28,7 +28,7 @@ + + # Apple extensions must be distributed as frameworks. This requires + # a specialist loader. +- if is_apple_mobile: ++ if needs_apple_fworks: + self.LoaderClass = self.machinery.AppleFrameworkLoader + else: + self.LoaderClass = self.machinery.ExtensionFileLoader +@@ -110,7 +110,7 @@ + + # Apple extensions must be distributed as frameworks. This requires + # a specialist loader. +- if is_apple_mobile: ++ if needs_apple_fworks: + self.LoaderClass = self.machinery.AppleFrameworkLoader + else: + self.LoaderClass = self.machinery.ExtensionFileLoader +@@ -198,7 +198,7 @@ + + # Apple extensions must be distributed as frameworks. This requires + # a specialist loader. +- if is_apple_mobile: ++ if needs_apple_fworks: + self.LoaderClass = self.machinery.AppleFrameworkLoader + else: + self.LoaderClass = self.machinery.ExtensionFileLoader +diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py +index 5de89714eb5..0c6661791ca 100644 +--- a/Lib/test/test_importlib/test_util.py ++++ b/Lib/test/test_importlib/test_util.py +@@ -714,7 +714,7 @@ + def test_incomplete_multi_phase_init_module(self): + # Apple extensions must be distributed as frameworks. This requires + # a specialist loader. +- if support.is_apple_mobile: ++ if support.needs_apple_fworks: + loader = "AppleFrameworkLoader" + else: + loader = "ExtensionFileLoader" diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py -index 6ba630ad527..7b447744d12 100644 +index 6ba630ad527..3bb82756e36 100644 --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -268,13 +268,21 @@ @@ -374,6 +583,58 @@ index 6ba630ad527..7b447744d12 100644 else: self.assertEqual(res.system, "") self.assertEqual(res.release, "") +@@ -477,7 +485,7 @@ + + # ios_ver is only fully available on iOS where ctypes is available. + if sys.platform == "ios" and _ctypes: +- system, release, model, is_simulator = result ++ system, release, model, is_simulator, is_catalyst = result + # Result is a namedtuple + self.assertEqual(result.system, system) + self.assertEqual(result.release, release) +@@ -488,6 +496,7 @@ + # ios_ver(), so we check that the values are broadly what we expect. + + # System is either iOS or iPadOS, depending on the test device ++ # Mac Catalyst returns iPadOS for whatever reason. + self.assertIn(system, {"iOS", "iPadOS"}) + + # Release is a numeric version specifier with at least 2 parts +@@ -500,6 +509,9 @@ + # we get a model descriptor like "iPhone13,1" + if is_simulator: + self.assertIn(model, {"iPhone", "iPad"}) ++ # Mac Catalyst identifies as iPad with no version. ++ elif is_catalyst: ++ self.assertEqual(model, "iPad") + else: + self.assertTrue( + (model.startswith("iPhone") or model.startswith("iPad")) +@@ -507,6 +519,10 @@ + ) + + self.assertEqual(type(is_simulator), bool) ++ ++ # Mac Catalyst platform will return iPadOS. ++ if is_catalyst: ++ self.assertEqual(system, "iPadOS") + else: + # On non-iOS platforms, calling ios_ver doesn't fail; you get + # default values +@@ -516,11 +532,12 @@ + self.assertFalse(result.is_simulator) + + # Check the fallback values can be overridden by arguments +- override = platform.ios_ver("Foo", "Bar", "Whiz", True) ++ override = platform.ios_ver("Foo", "Bar", "Whiz", True, True) + self.assertEqual(override.system, "Foo") + self.assertEqual(override.release, "Bar") + self.assertEqual(override.model, "Whiz") + self.assertTrue(override.is_simulator) ++ self.assertTrue(override.is_catalyst) + + @unittest.skipIf(support.is_emscripten, "Does not apply to Emscripten") + def test_libc_ver(self): diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py index 4c3ea1cd8df..04a210e5c86 100644 --- a/Lib/test/test_webbrowser.py @@ -415,8 +676,89 @@ index 232d3c3a9c5..e042c20ea54 100644 from _ios_support import objc if objc: # If objc exists, we know ctypes is also importable. +--- /dev/null ++++ b/MacCatalyst/Resources/Info.plist.in +@@ -0,0 +1,38 @@ ++ ++ ++ ++ ++ CFBundleDevelopmentRegion ++ en ++ CFBundleExecutable ++ Python ++ CFBundleGetInfoString ++ Python Runtime and Library ++ CFBundleIdentifier ++ @PYTHONFRAMEWORKIDENTIFIER@ ++ CFBundleInfoDictionaryVersion ++ 6.0 ++ CFBundleName ++ Python ++ CFBundlePackageType ++ FMWK ++ CFBundleShortVersionString ++ %VERSION% ++ CFBundleLongVersionString ++ %VERSION%, (c) 2001-2024 Python Software Foundation. ++ CFBundleSignature ++ ???? ++ CFBundleVersion ++ %VERSION% ++ CFBundleSupportedPlatforms ++ ++ MacOSX ++ ++ LSMinimumSystemVersion ++ @CATALYST_MACOS_VERSION@ ++ UIDeviceFamily ++ ++ 2 ++ ++ ++ +--- /dev/null ++++ b/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-ar +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk macosx${MACOSX_SDK_VERSION} ar "$@" +--- /dev/null ++++ b/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-clang +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk macosx${MACOSX_SDK_VERSION} clang -target arm64-apple-ios-macabi "$@" +--- /dev/null ++++ b/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-clang++ +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk macosx${MACOSX_SDK_VERSION} clang++ -target arm64-apple-ios-macabi "$@" +--- /dev/null ++++ b/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-cpp +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk macosx${MACOSX_SDK_VERSION} clang -target arm64-apple-ios-macabi -E "$@" +--- /dev/null ++++ b/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-ar +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk macosx${MACOSX_SDK_VERSION} ar "$@" +--- /dev/null ++++ b/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-clang +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk macosx${MACOSX_SDK_VERSION} clang -target x86_64-apple-ios-macabi "$@" +--- /dev/null ++++ b/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-clang++ +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk macosx${MACOSX_SDK_VERSION} clang++ -target x86_64-apple-ios-macabi "$@" +--- /dev/null ++++ b/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-cpp +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk macosx${MACOSX_SDK_VERSION} clang -target x86_64-apple-ios-macabi -E "$@" diff --git a/Makefile.pre.in b/Makefile.pre.in -index e10c78d6403..920e707ab26 100644 +index e10c78d6403..21b707bd017 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -209,6 +209,12 @@ @@ -432,7 +774,7 @@ index e10c78d6403..920e707ab26 100644 # Option to install to strip binaries STRIPFLAG=-s -@@ -2243,7 +2249,7 @@ +@@ -2243,31 +2249,64 @@ # a full Xcode install that has an iPhone SE (3rd edition) simulator available. # This must be run *after* a `make install` has completed the build. The # `--with-framework-name` argument *cannot* be used when configuring the build. @@ -441,17 +783,31 @@ index e10c78d6403..920e707ab26 100644 .PHONY: testios testios: @if test "$(MACHDEP)" != "ios"; then \ -@@ -2263,11 +2269,41 @@ + echo "Cannot run the iOS testbed for a non-iOS build."; \ exit 1;\ fi - -- # Clone the testbed project into the XCFOLDER -- $(PYTHON_FOR_BUILD) $(srcdir)/iOS/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER)" -+ # Clone the testbed project into the XCFOLDER-iOS -+ $(PYTHON_FOR_BUILD) $(srcdir)/iOS/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER-iOS)" ++ @if test $(PYTHONFRAMEWORK) != "Python"; then \ ++ echo "Cannot run the iOS testbed with a non-default framework name."; \ ++ exit 1;\ ++ fi ++ @if ! test -d $(PYTHONFRAMEWORKPREFIX); then \ ++ echo "Cannot find a finalized iOS Python.framework. Have you run 'make install' to finalize the framework build?"; \ ++ exit 1;\ ++ fi + -+ # Run the testbed project -+ $(PYTHON_FOR_BUILD) "$(XCFOLDER-iOS)" run --verbose -- test -uall --single-process --rerun -W + @if test "$(findstring -iphonesimulator,$(MULTIARCH))" != "-iphonesimulator"; then \ +- echo "Cannot run the iOS testbed for non-simulator builds."; \ ++ if test "$(findstring -macabi,$(MULTIARCH))" != "-macabi"; then \ ++ echo "Cannot run the iOS testbed for device builds."; \ ++ exit 1;\ ++ else \ ++ $(PYTHON_FOR_BUILD) $(srcdir)/iOS/testbed --catalyst clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER-iOS)"; \ ++ $(PYTHON_FOR_BUILD) "$(XCFOLDER-iOS)" --catalyst run --verbose -- test -uall --single-process --rerun -W; \ ++ fi \ ++ else \ ++ $(PYTHON_FOR_BUILD) $(srcdir)/iOS/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER-iOS)"; \ ++ $(PYTHON_FOR_BUILD) "$(XCFOLDER-iOS)" run --verbose -- test -uall --single-process --rerun -W; \ ++ fi + +# Run the test suite on the visionOS simulator. Must be run on a macOS machine with +# a full Xcode install that has an Apple Vision Pro simulator available. @@ -466,17 +822,21 @@ index e10c78d6403..920e707ab26 100644 + fi + @if test "$(findstring -xrsimulator,$(MULTIARCH))" != "-xrsimulator"; then \ + echo "Cannot run the visionOS testbed for non-simulator builds."; \ -+ exit 1;\ -+ fi -+ @if test $(PYTHONFRAMEWORK) != "Python"; then \ + exit 1;\ + fi + @if test $(PYTHONFRAMEWORK) != "Python"; then \ +- echo "Cannot run the iOS testbed with a non-default framework name."; \ + echo "Cannot run the visionOS testbed with a non-default framework name."; \ -+ exit 1;\ -+ fi -+ @if ! test -d $(PYTHONFRAMEWORKPREFIX); then \ + exit 1;\ + fi + @if ! test -d $(PYTHONFRAMEWORKPREFIX); then \ +- echo "Cannot find a finalized iOS Python.framework. Have you run 'make install' to finalize the framework build?"; \ + echo "Cannot find a finalized visionOS Python.framework. Have you run 'make install' to finalize the framework build?"; \ -+ exit 1;\ -+ fi -+ + exit 1;\ + fi + +- # Clone the testbed project into the XCFOLDER +- $(PYTHON_FOR_BUILD) $(srcdir)/iOS/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER)" + # Clone the testbed project into the XCFOLDER-visionOS + $(PYTHON_FOR_BUILD) $(srcdir)/visionOS/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER-visionOS)" @@ -487,10 +847,19 @@ index e10c78d6403..920e707ab26 100644 # Like test, but using --slow-ci which enables all test resources and use # longer timeout. Run an optional pybuildbot.identify script to include diff --git a/Misc/platform_triplet.c b/Misc/platform_triplet.c -index ec0857a4a99..e52f486cdb3 100644 +index ec0857a4a99..de56264da3b 100644 --- a/Misc/platform_triplet.c +++ b/Misc/platform_triplet.c -@@ -257,6 +257,32 @@ +@@ -254,9 +254,41 @@ + # else + PLATFORM_TRIPLET=arm64-iphonesimulator + # endif ++# elif defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST ++# if __x86_64__ ++PLATFORM_TRIPLET=x86_64-iphoneos-macabi ++# else ++PLATFORM_TRIPLET=arm64-iphoneos-macabi ++# endif # else PLATFORM_TRIPLET=arm64-iphoneos # endif @@ -524,7 +893,7 @@ index ec0857a4a99..e52f486cdb3 100644 # elif !defined(TARGET_OS_OSX) || TARGET_OS_OSX PLATFORM_TRIPLET=darwin diff --git a/config.sub b/config.sub -index 1bb6a05dc11..49febd56a37 100755 +index 1bb6a05dc11..6efa3fbf821 100755 --- a/config.sub +++ b/config.sub @@ -1743,7 +1743,7 @@ @@ -536,23 +905,35 @@ index 1bb6a05dc11..49febd56a37 100755 | mpw* | magic* | mmixware* | mon960* | lnews* \ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ | aos* | aros* | cloudabi* | sortix* | twizzler* \ -@@ -1867,7 +1867,7 @@ +@@ -1769,7 +1769,7 @@ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ + | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ +- | fiwix* | mlibc* | cos* | mbr* | ironclad* ) ++ | fiwix* | mlibc* | cos* | mbr* | ironclad* | macabi) + ;; + # This one is extra strict with allowed versions + sco3.2v2 | sco3.2v[4-9]* | sco5v6*) +@@ -1867,7 +1867,9 @@ ;; *-eabi*- | *-gnueabi*-) ;; - ios*-simulator- | tvos*-simulator- | watchos*-simulator- ) + ios*-simulator- | tvos*-simulator- | watchos*-simulator- | xros*-simulator-) ++ ;; ++ ios*-macabi- ) ;; none--*) # None (no kernel, i.e. freestanding / bare metal), diff --git a/configure b/configure -index 1b75ddfa26d..7b79dfc424c 100755 +index 1b75ddfa26d..9feb830657a 100755 --- a/configure +++ b/configure -@@ -978,6 +978,10 @@ +@@ -978,6 +978,11 @@ CFLAGS CC HAS_XCRUN ++CATALYST_MACOS_VERSION +EXPORT_XROS_DEPLOYMENT_TARGET +XROS_DEPLOYMENT_TARGET +WATCHOS_DEPLOYMENT_TARGET @@ -560,7 +941,25 @@ index 1b75ddfa26d..7b79dfc424c 100755 IPHONEOS_DEPLOYMENT_TARGET EXPORT_MACOSX_DEPLOYMENT_TARGET CONFIGURE_MACOSX_DEPLOYMENT_TARGET -@@ -4106,6 +4110,15 @@ +@@ -1081,6 +1086,7 @@ + with_framework_name + enable_framework + with_app_store_compliance ++with_catalyst_macos_version + enable_wasm_dynamic_linking + enable_wasm_pthreads + with_suffix +@@ -1868,6 +1874,9 @@ + Enable any patches required for compiliance with app + stores. Optional PATCH-FILE specifies the custom + patch to apply. ++ --with-catalyst-macos-version=VER ++ The minimum macOS version a Catalyst build can run ++ on (only valid for *-apple-ios*-macabi targets) + --with-suffix=SUFFIX set executable suffix to SUFFIX (default is empty, + yes is mapped to '.exe') + --without-static-libpython +@@ -4106,6 +4115,15 @@ *-apple-ios*) ac_sys_system=iOS ;; @@ -576,7 +975,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 *-*-darwin*) ac_sys_system=Darwin ;; -@@ -4187,7 +4200,7 @@ +@@ -4187,7 +4205,7 @@ # On cross-compile builds, configure will look for a host-specific compiler by # prepending the user-provided host triple to the required binary name. # @@ -585,10 +984,17 @@ index 1b75ddfa26d..7b79dfc424c 100755 # which isn't a binary that exists, and isn't very convenient, as it contains the # iOS version. As the default cross-compiler name won't exist, configure falls # back to gcc, which *definitely* won't work. We're providing wrapper scripts for -@@ -4202,6 +4215,17 @@ +@@ -4199,33 +4217,89 @@ + # configure will fail. + if test -z "$AR"; then + case "$host" in ++ x86_64-apple-ios*-macabi) AR=x86_64-apple-ios-macabi-ar ;; ++ aarch64-apple-ios*-macabi) AR=arm64-apple-ios-macabi-ar ;; ++ ++ x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;; aarch64-apple-ios*-simulator) AR=arm64-apple-ios-simulator-ar ;; aarch64-apple-ios*) AR=arm64-apple-ios-ar ;; - x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;; +- x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;; + + aarch64-apple-tvos*-simulator) AR=arm64-apple-tvos-simulator-ar ;; + aarch64-apple-tvos*) AR=arm64-apple-tvos-ar ;; @@ -603,10 +1009,15 @@ index 1b75ddfa26d..7b79dfc424c 100755 *) esac fi -@@ -4210,6 +4234,17 @@ + if test -z "$CC"; then + case "$host" in ++ x86_64-apple-ios*-macabi) CC=x86_64-apple-ios-macabi-clang ;; ++ aarch64-apple-ios*-macabi) CC=arm64-apple-ios-macabi-clang ;; ++ ++ x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;; aarch64-apple-ios*-simulator) CC=arm64-apple-ios-simulator-clang ;; aarch64-apple-ios*) CC=arm64-apple-ios-clang ;; - x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;; +- x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;; + + aarch64-apple-tvos*-simulator) CC=arm64-apple-tvos-simulator-clang ;; + aarch64-apple-tvos*) CC=arm64-apple-tvos-clang ;; @@ -621,10 +1032,15 @@ index 1b75ddfa26d..7b79dfc424c 100755 *) esac fi -@@ -4218,6 +4253,17 @@ + if test -z "$CPP"; then + case "$host" in ++ x86_64-apple-ios*-macabi) CPP=x86_64-apple-ios-macabi-cpp ;; ++ aarch64-apple-ios*-macabi) CPP=arm64-apple-ios-macabi-cpp ;; ++ ++ x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;; aarch64-apple-ios*-simulator) CPP=arm64-apple-ios-simulator-cpp ;; aarch64-apple-ios*) CPP=arm64-apple-ios-cpp ;; - x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;; +- x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;; + + aarch64-apple-tvos*-simulator) CPP=arm64-apple-tvos-simulator-cpp ;; + aarch64-apple-tvos*) CPP=arm64-apple-tvos-cpp ;; @@ -639,10 +1055,15 @@ index 1b75ddfa26d..7b79dfc424c 100755 *) esac fi -@@ -4226,6 +4272,17 @@ + if test -z "$CXX"; then + case "$host" in ++ x86_64-apple-ios*-macabi) CXX=x86_64-apple-ios-macabi-clang++ ;; ++ aarch64-apple-ios*-macabi) CXX=arm64-apple-ios-macabi-clang++ ;; ++ ++ x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;; aarch64-apple-ios*-simulator) CXX=arm64-apple-ios-simulator-clang++ ;; aarch64-apple-ios*) CXX=arm64-apple-ios-clang++ ;; - x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;; +- x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;; + + aarch64-apple-tvos*-simulator) CXX=arm64-apple-tvos-simulator-clang++ ;; + aarch64-apple-tvos*) CXX=arm64-apple-tvos-clang++ ;; @@ -657,7 +1078,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 *) esac fi -@@ -4348,8 +4405,11 @@ +@@ -4348,8 +4422,11 @@ case $enableval in yes) case $ac_sys_system in @@ -671,7 +1092,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 *) as_fn_error $? "Unknown platform for framework build" "$LINENO" 5 esac esac -@@ -4358,6 +4418,9 @@ +@@ -4358,6 +4435,9 @@ no) case $ac_sys_system in iOS) as_fn_error $? "iOS builds must use --enable-framework" "$LINENO" 5 ;; @@ -681,10 +1102,39 @@ index 1b75ddfa26d..7b79dfc424c 100755 *) PYTHONFRAMEWORK= PYTHONFRAMEWORKDIR=no-framework -@@ -4464,6 +4527,51 @@ - - ac_config_files="$ac_config_files iOS/Resources/Info.plist" +@@ -4451,6 +4531,67 @@ + ;; + iOS) : ++ _flag_ios_catalyst=`echo $host | cut -d '-' -f4` ++ case $_flag_ios_catalyst in ++ macabi) ++ FRAMEWORKINSTALLFIRST="frameworkinstallversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallversionedstructure " ++ FRAMEWORKINSTALLLAST="" ++ FRAMEWORKALTINSTALLLAST="" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++ prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR/Versions/$VERSION" ++ RESSRCDIR=MacCatalyst/Resources ++ ac_config_files="$ac_config_files MacCatalyst/Resources/Info.plist" ++ ++ ;; ++ *) ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=iOS/Resources ++ ac_config_files="$ac_config_files iOS/Resources/Info.plist" ++ ++ ;; ++ esac + ;; + tvOS) : + FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" @@ -717,23 +1167,22 @@ index 1b75ddfa26d..7b79dfc424c 100755 + + ;; + visionOS) : -+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " -+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKPYTHONW= -+ INSTALLTARGETS="libinstall inclinstall sharedinstall" -+ -+ prefix=$PYTHONFRAMEWORKPREFIX -+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" + FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" + FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " + FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" +@@ -4460,9 +4601,9 @@ + + prefix=$PYTHONFRAMEWORKPREFIX + PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" +- RESSRCDIR=iOS/Resources + RESSRCDIR=visionOS/Resources -+ + +- ac_config_files="$ac_config_files iOS/Resources/Info.plist" + ac_config_files="$ac_config_files visionOS/Resources/Info.plist" -+ + ;; *) - as_fn_error $? "Unknown platform for framework build" "$LINENO" 5 -@@ -4475,6 +4583,9 @@ +@@ -4475,6 +4616,9 @@ e) case $ac_sys_system in iOS) as_fn_error $? "iOS builds must use --enable-framework" "$LINENO" 5 ;; @@ -743,7 +1192,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 *) PYTHONFRAMEWORK= PYTHONFRAMEWORKDIR=no-framework -@@ -4529,8 +4640,8 @@ +@@ -4529,8 +4673,8 @@ case "$withval" in yes) case $ac_sys_system in @@ -754,7 +1203,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" ;; *) as_fn_error $? "no default app store compliance patch available for $ac_sys_system" "$LINENO" 5 ;; -@@ -4548,8 +4659,8 @@ +@@ -4548,8 +4692,8 @@ else case e in #( e) case $ac_sys_system in @@ -765,16 +1214,77 @@ index 1b75ddfa26d..7b79dfc424c 100755 APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: applying default app store compliance patch" >&5 printf "%s\n" "applying default app store compliance patch" >&6; } -@@ -4567,6 +4678,8 @@ +@@ -4568,6 +4712,40 @@ ++ ++# Check whether --with-catalyst-macos-version was given. ++if test ${with_catalyst_macos_version+y} ++then : ++ withval=$with_catalyst_macos_version; case "$host" in ++ *-apple-ios*-macabi) ++ CATALYST_MACOS_VERSION="$withval" ++ ;; ++ *) ++ as_fn_error $? "--with-catalyst-macos-version is only valid when targeting Mac Catalyst (*-apple-ios*-macabi)." "$LINENO" 5 ++ ;; ++ esac ++ ++else case e in #( ++ e) case "$host" in ++ *-apple-ios*-macabi) ++ CATALYST_MACOS_VERSION=11.2 ++ ;; ++ *) ++ CATALYST_MACOS_VERSION= ++ ;; ++ esac ++ ++ ;; ++esac ++fi ++ ++ ++ ++ ++ +EXPORT_XROS_DEPLOYMENT_TARGET='#' + - ++ if test "$cross_compiling" = yes; then case "$host" in -@@ -4604,6 +4717,78 @@ + *-*-linux*) +@@ -4582,6 +4760,28 @@ + *-*-cygwin*) + _host_ident= + ;; ++ *-apple-ios*-macabi) ++ _host_os=`echo $host | cut -d '-' -f3` ++ _host_device=`echo $host | cut -d '-' -f4` # should be macabi ++ _host_device=${_host_device:=os} ++ ++ # IPHONEOS_DEPLOYMENT_TARGET is the minimum supported iOS version ++ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking iOS deployment target" >&5 ++printf %s "checking iOS deployment target... " >&6; } ++ IPHONEOS_DEPLOYMENT_TARGET=$(echo ${_host_os} | cut -c4-) ++ IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET:=14.2} # else it returns invalid version number ++ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $IPHONEOS_DEPLOYMENT_TARGET" >&5 ++printf "%s\n" "$IPHONEOS_DEPLOYMENT_TARGET" >&6; } ++ ++ case "$host_cpu" in ++ aarch64) ++ _host_ident=${IPHONEOS_DEPLOYMENT_TARGET}-arm64-iphoneos-${_host_device} # platform_triplet.c uses iphoneos-macabi ++ ;; ++ *) ++ _host_ident=${IPHONEOS_DEPLOYMENT_TARGET}-$host_cpu-iphoneos-${_host_device} ++ ;; ++ esac ++ ;; + *-apple-ios*) + _host_os=`echo $host | cut -d '-' -f3` + _host_device=`echo $host | cut -d '-' -f4` +@@ -4604,6 +4804,78 @@ ;; esac ;; @@ -853,7 +1363,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 *-*-darwin*) case "$host_cpu" in arm*) -@@ -4694,9 +4879,15 @@ +@@ -4694,9 +4966,15 @@ define_xopen_source=no;; Darwin/[12][0-9].*) define_xopen_source=no;; @@ -870,7 +1380,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 # On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from # defining NI_NUMERICHOST. QNX/6.3.2) -@@ -4759,7 +4950,13 @@ +@@ -4759,7 +5037,17 @@ CONFIGURE_MACOSX_DEPLOYMENT_TARGET= EXPORT_MACOSX_DEPLOYMENT_TARGET='#' @@ -882,10 +1392,14 @@ index 1b75ddfa26d..7b79dfc424c 100755 + + +# XROS_DEPLOYMENT_TARGET should get exported ++ ++ ++# The minimum macOS version that a Mac Catalyst build can run on. ++ # checks for alternative programs -@@ -4800,6 +4997,16 @@ +@@ -4800,6 +5088,16 @@ as_fn_append CFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}" as_fn_append LDFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}" ;; #( @@ -902,7 +1416,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 *) : ;; esac -@@ -7169,6 +7376,12 @@ +@@ -7169,6 +7467,12 @@ MULTIARCH="" ;; #( iOS) : MULTIARCH="" ;; #( @@ -915,7 +1429,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 FreeBSD*) : MULTIARCH="" ;; #( *) : -@@ -7189,7 +7402,7 @@ +@@ -7189,7 +7493,7 @@ printf "%s\n" "$MULTIARCH" >&6; } case $ac_sys_system in #( @@ -924,7 +1438,15 @@ index 1b75ddfa26d..7b79dfc424c 100755 SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2` ;; #( *) : SOABI_PLATFORM=$PLATFORM_TRIPLET -@@ -7240,6 +7453,18 @@ +@@ -7236,10 +7540,26 @@ + PY_SUPPORT_TIER=3 ;; #( + x86_64-*-freebsd*/clang) : + PY_SUPPORT_TIER=3 ;; #( ++ aarch64-apple-ios*-macabi/clang) : ++ PY_SUPPORT_TIER=3 ;; #( ++ x86_64-apple-ios*-macabi/clang) : ++ PY_SUPPORT_TIER=3 ;; #( + aarch64-apple-ios*-simulator/clang) : PY_SUPPORT_TIER=3 ;; #( aarch64-apple-ios*/clang) : PY_SUPPORT_TIER=3 ;; #( @@ -943,7 +1465,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 aarch64-*-linux-android/clang) : PY_SUPPORT_TIER=3 ;; #( x86_64-*-linux-android/clang) : -@@ -7676,7 +7901,7 @@ +@@ -7676,7 +7996,7 @@ case $ac_sys_system in Darwin) LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)';; @@ -952,7 +1474,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 LDLIBRARY='$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)';; *) as_fn_error $? "Unknown platform for framework build" "$LINENO" 5;; -@@ -7742,7 +7967,7 @@ +@@ -7742,7 +8062,7 @@ BLDLIBRARY='-L. -lpython$(LDVERSION)' RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} ;; @@ -961,7 +1483,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 LDLIBRARY='libpython$(LDVERSION).dylib' ;; AIX*) -@@ -13550,7 +13775,7 @@ +@@ -13550,7 +13870,7 @@ BLDSHARED="$LDSHARED" fi ;; @@ -970,7 +1492,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' BLDSHARED="$LDSHARED" -@@ -13683,7 +13908,7 @@ +@@ -13683,7 +14003,7 @@ Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";; Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";; # -u libsys_s pulls in all symbols in libsys @@ -979,7 +1501,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 LINKFORSHARED="$extra_undefs -framework CoreFoundation" # Issue #18075: the default maximum stack size (8MBytes) is too -@@ -13707,7 +13932,7 @@ +@@ -13707,7 +14027,7 @@ LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' fi LINKFORSHARED="$LINKFORSHARED" @@ -988,7 +1510,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' fi ;; -@@ -15292,7 +15517,7 @@ +@@ -15292,7 +15612,7 @@ ctypes_malloc_closure=yes ;; #( @@ -997,7 +1519,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 ctypes_malloc_closure=yes ;; #( -@@ -19044,12 +19269,6 @@ +@@ -19044,12 +19364,6 @@ then : printf "%s\n" "#define HAVE_DUP3 1" >>confdefs.h @@ -1010,7 +1532,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 fi ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero" if test "x$ac_cv_func_explicit_bzero" = xyes -@@ -19110,18 +19329,6 @@ +@@ -19110,18 +19424,6 @@ then : printf "%s\n" "#define HAVE_FEXECVE 1" >>confdefs.h @@ -1029,7 +1551,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 fi ac_fn_c_check_func "$LINENO" "fpathconf" "ac_cv_func_fpathconf" if test "x$ac_cv_func_fpathconf" = xyes -@@ -19548,24 +19755,6 @@ +@@ -19548,24 +19850,6 @@ then : printf "%s\n" "#define HAVE_POSIX_OPENPT 1" >>confdefs.h @@ -1054,7 +1576,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 fi ac_fn_c_check_func "$LINENO" "pread" "ac_cv_func_pread" if test "x$ac_cv_func_pread" = xyes -@@ -19884,12 +20073,6 @@ +@@ -19884,12 +20168,6 @@ then : printf "%s\n" "#define HAVE_SIGACTION 1" >>confdefs.h @@ -1067,7 +1589,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 fi ac_fn_c_check_func "$LINENO" "sigfillset" "ac_cv_func_sigfillset" if test "x$ac_cv_func_sigfillset" = xyes -@@ -20158,11 +20341,11 @@ +@@ -20158,11 +20436,11 @@ fi @@ -1081,7 +1603,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy" if test "x$ac_cv_func_getentropy" = xyes then : -@@ -20184,6 +20367,53 @@ +@@ -20184,6 +20462,53 @@ fi @@ -1135,7 +1657,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } if test ${ac_cv_c_undeclared_builtin_options+y} -@@ -23266,7 +23496,8 @@ +@@ -23266,7 +23591,8 @@ # check for openpty, login_tty, and forkpty @@ -1145,7 +1667,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 for ac_func in openpty do : -@@ -23380,7 +23611,7 @@ +@@ -23380,7 +23706,7 @@ fi done @@ -1154,7 +1676,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 printf %s "checking for library containing login_tty... " >&6; } if test ${ac_cv_search_login_tty+y} then : -@@ -23563,6 +23794,7 @@ +@@ -23563,6 +23889,7 @@ fi done @@ -1162,7 +1684,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 # check for long file support functions ac_fn_c_check_func "$LINENO" "fseek64" "ac_cv_func_fseek64" -@@ -23828,10 +24060,10 @@ +@@ -23828,10 +24155,10 @@ done @@ -1175,7 +1697,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 then for ac_func in clock_settime -@@ -24148,7 +24380,7 @@ +@@ -24148,7 +24475,7 @@ e) if test "$cross_compiling" = yes then : @@ -1184,7 +1706,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 ac_cv_buggy_getaddrinfo="no" elif test "${enable_ipv6+set}" = set; then ac_cv_buggy_getaddrinfo="no -- configured with --(en|dis)able-ipv6" -@@ -26170,8 +26402,8 @@ +@@ -26170,8 +26497,8 @@ LIBPYTHON="\$(BLDLIBRARY)" fi @@ -1195,7 +1717,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 MODULE_DEPS_SHARED="$MODULE_DEPS_SHARED \$(PYTHONFRAMEWORKDIR)/\$(PYTHONFRAMEWORK)" fi -@@ -29041,7 +29273,7 @@ +@@ -29041,7 +29368,7 @@ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for device files" >&5 printf "%s\n" "$as_me: checking for device files" >&6;} @@ -1204,7 +1726,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no else -@@ -29550,7 +29782,7 @@ +@@ -29550,7 +29877,7 @@ with_ensurepip=no ;; #( WASI) : with_ensurepip=no ;; #( @@ -1213,7 +1735,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 with_ensurepip=no ;; #( *) : with_ensurepip=upgrade -@@ -30499,7 +30731,7 @@ +@@ -30499,7 +30826,7 @@ SunOS*) _PYTHREAD_NAME_MAXLEN=31;; NetBSD*) _PYTHREAD_NAME_MAXLEN=15;; # gh-131268 Darwin) _PYTHREAD_NAME_MAXLEN=63;; @@ -1222,18 +1744,36 @@ index 1b75ddfa26d..7b79dfc424c 100755 FreeBSD*) _PYTHREAD_NAME_MAXLEN=19;; # gh-131268 OpenBSD*) _PYTHREAD_NAME_MAXLEN=23;; # gh-131268 *) _PYTHREAD_NAME_MAXLEN=;; -@@ -30531,7 +30763,7 @@ +@@ -30531,8 +30858,15 @@ ;; #( Darwin) : ;; #( - iOS) : + iOS|tvOS|watchOS|visionOS) : ++ case "$_host_device" in ++ macabi) ;; ++ *) ++ ++ py_cv_module__posixsubprocess=n/a ++ ;; ++ esac -@@ -34605,6 +34837,9 @@ + py_cv_module__curses=n/a +@@ -30540,7 +30874,6 @@ + py_cv_module__gdbm=n/a + py_cv_module__multiprocessing=n/a + py_cv_module__posixshmem=n/a +- py_cv_module__posixsubprocess=n/a + py_cv_module__scproxy=n/a + py_cv_module__tkinter=n/a + py_cv_module_grp=n/a +@@ -34604,7 +34937,11 @@ + "Mac/PythonLauncher/Makefile") CONFIG_FILES="$CONFIG_FILES Mac/PythonLauncher/Makefile" ;; "Mac/Resources/framework/Info.plist") CONFIG_FILES="$CONFIG_FILES Mac/Resources/framework/Info.plist" ;; "Mac/Resources/app/Info.plist") CONFIG_FILES="$CONFIG_FILES Mac/Resources/app/Info.plist" ;; ++ "MacCatalyst/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES MacCatalyst/Resources/Info.plist" ;; "iOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES iOS/Resources/Info.plist" ;; + "tvOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES tvOS/Resources/Info.plist" ;; + "watchOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES watchOS/Resources/Info.plist" ;; @@ -1242,7 +1782,7 @@ index 1b75ddfa26d..7b79dfc424c 100755 "Misc/python.pc") CONFIG_FILES="$CONFIG_FILES Misc/python.pc" ;; "Misc/python-embed.pc") CONFIG_FILES="$CONFIG_FILES Misc/python-embed.pc" ;; diff --git a/configure.ac b/configure.ac -index c449bb5ebb3..29b9a82374b 100644 +index c449bb5ebb3..4b5ba577882 100644 --- a/configure.ac +++ b/configure.ac @@ -330,6 +330,15 @@ @@ -1270,10 +1810,17 @@ index c449bb5ebb3..29b9a82374b 100644 # which isn't a binary that exists, and isn't very convenient, as it contains the # iOS version. As the default cross-compiler name won't exist, configure falls # back to gcc, which *definitely* won't work. We're providing wrapper scripts for -@@ -420,6 +429,17 @@ +@@ -417,33 +426,89 @@ + # configure will fail. + if test -z "$AR"; then + case "$host" in ++ x86_64-apple-ios*-macabi) AR=x86_64-apple-ios-macabi-ar ;; ++ aarch64-apple-ios*-macabi) AR=arm64-apple-ios-macabi-ar ;; ++ ++ x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;; aarch64-apple-ios*-simulator) AR=arm64-apple-ios-simulator-ar ;; aarch64-apple-ios*) AR=arm64-apple-ios-ar ;; - x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;; +- x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;; + + aarch64-apple-tvos*-simulator) AR=arm64-apple-tvos-simulator-ar ;; + aarch64-apple-tvos*) AR=arm64-apple-tvos-ar ;; @@ -1288,10 +1835,15 @@ index c449bb5ebb3..29b9a82374b 100644 *) esac fi -@@ -428,6 +448,17 @@ + if test -z "$CC"; then + case "$host" in ++ x86_64-apple-ios*-macabi) CC=x86_64-apple-ios-macabi-clang ;; ++ aarch64-apple-ios*-macabi) CC=arm64-apple-ios-macabi-clang ;; ++ ++ x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;; aarch64-apple-ios*-simulator) CC=arm64-apple-ios-simulator-clang ;; aarch64-apple-ios*) CC=arm64-apple-ios-clang ;; - x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;; +- x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;; + + aarch64-apple-tvos*-simulator) CC=arm64-apple-tvos-simulator-clang ;; + aarch64-apple-tvos*) CC=arm64-apple-tvos-clang ;; @@ -1306,10 +1858,15 @@ index c449bb5ebb3..29b9a82374b 100644 *) esac fi -@@ -436,6 +467,17 @@ + if test -z "$CPP"; then + case "$host" in ++ x86_64-apple-ios*-macabi) CPP=x86_64-apple-ios-macabi-cpp ;; ++ aarch64-apple-ios*-macabi) CPP=arm64-apple-ios-macabi-cpp ;; ++ ++ x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;; aarch64-apple-ios*-simulator) CPP=arm64-apple-ios-simulator-cpp ;; aarch64-apple-ios*) CPP=arm64-apple-ios-cpp ;; - x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;; +- x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;; + + aarch64-apple-tvos*-simulator) CPP=arm64-apple-tvos-simulator-cpp ;; + aarch64-apple-tvos*) CPP=arm64-apple-tvos-cpp ;; @@ -1324,10 +1881,15 @@ index c449bb5ebb3..29b9a82374b 100644 *) esac fi -@@ -444,6 +486,17 @@ + if test -z "$CXX"; then + case "$host" in ++ x86_64-apple-ios*-macabi) CXX=x86_64-apple-ios-macabi-clang++ ;; ++ aarch64-apple-ios*-macabi) CXX=arm64-apple-ios-macabi-clang++ ;; ++ ++ x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;; aarch64-apple-ios*-simulator) CXX=arm64-apple-ios-simulator-clang++ ;; aarch64-apple-ios*) CXX=arm64-apple-ios-clang++ ;; - x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;; +- x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;; + + aarch64-apple-tvos*-simulator) CXX=arm64-apple-tvos-simulator-clang++ ;; + aarch64-apple-tvos*) CXX=arm64-apple-tvos-clang++ ;; @@ -1342,7 +1904,7 @@ index c449bb5ebb3..29b9a82374b 100644 *) esac fi -@@ -558,8 +611,11 @@ +@@ -558,8 +623,11 @@ case $enableval in yes) case $ac_sys_system in @@ -1356,7 +1918,7 @@ index c449bb5ebb3..29b9a82374b 100644 *) AC_MSG_ERROR([Unknown platform for framework build]) esac esac -@@ -568,6 +624,9 @@ +@@ -568,6 +636,9 @@ no) case $ac_sys_system in iOS) AC_MSG_ERROR([iOS builds must use --enable-framework]) ;; @@ -1366,22 +1928,50 @@ index c449bb5ebb3..29b9a82374b 100644 *) PYTHONFRAMEWORK= PYTHONFRAMEWORKDIR=no-framework -@@ -670,6 +729,48 @@ - - AC_CONFIG_FILES([iOS/Resources/Info.plist]) +@@ -657,6 +728,35 @@ + AC_CONFIG_FILES([Mac/Resources/app/Info.plist]) ;; + iOS) : ++ _flag_ios_catalyst=`echo $host | cut -d '-' -f4` ++ case $_flag_ios_catalyst in ++ macabi) ++ FRAMEWORKINSTALLFIRST="frameworkinstallversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallversionedstructure " ++ FRAMEWORKINSTALLLAST="" ++ FRAMEWORKALTINSTALLLAST="" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++ prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR/Versions/$VERSION" ++ RESSRCDIR=MacCatalyst/Resources ++ AC_CONFIG_FILES([MacCatalyst/Resources/Info.plist]) ++ ;; ++ *) ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=iOS/Resources ++ AC_CONFIG_FILES([iOS/Resources/Info.plist]) ++ ;; ++ esac ++ ;; + tvOS) : -+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " -+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKPYTHONW= -+ INSTALLTARGETS="libinstall inclinstall sharedinstall" -+ -+ prefix=$PYTHONFRAMEWORKPREFIX -+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" + FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" + FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " + FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" +@@ -666,9 +766,37 @@ + + prefix=$PYTHONFRAMEWORKPREFIX + PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" +- RESSRCDIR=iOS/Resources + RESSRCDIR=tvOS/Resources -+ + +- AC_CONFIG_FILES([iOS/Resources/Info.plist]) + AC_CONFIG_FILES([tvOS/Resources/Info.plist]) + ;; + watchOS) : @@ -1411,11 +2001,10 @@ index c449bb5ebb3..29b9a82374b 100644 + RESSRCDIR=visionOS/Resources + + AC_CONFIG_FILES([visionOS/Resources/Info.plist]) -+ ;; + ;; *) AC_MSG_ERROR([Unknown platform for framework build]) - ;; -@@ -678,6 +779,9 @@ +@@ -678,6 +806,9 @@ ],[ case $ac_sys_system in iOS) AC_MSG_ERROR([iOS builds must use --enable-framework]) ;; @@ -1425,7 +2014,7 @@ index c449bb5ebb3..29b9a82374b 100644 *) PYTHONFRAMEWORK= PYTHONFRAMEWORKDIR=no-framework -@@ -730,8 +834,8 @@ +@@ -730,8 +861,8 @@ case "$withval" in yes) case $ac_sys_system in @@ -1436,7 +2025,7 @@ index c449bb5ebb3..29b9a82374b 100644 APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" ;; *) AC_MSG_ERROR([no default app store compliance patch available for $ac_sys_system]) ;; -@@ -745,8 +849,8 @@ +@@ -745,8 +876,8 @@ esac ],[ case $ac_sys_system in @@ -1447,16 +2036,70 @@ index c449bb5ebb3..29b9a82374b 100644 APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" AC_MSG_RESULT([applying default app store compliance patch]) ;; -@@ -759,6 +863,8 @@ +@@ -759,6 +890,35 @@ ]) AC_SUBST([APP_STORE_COMPLIANCE_PATCH]) ++ ++AC_ARG_WITH([catalyst-macos-version], ++ [AS_HELP_STRING([--with-catalyst-macos-version=VER], ++ [The minimum macOS version a Catalyst build can run on (only valid for *-apple-ios*-macabi targets)])], ++ [case "$host" in ++ *-apple-ios*-macabi) ++ CATALYST_MACOS_VERSION="$withval" ++ ;; ++ *) ++ AC_MSG_ERROR([--with-catalyst-macos-version is only valid when targeting Mac Catalyst (*-apple-ios*-macabi).]) ++ ;; ++ esac ++ ], ++ [case "$host" in ++ *-apple-ios*-macabi) ++ CATALYST_MACOS_VERSION=11.2 ++ ;; ++ *) ++ CATALYST_MACOS_VERSION= ++ ;; ++ esac ++ ] ++) ++ ++ ++ ++ +EXPORT_XROS_DEPLOYMENT_TARGET='#' + AC_SUBST([_PYTHON_HOST_PLATFORM]) if test "$cross_compiling" = yes; then case "$host" in -@@ -794,6 +900,70 @@ +@@ -774,6 +934,26 @@ + *-*-cygwin*) + _host_ident= + ;; ++ *-apple-ios*-macabi) ++ _host_os=`echo $host | cut -d '-' -f3` ++ _host_device=`echo $host | cut -d '-' -f4` # should be macabi ++ _host_device=${_host_device:=os} ++ ++ # IPHONEOS_DEPLOYMENT_TARGET is the minimum supported iOS version ++ AC_MSG_CHECKING([iOS deployment target]) ++ IPHONEOS_DEPLOYMENT_TARGET=$(echo ${_host_os} | cut -c4-) ++ IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET:=14.2} # else it returns invalid version number ++ AC_MSG_RESULT([$IPHONEOS_DEPLOYMENT_TARGET]) ++ ++ case "$host_cpu" in ++ aarch64) ++ _host_ident=${IPHONEOS_DEPLOYMENT_TARGET}-arm64-iphoneos-${_host_device} # platform_triplet.c uses iphoneos-macabi ++ ;; ++ *) ++ _host_ident=${IPHONEOS_DEPLOYMENT_TARGET}-$host_cpu-iphoneos-${_host_device} ++ ;; ++ esac ++ ;; + *-apple-ios*) + _host_os=`echo $host | cut -d '-' -f3` + _host_device=`echo $host | cut -d '-' -f4` +@@ -794,6 +974,70 @@ ;; esac ;; @@ -1527,7 +2170,7 @@ index c449bb5ebb3..29b9a82374b 100644 *-*-darwin*) case "$host_cpu" in arm*) -@@ -883,9 +1053,15 @@ +@@ -883,9 +1127,15 @@ define_xopen_source=no;; Darwin/@<:@[12]@:>@@<:@0-9@:>@.*) define_xopen_source=no;; @@ -1544,7 +2187,7 @@ index c449bb5ebb3..29b9a82374b 100644 # On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from # defining NI_NUMERICHOST. QNX/6.3.2) -@@ -944,8 +1120,14 @@ +@@ -944,8 +1194,18 @@ CONFIGURE_MACOSX_DEPLOYMENT_TARGET= EXPORT_MACOSX_DEPLOYMENT_TARGET='#' @@ -1557,10 +2200,14 @@ index c449bb5ebb3..29b9a82374b 100644 +AC_SUBST([XROS_DEPLOYMENT_TARGET]) +# XROS_DEPLOYMENT_TARGET should get exported +AC_SUBST([EXPORT_XROS_DEPLOYMENT_TARGET]) ++ ++# The minimum macOS version that a Mac Catalyst build can run on. ++AC_SUBST([CATALYST_MACOS_VERSION]) ++ # checks for alternative programs -@@ -979,11 +1161,19 @@ +@@ -979,11 +1239,19 @@ ], ) @@ -1581,7 +2228,7 @@ index c449bb5ebb3..29b9a82374b 100644 ], ) -@@ -1172,6 +1362,9 @@ +@@ -1172,6 +1440,9 @@ AS_CASE([$ac_sys_system], [Darwin*], [MULTIARCH=""], [iOS], [MULTIARCH=""], @@ -1591,7 +2238,7 @@ index c449bb5ebb3..29b9a82374b 100644 [FreeBSD*], [MULTIARCH=""], [MULTIARCH=$($CC --print-multiarch 2>/dev/null)] ) -@@ -1193,7 +1386,7 @@ +@@ -1193,7 +1464,7 @@ dnl use a single "fat" binary at runtime. SOABI_PLATFORM is the component of dnl the PLATFORM_TRIPLET that will be used in binary module extensions. AS_CASE([$ac_sys_system], @@ -1600,8 +2247,12 @@ index c449bb5ebb3..29b9a82374b 100644 [SOABI_PLATFORM=$PLATFORM_TRIPLET] ) -@@ -1227,6 +1420,12 @@ +@@ -1225,8 +1496,16 @@ + [powerpc64le-*-linux-gnu/clang], [PY_SUPPORT_TIER=3], dnl Linux on PPC64 little endian, glibc, clang + [s390x-*-linux-gnu/gcc], [PY_SUPPORT_TIER=3], dnl Linux on 64bit s390x (big endian), glibc, gcc [x86_64-*-freebsd*/clang], [PY_SUPPORT_TIER=3], dnl FreeBSD on AMD64 ++ [aarch64-apple-ios*-macabi/clang], [PY_SUPPORT_TIER=3], dnl MacCatalyst on arm64 ++ [x86_64-apple-ios*-macabi/clang], [PY_SUPPORT_TIER=3], dnl MacCatalyst on x86_64 [aarch64-apple-ios*-simulator/clang], [PY_SUPPORT_TIER=3], dnl iOS Simulator on arm64 [aarch64-apple-ios*/clang], [PY_SUPPORT_TIER=3], dnl iOS on ARM64 + [aarch64-apple-tvos*-simulator/clang], [PY_SUPPORT_TIER=3], dnl tvOS Simulator on arm64 @@ -1613,7 +2264,7 @@ index c449bb5ebb3..29b9a82374b 100644 [aarch64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on ARM64 [x86_64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on AMD64 -@@ -1536,7 +1735,7 @@ +@@ -1536,7 +1815,7 @@ case $ac_sys_system in Darwin) LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)';; @@ -1622,7 +2273,7 @@ index c449bb5ebb3..29b9a82374b 100644 LDLIBRARY='$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)';; *) AC_MSG_ERROR([Unknown platform for framework build]);; -@@ -1601,7 +1800,7 @@ +@@ -1601,7 +1880,7 @@ BLDLIBRARY='-L. -lpython$(LDVERSION)' RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} ;; @@ -1631,7 +2282,7 @@ index c449bb5ebb3..29b9a82374b 100644 LDLIBRARY='libpython$(LDVERSION).dylib' ;; AIX*) -@@ -3456,7 +3655,7 @@ +@@ -3456,7 +3735,7 @@ BLDSHARED="$LDSHARED" fi ;; @@ -1640,7 +2291,7 @@ index c449bb5ebb3..29b9a82374b 100644 LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' BLDSHARED="$LDSHARED" -@@ -3580,7 +3779,7 @@ +@@ -3580,7 +3859,7 @@ Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";; Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";; # -u libsys_s pulls in all symbols in libsys @@ -1649,7 +2300,7 @@ index c449bb5ebb3..29b9a82374b 100644 LINKFORSHARED="$extra_undefs -framework CoreFoundation" # Issue #18075: the default maximum stack size (8MBytes) is too -@@ -3604,7 +3803,7 @@ +@@ -3604,7 +3883,7 @@ LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' fi LINKFORSHARED="$LINKFORSHARED" @@ -1658,7 +2309,7 @@ index c449bb5ebb3..29b9a82374b 100644 LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' fi ;; -@@ -4024,7 +4223,7 @@ +@@ -4024,7 +4303,7 @@ dnl when do we need USING_APPLE_OS_LIBFFI? ctypes_malloc_closure=yes ], @@ -1667,7 +2318,7 @@ index c449bb5ebb3..29b9a82374b 100644 ctypes_malloc_closure=yes ], [sunos5], [AS_VAR_APPEND([LIBFFI_LIBS], [" -mimpure-text"])] -@@ -5133,9 +5332,9 @@ +@@ -5133,9 +5412,9 @@ # checks for library functions AC_CHECK_FUNCS([ \ accept4 alarm bind_textdomain_codeset chmod chown clock closefrom close_range confstr \ @@ -1679,7 +2330,7 @@ index c449bb5ebb3..29b9a82374b 100644 gai_strerror getegid geteuid getgid getgrent getgrgid getgrgid_r \ getgrnam_r getgrouplist gethostname getitimer getloadavg getlogin \ getpeername getpgid getpid getppid getpriority _getpty \ -@@ -5143,8 +5342,7 @@ +@@ -5143,8 +5422,7 @@ getspnam getuid getwd grantpt if_nameindex initgroups kill killpg lchown linkat \ lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \ mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \ @@ -1689,7 +2340,7 @@ index c449bb5ebb3..29b9a82374b 100644 pread preadv preadv2 process_vm_readv \ pthread_cond_timedwait_relative_np pthread_condattr_setclock pthread_init \ pthread_kill pthread_get_name_np pthread_getname_np pthread_set_name_np -@@ -5154,7 +5352,7 @@ +@@ -5154,7 +5432,7 @@ sched_setparam sched_setscheduler sem_clockwait sem_getvalue sem_open \ sem_timedwait sem_unlink sendfile setegid seteuid setgid sethostname \ setitimer setlocale setpgid setpgrp setpriority setregid setresgid \ @@ -1698,7 +2349,7 @@ index c449bb5ebb3..29b9a82374b 100644 sigfillset siginterrupt sigpending sigrelse sigtimedwait sigwait \ sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \ sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \ -@@ -5169,12 +5367,20 @@ +@@ -5169,12 +5447,20 @@ AC_CHECK_FUNCS([lchmod]) fi @@ -1722,7 +2373,7 @@ index c449bb5ebb3..29b9a82374b 100644 fi AC_CHECK_DECL([dirfd], -@@ -5428,20 +5634,22 @@ +@@ -5428,20 +5714,22 @@ ]) # check for openpty, login_tty, and forkpty @@ -1759,7 +2410,7 @@ index c449bb5ebb3..29b9a82374b 100644 # check for long file support functions AC_CHECK_FUNCS([fseek64 fseeko fstatvfs ftell64 ftello statvfs]) -@@ -5480,10 +5688,10 @@ +@@ -5480,10 +5768,10 @@ ]) ]) @@ -1772,7 +2423,7 @@ index c449bb5ebb3..29b9a82374b 100644 then AC_CHECK_FUNCS([clock_settime], [], [ AC_CHECK_LIB([rt], [clock_settime], [ -@@ -5641,7 +5849,7 @@ +@@ -5641,7 +5929,7 @@ [ac_cv_buggy_getaddrinfo=no], [ac_cv_buggy_getaddrinfo=yes], [ @@ -1781,7 +2432,7 @@ index c449bb5ebb3..29b9a82374b 100644 ac_cv_buggy_getaddrinfo="no" elif test "${enable_ipv6+set}" = set; then ac_cv_buggy_getaddrinfo="no -- configured with --(en|dis)able-ipv6" -@@ -6234,8 +6442,8 @@ +@@ -6234,8 +6522,8 @@ LIBPYTHON="\$(BLDLIBRARY)" fi @@ -1792,7 +2443,7 @@ index c449bb5ebb3..29b9a82374b 100644 MODULE_DEPS_SHARED="$MODULE_DEPS_SHARED \$(PYTHONFRAMEWORKDIR)/\$(PYTHONFRAMEWORK)" fi -@@ -6894,7 +7102,7 @@ +@@ -6894,7 +7182,7 @@ dnl NOTE: Inform user how to proceed with files when cross compiling. dnl Some cross-compile builds are predictable; they won't ever dnl have /dev/ptmx or /dev/ptc, so we can set them explicitly. @@ -1801,7 +2452,7 @@ index c449bb5ebb3..29b9a82374b 100644 ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no else -@@ -7195,7 +7403,7 @@ +@@ -7195,7 +7483,7 @@ AS_CASE([$ac_sys_system], [Emscripten], [with_ensurepip=no], [WASI], [with_ensurepip=no], @@ -1810,7 +2461,7 @@ index c449bb5ebb3..29b9a82374b 100644 [with_ensurepip=upgrade] ) ]) -@@ -7582,7 +7790,7 @@ +@@ -7582,7 +7870,7 @@ SunOS*) _PYTHREAD_NAME_MAXLEN=31;; NetBSD*) _PYTHREAD_NAME_MAXLEN=15;; # gh-131268 Darwin) _PYTHREAD_NAME_MAXLEN=63;; @@ -1819,7 +2470,7 @@ index c449bb5ebb3..29b9a82374b 100644 FreeBSD*) _PYTHREAD_NAME_MAXLEN=19;; # gh-131268 OpenBSD*) _PYTHREAD_NAME_MAXLEN=23;; # gh-131268 *) _PYTHREAD_NAME_MAXLEN=;; -@@ -7607,7 +7815,7 @@ +@@ -7607,18 +7895,22 @@ [VxWorks*], [PY_STDLIB_MOD_SET_NA([_scproxy], [termios], [grp])], dnl The _scproxy module is available on macOS [Darwin], [], @@ -1828,6 +2479,22 @@ index c449bb5ebb3..29b9a82374b 100644 dnl subprocess and multiprocessing are not supported (no fork syscall). dnl curses and tkinter user interface are not available. dnl gdbm and nis aren't available + dnl Stub implementations are provided for pwd, grp etc APIs ++ dnl subprocess is however supported for Mac Catalyst ++ case "$_host_device" in ++ macabi) ;; ++ *) PY_STDLIB_MOD_SET_NA([_posixsubprocess]) ;; ++ esac + PY_STDLIB_MOD_SET_NA( + [_curses], + [_curses_panel], + [_gdbm], + [_multiprocessing], + [_posixshmem], +- [_posixsubprocess], + [_scproxy], + [_tkinter], + [grp], diff --git a/iOS/Resources/Info.plist.in b/iOS/Resources/Info.plist.in index c3e261ecd9e..26ef7a95de4 100644 --- a/iOS/Resources/Info.plist.in @@ -1848,6 +2515,458 @@ index c3e261ecd9e..26ef7a95de4 100644 CFBundleSupportedPlatforms iPhoneOS +diff --git a/iOS/testbed/Python.xcframework/Info.plist b/iOS/testbed/Python.xcframework/Info.plist +index c6418de6e74..7b32df19ab4 100644 +--- a/iOS/testbed/Python.xcframework/Info.plist ++++ b/iOS/testbed/Python.xcframework/Info.plist +@@ -4,6 +4,23 @@ + + AvailableLibraries + ++ ++ BinaryPath ++ Python.framework/Versions/Latest/Python ++ LibraryIdentifier ++ ios-arm64_x86_64-maccatalyst ++ LibraryPath ++ python.framework ++ SupportedArchitectures ++ ++ x86_64 ++ arm64 ++ ++ SupportedPlatform ++ ios ++ SupportedPlatformVariant ++ maccatalyst ++ + + BinaryPath + Python.framework/Python +--- /dev/null ++++ b/iOS/testbed/Python.xcframework/ios-arm64_x86_64-maccatalyst/README +@@ -0,0 +1,4 @@ ++This directory is intentionally empty. ++ ++It is a placeholder slice for the XCFramework on Mac Catalyst, ++to install or copy your built framework to. +diff --git a/iOS/testbed/__main__.py b/iOS/testbed/__main__.py +index b436c9af99d..9ef96075a01 100644 +--- a/iOS/testbed/__main__.py ++++ b/iOS/testbed/__main__.py +@@ -28,6 +28,15 @@ + r"\s+\(Python\)\s" # Logger name + ) + ++# Prefix: 2025-04-27 21:43:38.530606-0500 iOSTestbed[96892:48053672] ++CATALYST_LOG_PREFIX_REGEX = re.compile( ++ r"^\d{4}-\d{2}-\d{2}" # YYYY-MM-DD ++ r"\s+\d{2}:\d{2}:\d{2}\.\d{6}" # HH:MM:SS.ssssss (microseconds, 6 digits) ++ r"[-+]\d{4}" # Timezone offset like -0500 ++ r"\s+iOSTestbed\[\d+:\d+\] " # iOSTestbed[ProcessID:ThreadID] (both numbers), then a space ++) ++ ++ + + # Work around a bug involving sys.exit and TaskGroups + # (https://github.com/python/cpython/issues/101515). +@@ -213,9 +222,13 @@ + sys.stdout.flush() + + +-async def xcode_test(location, simulator, verbose): ++async def xcode_test(location, simulator, verbose, catalyst): + # Run the test suite on the named simulator + print("Starting xcodebuild...", flush=True) ++ if catalyst: ++ destination_arg = "platform=macOS,variant=Mac Catalyst" ++ else: ++ destination_arg = f"platform=iOS Simulator,name={simulator}"; + args = [ + "xcodebuild", + "test", +@@ -224,13 +237,13 @@ + "-scheme", + "iOSTestbed", + "-destination", +- f"platform=iOS Simulator,name={simulator}", ++ destination_arg, + "-resultBundlePath", + str(location / f"{datetime.now():%Y%m%d-%H%M%S}.xcresult"), + "-derivedDataPath", + str(location / "DerivedData"), + ] +- if not verbose: ++ if not verbose and not catalyst: + args += ["-quiet"] + + async with async_process( +@@ -239,8 +252,16 @@ + stderr=subprocess.STDOUT, + ) as process: + while line := (await process.stdout.readline()).decode(*DECODE_ARGS): +- sys.stdout.write(line) +- sys.stdout.flush() ++ # For Mac Catalyst, the *actual* logs are streamed here. Only stream ++ # things that does NOT come from the process when verbose. ++ if catalyst: ++ if CATALYST_LOG_PREFIX_REGEX.match(line) or verbose: ++ line = CATALYST_LOG_PREFIX_REGEX.sub("", line) ++ sys.stdout.write(line) ++ sys.stdout.flush() ++ else: ++ sys.stdout.write(line) ++ sys.stdout.flush() + + status = await asyncio.wait_for(process.wait(), timeout=1) + exit(status) +@@ -251,20 +272,31 @@ + target: Path, + framework: Path, + apps: list[Path], ++ catalyst: bool, + ) -> None: + if target.exists(): + print(f"{target} already exists; aborting without creating project.") + sys.exit(10) + + if framework is None: +- if not ( +- source / "Python.xcframework/ios-arm64_x86_64-simulator/bin" +- ).is_dir(): +- print( +- f"The testbed being cloned ({source}) does not contain " +- f"a simulator framework. Re-run with --framework" +- ) +- sys.exit(11) ++ if catalyst: ++ if not ( ++ source / "Python.xcframework/ios-arm64_x86_64-maccatalyst/Python.framework/Versions" ++ ).is_dir(): ++ print( ++ f"The testbed being cloned ({source}) does not contain " ++ f"a Mac Catalyst framework. Re-run with --framework" ++ ) ++ sys.exit(11) ++ else: ++ if not ( ++ source / "Python.xcframework/ios-arm64_x86_64-simulator/bin" ++ ).is_dir(): ++ print( ++ f"The testbed being cloned ({source}) does not contain " ++ f"a simulator framework. Re-run with --framework" ++ ) ++ sys.exit(11) + else: + if not framework.is_dir(): + print(f"{framework} does not exist.") +@@ -275,7 +307,7 @@ + ): + print( + f"{framework} is not an XCframework, " +- f"or a simulator slice of a framework build." ++ f"or a simulator / Catalyst slice of a framework build." + ) + sys.exit(13) + +@@ -285,7 +317,10 @@ + print(" done") + + xc_framework_path = target / "Python.xcframework" +- sim_framework_path = xc_framework_path / "ios-arm64_x86_64-simulator" ++ if catalyst: ++ sim_framework_path = xc_framework_path / "ios-arm64_x86_64-maccatalyst" ++ else: ++ sim_framework_path = xc_framework_path / "ios-arm64_x86_64-simulator" + if framework is not None: + if framework.suffix == ".xcframework": + print(" Installing XCFramework...", end="", flush=True) +@@ -298,7 +333,7 @@ + ) + print(" done") + else: +- print(" Installing simulator framework...", end="", flush=True) ++ print(" Installing simulator/catalyst framework...", end="", flush=True) + if sim_framework_path.is_dir(): + shutil.rmtree(sim_framework_path) + else: +@@ -330,7 +365,7 @@ + sim_framework_path.is_symlink() + and not sim_framework_path.readlink().is_absolute() + ): +- print(" Rewriting symlink to simulator framework...", end="", flush=True) ++ print(" Rewriting symlink to simulator/catalyst framework...", end="", flush=True) + # Simulator framework is a relative symlink. Rewrite the symlink + # relative to the new location. + orig_sim_framework_path = ( +@@ -371,38 +406,42 @@ + plistlib.dump(info, f) + + +-async def run_testbed(simulator: str, args: list[str], verbose: bool=False): ++async def run_testbed(simulator: str, args: list[str], catalyst: bool, verbose: bool=False): + location = Path(__file__).parent + print("Updating plist...", end="", flush=True) + update_plist(location, args) + print(" done.", flush=True) + +- # We need to get an exclusive lock on simulator creation, to avoid issues +- # with multiple simulators starting and being unable to tell which +- # simulator is due to which testbed instance. See +- # https://github.com/python/cpython/issues/130294 for details. Wait up to +- # 10 minutes for a simulator to boot. +- print("Obtaining lock on simulator creation...", flush=True) +- simulator_lock = SimulatorLock(timeout=10*60) +- await simulator_lock.acquire() +- print("Simulator lock acquired.", flush=True) +- +- # Get the list of devices that are booted at the start of the test run. +- # The simulator started by the test suite will be detected as the new +- # entry that appears on the device list. +- initial_devices = await list_devices() +- +- try: ++ if not catalyst: ++ # We need to get an exclusive lock on simulator creation, to avoid issues ++ # with multiple simulators starting and being unable to tell which ++ # simulator is due to which testbed instance. See ++ # https://github.com/python/cpython/issues/130294 for details. Wait up to ++ # 10 minutes for a simulator to boot. ++ print("Obtaining lock on simulator creation...", flush=True) ++ simulator_lock = SimulatorLock(timeout=10*60) ++ await simulator_lock.acquire() ++ print("Simulator lock acquired.", flush=True) ++ ++ # Get the list of devices that are booted at the start of the test run. ++ # The simulator started by the test suite will be detected as the new ++ # entry that appears on the device list. ++ initial_devices = await list_devices() ++ ++ try: ++ async with asyncio.TaskGroup() as tg: ++ tg.create_task(log_stream_task(initial_devices, simulator_lock)) ++ tg.create_task(xcode_test(location, simulator=simulator, verbose=verbose, catalyst=False)) ++ except* MySystemExit as e: ++ raise SystemExit(*e.exceptions[0].args) from None ++ except* subprocess.CalledProcessError as e: ++ # Extract it from the ExceptionGroup so it can be handled by `main`. ++ raise e.exceptions[0] ++ finally: ++ simulator_lock.release() ++ else: + async with asyncio.TaskGroup() as tg: +- tg.create_task(log_stream_task(initial_devices, simulator_lock)) +- tg.create_task(xcode_test(location, simulator=simulator, verbose=verbose)) +- except* MySystemExit as e: +- raise SystemExit(*e.exceptions[0].args) from None +- except* subprocess.CalledProcessError as e: +- # Extract it from the ExceptionGroup so it can be handled by `main`. +- raise e.exceptions[0] +- finally: +- simulator_lock.release() ++ tg.create_task(xcode_test(location, simulator="", verbose=verbose, catalyst=True)) + + + def main(): +@@ -414,6 +453,12 @@ + + subcommands = parser.add_subparsers(dest="subcommand") + ++ parser.add_argument( ++ "--catalyst", ++ action="store_true", ++ help="Use Mac Catalyst.", ++ ) ++ + clone = subcommands.add_parser( + "clone", + description=( +@@ -478,11 +523,16 @@ + target=Path(context.location).resolve(), + framework=Path(context.framework).resolve() if context.framework else None, + apps=[Path(app) for app in context.apps], ++ catalyst = context.catalyst + ) + elif context.subcommand == "run": + if test_args: ++ if context.catalyst: ++ expected_location = "Python.xcframework/ios-arm64_x86_64-maccatalyst/Python.framework" ++ else: ++ expected_location = "Python.xcframework/ios-arm64_x86_64-simulator/bin" + if not ( +- Path(__file__).parent / "Python.xcframework/ios-arm64_x86_64-simulator/bin" ++ Path(__file__).parent / expected_location + ).is_dir(): + print( + f"Testbed does not contain a compiled iOS framework. Use " +@@ -494,8 +544,10 @@ + asyncio.run( + run_testbed( + simulator=context.simulator, ++ # Mac catalyst requires verbose, or no logs will print. + verbose=context.verbose, + args=test_args, ++ catalyst=context.catalyst + ) + ) + else: +diff --git a/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj b/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj +index c7d63909ee2..ace08f7efd9 100644 +--- a/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj ++++ b/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj +@@ -70,6 +70,7 @@ + 607A66592B0F08600010BFC8 /* iOSTestbed-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "iOSTestbed-Info.plist"; sourceTree = ""; }; + 608619532CB77BA900F46182 /* app_packages */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app_packages; sourceTree = ""; }; + 608619552CB7819B00F46182 /* app */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app; sourceTree = ""; }; ++ EE325B2A2DBE97CD000142D0 /* iOSTestbed.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = iOSTestbed.entitlements; sourceTree = ""; }; + /* End PBXFileReference section */ + + /* Begin PBXFrameworksBuildPhase section */ +@@ -115,6 +116,7 @@ + 607A66142B0EFA380010BFC8 /* iOSTestbed */ = { + isa = PBXGroup; + children = ( ++ EE325B2A2DBE97CD000142D0 /* iOSTestbed.entitlements */, + 608619552CB7819B00F46182 /* app */, + 608619532CB77BA900F46182 /* app_packages */, + 607A66592B0F08600010BFC8 /* iOSTestbed-Info.plist */, +@@ -262,7 +264,7 @@ + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; +- shellScript = "set -e\n\nmkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-iphonesimulator\" ]; then\n echo \"Installing Python modules for iOS Simulator\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-simulator/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nelse\n echo \"Installing Python modules for iOS Device\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nfi\n"; ++ shellScript = "set -e\n\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-iphonesimulator\" ]; then\n mkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\n echo \"Installing Python modules for iOS Simulator\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-simulator/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nelif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-maccatalyst\" ]; then\n mkdir -p \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python/lib\"\n echo \"Installing Python modules for Mac Catalyst\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-maccatalyst/Python.framework/Versions/3.14/lib/\" \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python/lib/\"\nelse\n mkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\n echo \"Installing Python modules for iOS Device\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\"\nfi\n"; + showEnvVarsInLog = 0; + }; + 607A66562B0F06200010BFC8 /* Prepare Python Binary Modules */ = { +@@ -282,7 +284,7 @@ + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; +- shellScript = "set -e\n\ninstall_dylib () {\n INSTALL_BASE=$1\n FULL_EXT=$2\n\n # The name of the extension file\n EXT=$(basename \"$FULL_EXT\")\n # The location of the extension file, relative to the bundle\n RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/} \n # The path to the extension file, relative to the install base\n PYTHON_EXT=${RELATIVE_EXT/$INSTALL_BASE/}\n # The full dotted name of the extension module, constructed from the file path.\n FULL_MODULE_NAME=$(echo $PYTHON_EXT | cut -d \".\" -f 1 | tr \"/\" \".\"); \n # A bundle identifier; not actually used, but required by Xcode framework packaging\n FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr \"_\" \"-\")\n # The name of the framework folder.\n FRAMEWORK_FOLDER=\"Frameworks/$FULL_MODULE_NAME.framework\"\n\n # If the framework folder doesn't exist, create it.\n if [ ! -d \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\" ]; then\n echo \"Creating framework for $RELATIVE_EXT\" \n mkdir -p \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\"\n cp \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleExecutable -string \"$FULL_MODULE_NAME\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleIdentifier -string \"$FRAMEWORK_BUNDLE_ID\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n fi\n \n echo \"Installing binary for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" \n mv \"$FULL_EXT\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\"\n # Create a placeholder .fwork file where the .so was\n echo \"$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" > ${FULL_EXT%.so}.fwork\n # Create a back reference to the .so file location in the framework\n echo \"${RELATIVE_EXT%.so}.fwork\" > \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin\" \n}\n\nPYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/python/lib\")\necho \"Install Python $PYTHON_VER standard library extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/python/lib/$PYTHON_VER/lib-dynload\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib python/lib/$PYTHON_VER/lib-dynload/ \"$FULL_EXT\"\ndone\necho \"Install app package extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/app_packages\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app_packages/ \"$FULL_EXT\"\ndone\necho \"Install app extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/app\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app/ \"$FULL_EXT\"\ndone\n\n# Clean up dylib template \nrm -f \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\"\necho \"Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)...\"\nfind \"$CODESIGNING_FOLDER_PATH/Frameworks\" -name \"*.framework\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der \"{}\" \\; \n"; ++ shellScript = "set -e\n\ninstall_dylib () {\n INSTALL_BASE=$1\n FULL_EXT=$2\n\n # The name of the extension file\n EXT=$(basename \"$FULL_EXT\")\n # The location of the extension file, relative to the bundle\n RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/} \n # The path to the extension file, relative to the install base\n PYTHON_EXT=${RELATIVE_EXT/$INSTALL_BASE/}\n # The full dotted name of the extension module, constructed from the file path.\n FULL_MODULE_NAME=$(echo $PYTHON_EXT | cut -d \".\" -f 1 | tr \"/\" \".\"); \n # A bundle identifier; not actually used, but required by Xcode framework packaging\n FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr \"_\" \"-\")\n # The name of the framework folder.\n FRAMEWORK_FOLDER=\"Frameworks/$FULL_MODULE_NAME.framework\"\n\n # If the framework folder doesn't exist, create it.\n if [ ! -d \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\" ]; then\n echo \"Creating framework for $RELATIVE_EXT\" \n mkdir -p \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\"\n cp \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleExecutable -string \"$FULL_MODULE_NAME\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleIdentifier -string \"$FRAMEWORK_BUNDLE_ID\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n fi\n \n echo \"Installing binary for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" \n mv \"$FULL_EXT\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\"\n # Create a placeholder .fwork file where the .so was\n echo \"$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" > ${FULL_EXT%.so}.fwork\n # Create a back reference to the .so file location in the framework\n echo \"${RELATIVE_EXT%.so}.fwork\" > \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin\" \n}\n\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-maccatalyst\" ]; then\n PYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python/lib\")\n find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python/lib/$PYTHON_VER/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 {} \\;\n find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/app_packages\" -name \"*.so\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/app\" -name \"*.so\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n \nelse\n PYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/python/lib\")\n echo \"Install Python $PYTHON_VER standard library extension modules...\"\n find \"$CODESIGNING_FOLDER_PATH/python/lib/$PYTHON_VER/lib-dynload\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib python/lib/$PYTHON_VER/lib-dynload/ \"$FULL_EXT\"\n done\n echo \"Install app package extension modules...\"\n find \"$CODESIGNING_FOLDER_PATH/app_packages\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app_packages/ \"$FULL_EXT\"\n done\n echo \"Install app extension modules...\"\n find \"$CODESIGNING_FOLDER_PATH/app\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app/ \"$FULL_EXT\"\n done\n\n # Clean up dylib template \n rm -f \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\"\n echo \"Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)...\"\n find \"$CODESIGNING_FOLDER_PATH/Frameworks\" -name \"*.framework\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der \"{}\" \\; \nfi\n"; + showEnvVarsInLog = 0; + }; + /* End PBXShellScriptBuildPhase section */ +@@ -362,6 +364,7 @@ + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; ++ ENABLE_HARDENED_RUNTIME = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; +@@ -381,6 +384,7 @@ + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; ++ MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; +@@ -423,6 +427,7 @@ + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ ENABLE_HARDENED_RUNTIME = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; +@@ -436,6 +441,7 @@ + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; ++ MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; +@@ -449,9 +455,12 @@ + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; ++ CODE_SIGN_ENTITLEMENTS = iOSTestbed/iOSTestbed.entitlements; ++ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; ++ ENABLE_HARDENED_RUNTIME = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\""; + INFOPLIST_FILE = "iOSTestbed/iOSTestbed-Info.plist"; +@@ -468,6 +477,9 @@ + MARKETING_VERSION = 3.13.0a1; + PRODUCT_BUNDLE_IDENTIFIER = org.python.iOSTestbed; + PRODUCT_NAME = "$(TARGET_NAME)"; ++ PROVISIONING_PROFILE_SPECIFIER = ""; ++ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; ++ SUPPORTS_MACCATALYST = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; +@@ -479,9 +491,12 @@ + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; ++ CODE_SIGN_ENTITLEMENTS = iOSTestbed/iOSTestbed.entitlements; ++ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; ++ ENABLE_HARDENED_RUNTIME = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\""; +@@ -499,6 +514,9 @@ + MARKETING_VERSION = 3.13.0a1; + PRODUCT_BUNDLE_IDENTIFIER = org.python.iOSTestbed; + PRODUCT_NAME = "$(TARGET_NAME)"; ++ PROVISIONING_PROFILE_SPECIFIER = ""; ++ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; ++ SUPPORTS_MACCATALYST = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; +@@ -509,9 +527,10 @@ + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; ++ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; +- DEVELOPMENT_TEAM = 3HEZE76D99; ++ DEVELOPMENT_TEAM = ""; + GENERATE_INFOPLIST_FILE = YES; + HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\""; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; +@@ -529,9 +548,10 @@ + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; ++ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; +- DEVELOPMENT_TEAM = 3HEZE76D99; ++ DEVELOPMENT_TEAM = ""; + GENERATE_INFOPLIST_FILE = YES; + HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\""; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; +--- /dev/null ++++ b/iOS/testbed/iOSTestbed/iOSTestbed.entitlements +@@ -0,0 +1,14 @@ ++ ++ ++ ++ ++ com.apple.security.app-sandbox ++ ++ com.apple.security.cs.disable-library-validation ++ ++ com.apple.security.network.client ++ ++ com.apple.security.network.server ++ ++ ++ --- /dev/null +++ b/tvOS/README.rst @@ -0,0 +1,108 @@ @@ -2126,7 +3245,7 @@ index c3e261ecd9e..26ef7a95de4 100644 + %VERSION% + CFBundleSupportedPlatforms + -+ xrOS ++ XROS + + MinimumOSVersion + @XROS_DEPLOYMENT_TARGET@ @@ -2174,31 +3293,35 @@ index c3e261ecd9e..26ef7a95de4 100644 +xcrun --sdk xrsimulator clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET}-simulator -E "$@" --- /dev/null +++ b/visionOS/Resources/dylib-Info-template.plist -@@ -0,0 +1,26 @@ +@@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + en ++ CFBundleInfoDictionaryVersion ++ 6.0 + CFBundleExecutable + + CFBundleIdentifier + -+ CFBundleInfoDictionaryVersion -+ 6.0 + CFBundlePackageType -+ APPL ++ FMWK + CFBundleShortVersionString + 1.0 + CFBundleSupportedPlatforms + -+ xrOS ++ XROS + -+ MinimumOSVersion -+ 2.0 + CFBundleVersion + 1 ++ MinimumOSVersion ++ 2.0 ++ UIDeviceFamily ++ ++ 7 ++ + + --- /dev/null @@ -2248,6 +3371,20 @@ index c3e261ecd9e..26ef7a95de4 100644 + + --- /dev/null ++++ b/visionOS/testbed/Python.xcframework/xros-arm64-simulator/README +@@ -0,0 +1,4 @@ ++This directory is intentionally empty. ++ ++It should be used as a target for `--enable-framework` when compiling an visionOS simulator ++build for testing purposes (either x86_64 or ARM64). +--- /dev/null ++++ b/visionOS/testbed/Python.xcframework/xros-arm64/README +@@ -0,0 +1,4 @@ ++This directory is intentionally empty. ++ ++It should be used as a target for `--enable-framework` when compiling an visionOS on-device ++build for testing purposes. +--- /dev/null +++ b/visionOS/testbed/__main__.py @@ -0,0 +1,512 @@ +import argparse @@ -3443,31 +4580,35 @@ index c3e261ecd9e..26ef7a95de4 100644 +When the test suite runs, this folder will be on the PYTHONPATH. --- /dev/null +++ b/visionOS/testbed/visionOSTestbed/dylib-Info-template.plist -@@ -0,0 +1,26 @@ +@@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + en ++ CFBundleInfoDictionaryVersion ++ 6.0 + CFBundleExecutable + + CFBundleIdentifier + -+ CFBundleInfoDictionaryVersion -+ 6.0 + CFBundlePackageType -+ APPL ++ FMWK + CFBundleShortVersionString + 1.0 + CFBundleSupportedPlatforms + -+ VisionOS ++ XROS + -+ MinimumOSVersion -+ 12.0 + CFBundleVersion + 1 ++ MinimumOSVersion ++ 2.0 ++ UIDeviceFamily ++ ++ 7 ++ + + --- /dev/null From e9ff8156880bad2209ac20ca0f2da9c86c0c395e Mon Sep 17 00:00:00 2001 From: John Zhou Date: Sat, 3 May 2025 18:48:23 -0500 Subject: [PATCH 02/11] fix stuff --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f45af32..f2ed5ee 100644 --- a/Makefile +++ b/Makefile @@ -146,7 +146,7 @@ endif # Inherit the basename for the configure flags. ifdef CONFIGFLAGS-$$(BASE-$(target)) -CONFIGFLAGS-$(target)=$$(CONFIGFLAGS-$$(BASE-$(target)) +CONFIGFLAGS-$(target)=$$(CONFIGFLAGS-$$(BASE-$(target))) else CONFIGFLAGS-$(target)= endif @@ -397,8 +397,11 @@ $(target): $$(PYTHON_PLATFORM_SITECUSTOMIZE-$(target)) $$(PYTHON_LIB-$(target)) vars-$(target): @echo ">>> Environment variables for $(target)" + @echo "BASE-$(target): $$(BASE-$(target))" @echo "SDK-$(target): $$(SDK-$(target))" @echo "ARCH-$(target): $$(ARCH-$(target))" + @echo "CONFIGFLAGS-$(target): $$(CONFIGFLAGS-$(target))" + @echo "VERSION_MIN-$(target): $$(VERSION_MIN-$(target))" @echo "TARGET_TRIPLE-$(target): $$(TARGET_TRIPLE-$(target))" @echo "SDK_ROOT-$(target): $$(SDK_ROOT-$(target))" @echo "BZIP2_INSTALL-$(target): $$(BZIP2_INSTALL-$(target))" From 34d116f639793baed74e8e7ef4d9a37a4a9a9de2 Mon Sep 17 00:00:00 2001 From: John Zhou Date: Sun, 4 May 2025 14:18:17 -0500 Subject: [PATCH 03/11] misc stuff --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index f2ed5ee..6a8b04c 100644 --- a/Makefile +++ b/Makefile @@ -287,8 +287,13 @@ ifneq ($(os),macOS) PYTHON_SRCDIR-$(target)=build/$(os)/$(target)/python-$(PYTHON_VERSION) PYTHON_INSTALL-$(target)=$(PROJECT_DIR)/install/$(os)/$(target)/python-$(PYTHON_VERSION) PYTHON_FRAMEWORK-$(target)=$$(PYTHON_INSTALL-$(target))/Python.framework +ifneq ($$(BASE-$(target)),macabi) PYTHON_LIB-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Python PYTHON_BIN-$(target)=$$(PYTHON_INSTALL-$(target))/bin +else +PYTHON_LIB-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Versions/$(PYTHON_VER)/Python +PYTHON_BIN-$(target)=$$(PYTHON_INSTALL-$(target))/Python.framework/Versions/$(PYTHON_VER)/bin +endif PYTHON_INCLUDE-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Headers PYTHON_STDLIB-$(target)=$$(PYTHON_INSTALL-$(target))/lib/python$(PYTHON_VER) PYTHON_PLATFORM_CONFIG-$(target)=$$(PYTHON_INSTALL-$(target))/platform-config/$$(ARCH-$(target))-$$(SDK-$(target)) From ca896cff7c148a5b3ce51f4ef0709066fa78dba2 Mon Sep 17 00:00:00 2001 From: John Zhou Date: Mon, 5 May 2025 21:44:26 -0500 Subject: [PATCH 04/11] sort out build issues --- Makefile | 49 +++++++++++++++++++++++++++++++++------ patch/Python/Python.patch | 39 +++++++++++++++++++++++++------ 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 60a8d7b..4ef5efc 100644 --- a/Makefile +++ b/Makefile @@ -290,12 +290,14 @@ PYTHON_FRAMEWORK-$(target)=$$(PYTHON_INSTALL-$(target))/Python.framework ifneq ($$(BASE-$(target)),macabi) PYTHON_LIB-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Python PYTHON_BIN-$(target)=$$(PYTHON_INSTALL-$(target))/bin +PYTHON_INCLUDE-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Headers +PYTHON_STDLIB-$(target)=$$(PYTHON_INSTALL-$(target))/lib/python$(PYTHON_VER) else PYTHON_LIB-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Versions/$(PYTHON_VER)/Python -PYTHON_BIN-$(target)=$$(PYTHON_INSTALL-$(target))/Python.framework/Versions/$(PYTHON_VER)/bin +PYTHON_BIN-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Versions/$(PYTHON_VER)/bin +PYTHON_INCLUDE-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Versions/$(PYTHON_VER)/Headers +PYTHON_STDLIB-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Versions/$(PYTHON_VER)/lib/python$(PYTHON_VER) endif -PYTHON_INCLUDE-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Headers -PYTHON_STDLIB-$(target)=$$(PYTHON_INSTALL-$(target))/lib/python$(PYTHON_VER) PYTHON_PLATFORM_CONFIG-$(target)=$$(PYTHON_INSTALL-$(target))/platform-config/$$(ARCH-$(target))-$$(SDK-$(target)) PYTHON_PLATFORM_SITECUSTOMIZE-$(target)=$$(PYTHON_PLATFORM_CONFIG-$(target))/sitecustomize.py @@ -484,22 +486,43 @@ else PYTHON_INSTALL-$(sdk)=$(PROJECT_DIR)/install/$(os)/$(sdk)/python-$(PYTHON_VERSION) PYTHON_MODULEMAP-$(sdk)=$$(PYTHON_INCLUDE-$(sdk))/module.modulemap PYTHON_FRAMEWORK-$(sdk)=$$(PYTHON_INSTALL-$(sdk))/Python.framework +ifneq ($(sdk),macabi) PYTHON_LIB-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Python PYTHON_BIN-$(sdk)=$$(PYTHON_INSTALL-$(sdk))/bin PYTHON_INCLUDE-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Headers PYTHON_STDLIB-$(sdk)=$$(PYTHON_INSTALL-$(sdk))/lib/python$(PYTHON_VER) +else +PYTHON_LIB-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Python +PYTHON_BIN-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/bin +PYTHON_INCLUDE-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Headers +PYTHON_STDLIB-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/lib/python$(PYTHON_VER) +endif PYTHON_PLATFORM_CONFIG-$(sdk)=$$(PYTHON_INSTALL-$(sdk))/platform-config $$(PYTHON_LIB-$(sdk)): $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_LIB-$$(target))) @echo ">>> Build Python fat library for the $(sdk) SDK" mkdir -p $$(dir $$(PYTHON_LIB-$(sdk))) +ifeq ($(sdk),macabi) + ln -si $(PYTHON_VER) $$(PYTHON_FRAMEWORK-$(sdk))/Versions/Current + ln -si Versions/Current/Headers $$(PYTHON_FRAMEWORK-$(sdk))/Headers + ln -si Versions/Current/Resources $$(PYTHON_FRAMEWORK-$(sdk))/Resources + ln -si Versions/Current/Python $$(PYTHON_FRAMEWORK-$(sdk))/Python +endif lipo -create -output $$@ $$^ \ 2>&1 | tee -a install/$(os)/$(sdk)/python-$(PYTHON_VERSION).lipo.log +ifneq ($(sdk),macabi) $$(PYTHON_FRAMEWORK-$(sdk))/Info.plist: $$(PYTHON_LIB-$(sdk)) +else +$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources/Info.plist: $$(PYTHON_LIB-$(sdk)) +endif @echo ">>> Install Info.plist for the $(sdk) SDK" # Copy Info.plist as-is from the first target in the $(sdk) SDK +ifneq ($(sdk),macabi) cp -r $$(PYTHON_FRAMEWORK-$$(firstword $$(SDK_TARGETS-$(sdk))))/Info.plist $$(PYTHON_FRAMEWORK-$(sdk)) +else + cp -r $$(PYTHON_FRAMEWORK-$$(firstword $$(SDK_TARGETS-$(sdk))))/Versions/$(PYTHON_VER)/Resources/Info.plist $$(PYTHON_FRAMEWORK-$(sdk)) +endif $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h: $$(PYTHON_LIB-$(sdk)) @echo ">>> Build Python fat headers for the $(sdk) SDK" @@ -523,11 +546,19 @@ $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h: $$(PYTHON_LIB-$(sdk)) echo "\n}" >> $$(PYTHON_MODULEMAP-$(sdk)) # Link the PYTHONHOME version of the headers +ifneq ($(sdk),macabi) mkdir -p $$(PYTHON_INSTALL-$(sdk))/include ln -si ../Python.framework/Headers $$(PYTHON_INSTALL-$(sdk))/include/python$(PYTHON_VER) +else + mkdir -p $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/include + ln -si ../Headers $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/include/python$(PYTHON_VER) +endif ifeq ($(os), visionOS) echo "Skipping arch-specific header copying for visionOS" + + # Add the headers from each target -- there's should only be one target, so we copy it to the same name. + $$(foreach target,$$(SDK_TARGETS-$(sdk)),cp $$(PYTHON_INCLUDE-$$(target))/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h; ) else # Add the individual headers from each target in an arch-specific name $$(foreach target,$$(SDK_TARGETS-$(sdk)),cp $$(PYTHON_INCLUDE-$$(target))/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig-$$(ARCH-$$(target)).h; ) @@ -536,8 +567,11 @@ else cp $$(RESCDIR-$$(firstword $$(SDK_TARGETS-$(sdk))))/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h endif - +ifneq ($(sdk),macabi) $$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Info.plist $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) +else +$$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources/Info.plist $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) +endif @echo ">>> Build Python stdlib for the $(sdk) SDK" mkdir -p $$(PYTHON_STDLIB-$(sdk))/lib-dynload # Copy stdlib from the first target associated with the $(sdk) SDK @@ -694,9 +728,10 @@ $$(PYTHON_XCFRAMEWORK-$(os))/Info.plist: \ 2>&1 | tee -a support/$(PYTHON_VER)/python-$(os).xcframework.log @echo ">>> Install PYTHONHOME for $(os)" - $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/include $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) - $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/bin $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) - $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/lib $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) + # Do not install stuff for macabi becuase it's already built into the framework. + $$(foreach sdk,$$(filter-out macabi,$$(SDKS-$(os))),cp -r $$(PYTHON_INSTALL-$$(sdk))/include $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) + $$(foreach sdk,$$(filter-out macabi,$$(SDKS-$(os))),cp -r $$(PYTHON_INSTALL-$$(sdk))/bin $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) + $$(foreach sdk,$$(filter-out macabi,$$(SDKS-$(os))),cp -r $$(PYTHON_INSTALL-$$(sdk))/lib $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/platform-config $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) ifeq ($(filter $(os),iOS visionOS),$(os)) diff --git a/patch/Python/Python.patch b/patch/Python/Python.patch index c19a626..9293d15 100644 --- a/patch/Python/Python.patch +++ b/patch/Python/Python.patch @@ -757,8 +757,18 @@ index 232d3c3a9c5..e042c20ea54 100644 @@ -0,0 +1,2 @@ +#!/bin/sh +xcrun --sdk macosx${MACOSX_SDK_VERSION} clang -target x86_64-apple-ios-macabi -E "$@" +--- /dev/null ++++ b/MacCatalyst/Resources/pyconfig.h +@@ -0,0 +1,7 @@ ++#ifdef __arm64__ ++#include "pyconfig-arm64.h" ++#endif ++ ++#ifdef __x86_64__ ++#include "pyconfig-x86_64.h" ++#endif diff --git a/Makefile.pre.in b/Makefile.pre.in -index e10c78d6403..21b707bd017 100644 +index e10c78d6403..c77fb73513d 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -209,6 +209,12 @@ @@ -846,6 +856,21 @@ index e10c78d6403..21b707bd017 100644 # Like test, but using --slow-ci which enables all test resources and use # longer timeout. Run an optional pybuildbot.identify script to include +@@ -2980,6 +3019,14 @@ + $(INSTALL) -m $(EXEMODE) $$file $(DESTDIR)$(BINDIR); \ + done + ++# Stub compilation assistance binaries are installed separately on Mac Catalyst. ++.PHONY: frameworkinstallcatalyststubs ++frameworkinstallcatalyststubs: $(LDLIBRARY) ++ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(BINDIR) ++ for file in $(srcdir)/$(RESSRCDIR)/bin/* ; do \ ++ $(INSTALL) -m $(EXEMODE) $$file $(DESTDIR)$(BINDIR); \ ++ done ++ + # This installs Mac/Lib into the framework + # Install a number of symlinks to keep software that expects a normal unix + # install (which includes python-config) happy. diff --git a/Misc/platform_triplet.c b/Misc/platform_triplet.c index ec0857a4a99..de56264da3b 100644 --- a/Misc/platform_triplet.c @@ -926,7 +951,7 @@ index 1bb6a05dc11..6efa3fbf821 100755 none--*) # None (no kernel, i.e. freestanding / bare metal), diff --git a/configure b/configure -index 1b75ddfa26d..9feb830657a 100755 +index 1b75ddfa26d..4c2defa706e 100755 --- a/configure +++ b/configure @@ -978,6 +978,11 @@ @@ -1109,8 +1134,8 @@ index 1b75ddfa26d..9feb830657a 100755 + _flag_ios_catalyst=`echo $host | cut -d '-' -f4` + case $_flag_ios_catalyst in + macabi) -+ FRAMEWORKINSTALLFIRST="frameworkinstallversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallversionedstructure " ++ FRAMEWORKINSTALLFIRST="frameworkinstallversionedstructure frameworkinstallcatalyststubs" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallversionedstructure frameworkinstallcatalyststubs " + FRAMEWORKINSTALLLAST="" + FRAMEWORKALTINSTALLLAST="" + FRAMEWORKPYTHONW= @@ -1782,7 +1807,7 @@ index 1b75ddfa26d..9feb830657a 100755 "Misc/python.pc") CONFIG_FILES="$CONFIG_FILES Misc/python.pc" ;; "Misc/python-embed.pc") CONFIG_FILES="$CONFIG_FILES Misc/python-embed.pc" ;; diff --git a/configure.ac b/configure.ac -index c449bb5ebb3..4b5ba577882 100644 +index c449bb5ebb3..aaf40d540f7 100644 --- a/configure.ac +++ b/configure.ac @@ -330,6 +330,15 @@ @@ -1935,8 +1960,8 @@ index c449bb5ebb3..4b5ba577882 100644 + _flag_ios_catalyst=`echo $host | cut -d '-' -f4` + case $_flag_ios_catalyst in + macabi) -+ FRAMEWORKINSTALLFIRST="frameworkinstallversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallversionedstructure " ++ FRAMEWORKINSTALLFIRST="frameworkinstallversionedstructure frameworkinstallcatalyststubs" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallversionedstructure frameworkinstallcatalyststubs " + FRAMEWORKINSTALLLAST="" + FRAMEWORKALTINSTALLLAST="" + FRAMEWORKPYTHONW= From fbb6fb23f644c11d3e463a14c066c3826f15672f Mon Sep 17 00:00:00 2001 From: John Zhou Date: Mon, 5 May 2025 22:06:31 -0500 Subject: [PATCH 05/11] more fix --- Makefile | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4ef5efc..c37f90c 100644 --- a/Makefile +++ b/Makefile @@ -451,8 +451,12 @@ SDK_TARGETS-$(sdk)=$$(filter $(sdk).%,$$(TARGETS-$(os))) SDK_ARCHES-$(sdk)=$$(sort $$(subst .,,$$(suffix $$(SDK_TARGETS-$(sdk))))) ifeq ($$(findstring simulator,$(sdk)),) +ifeq ($$(findstring catalyst,$(sdk)),) SDK_SLICE-$(sdk)=$$(TRIPLE_OS-$(os))-$$(shell echo $$(SDK_ARCHES-$(sdk)) | sed "s/ /_/g") else +SDK_SLICE-$(sdk)=$$(TRIPLE_OS-$(os))-$$(shell echo $$(SDK_ARCHES-$(sdk)) | sed "s/ /_/g")-maccatalyst +endif +else SDK_SLICE-$(sdk)=$$(TRIPLE_OS-$(os))-$$(shell echo $$(SDK_ARCHES-$(sdk)) | sed "s/ /_/g")-simulator endif @@ -567,8 +571,15 @@ else cp $$(RESCDIR-$$(firstword $$(SDK_TARGETS-$(sdk))))/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h endif +ifeq ($(sdk),macabi) +$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources: + echo ">>> Copying Resources Folder for Versioned Framework" + mkdir -p $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER) + cp -r $$(PYTHON_FRAMEWORK-$$(firstword $$(SDK_TARGETS-$(sdk))))/Versions/$(PYTHON_VER)/Resources $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER) +endif + ifneq ($(sdk),macabi) -$$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Info.plist $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) +$$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Info.plist $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) else $$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources/Info.plist $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) endif From 0147c7ceb43021e272b557c797c9dbb582db9724 Mon Sep 17 00:00:00 2001 From: John Zhou Date: Tue, 6 May 2025 21:08:05 -0500 Subject: [PATCH 06/11] have more code --- Makefile | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index c37f90c..7a13087 100644 --- a/Makefile +++ b/Makefile @@ -517,15 +517,15 @@ endif ifneq ($(sdk),macabi) $$(PYTHON_FRAMEWORK-$(sdk))/Info.plist: $$(PYTHON_LIB-$(sdk)) -else -$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources/Info.plist: $$(PYTHON_LIB-$(sdk)) -endif @echo ">>> Install Info.plist for the $(sdk) SDK" # Copy Info.plist as-is from the first target in the $(sdk) SDK -ifneq ($(sdk),macabi) cp -r $$(PYTHON_FRAMEWORK-$$(firstword $$(SDK_TARGETS-$(sdk))))/Info.plist $$(PYTHON_FRAMEWORK-$(sdk)) else - cp -r $$(PYTHON_FRAMEWORK-$$(firstword $$(SDK_TARGETS-$(sdk))))/Versions/$(PYTHON_VER)/Resources/Info.plist $$(PYTHON_FRAMEWORK-$(sdk)) +$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources: + echo ">>> Copying Resources Folder for Versioned Framework from the first target in the SDK" + mkdir -p $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER) + # Copy Resources as-is from the first target in the $(sdk) SDK + cp -r $$(PYTHON_FRAMEWORK-$$(firstword $$(SDK_TARGETS-$(sdk))))/Versions/$(PYTHON_VER)/Resources $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER) endif $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h: $$(PYTHON_LIB-$(sdk)) @@ -571,17 +571,10 @@ else cp $$(RESCDIR-$$(firstword $$(SDK_TARGETS-$(sdk))))/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h endif -ifeq ($(sdk),macabi) -$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources: - echo ">>> Copying Resources Folder for Versioned Framework" - mkdir -p $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER) - cp -r $$(PYTHON_FRAMEWORK-$$(firstword $$(SDK_TARGETS-$(sdk))))/Versions/$(PYTHON_VER)/Resources $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER) -endif - ifneq ($(sdk),macabi) -$$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Info.plist $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) +$$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Info.plist $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) else -$$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources/Info.plist $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) +$$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) endif @echo ">>> Build Python stdlib for the $(sdk) SDK" mkdir -p $$(PYTHON_STDLIB-$(sdk))/lib-dynload From fd14da25a52f0b6b5fdb373841e42689d9314866 Mon Sep 17 00:00:00 2001 From: John Zhou Date: Wed, 7 May 2025 22:07:21 -0500 Subject: [PATCH 07/11] fix --- Makefile | 18 ++- patch/Python/Python.patch | 287 ++++++++++++++++++++++++++------------ 2 files changed, 212 insertions(+), 93 deletions(-) diff --git a/Makefile b/Makefile index 7a13087..c1369ce 100644 --- a/Makefile +++ b/Makefile @@ -294,9 +294,9 @@ PYTHON_INCLUDE-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Headers PYTHON_STDLIB-$(target)=$$(PYTHON_INSTALL-$(target))/lib/python$(PYTHON_VER) else PYTHON_LIB-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Versions/$(PYTHON_VER)/Python -PYTHON_BIN-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Versions/$(PYTHON_VER)/bin +PYTHON_BIN-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Versions/$(PYTHON_VER)/Resources/bin PYTHON_INCLUDE-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Versions/$(PYTHON_VER)/Headers -PYTHON_STDLIB-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Versions/$(PYTHON_VER)/lib/python$(PYTHON_VER) +PYTHON_STDLIB-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Versions/$(PYTHON_VER)/Resources/lib/python$(PYTHON_VER) endif PYTHON_PLATFORM_CONFIG-$(target)=$$(PYTHON_INSTALL-$(target))/platform-config/$$(ARCH-$(target))-$$(SDK-$(target)) PYTHON_PLATFORM_SITECUSTOMIZE-$(target)=$$(PYTHON_PLATFORM_CONFIG-$(target))/sitecustomize.py @@ -497,9 +497,9 @@ PYTHON_INCLUDE-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Headers PYTHON_STDLIB-$(sdk)=$$(PYTHON_INSTALL-$(sdk))/lib/python$(PYTHON_VER) else PYTHON_LIB-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Python -PYTHON_BIN-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/bin +PYTHON_BIN-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources/bin PYTHON_INCLUDE-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Headers -PYTHON_STDLIB-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/lib/python$(PYTHON_VER) +PYTHON_STDLIB-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources/lib/python$(PYTHON_VER) endif PYTHON_PLATFORM_CONFIG-$(sdk)=$$(PYTHON_INSTALL-$(sdk))/platform-config @@ -530,8 +530,11 @@ endif $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h: $$(PYTHON_LIB-$(sdk)) @echo ">>> Build Python fat headers for the $(sdk) SDK" + # Copying for Mac Catalyst is done already with the Resources folder +ifneq ($(sdk),macabi) # Copy binary helpers from the first target in the $(sdk) SDK cp -r $$(PYTHON_BIN-$$(firstword $$(SDK_TARGETS-$(sdk)))) $$(PYTHON_BIN-$(sdk)) +endif # Create a non-executable stub binary python3 echo "#!/bin/bash\necho Can\\'t run $(sdk) binary\nexit 1" > $$(PYTHON_BIN-$(sdk))/python$(PYTHON_VER) @@ -554,8 +557,9 @@ ifneq ($(sdk),macabi) mkdir -p $$(PYTHON_INSTALL-$(sdk))/include ln -si ../Python.framework/Headers $$(PYTHON_INSTALL-$(sdk))/include/python$(PYTHON_VER) else - mkdir -p $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/include - ln -si ../Headers $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/include/python$(PYTHON_VER) + mkdir -p $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources/include + rm -rf $(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources/include/* + ln -si ../../Headers $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources/include/python$(PYTHON_VER) endif ifeq ($(os), visionOS) @@ -577,9 +581,11 @@ else $$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER)/Resources $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) endif @echo ">>> Build Python stdlib for the $(sdk) SDK" +ifneq ($(sdk),macabi) mkdir -p $$(PYTHON_STDLIB-$(sdk))/lib-dynload # Copy stdlib from the first target associated with the $(sdk) SDK cp -r $$(PYTHON_STDLIB-$$(firstword $$(SDK_TARGETS-$(sdk))))/ $$(PYTHON_STDLIB-$(sdk)) +endif # Delete the single-SDK parts of the standard library rm -rf \ diff --git a/patch/Python/Python.patch b/patch/Python/Python.patch index 9293d15..1c7b20c 100644 --- a/patch/Python/Python.patch +++ b/patch/Python/Python.patch @@ -768,7 +768,7 @@ index 232d3c3a9c5..e042c20ea54 100644 +#include "pyconfig-x86_64.h" +#endif diff --git a/Makefile.pre.in b/Makefile.pre.in -index e10c78d6403..c77fb73513d 100644 +index e10c78d6403..318d6449e4a 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -209,6 +209,12 @@ @@ -856,7 +856,36 @@ index e10c78d6403..c77fb73513d 100644 # Like test, but using --slow-ci which enables all test resources and use # longer timeout. Run an optional pybuildbot.identify script to include -@@ -2980,6 +3019,14 @@ +@@ -2936,6 +2975,9 @@ + .PHONY: frameworkinstallframework + frameworkinstallframework: @FRAMEWORKINSTALLFIRST@ install frameworkinstallmaclib + ++structureprefix=@structureprefix@ ++includelinklocation=@includelinklocation@ ++ + # macOS uses a versioned frameworks structure that includes a full install + .PHONY: frameworkinstallversionedstructure + frameworkinstallversionedstructure: $(LDLIBRARY) +@@ -2944,15 +2986,15 @@ + exit 1; \ + else true; \ + fi +- @for i in $(prefix)/Resources/English.lproj $(prefix)/lib; do\ ++ @for i in $(structureprefix)/Resources/English.lproj $(prefix)/lib; do\ + if test ! -d $(DESTDIR)$$i; then \ + echo "Creating directory $(DESTDIR)$$i"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \ + else true; \ + fi; \ + done +- $(LN) -fsn include/python$(LDVERSION) $(DESTDIR)$(prefix)/Headers +- sed 's/%VERSION%/'"`$(RUNSHARED) ./$(BUILDPYTHON) -c 'import platform; print(platform.python_version())'`"'/g' < $(RESSRCDIR)/Info.plist > $(DESTDIR)$(prefix)/Resources/Info.plist ++ $(LN) -fsn $(includelinklocation)include/python$(LDVERSION) $(DESTDIR)$(structureprefix)/Headers ++ sed 's/%VERSION%/'"`$(RUNSHARED) ./$(PYTHON_FOR_BUILD) -c 'import platform; print(platform.python_version())'`"'/g' < $(RESSRCDIR)/Info.plist > $(DESTDIR)$(structureprefix)/Resources/Info.plist + $(LN) -fsn $(VERSION) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Versions/Current + $(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/$(PYTHONFRAMEWORK) + $(LN) -fsn Versions/Current/Headers $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Headers +@@ -2980,6 +3022,14 @@ $(INSTALL) -m $(EXEMODE) $$file $(DESTDIR)$(BINDIR); \ done @@ -951,10 +980,10 @@ index 1bb6a05dc11..6efa3fbf821 100755 none--*) # None (no kernel, i.e. freestanding / bare metal), diff --git a/configure b/configure -index 1b75ddfa26d..4c2defa706e 100755 +index 1b75ddfa26d..ba0e59d302d 100755 --- a/configure +++ b/configure -@@ -978,6 +978,11 @@ +@@ -978,11 +978,18 @@ CFLAGS CC HAS_XCRUN @@ -966,7 +995,14 @@ index 1b75ddfa26d..4c2defa706e 100755 IPHONEOS_DEPLOYMENT_TARGET EXPORT_MACOSX_DEPLOYMENT_TARGET CONFIGURE_MACOSX_DEPLOYMENT_TARGET -@@ -1081,6 +1086,7 @@ + _PYTHON_HOST_PLATFORM + APP_STORE_COMPLIANCE_PATCH ++includelinklocation ++structureprefix + INSTALLTARGETS + FRAMEWORKINSTALLAPPSPREFIX + FRAMEWORKUNIXTOOLSPREFIX +@@ -1081,6 +1088,7 @@ with_framework_name enable_framework with_app_store_compliance @@ -974,7 +1010,7 @@ index 1b75ddfa26d..4c2defa706e 100755 enable_wasm_dynamic_linking enable_wasm_pthreads with_suffix -@@ -1868,6 +1874,9 @@ +@@ -1868,6 +1876,9 @@ Enable any patches required for compiliance with app stores. Optional PATCH-FILE specifies the custom patch to apply. @@ -984,7 +1020,7 @@ index 1b75ddfa26d..4c2defa706e 100755 --with-suffix=SUFFIX set executable suffix to SUFFIX (default is empty, yes is mapped to '.exe') --without-static-libpython -@@ -4106,6 +4115,15 @@ +@@ -4106,6 +4117,15 @@ *-apple-ios*) ac_sys_system=iOS ;; @@ -1000,7 +1036,7 @@ index 1b75ddfa26d..4c2defa706e 100755 *-*-darwin*) ac_sys_system=Darwin ;; -@@ -4187,7 +4205,7 @@ +@@ -4187,7 +4207,7 @@ # On cross-compile builds, configure will look for a host-specific compiler by # prepending the user-provided host triple to the required binary name. # @@ -1009,7 +1045,7 @@ index 1b75ddfa26d..4c2defa706e 100755 # which isn't a binary that exists, and isn't very convenient, as it contains the # iOS version. As the default cross-compiler name won't exist, configure falls # back to gcc, which *definitely* won't work. We're providing wrapper scripts for -@@ -4199,33 +4217,89 @@ +@@ -4199,33 +4219,89 @@ # configure will fail. if test -z "$AR"; then case "$host" in @@ -1103,7 +1139,7 @@ index 1b75ddfa26d..4c2defa706e 100755 *) esac fi -@@ -4348,8 +4422,11 @@ +@@ -4348,8 +4424,11 @@ case $enableval in yes) case $ac_sys_system in @@ -1117,7 +1153,7 @@ index 1b75ddfa26d..4c2defa706e 100755 *) as_fn_error $? "Unknown platform for framework build" "$LINENO" 5 esac esac -@@ -4358,6 +4435,9 @@ +@@ -4358,6 +4437,9 @@ no) case $ac_sys_system in iOS) as_fn_error $? "iOS builds must use --enable-framework" "$LINENO" 5 ;; @@ -1127,7 +1163,16 @@ index 1b75ddfa26d..4c2defa706e 100755 *) PYTHONFRAMEWORK= PYTHONFRAMEWORKDIR=no-framework -@@ -4451,6 +4531,67 @@ +@@ -4436,6 +4518,8 @@ + esac + + prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION ++ structureprefix=${prefix} ++ includelinklocation= + PYTHONFRAMEWORKINSTALLNAMEPREFIX=${prefix} + RESSRCDIR=Mac/Resources/framework + +@@ -4451,6 +4535,69 @@ ;; iOS) : @@ -1140,7 +1185,9 @@ index 1b75ddfa26d..4c2defa706e 100755 + FRAMEWORKALTINSTALLLAST="" + FRAMEWORKPYTHONW= + INSTALLTARGETS="libinstall inclinstall sharedinstall" -+ prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION ++ prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION/Resources ++ structureprefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION ++ includelinklocation=Resources/ + PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR/Versions/$VERSION" + RESSRCDIR=MacCatalyst/Resources + ac_config_files="$ac_config_files MacCatalyst/Resources/Info.plist" @@ -1195,7 +1242,7 @@ index 1b75ddfa26d..4c2defa706e 100755 FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -@@ -4460,9 +4601,9 @@ +@@ -4460,9 +4607,9 @@ prefix=$PYTHONFRAMEWORKPREFIX PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" @@ -1207,7 +1254,7 @@ index 1b75ddfa26d..4c2defa706e 100755 ;; *) -@@ -4475,6 +4616,9 @@ +@@ -4475,6 +4622,9 @@ e) case $ac_sys_system in iOS) as_fn_error $? "iOS builds must use --enable-framework" "$LINENO" 5 ;; @@ -1217,7 +1264,16 @@ index 1b75ddfa26d..4c2defa706e 100755 *) PYTHONFRAMEWORK= PYTHONFRAMEWORKDIR=no-framework -@@ -4529,8 +4673,8 @@ +@@ -4516,6 +4666,8 @@ + + + ++ ++ + printf "%s\n" "#define _PYTHONFRAMEWORK \"${PYTHONFRAMEWORK}\"" >>confdefs.h + + +@@ -4529,8 +4681,8 @@ case "$withval" in yes) case $ac_sys_system in @@ -1228,7 +1284,7 @@ index 1b75ddfa26d..4c2defa706e 100755 APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" ;; *) as_fn_error $? "no default app store compliance patch available for $ac_sys_system" "$LINENO" 5 ;; -@@ -4548,8 +4692,8 @@ +@@ -4548,8 +4700,8 @@ else case e in #( e) case $ac_sys_system in @@ -1239,7 +1295,7 @@ index 1b75ddfa26d..4c2defa706e 100755 APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: applying default app store compliance patch" >&5 printf "%s\n" "applying default app store compliance patch" >&6; } -@@ -4568,6 +4712,40 @@ +@@ -4568,6 +4720,40 @@ @@ -1280,7 +1336,7 @@ index 1b75ddfa26d..4c2defa706e 100755 if test "$cross_compiling" = yes; then case "$host" in *-*-linux*) -@@ -4582,6 +4760,28 @@ +@@ -4582,6 +4768,28 @@ *-*-cygwin*) _host_ident= ;; @@ -1309,7 +1365,7 @@ index 1b75ddfa26d..4c2defa706e 100755 *-apple-ios*) _host_os=`echo $host | cut -d '-' -f3` _host_device=`echo $host | cut -d '-' -f4` -@@ -4604,6 +4804,78 @@ +@@ -4604,6 +4812,78 @@ ;; esac ;; @@ -1388,7 +1444,7 @@ index 1b75ddfa26d..4c2defa706e 100755 *-*-darwin*) case "$host_cpu" in arm*) -@@ -4694,9 +4966,15 @@ +@@ -4694,9 +4974,15 @@ define_xopen_source=no;; Darwin/[12][0-9].*) define_xopen_source=no;; @@ -1405,7 +1461,7 @@ index 1b75ddfa26d..4c2defa706e 100755 # On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from # defining NI_NUMERICHOST. QNX/6.3.2) -@@ -4759,7 +5037,17 @@ +@@ -4759,7 +5045,17 @@ CONFIGURE_MACOSX_DEPLOYMENT_TARGET= EXPORT_MACOSX_DEPLOYMENT_TARGET='#' @@ -1424,7 +1480,7 @@ index 1b75ddfa26d..4c2defa706e 100755 # checks for alternative programs -@@ -4800,6 +5088,16 @@ +@@ -4800,6 +5096,16 @@ as_fn_append CFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}" as_fn_append LDFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}" ;; #( @@ -1441,7 +1497,7 @@ index 1b75ddfa26d..4c2defa706e 100755 *) : ;; esac -@@ -7169,6 +7467,12 @@ +@@ -7169,6 +7475,12 @@ MULTIARCH="" ;; #( iOS) : MULTIARCH="" ;; #( @@ -1454,7 +1510,7 @@ index 1b75ddfa26d..4c2defa706e 100755 FreeBSD*) : MULTIARCH="" ;; #( *) : -@@ -7189,7 +7493,7 @@ +@@ -7189,7 +7501,7 @@ printf "%s\n" "$MULTIARCH" >&6; } case $ac_sys_system in #( @@ -1463,7 +1519,7 @@ index 1b75ddfa26d..4c2defa706e 100755 SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2` ;; #( *) : SOABI_PLATFORM=$PLATFORM_TRIPLET -@@ -7236,10 +7540,26 @@ +@@ -7236,10 +7548,26 @@ PY_SUPPORT_TIER=3 ;; #( x86_64-*-freebsd*/clang) : PY_SUPPORT_TIER=3 ;; #( @@ -1490,7 +1546,7 @@ index 1b75ddfa26d..4c2defa706e 100755 aarch64-*-linux-android/clang) : PY_SUPPORT_TIER=3 ;; #( x86_64-*-linux-android/clang) : -@@ -7676,7 +7996,7 @@ +@@ -7676,7 +8004,7 @@ case $ac_sys_system in Darwin) LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)';; @@ -1499,7 +1555,7 @@ index 1b75ddfa26d..4c2defa706e 100755 LDLIBRARY='$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)';; *) as_fn_error $? "Unknown platform for framework build" "$LINENO" 5;; -@@ -7742,7 +8062,7 @@ +@@ -7742,7 +8070,7 @@ BLDLIBRARY='-L. -lpython$(LDVERSION)' RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} ;; @@ -1508,7 +1564,7 @@ index 1b75ddfa26d..4c2defa706e 100755 LDLIBRARY='libpython$(LDVERSION).dylib' ;; AIX*) -@@ -13550,7 +13870,7 @@ +@@ -13550,7 +13878,7 @@ BLDSHARED="$LDSHARED" fi ;; @@ -1517,7 +1573,7 @@ index 1b75ddfa26d..4c2defa706e 100755 LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' BLDSHARED="$LDSHARED" -@@ -13683,7 +14003,7 @@ +@@ -13683,7 +14011,7 @@ Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";; Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";; # -u libsys_s pulls in all symbols in libsys @@ -1526,7 +1582,7 @@ index 1b75ddfa26d..4c2defa706e 100755 LINKFORSHARED="$extra_undefs -framework CoreFoundation" # Issue #18075: the default maximum stack size (8MBytes) is too -@@ -13707,7 +14027,7 @@ +@@ -13707,7 +14035,7 @@ LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' fi LINKFORSHARED="$LINKFORSHARED" @@ -1535,7 +1591,7 @@ index 1b75ddfa26d..4c2defa706e 100755 LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' fi ;; -@@ -15292,7 +15612,7 @@ +@@ -15292,7 +15620,7 @@ ctypes_malloc_closure=yes ;; #( @@ -1544,7 +1600,7 @@ index 1b75ddfa26d..4c2defa706e 100755 ctypes_malloc_closure=yes ;; #( -@@ -19044,12 +19364,6 @@ +@@ -19044,12 +19372,6 @@ then : printf "%s\n" "#define HAVE_DUP3 1" >>confdefs.h @@ -1557,7 +1613,7 @@ index 1b75ddfa26d..4c2defa706e 100755 fi ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero" if test "x$ac_cv_func_explicit_bzero" = xyes -@@ -19110,18 +19424,6 @@ +@@ -19110,18 +19432,6 @@ then : printf "%s\n" "#define HAVE_FEXECVE 1" >>confdefs.h @@ -1576,7 +1632,7 @@ index 1b75ddfa26d..4c2defa706e 100755 fi ac_fn_c_check_func "$LINENO" "fpathconf" "ac_cv_func_fpathconf" if test "x$ac_cv_func_fpathconf" = xyes -@@ -19548,24 +19850,6 @@ +@@ -19548,24 +19858,6 @@ then : printf "%s\n" "#define HAVE_POSIX_OPENPT 1" >>confdefs.h @@ -1601,7 +1657,7 @@ index 1b75ddfa26d..4c2defa706e 100755 fi ac_fn_c_check_func "$LINENO" "pread" "ac_cv_func_pread" if test "x$ac_cv_func_pread" = xyes -@@ -19884,12 +20168,6 @@ +@@ -19884,12 +20176,6 @@ then : printf "%s\n" "#define HAVE_SIGACTION 1" >>confdefs.h @@ -1614,7 +1670,7 @@ index 1b75ddfa26d..4c2defa706e 100755 fi ac_fn_c_check_func "$LINENO" "sigfillset" "ac_cv_func_sigfillset" if test "x$ac_cv_func_sigfillset" = xyes -@@ -20158,11 +20436,11 @@ +@@ -20158,11 +20444,11 @@ fi @@ -1628,7 +1684,7 @@ index 1b75ddfa26d..4c2defa706e 100755 ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy" if test "x$ac_cv_func_getentropy" = xyes then : -@@ -20184,6 +20462,53 @@ +@@ -20184,6 +20470,53 @@ fi @@ -1682,7 +1738,7 @@ index 1b75ddfa26d..4c2defa706e 100755 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } if test ${ac_cv_c_undeclared_builtin_options+y} -@@ -23266,7 +23591,8 @@ +@@ -23266,7 +23599,8 @@ # check for openpty, login_tty, and forkpty @@ -1692,7 +1748,7 @@ index 1b75ddfa26d..4c2defa706e 100755 for ac_func in openpty do : -@@ -23380,7 +23706,7 @@ +@@ -23380,7 +23714,7 @@ fi done @@ -1701,7 +1757,7 @@ index 1b75ddfa26d..4c2defa706e 100755 printf %s "checking for library containing login_tty... " >&6; } if test ${ac_cv_search_login_tty+y} then : -@@ -23563,6 +23889,7 @@ +@@ -23563,6 +23897,7 @@ fi done @@ -1709,7 +1765,7 @@ index 1b75ddfa26d..4c2defa706e 100755 # check for long file support functions ac_fn_c_check_func "$LINENO" "fseek64" "ac_cv_func_fseek64" -@@ -23828,10 +24155,10 @@ +@@ -23828,10 +24163,10 @@ done @@ -1722,7 +1778,7 @@ index 1b75ddfa26d..4c2defa706e 100755 then for ac_func in clock_settime -@@ -24148,7 +24475,7 @@ +@@ -24148,7 +24483,7 @@ e) if test "$cross_compiling" = yes then : @@ -1731,7 +1787,7 @@ index 1b75ddfa26d..4c2defa706e 100755 ac_cv_buggy_getaddrinfo="no" elif test "${enable_ipv6+set}" = set; then ac_cv_buggy_getaddrinfo="no -- configured with --(en|dis)able-ipv6" -@@ -26170,8 +26497,8 @@ +@@ -26170,8 +26505,8 @@ LIBPYTHON="\$(BLDLIBRARY)" fi @@ -1742,7 +1798,7 @@ index 1b75ddfa26d..4c2defa706e 100755 MODULE_DEPS_SHARED="$MODULE_DEPS_SHARED \$(PYTHONFRAMEWORKDIR)/\$(PYTHONFRAMEWORK)" fi -@@ -29041,7 +29368,7 @@ +@@ -29041,7 +29376,7 @@ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for device files" >&5 printf "%s\n" "$as_me: checking for device files" >&6;} @@ -1751,7 +1807,7 @@ index 1b75ddfa26d..4c2defa706e 100755 ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no else -@@ -29550,7 +29877,7 @@ +@@ -29550,7 +29885,7 @@ with_ensurepip=no ;; #( WASI) : with_ensurepip=no ;; #( @@ -1760,7 +1816,7 @@ index 1b75ddfa26d..4c2defa706e 100755 with_ensurepip=no ;; #( *) : with_ensurepip=upgrade -@@ -30499,7 +30826,7 @@ +@@ -30499,7 +30834,7 @@ SunOS*) _PYTHREAD_NAME_MAXLEN=31;; NetBSD*) _PYTHREAD_NAME_MAXLEN=15;; # gh-131268 Darwin) _PYTHREAD_NAME_MAXLEN=63;; @@ -1769,7 +1825,7 @@ index 1b75ddfa26d..4c2defa706e 100755 FreeBSD*) _PYTHREAD_NAME_MAXLEN=19;; # gh-131268 OpenBSD*) _PYTHREAD_NAME_MAXLEN=23;; # gh-131268 *) _PYTHREAD_NAME_MAXLEN=;; -@@ -30531,8 +30858,15 @@ +@@ -30531,8 +30866,15 @@ ;; #( Darwin) : ;; #( @@ -1786,7 +1842,7 @@ index 1b75ddfa26d..4c2defa706e 100755 py_cv_module__curses=n/a -@@ -30540,7 +30874,6 @@ +@@ -30540,7 +30882,6 @@ py_cv_module__gdbm=n/a py_cv_module__multiprocessing=n/a py_cv_module__posixshmem=n/a @@ -1794,7 +1850,7 @@ index 1b75ddfa26d..4c2defa706e 100755 py_cv_module__scproxy=n/a py_cv_module__tkinter=n/a py_cv_module_grp=n/a -@@ -34604,7 +34937,11 @@ +@@ -34604,7 +34945,11 @@ "Mac/PythonLauncher/Makefile") CONFIG_FILES="$CONFIG_FILES Mac/PythonLauncher/Makefile" ;; "Mac/Resources/framework/Info.plist") CONFIG_FILES="$CONFIG_FILES Mac/Resources/framework/Info.plist" ;; "Mac/Resources/app/Info.plist") CONFIG_FILES="$CONFIG_FILES Mac/Resources/app/Info.plist" ;; @@ -1807,7 +1863,7 @@ index 1b75ddfa26d..4c2defa706e 100755 "Misc/python.pc") CONFIG_FILES="$CONFIG_FILES Misc/python.pc" ;; "Misc/python-embed.pc") CONFIG_FILES="$CONFIG_FILES Misc/python-embed.pc" ;; diff --git a/configure.ac b/configure.ac -index c449bb5ebb3..aaf40d540f7 100644 +index c449bb5ebb3..70ef7afa402 100644 --- a/configure.ac +++ b/configure.ac @@ -330,6 +330,15 @@ @@ -1953,7 +2009,16 @@ index c449bb5ebb3..aaf40d540f7 100644 *) PYTHONFRAMEWORK= PYTHONFRAMEWORKDIR=no-framework -@@ -657,6 +728,35 @@ +@@ -646,6 +717,8 @@ + esac + + prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION ++ structureprefix=${prefix} ++ includelinklocation= + PYTHONFRAMEWORKINSTALLNAMEPREFIX=${prefix} + RESSRCDIR=Mac/Resources/framework + +@@ -657,6 +730,37 @@ AC_CONFIG_FILES([Mac/Resources/app/Info.plist]) ;; iOS) : @@ -1966,7 +2031,9 @@ index c449bb5ebb3..aaf40d540f7 100644 + FRAMEWORKALTINSTALLLAST="" + FRAMEWORKPYTHONW= + INSTALLTARGETS="libinstall inclinstall sharedinstall" -+ prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION ++ prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION/Resources ++ structureprefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION ++ includelinklocation=Resources/ + PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR/Versions/$VERSION" + RESSRCDIR=MacCatalyst/Resources + AC_CONFIG_FILES([MacCatalyst/Resources/Info.plist]) @@ -1989,7 +2056,7 @@ index c449bb5ebb3..aaf40d540f7 100644 FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -@@ -666,9 +766,37 @@ +@@ -666,9 +770,37 @@ prefix=$PYTHONFRAMEWORKPREFIX PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" @@ -2029,7 +2096,7 @@ index c449bb5ebb3..aaf40d540f7 100644 ;; *) AC_MSG_ERROR([Unknown platform for framework build]) -@@ -678,6 +806,9 @@ +@@ -678,6 +810,9 @@ ],[ case $ac_sys_system in iOS) AC_MSG_ERROR([iOS builds must use --enable-framework]) ;; @@ -2039,7 +2106,16 @@ index c449bb5ebb3..aaf40d540f7 100644 *) PYTHONFRAMEWORK= PYTHONFRAMEWORKDIR=no-framework -@@ -730,8 +861,8 @@ +@@ -714,6 +849,8 @@ + AC_SUBST([FRAMEWORKUNIXTOOLSPREFIX]) + AC_SUBST([FRAMEWORKINSTALLAPPSPREFIX]) + AC_SUBST([INSTALLTARGETS]) ++AC_SUBST([structureprefix]) ++AC_SUBST([includelinklocation]) + + AC_DEFINE_UNQUOTED([_PYTHONFRAMEWORK], ["${PYTHONFRAMEWORK}"], + [framework name]) +@@ -730,8 +867,8 @@ case "$withval" in yes) case $ac_sys_system in @@ -2050,7 +2126,7 @@ index c449bb5ebb3..aaf40d540f7 100644 APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" ;; *) AC_MSG_ERROR([no default app store compliance patch available for $ac_sys_system]) ;; -@@ -745,8 +876,8 @@ +@@ -745,8 +882,8 @@ esac ],[ case $ac_sys_system in @@ -2061,7 +2137,7 @@ index c449bb5ebb3..aaf40d540f7 100644 APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" AC_MSG_RESULT([applying default app store compliance patch]) ;; -@@ -759,6 +890,35 @@ +@@ -759,6 +896,35 @@ ]) AC_SUBST([APP_STORE_COMPLIANCE_PATCH]) @@ -2097,7 +2173,7 @@ index c449bb5ebb3..aaf40d540f7 100644 AC_SUBST([_PYTHON_HOST_PLATFORM]) if test "$cross_compiling" = yes; then case "$host" in -@@ -774,6 +934,26 @@ +@@ -774,6 +940,26 @@ *-*-cygwin*) _host_ident= ;; @@ -2124,7 +2200,7 @@ index c449bb5ebb3..aaf40d540f7 100644 *-apple-ios*) _host_os=`echo $host | cut -d '-' -f3` _host_device=`echo $host | cut -d '-' -f4` -@@ -794,6 +974,70 @@ +@@ -794,6 +980,70 @@ ;; esac ;; @@ -2195,7 +2271,7 @@ index c449bb5ebb3..aaf40d540f7 100644 *-*-darwin*) case "$host_cpu" in arm*) -@@ -883,9 +1127,15 @@ +@@ -883,9 +1133,15 @@ define_xopen_source=no;; Darwin/@<:@[12]@:>@@<:@0-9@:>@.*) define_xopen_source=no;; @@ -2212,7 +2288,7 @@ index c449bb5ebb3..aaf40d540f7 100644 # On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from # defining NI_NUMERICHOST. QNX/6.3.2) -@@ -944,8 +1194,18 @@ +@@ -944,8 +1200,18 @@ CONFIGURE_MACOSX_DEPLOYMENT_TARGET= EXPORT_MACOSX_DEPLOYMENT_TARGET='#' @@ -2232,7 +2308,7 @@ index c449bb5ebb3..aaf40d540f7 100644 # checks for alternative programs -@@ -979,11 +1239,19 @@ +@@ -979,11 +1245,19 @@ ], ) @@ -2253,7 +2329,7 @@ index c449bb5ebb3..aaf40d540f7 100644 ], ) -@@ -1172,6 +1440,9 @@ +@@ -1172,6 +1446,9 @@ AS_CASE([$ac_sys_system], [Darwin*], [MULTIARCH=""], [iOS], [MULTIARCH=""], @@ -2263,7 +2339,7 @@ index c449bb5ebb3..aaf40d540f7 100644 [FreeBSD*], [MULTIARCH=""], [MULTIARCH=$($CC --print-multiarch 2>/dev/null)] ) -@@ -1193,7 +1464,7 @@ +@@ -1193,7 +1470,7 @@ dnl use a single "fat" binary at runtime. SOABI_PLATFORM is the component of dnl the PLATFORM_TRIPLET that will be used in binary module extensions. AS_CASE([$ac_sys_system], @@ -2272,7 +2348,7 @@ index c449bb5ebb3..aaf40d540f7 100644 [SOABI_PLATFORM=$PLATFORM_TRIPLET] ) -@@ -1225,8 +1496,16 @@ +@@ -1225,8 +1502,16 @@ [powerpc64le-*-linux-gnu/clang], [PY_SUPPORT_TIER=3], dnl Linux on PPC64 little endian, glibc, clang [s390x-*-linux-gnu/gcc], [PY_SUPPORT_TIER=3], dnl Linux on 64bit s390x (big endian), glibc, gcc [x86_64-*-freebsd*/clang], [PY_SUPPORT_TIER=3], dnl FreeBSD on AMD64 @@ -2289,7 +2365,7 @@ index c449bb5ebb3..aaf40d540f7 100644 [aarch64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on ARM64 [x86_64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on AMD64 -@@ -1536,7 +1815,7 @@ +@@ -1536,7 +1821,7 @@ case $ac_sys_system in Darwin) LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)';; @@ -2298,7 +2374,7 @@ index c449bb5ebb3..aaf40d540f7 100644 LDLIBRARY='$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)';; *) AC_MSG_ERROR([Unknown platform for framework build]);; -@@ -1601,7 +1880,7 @@ +@@ -1601,7 +1886,7 @@ BLDLIBRARY='-L. -lpython$(LDVERSION)' RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} ;; @@ -2307,7 +2383,7 @@ index c449bb5ebb3..aaf40d540f7 100644 LDLIBRARY='libpython$(LDVERSION).dylib' ;; AIX*) -@@ -3456,7 +3735,7 @@ +@@ -3456,7 +3741,7 @@ BLDSHARED="$LDSHARED" fi ;; @@ -2316,7 +2392,7 @@ index c449bb5ebb3..aaf40d540f7 100644 LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' BLDSHARED="$LDSHARED" -@@ -3580,7 +3859,7 @@ +@@ -3580,7 +3865,7 @@ Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";; Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";; # -u libsys_s pulls in all symbols in libsys @@ -2325,7 +2401,7 @@ index c449bb5ebb3..aaf40d540f7 100644 LINKFORSHARED="$extra_undefs -framework CoreFoundation" # Issue #18075: the default maximum stack size (8MBytes) is too -@@ -3604,7 +3883,7 @@ +@@ -3604,7 +3889,7 @@ LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' fi LINKFORSHARED="$LINKFORSHARED" @@ -2334,7 +2410,7 @@ index c449bb5ebb3..aaf40d540f7 100644 LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' fi ;; -@@ -4024,7 +4303,7 @@ +@@ -4024,7 +4309,7 @@ dnl when do we need USING_APPLE_OS_LIBFFI? ctypes_malloc_closure=yes ], @@ -2343,7 +2419,7 @@ index c449bb5ebb3..aaf40d540f7 100644 ctypes_malloc_closure=yes ], [sunos5], [AS_VAR_APPEND([LIBFFI_LIBS], [" -mimpure-text"])] -@@ -5133,9 +5412,9 @@ +@@ -5133,9 +5418,9 @@ # checks for library functions AC_CHECK_FUNCS([ \ accept4 alarm bind_textdomain_codeset chmod chown clock closefrom close_range confstr \ @@ -2355,7 +2431,7 @@ index c449bb5ebb3..aaf40d540f7 100644 gai_strerror getegid geteuid getgid getgrent getgrgid getgrgid_r \ getgrnam_r getgrouplist gethostname getitimer getloadavg getlogin \ getpeername getpgid getpid getppid getpriority _getpty \ -@@ -5143,8 +5422,7 @@ +@@ -5143,8 +5428,7 @@ getspnam getuid getwd grantpt if_nameindex initgroups kill killpg lchown linkat \ lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \ mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \ @@ -2365,7 +2441,7 @@ index c449bb5ebb3..aaf40d540f7 100644 pread preadv preadv2 process_vm_readv \ pthread_cond_timedwait_relative_np pthread_condattr_setclock pthread_init \ pthread_kill pthread_get_name_np pthread_getname_np pthread_set_name_np -@@ -5154,7 +5432,7 @@ +@@ -5154,7 +5438,7 @@ sched_setparam sched_setscheduler sem_clockwait sem_getvalue sem_open \ sem_timedwait sem_unlink sendfile setegid seteuid setgid sethostname \ setitimer setlocale setpgid setpgrp setpriority setregid setresgid \ @@ -2374,7 +2450,7 @@ index c449bb5ebb3..aaf40d540f7 100644 sigfillset siginterrupt sigpending sigrelse sigtimedwait sigwait \ sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \ sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \ -@@ -5169,12 +5447,20 @@ +@@ -5169,12 +5453,20 @@ AC_CHECK_FUNCS([lchmod]) fi @@ -2398,7 +2474,7 @@ index c449bb5ebb3..aaf40d540f7 100644 fi AC_CHECK_DECL([dirfd], -@@ -5428,20 +5714,22 @@ +@@ -5428,20 +5720,22 @@ ]) # check for openpty, login_tty, and forkpty @@ -2435,7 +2511,7 @@ index c449bb5ebb3..aaf40d540f7 100644 # check for long file support functions AC_CHECK_FUNCS([fseek64 fseeko fstatvfs ftell64 ftello statvfs]) -@@ -5480,10 +5768,10 @@ +@@ -5480,10 +5774,10 @@ ]) ]) @@ -2448,7 +2524,7 @@ index c449bb5ebb3..aaf40d540f7 100644 then AC_CHECK_FUNCS([clock_settime], [], [ AC_CHECK_LIB([rt], [clock_settime], [ -@@ -5641,7 +5929,7 @@ +@@ -5641,7 +5935,7 @@ [ac_cv_buggy_getaddrinfo=no], [ac_cv_buggy_getaddrinfo=yes], [ @@ -2457,7 +2533,7 @@ index c449bb5ebb3..aaf40d540f7 100644 ac_cv_buggy_getaddrinfo="no" elif test "${enable_ipv6+set}" = set; then ac_cv_buggy_getaddrinfo="no -- configured with --(en|dis)able-ipv6" -@@ -6234,8 +6522,8 @@ +@@ -6234,8 +6528,8 @@ LIBPYTHON="\$(BLDLIBRARY)" fi @@ -2468,7 +2544,7 @@ index c449bb5ebb3..aaf40d540f7 100644 MODULE_DEPS_SHARED="$MODULE_DEPS_SHARED \$(PYTHONFRAMEWORKDIR)/\$(PYTHONFRAMEWORK)" fi -@@ -6894,7 +7182,7 @@ +@@ -6894,7 +7188,7 @@ dnl NOTE: Inform user how to proceed with files when cross compiling. dnl Some cross-compile builds are predictable; they won't ever dnl have /dev/ptmx or /dev/ptc, so we can set them explicitly. @@ -2477,7 +2553,7 @@ index c449bb5ebb3..aaf40d540f7 100644 ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no else -@@ -7195,7 +7483,7 @@ +@@ -7195,7 +7489,7 @@ AS_CASE([$ac_sys_system], [Emscripten], [with_ensurepip=no], [WASI], [with_ensurepip=no], @@ -2486,7 +2562,7 @@ index c449bb5ebb3..aaf40d540f7 100644 [with_ensurepip=upgrade] ) ]) -@@ -7582,7 +7870,7 @@ +@@ -7582,7 +7876,7 @@ SunOS*) _PYTHREAD_NAME_MAXLEN=31;; NetBSD*) _PYTHREAD_NAME_MAXLEN=15;; # gh-131268 Darwin) _PYTHREAD_NAME_MAXLEN=63;; @@ -2495,7 +2571,7 @@ index c449bb5ebb3..aaf40d540f7 100644 FreeBSD*) _PYTHREAD_NAME_MAXLEN=19;; # gh-131268 OpenBSD*) _PYTHREAD_NAME_MAXLEN=23;; # gh-131268 *) _PYTHREAD_NAME_MAXLEN=;; -@@ -7607,18 +7895,22 @@ +@@ -7607,18 +7901,22 @@ [VxWorks*], [PY_STDLIB_MOD_SET_NA([_scproxy], [termios], [grp])], dnl The _scproxy module is available on macOS [Darwin], [], @@ -2836,7 +2912,7 @@ index b436c9af99d..9ef96075a01 100644 ) else: diff --git a/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj b/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj -index c7d63909ee2..ace08f7efd9 100644 +index c7d63909ee2..feff0b0c46e 100644 --- a/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj +++ b/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj @@ -70,6 +70,7 @@ @@ -2855,12 +2931,23 @@ index c7d63909ee2..ace08f7efd9 100644 608619552CB7819B00F46182 /* app */, 608619532CB77BA900F46182 /* app_packages */, 607A66592B0F08600010BFC8 /* iOSTestbed-Info.plist */, +@@ -153,9 +155,9 @@ + 607A660E2B0EFA380010BFC8 /* Sources */, + 607A660F2B0EFA380010BFC8 /* Frameworks */, + 607A66102B0EFA380010BFC8 /* Resources */, ++ 607A664E2B0EFC080010BFC8 /* Embed Frameworks */, + 607A66552B0F061D0010BFC8 /* Install Target Specific Python Standard Library */, + 607A66562B0F06200010BFC8 /* Prepare Python Binary Modules */, +- 607A664E2B0EFC080010BFC8 /* Embed Frameworks */, + ); + buildRules = ( + ); @@ -262,7 +264,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -e\n\nmkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-iphonesimulator\" ]; then\n echo \"Installing Python modules for iOS Simulator\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-simulator/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nelse\n echo \"Installing Python modules for iOS Device\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nfi\n"; -+ shellScript = "set -e\n\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-iphonesimulator\" ]; then\n mkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\n echo \"Installing Python modules for iOS Simulator\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-simulator/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nelif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-maccatalyst\" ]; then\n mkdir -p \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python/lib\"\n echo \"Installing Python modules for Mac Catalyst\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-maccatalyst/Python.framework/Versions/3.14/lib/\" \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python/lib/\"\nelse\n mkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\n echo \"Installing Python modules for iOS Device\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\"\nfi\n"; ++ shellScript = "set -e\n\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-iphonesimulator\" ]; then\n mkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\n echo \"Installing Python modules for iOS Simulator\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-simulator/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nelif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-maccatalyst\" ]; then\n : # No action needed; the framework gets embedded\nelse\n mkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\n echo \"Installing Python modules for iOS Device\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\"\nfi\n"; showEnvVarsInLog = 0; }; 607A66562B0F06200010BFC8 /* Prepare Python Binary Modules */ = { @@ -2869,7 +2956,7 @@ index c7d63909ee2..ace08f7efd9 100644 runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -e\n\ninstall_dylib () {\n INSTALL_BASE=$1\n FULL_EXT=$2\n\n # The name of the extension file\n EXT=$(basename \"$FULL_EXT\")\n # The location of the extension file, relative to the bundle\n RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/} \n # The path to the extension file, relative to the install base\n PYTHON_EXT=${RELATIVE_EXT/$INSTALL_BASE/}\n # The full dotted name of the extension module, constructed from the file path.\n FULL_MODULE_NAME=$(echo $PYTHON_EXT | cut -d \".\" -f 1 | tr \"/\" \".\"); \n # A bundle identifier; not actually used, but required by Xcode framework packaging\n FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr \"_\" \"-\")\n # The name of the framework folder.\n FRAMEWORK_FOLDER=\"Frameworks/$FULL_MODULE_NAME.framework\"\n\n # If the framework folder doesn't exist, create it.\n if [ ! -d \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\" ]; then\n echo \"Creating framework for $RELATIVE_EXT\" \n mkdir -p \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\"\n cp \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleExecutable -string \"$FULL_MODULE_NAME\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleIdentifier -string \"$FRAMEWORK_BUNDLE_ID\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n fi\n \n echo \"Installing binary for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" \n mv \"$FULL_EXT\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\"\n # Create a placeholder .fwork file where the .so was\n echo \"$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" > ${FULL_EXT%.so}.fwork\n # Create a back reference to the .so file location in the framework\n echo \"${RELATIVE_EXT%.so}.fwork\" > \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin\" \n}\n\nPYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/python/lib\")\necho \"Install Python $PYTHON_VER standard library extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/python/lib/$PYTHON_VER/lib-dynload\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib python/lib/$PYTHON_VER/lib-dynload/ \"$FULL_EXT\"\ndone\necho \"Install app package extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/app_packages\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app_packages/ \"$FULL_EXT\"\ndone\necho \"Install app extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/app\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app/ \"$FULL_EXT\"\ndone\n\n# Clean up dylib template \nrm -f \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\"\necho \"Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)...\"\nfind \"$CODESIGNING_FOLDER_PATH/Frameworks\" -name \"*.framework\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der \"{}\" \\; \n"; -+ shellScript = "set -e\n\ninstall_dylib () {\n INSTALL_BASE=$1\n FULL_EXT=$2\n\n # The name of the extension file\n EXT=$(basename \"$FULL_EXT\")\n # The location of the extension file, relative to the bundle\n RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/} \n # The path to the extension file, relative to the install base\n PYTHON_EXT=${RELATIVE_EXT/$INSTALL_BASE/}\n # The full dotted name of the extension module, constructed from the file path.\n FULL_MODULE_NAME=$(echo $PYTHON_EXT | cut -d \".\" -f 1 | tr \"/\" \".\"); \n # A bundle identifier; not actually used, but required by Xcode framework packaging\n FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr \"_\" \"-\")\n # The name of the framework folder.\n FRAMEWORK_FOLDER=\"Frameworks/$FULL_MODULE_NAME.framework\"\n\n # If the framework folder doesn't exist, create it.\n if [ ! -d \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\" ]; then\n echo \"Creating framework for $RELATIVE_EXT\" \n mkdir -p \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\"\n cp \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleExecutable -string \"$FULL_MODULE_NAME\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleIdentifier -string \"$FRAMEWORK_BUNDLE_ID\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n fi\n \n echo \"Installing binary for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" \n mv \"$FULL_EXT\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\"\n # Create a placeholder .fwork file where the .so was\n echo \"$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" > ${FULL_EXT%.so}.fwork\n # Create a back reference to the .so file location in the framework\n echo \"${RELATIVE_EXT%.so}.fwork\" > \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin\" \n}\n\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-maccatalyst\" ]; then\n PYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python/lib\")\n find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python/lib/$PYTHON_VER/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 {} \\;\n find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/app_packages\" -name \"*.so\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/app\" -name \"*.so\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n \nelse\n PYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/python/lib\")\n echo \"Install Python $PYTHON_VER standard library extension modules...\"\n find \"$CODESIGNING_FOLDER_PATH/python/lib/$PYTHON_VER/lib-dynload\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib python/lib/$PYTHON_VER/lib-dynload/ \"$FULL_EXT\"\n done\n echo \"Install app package extension modules...\"\n find \"$CODESIGNING_FOLDER_PATH/app_packages\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app_packages/ \"$FULL_EXT\"\n done\n echo \"Install app extension modules...\"\n find \"$CODESIGNING_FOLDER_PATH/app\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app/ \"$FULL_EXT\"\n done\n\n # Clean up dylib template \n rm -f \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\"\n echo \"Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)...\"\n find \"$CODESIGNING_FOLDER_PATH/Frameworks\" -name \"*.framework\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der \"{}\" \\; \nfi\n"; ++ shellScript = "set -e\n\ninstall_dylib () {\n INSTALL_BASE=$1\n FULL_EXT=$2\n\n # The name of the extension file\n EXT=$(basename \"$FULL_EXT\")\n # The location of the extension file, relative to the bundle\n RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/} \n # The path to the extension file, relative to the install base\n PYTHON_EXT=${RELATIVE_EXT/$INSTALL_BASE/}\n # The full dotted name of the extension module, constructed from the file path.\n FULL_MODULE_NAME=$(echo $PYTHON_EXT | cut -d \".\" -f 1 | tr \"/\" \".\"); \n # A bundle identifier; not actually used, but required by Xcode framework packaging\n FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr \"_\" \"-\")\n # The name of the framework folder.\n FRAMEWORK_FOLDER=\"Frameworks/$FULL_MODULE_NAME.framework\"\n\n # If the framework folder doesn't exist, create it.\n if [ ! -d \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\" ]; then\n echo \"Creating framework for $RELATIVE_EXT\" \n mkdir -p \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\"\n cp \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleExecutable -string \"$FULL_MODULE_NAME\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleIdentifier -string \"$FRAMEWORK_BUNDLE_ID\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n fi\n \n echo \"Installing binary for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" \n mv \"$FULL_EXT\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\"\n # Create a placeholder .fwork file where the .so was\n echo \"$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" > ${FULL_EXT%.so}.fwork\n # Create a back reference to the .so file location in the framework\n echo \"${RELATIVE_EXT%.so}.fwork\" > \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin\" \n}\n\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-maccatalyst\" ]; then\n PYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/Contents/Frameworks/Python.framework/Resources/lib\")\n find \"$CODESIGNING_FOLDER_PATH/Contents/Frameworks/Python.framework/Resources/lib/$PYTHON_VER/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 {} \\;\n find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/app_packages\" -name \"*.so\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/app\" -name \"*.so\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n \nelse\n PYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/python/lib\")\n echo \"Install Python $PYTHON_VER standard library extension modules...\"\n find \"$CODESIGNING_FOLDER_PATH/python/lib/$PYTHON_VER/lib-dynload\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib python/lib/$PYTHON_VER/lib-dynload/ \"$FULL_EXT\"\n done\n echo \"Install app package extension modules...\"\n find \"$CODESIGNING_FOLDER_PATH/app_packages\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app_packages/ \"$FULL_EXT\"\n done\n echo \"Install app extension modules...\"\n find \"$CODESIGNING_FOLDER_PATH/app\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app/ \"$FULL_EXT\"\n done\n\n # Clean up dylib template \n rm -f \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\"\n echo \"Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)...\"\n find \"$CODESIGNING_FOLDER_PATH/Frameworks\" -name \"*.framework\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der \"{}\" \\; \nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -2992,6 +3079,32 @@ index c7d63909ee2..ace08f7efd9 100644 + + + +diff --git a/iOS/testbed/iOSTestbedTests/iOSTestbedTests.m b/iOS/testbed/iOSTestbedTests/iOSTestbedTests.m +index dd6e76f9496..6f7b62ebcf0 100644 +--- a/iOS/testbed/iOSTestbedTests/iOSTestbedTests.m ++++ b/iOS/testbed/iOSTestbedTests/iOSTestbedTests.m +@@ -22,6 +22,9 @@ + NSString *path; + wchar_t *wtmp_str; + ++#if TARGET_OS_MACCATALYST ++ NSString *fworkResourcePath = [[NSBundle bundleWithIdentifier:@"org.python.python"] resourcePath]; ++#endif + NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; + + // Set some other common environment indicators to disable color, as the +@@ -76,7 +79,11 @@ + } + + // Set the home for the Python interpreter ++#if TARGET_OS_MACCATALYST ++ python_home = [NSString stringWithFormat:@"%@", fworkResourcePath, nil]; ++#else + python_home = [NSString stringWithFormat:@"%@/python", resourcePath, nil]; ++#endif + NSLog(@"PythonHome: %@", python_home); + wtmp_str = Py_DecodeLocale([python_home UTF8String], NULL); + status = PyConfig_SetString(&config, &config.home, wtmp_str); --- /dev/null +++ b/tvOS/README.rst @@ -0,0 +1,108 @@ From 3d02e52a1cdee1e4dc7bb075c4eb260d2fe7fd09 Mon Sep 17 00:00:00 2001 From: John Zhou Date: Thu, 8 May 2025 17:21:27 -0500 Subject: [PATCH 08/11] Use a separate OS. --- Makefile | 43 +++++++++++------------- patch/Python/release.MacCatalyst.exclude | 6 ++++ 2 files changed, 25 insertions(+), 24 deletions(-) create mode 100644 patch/Python/release.MacCatalyst.exclude diff --git a/Makefile b/Makefile index c1369ce..f9b2452 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ OPENSSL_VERSION=3.0.16-2 XZ_VERSION=5.6.4-2 # Supported OS -OS_LIST=macOS iOS tvOS watchOS visionOS +OS_LIST=macOS iOS tvOS watchOS visionOS MacCatalyst CURL_FLAGS=--disable --fail --location --create-dirs --progress-bar @@ -42,27 +42,37 @@ CURL_FLAGS=--disable --fail --location --create-dirs --progress-bar TARGETS-macOS=macosx.x86_64 macosx.arm64 TRIPLE_OS-macOS=macos VERSION_MIN-macOS=11.0 +CONFIGFLAGS-macOS= # iOS targets -TARGETS-iOS=iphonesimulator.x86_64 iphonesimulator.arm64 iphoneos.arm64 macabi.x86_64 macabi.arm64 +TARGETS-iOS=iphonesimulator.x86_64 iphonesimulator.arm64 iphoneos.arm64 TRIPLE_OS-iOS=ios VERSION_MIN-iOS=13.0 -VERSION_MIN_OVERRIDE-macabi=14.2 -CONFIGFLAGS-macabi=--with-catalyst-macos-version=11.2 +CONFIGFLAGS-iOS= # tvOS targets TARGETS-tvOS=appletvsimulator.x86_64 appletvsimulator.arm64 appletvos.arm64 TRIPLE_OS-tvOS=tvos VERSION_MIN-tvOS=12.0 +CONFIGFLAGS-tvOS= # watchOS targets TARGETS-watchOS=watchsimulator.x86_64 watchsimulator.arm64 watchos.arm64_32 TRIPLE_OS-watchOS=watchos VERSION_MIN-watchOS=4.0 +CONFIGFLAGS-watchOS= +# visionOS targets TARGETS-visionOS=xrsimulator.arm64 xros.arm64 TRIPLE_OS-visionOS=xros VERSION_MIN-visionOS=2.0 +CONFIGFLAGS-visionOS= + +# Mac Catalyst Targets +TARGETS-MacCatalyst=macabi.x86_64 macabi.arm64 +TRIPLE_OS-MacCatalyst=ios +VERSION_MIN-MacCatalyst=14.2 +CONFIGFLAGS-MacCatalyst=--with-catalyst-macos-version=11.2 # The architecture of the machine doing the build HOST_ARCH=$(shell uname -m) @@ -138,30 +148,17 @@ BASE-$(target)=$$(basename $(target)) SDK-$(target)=$$(subst macabi,macosx,$$(BASE-$(target))) ARCH-$(target)=$$(subst .,,$$(suffix $(target))) -# Compute version minimum for the target -VERSION_MIN-$(target)=$$(VERSION_MIN-$(os)) -ifdef VERSION_MIN_OVERRIDE-$$(BASE-$(target)) -VERSION_MIN-$(target)=$$(VERSION_MIN_OVERRIDE-$$(BASE-$(target))) -endif - -# Inherit the basename for the configure flags. -ifdef CONFIGFLAGS-$$(BASE-$(target)) -CONFIGFLAGS-$(target)=$$(CONFIGFLAGS-$$(BASE-$(target))) -else -CONFIGFLAGS-$(target)= -endif - ifneq ($(os),macOS) ifeq ($$(findstring simulator,$$(BASE-$(target))),) ifeq ($$(findstring macabi,$$(BASE-$(target))),) -TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(target)) +TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(os)) IS_SIMULATOR-$(target)=False else -TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(target))-macabi +TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(os))-macabi IS_SIMULATOR-$(target)=False endif else -TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(target))-simulator +TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(os))-simulator IS_SIMULATOR-$(target)=True endif endif @@ -347,7 +344,7 @@ $$(PYTHON_SRCDIR-$(target))/Makefile: \ --with-openssl="$$(OPENSSL_INSTALL-$(target))" \ --enable-framework="$$(PYTHON_INSTALL-$(target))" \ --with-system-libmpdec \ - $$(CONFIGFLAGS-$(target)) \ + $$(CONFIGFLAGS-$(os)) \ 2>&1 | tee -a ../python-$(PYTHON_VERSION).config.log $$(PYTHON_SRCDIR-$(target))/python.exe: $$(PYTHON_SRCDIR-$(target))/Makefile @@ -386,7 +383,7 @@ $$(PYTHON_PLATFORM_SITECUSTOMIZE-$(target)): | sed -e "s/{{platform}}/$$(OS_LOWER-$(target))/g" \ | sed -e "s/{{arch}}/$$(ARCH-$(target))/g" \ | sed -e "s/{{sdk}}/$$(SDK-$(target))/g" \ - | sed -e "s/{{version_min}}/$$(VERSION_MIN-$(target))/g" \ + | sed -e "s/{{version_min}}/$$(VERSION_MIN-$(os))/g" \ | sed -e "s/{{is_simulator}}/$$(IS_SIMULATOR-$(target))/g" \ > $$(PYTHON_PLATFORM_CONFIG-$(target))/_cross_$$(ARCH-$(target))_$$(SDK-$(target)).py cat $(PROJECT_DIR)/patch/Python/sitecustomize.py.tmpl \ @@ -407,8 +404,6 @@ vars-$(target): @echo "BASE-$(target): $$(BASE-$(target))" @echo "SDK-$(target): $$(SDK-$(target))" @echo "ARCH-$(target): $$(ARCH-$(target))" - @echo "CONFIGFLAGS-$(target): $$(CONFIGFLAGS-$(target))" - @echo "VERSION_MIN-$(target): $$(VERSION_MIN-$(target))" @echo "TARGET_TRIPLE-$(target): $$(TARGET_TRIPLE-$(target))" @echo "SDK_ROOT-$(target): $$(SDK_ROOT-$(target))" @echo "BZIP2_INSTALL-$(target): $$(BZIP2_INSTALL-$(target))" diff --git a/patch/Python/release.MacCatalyst.exclude b/patch/Python/release.MacCatalyst.exclude new file mode 100644 index 0000000..f1d0f75 --- /dev/null +++ b/patch/Python/release.MacCatalyst.exclude @@ -0,0 +1,6 @@ +# This is a list of support package path patterns that we exclude +# from all Python-Apple-support tarballs. +# It is used by `tar -X` during the Makefile build. +# Remove pyc files. These take up space, but since most stdlib modules are +# never imported by user code, they mostly have no value. +*/__pycache__ From 933aa141f11d8aaa24d9b165b9eb8bdbce522e2c Mon Sep 17 00:00:00 2001 From: John Zhou Date: Thu, 8 May 2025 17:24:05 -0500 Subject: [PATCH 09/11] fix workflows --- .github/workflows/ci.yaml | 2 +- .github/workflows/publish.yaml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 924ce56..153596e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -89,7 +89,7 @@ jobs: strategy: fail-fast: false matrix: - target: ['macOS', 'iOS', 'tvOS', 'watchOS', 'visionOS'] + target: ['macOS', 'iOS', 'tvOS', 'watchOS', 'visionOS', 'MacCatalyst'] include: - briefcase-run-args: - run-tests: false diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 587abe8..ec42173 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -51,3 +51,6 @@ jobs: # visionOS build curl -o visionOS-artefact.tar.gz -L https://github.com/beeware/Python-Apple-support/releases/download/${{ steps.build-vars.outputs.TAG }}/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-visionOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz aws s3 cp visionOS-artefact.tar.gz s3://briefcase-support/python/${{ steps.build-vars.outputs.PYTHON_VER }}/visionOS/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-visionOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz + # MacCatalyst build + curl -o MacCatalyst-artefact.tar.gz -L https://github.com/beeware/Python-Apple-support/releases/download/${{ steps.build-vars.outputs.TAG }}/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-MacCatalyst-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz + aws s3 cp MacCatalyst-artefact.tar.gz s3://briefcase-support/python/${{ steps.build-vars.outputs.PYTHON_VER }}/MacCatalyst/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-MacCatalyst-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz From d248165b8f8a75aa650ef125b6d961099e2c0cd5 Mon Sep 17 00:00:00 2001 From: John Zhou Date: Thu, 8 May 2025 17:32:46 -0500 Subject: [PATCH 10/11] grumble --- Makefile | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index f9b2452..7905759 100644 --- a/Makefile +++ b/Makefile @@ -299,13 +299,6 @@ PYTHON_PLATFORM_CONFIG-$(target)=$$(PYTHON_INSTALL-$(target))/platform-config/$$ PYTHON_PLATFORM_SITECUSTOMIZE-$(target)=$$(PYTHON_PLATFORM_CONFIG-$(target))/sitecustomize.py - -ifneq ($$(BASE-$(target)),macabi) -RESCDIR-$(target)=$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources -else -RESCDIR-$(target)=$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/MacCatalyst/Resources -endif - $$(PYTHON_SRCDIR-$(target))/configure: \ downloads/Python-$(PYTHON_VERSION).tar.gz \ $$(BZIP2_LIB-$(target)) \ @@ -319,7 +312,7 @@ $$(PYTHON_SRCDIR-$(target))/configure: \ # Apply target Python patches cd $$(PYTHON_SRCDIR-$(target)) && patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch # Make sure the binary scripts are executable - chmod 755 $$(RESCDIR-$(target))/bin/* + chmod 755 $$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin/* # Touch the configure script to ensure that Make identifies it as up to date. touch $$(PYTHON_SRCDIR-$(target))/configure @@ -327,7 +320,7 @@ $$(PYTHON_SRCDIR-$(target))/Makefile: \ $$(PYTHON_SRCDIR-$(target))/configure # Configure target Python cd $$(PYTHON_SRCDIR-$(target)) && \ - PATH="$$(RESCDIR-$(target))/bin:$(PATH)" \ + PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin:$(PATH)" \ ./configure \ LIBLZMA_CFLAGS="-I$$(XZ_INSTALL-$(target))/include" \ LIBLZMA_LIBS="-L$$(XZ_INSTALL-$(target))/lib -llzma" \ @@ -351,14 +344,14 @@ $$(PYTHON_SRCDIR-$(target))/python.exe: $$(PYTHON_SRCDIR-$(target))/Makefile @echo ">>> Build Python for $(target)" cd $$(PYTHON_SRCDIR-$(target)) && \ - PATH="$$(RESCDIR-$(target))/bin:$(PATH)" \ + PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin:$(PATH)" \ make -j8 all \ 2>&1 | tee -a ../python-$(PYTHON_VERSION).build.log $$(PYTHON_LIB-$(target)): $$(PYTHON_SRCDIR-$(target))/python.exe @echo ">>> Install Python for $(target)" cd $$(PYTHON_SRCDIR-$(target)) && \ - PATH="$$(RESCDIR-$(target))/bin:$(PATH)" \ + PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin:$(PATH)" \ make install \ 2>&1 | tee -a ../python-$(PYTHON_VERSION).install.log @@ -567,7 +560,7 @@ else $$(foreach target,$$(SDK_TARGETS-$(sdk)),cp $$(PYTHON_INCLUDE-$$(target))/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig-$$(ARCH-$$(target)).h; ) # Copy the cross-target header from the source folder of the first target in the $(sdk) SDK - cp $$(RESCDIR-$$(firstword $$(SDK_TARGETS-$(sdk))))/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h + cp $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$(sdk))))/$(os)/Resources/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h endif ifneq ($(sdk),macabi) @@ -739,7 +732,7 @@ $$(PYTHON_XCFRAMEWORK-$(os))/Info.plist: \ $$(foreach sdk,$$(filter-out macabi,$$(SDKS-$(os))),cp -r $$(PYTHON_INSTALL-$$(sdk))/lib $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/platform-config $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) -ifeq ($(filter $(os),iOS visionOS),$(os)) +ifeq ($(filter $(os),iOS visionOS MacCatalyst),$(os)) @echo ">>> Clone testbed project for $(os)" $(HOST_PYTHON) $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/$(os)/testbed clone --framework $$(PYTHON_XCFRAMEWORK-$(os)) support/$(PYTHON_VER)/$(os)/testbed endif From e19e672f26dfc6db37ffc1e6c0e55eb869fd6d85 Mon Sep 17 00:00:00 2001 From: John Zhou Date: Thu, 8 May 2025 17:40:50 -0500 Subject: [PATCH 11/11] more grumbling... why did i even request a review? --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7905759..610763c 100644 --- a/Makefile +++ b/Makefile @@ -734,7 +734,7 @@ $$(PYTHON_XCFRAMEWORK-$(os))/Info.plist: \ ifeq ($(filter $(os),iOS visionOS MacCatalyst),$(os)) @echo ">>> Clone testbed project for $(os)" - $(HOST_PYTHON) $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/$(os)/testbed clone --framework $$(PYTHON_XCFRAMEWORK-$(os)) support/$(PYTHON_VER)/$(os)/testbed + $(HOST_PYTHON) $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/$$(subst MacCatalyst,iOS,$(os))/testbed clone --framework $$(PYTHON_XCFRAMEWORK-$(os)) support/$(PYTHON_VER)/$(os)/testbed endif @echo ">>> Create VERSIONS file for $(os)"