diff --git a/.gitignore b/.gitignore
index 5ecdde8ee32ce90..0212701e9a349c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -72,16 +72,19 @@ Lib/test/data/*
/_bootstrap_python
/Makefile
/Makefile.pre
-/iOSTestbed.*
-Apple/iOS/Frameworks/
-Apple/iOS/Resources/Info.plist
-Apple/testbed/build
+/AppleTestbed.*
+Platforms/Apple/iOS/Frameworks/*
+Platforms/Apple/iOS/Resources/Info.plist
Platforms/Apple/testbed/Python*.xcframework/*/bin
Platforms/Apple/testbed/Python*.xcframework/*/include
Platforms/Apple/testbed/Python*.xcframework/*/lib
Platforms/Apple/testbed/Python*.xcframework/*/Python*.framework
-Apple/testbed/*Testbed.xcodeproj/project.xcworkspace
-Apple/testbed/*Testbed.xcodeproj/xcuserdata
+Platforms/Apple/tvOS/Frameworks/*
+Platforms/Apple/tvOS/Resources/Info.plist
+Platforms/Apple/visionOS/Frameworks/*
+Platforms/Apple/visionOS/Resources/Info.plist
+Platforms/Apple/watchOS/Frameworks/*
+Platforms/Apple/watchOS/Resources/Info.plist
Mac/Makefile
Mac/PythonLauncher/Info.plist
Mac/PythonLauncher/Makefile
diff --git a/Include/cpython/object.h b/Include/cpython/object.h
index 12d2e614623e30b..da94a640fc86430 100644
--- a/Include/cpython/object.h
+++ b/Include/cpython/object.h
@@ -469,8 +469,12 @@ _Py_ThreadId(void)
#elif defined(__arm__) && __ARM_ARCH >= 7
__asm__ ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tid));
#elif defined(__aarch64__) && defined(__APPLE__)
- __asm__ ("mrs %0, tpidrro_el0" : "=r" (tid));
-#elif defined(__aarch64__)
+ // Use a 64-bit temporary: on arm64_32 (ILP32), uintptr_t is 32 bits
+ // but system registers are 64 bits.
+ uint64_t tp;
+ __asm__ ("mrs %0, tpidrro_el0" : "=r" (tp));
+ tid = (uintptr_t)tp;
+#elif defined (__aarch64__)
__asm__ ("mrs %0, tpidr_el0" : "=r" (tid));
#elif defined(__powerpc64__)
#if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer)
diff --git a/Include/internal/mimalloc/mimalloc/prim.h b/Include/internal/mimalloc/mimalloc/prim.h
index a73d795c7d4f8fe..fce93b132af2904 100644
--- a/Include/internal/mimalloc/mimalloc/prim.h
+++ b/Include/internal/mimalloc/mimalloc/prim.h
@@ -166,12 +166,17 @@ static inline void* mi_prim_tls_slot(size_t slot) mi_attr_noexcept {
__asm__ volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb));
res = tcb[slot];
#elif defined(__aarch64__)
- void** tcb; MI_UNUSED(ofs);
+ // CPython: patched for watchOS support.
+ // Submitted upstream as microsoft/mimalloc#1444
+ // Use a 64-bit temporary: on arm64_32 (ILP32), pointers are 32 bits
+ // but system registers are 64 bits.
+ uint64_t tp; MI_UNUSED(ofs);
#if defined(__APPLE__) // M1, issue #343
- __asm__ volatile ("mrs %0, tpidrro_el0\nbic %0, %0, #7" : "=r" (tcb));
+ __asm__ volatile ("mrs %0, tpidrro_el0\nbic %0, %0, #7" : "=r" (tp));
#else
- __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb));
+ __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tp));
#endif
+ void** tcb = (void**)(uintptr_t)tp;
res = tcb[slot];
#elif defined(__riscv)
void** tcb; MI_UNUSED(ofs);
@@ -200,12 +205,15 @@ static inline void mi_prim_tls_slot_set(size_t slot, void* value) mi_attr_noexce
__asm__ volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb));
tcb[slot] = value;
#elif defined(__aarch64__)
- void** tcb; MI_UNUSED(ofs);
+ // Use a 64-bit temporary: on arm64_32 (ILP32), pointers are 32 bits
+ // but system registers are 64 bits.
+ uint64_t tp; MI_UNUSED(ofs);
#if defined(__APPLE__) // M1, issue #343
- __asm__ volatile ("mrs %0, tpidrro_el0\nbic %0, %0, #7" : "=r" (tcb));
+ __asm__ volatile ("mrs %0, tpidrro_el0\nbic %0, %0, #7" : "=r" (tp));
#else
- __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb));
+ __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tp));
#endif
+ void** tcb = (void**)(uintptr_t)tp;
tcb[slot] = value;
#elif defined(__riscv)
void** tcb; MI_UNUSED(ofs);
diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h
index 16f876140020bb7..0a764d886c6a31c 100644
--- a/Include/internal/pycore_pystate.h
+++ b/Include/internal/pycore_pystate.h
@@ -342,7 +342,11 @@ _Py_get_machine_stack_pointer(void) {
#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
result = (uintptr_t)_AddressOfReturnAddress();
#elif defined(__aarch64__)
- __asm__ ("mov %0, sp" : "=r" (result));
+ // Use a 64-bit temporary: on arm64_32 (ILP32), uintptr_t is 32 bits
+ // but sp is a 64-bit register.
+ uint64_t sp;
+ __asm__ ("mov %0, sp" : "=r" (sp));
+ result = (uintptr_t)sp;
#elif defined(__x86_64__)
__asm__ ("{movq %%rsp, %0|mov %0, rsp}" : "=r" (result));
#else
diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py
index 4b41bc7869de1dd..e9e60d8874f7d40 100644
--- a/Lib/asyncio/unix_events.py
+++ b/Lib/asyncio/unix_events.py
@@ -681,10 +681,10 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None):
# end polls as readable whenever unread data sits in the FIFO, and no
# event is delivered when the read end is closed, so it can only
# ever report a false disconnection (gh-145030). The same XNU
- # behaviour applies on iOS/tvOS/watchOS (sys.platform is not
+ # behaviour applies on iOS/tvOS/visionOS/watchOS (sys.platform is not
# "darwin" there).
is_named_fifo_without_close_event = (
- sys.platform in {"darwin", "ios", "tvos", "watchos", "sunos5"}
+ sys.platform in {"darwin", "ios", "tvos", "visionos", "watchos", "sunos5"}
and is_fifo and pipe_stat.st_nlink > 0)
if is_socket or (is_fifo
and not sys.platform.startswith("aix")
diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py
index 8b7089b6e578a9d..695851b7ef11f57 100644
--- a/Lib/ctypes/__init__.py
+++ b/Lib/ctypes/__init__.py
@@ -447,9 +447,9 @@ def _load_library(self, name, mode, handle, winmode):
else:
def _load_library(self, name, mode, handle, winmode):
- # If the filename that has been provided is an iOS/tvOS/watchOS
- # .fwork file, dereference the location to the true origin of the
- # binary.
+ # If the filename that has been provided is an iOS, tvOS, visionOS
+ # or watchOS .fwork file, dereference the location to the true
+ # origin of the binary.
if name and name.endswith(".fwork"):
with open(name) as f:
name = _os.path.join(
diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py
index f4fb05c29b4ca45..3ca2458a2a653e2 100644
--- a/Lib/ctypes/util.py
+++ b/Lib/ctypes/util.py
@@ -104,7 +104,7 @@ def dllist():
if (name := _get_module_filename(h)) is not None]
return libraries
-elif os.name == "posix" and sys.platform in {"darwin", "ios", "tvos", "watchos"}:
+elif os.name == "posix" and sys.platform in {"darwin", "ios", "tvos", "visionos", "watchos"}:
from ctypes.macholib.dyld import dyld_find as _dyld_find
def find_library(name):
possible = ['lib%s.dylib' % name,
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index 484e0457eb0d732..2c8d482e4f64366 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -55,7 +55,7 @@
# Bootstrap-related code ######################################################
_CASE_INSENSITIVE_PLATFORMS_STR_KEY = 'win',
-_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin', 'ios', 'tvos', 'watchos'
+_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin', 'ios', 'tvos', 'visionos', 'watchos'
_CASE_INSENSITIVE_PLATFORMS = (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY
+ _CASE_INSENSITIVE_PLATFORMS_STR_KEY)
@@ -1570,7 +1570,7 @@ def _get_supported_file_loaders():
"""
extension_loaders = []
if hasattr(_imp, 'create_dynamic'):
- if sys.platform in {"ios", "tvos", "watchos"}:
+ if sys.platform in {"ios", "tvos", "visionos", "watchos"}:
extension_loaders = [(AppleFrameworkLoader, [
suffix.replace(".so", ".fwork")
for suffix in _imp.extension_suffixes()
diff --git a/Lib/platform.py b/Lib/platform.py
index c4ef1c3eb20edf4..cd71bafadd9e04f 100644
--- a/Lib/platform.py
+++ b/Lib/platform.py
@@ -526,13 +526,13 @@ def mac_ver(release='', versioninfo=('', '', ''), machine=''):
def ios_ver(system="", release="", model="", is_simulator=False):
- """Get iOS version information, and return it as a namedtuple:
- (system, release, model, is_simulator).
+ """Get iOS/tvOS/watchOS/visionOS version information, and return it as a
+ namedtuple: (system, release, model, is_simulator).
If values can't be determined, they are set to values provided as
parameters.
"""
- if sys.platform == "ios":
+ if sys.platform in {"ios", "tvos", "visionos", "watchos"}:
import _ios_support
result = _ios_support.get_platform_ios()
if result is not None:
@@ -685,7 +685,7 @@ def _syscmd_file(target, default=''):
default in case the command should fail.
"""
- if sys.platform in {'dos', 'win32', 'win16', 'ios', 'tvos', 'watchos'}:
+ if sys.platform in {'dos', 'win32', 'win16', 'ios', 'tvos', 'visionos', 'watchos'}:
# XXX Others too ?
return default
@@ -849,14 +849,30 @@ def get_OpenVMS():
csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0)
return 'Alpha' if cpu_number >= 128 else 'VAX'
- # On the iOS simulator, os.uname returns the architecture as uname.machine.
- # On device it returns the model name for some reason; but there's only one
- # CPU architecture for iOS devices, so we know the right answer.
+ # On the iOS/tvOS/visionOS/watchOS simulator, os.uname returns the
+ # architecture as uname.machine. On device it returns the model name for
+ # some reason; but 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'
+ def get_tvos():
+ if sys.implementation._multiarch.endswith("simulator"):
+ return os.uname().machine
+ return 'arm64'
+
+ def get_visionos():
+ if sys.implementation._multiarch.endswith("simulator"):
+ return os.uname().machine
+ return 'arm64'
+
+ def get_watchos():
+ if sys.implementation._multiarch.endswith("simulator"):
+ return os.uname().machine
+ return 'arm64_32'
+
def from_subprocess():
"""
Fall back to `uname -p`
@@ -1009,8 +1025,8 @@ def uname():
system = 'Android'
release = android_ver().release
- # Normalize responses on iOS
- if sys.platform == 'ios':
+ # Normalize responses on Apple mobile platforms
+ if sys.platform in {"ios", "tvos", "visionos", "watchos"}:
system, release, _, _ = ios_ver()
vals = system, node, release, version, machine
@@ -1299,7 +1315,7 @@ def platform(aliased=False, terse=False):
if system == 'Darwin':
# macOS and iOS both report as a "Darwin" kernel
- if sys.platform == "ios":
+ if sys.platform in {"ios", "tvos", "visionos", "watchos"}:
system, release, _, _ = ios_ver()
else:
macos_release = mac_ver()[0]
diff --git a/Lib/site.py b/Lib/site.py
index 294a4d6f641c39d..d763168afbd33cb 100644
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -653,8 +653,8 @@ def _getuserbase():
if env_base:
return env_base
- # Emscripten, iOS, tvOS, VxWorks, WASI, and watchOS have no home directories
- if sys.platform in {"emscripten", "ios", "tvos", "vxworks", "wasi", "watchos"}:
+ # Emscripten, iOS, tvOS, visionOS, VxWorks, WASI, and watchOS have no home directories
+ if sys.platform in {"emscripten", "ios", "tvos", "vxworks", "visionos", "wasi", "watchos"}:
return None
def joinuser(*args):
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index 466f2c10a2c3d4d..e2dac4938d57d28 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -75,7 +75,7 @@
_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", "visionos", "watchos"}
if _mswindows:
import _winapi
diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py
index 0657e458806e9b6..dfed1cd1435c995 100644
--- a/Lib/sysconfig/__init__.py
+++ b/Lib/sysconfig/__init__.py
@@ -23,6 +23,9 @@
_ALWAYS_STR = {
'IPHONEOS_DEPLOYMENT_TARGET',
'MACOSX_DEPLOYMENT_TARGET',
+ 'TVOS_DEPLOYMENT_TARGET',
+ 'WATCHOS_DEPLOYMENT_TARGET',
+ 'XROS_DEPLOYMENT_TARGET',
}
_INSTALL_SCHEMES = {
@@ -119,7 +122,7 @@ def _getuserbase():
# Emscripten, iOS, tvOS, VxWorks, WASI, and watchOS have no home directories.
# Use _PYTHON_HOST_PLATFORM to get the correct platform when cross-compiling.
system_name = os.environ.get('_PYTHON_HOST_PLATFORM', sys.platform).split('-')[0]
- if system_name in {"emscripten", "ios", "tvos", "vxworks", "wasi", "watchos"}:
+ if system_name in {"emscripten", "ios", "tvos", "visionos", "vxworks", "wasi", "watchos"}:
return None
def joinuser(*args):
@@ -750,6 +753,18 @@ def get_platform():
release = get_config_vars().get("IPHONEOS_DEPLOYMENT_TARGET", "13.0")
osname = sys.platform
machine = sys.implementation._multiarch
+ elif sys.platform == "tvos":
+ release = get_config_vars().get("TVOS_DEPLOYMENT_TARGET", "12.0")
+ osname = sys.platform
+ machine = sys.implementation._multiarch
+ elif sys.platform == "watchos":
+ release = get_config_vars().get("WATCHOS_DEPLOYMENT_TARGET", "9.0")
+ osname = sys.platform
+ machine = sys.implementation._multiarch
+ elif sys.platform == "visionos":
+ release = get_config_vars().get("XROS_DEPLOYMENT_TARGET", "2.0")
+ osname = sys.platform
+ machine = sys.implementation._multiarch
else:
import _osx_support
osname, release, machine = _osx_support.get_platform_osx(
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
index df7d540cb362f75..c74a42ab127ab54 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -7475,9 +7475,9 @@ def test_datetime_from_timestamp(self):
self.assertEqual(dt_orig, dt_rt)
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.
- if sys.platform == "ios":
+ if support.is_apple_mobile:
extension_loader = "AppleFrameworkLoader"
else:
extension_loader = "ExtensionFileLoader"
diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py
index bc6735d0749f526..4b31d2f775e4be9 100644
--- a/Lib/test/pythoninfo.py
+++ b/Lib/test/pythoninfo.py
@@ -9,7 +9,7 @@
MS_WINDOWS = (sys.platform == "win32")
-APPLE = (sys.platform in ("darwin", "ios", "tvos", "watchos"))
+APPLE = (sys.platform in ("darwin", "ios", "tvos", "watchos", "visionos"))
COMMAND_TIMEOUT = 60.0
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 8950aa985421d99..4f27a23b1a62b1d 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -628,7 +628,7 @@ def skip_android_selinux(name):
sys.platform == "android", f"Android blocks {name} with SELinux"
)
-if sys.platform not in {"win32", "vxworks", "ios", "tvos", "watchos"}:
+if sys.platform not in {"win32", "vxworks", "ios", "tvos", "visionos", "watchos"}:
unix_shell = '/system/bin/sh' if is_android else '/bin/sh'
else:
unix_shell = None
@@ -647,7 +647,7 @@ def skip_emscripten_stack_overflow():
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", "visionos", "watchos"}
is_apple = is_apple_mobile or sys.platform == "darwin"
has_fork_support = hasattr(os, "fork") and not (
diff --git a/Lib/test/test__interpreters.py b/Lib/test/test__interpreters.py
index ec5a26bc1c05ad8..1b66f9c7646eb72 100644
--- a/Lib/test/test__interpreters.py
+++ b/Lib/test/test__interpreters.py
@@ -612,6 +612,7 @@ def test_shareable_types(self):
f'assert(obj == {obj!r})',
)
+ @support.requires_subprocess()
def test_os_exec(self):
expected = 'spam spam spam spam spam'
subinterp = _interpreters.create()
diff --git a/Lib/test/test_ctypes/test_dllist.py b/Lib/test/test_ctypes/test_dllist.py
index 15603dc3d779726..bff6c0fb95f129e 100644
--- a/Lib/test/test_ctypes/test_dllist.py
+++ b/Lib/test/test_ctypes/test_dllist.py
@@ -7,7 +7,7 @@
WINDOWS = os.name == "nt"
-APPLE = sys.platform in {"darwin", "ios", "tvos", "watchos"}
+APPLE = sys.platform in {"darwin", "ios", "tvos", "watchos", "visionos"}
if WINDOWS:
KNOWN_LIBRARIES = ["KERNEL32.DLL"]
diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py
index 3503eaefaf8e9e7..792a47298caed56 100644
--- a/Lib/test/test_platform.py
+++ b/Lib/test/test_platform.py
@@ -287,12 +287,18 @@ def test_uname(self):
if sys.platform == "android":
self.assertEqual(res.system, "Android")
self.assertEqual(res.release, platform.android_ver().release)
- elif sys.platform == "ios":
+ elif support.is_apple_mobile:
# Platform module needs ctypes for full operation. If ctypes
# isn't available, there's no ObjC module, and dummy values are
# returned.
if _ctypes:
- self.assertIn(res.system, {"iOS", "iPadOS"})
+ if sys.platform == "ios":
+ # iPads also identify as iOS
+ self.assertIn(res.system, {"iOS", "iPadOS"})
+ else:
+ # All other platforms - sys.platform is the lower case
+ # form of system (e.g., visionOS->visionos)
+ self.assertEqual(res.system.lower(), sys.platform)
self.assertEqual(res.release, platform.ios_ver().release)
else:
self.assertEqual(res.system, "")
@@ -485,8 +491,8 @@ def test_mac_ver_with_fork(self):
def test_ios_ver(self):
result = platform.ios_ver()
- # ios_ver is only fully available on iOS where ctypes is available.
- if sys.platform == "ios" and _ctypes:
+ # ios_ver is only fully available on Apple mobile platorms where ctypes is available.
+ if sys.platform in {"ios", "tvos", "visionos", "watchos"} and _ctypes:
system, release, model, is_simulator = result
# Result is a namedtuple
self.assertEqual(result.system, system)
@@ -498,7 +504,10 @@ def test_ios_ver(self):
# ios_ver(), so we check that the values are broadly what we expect.
# System is either iOS or iPadOS, depending on the test device
- self.assertIn(system, {"iOS", "iPadOS"})
+ if sys.platform == "ios":
+ self.assertIn(system, {"iOS", "iPadOS"})
+ else:
+ self.assertEqual(system.lower(), sys.platform)
# Release is a numeric version specifier with at least 2 parts
parts = release.split(".")
@@ -508,11 +517,17 @@ def test_ios_ver(self):
# If this is a simulator, we get a high level device descriptor
# with no identifying model number. If this is a physical device,
# we get a model descriptor like "iPhone13,1"
+ devices = {
+ "ios": {"iPhone", "iPad"},
+ "tvos": {"Apple TV"},
+ "visionos": {"Apple Vision Pro"},
+ "watchos": {"Apple Watch"},
+ }[sys.platform]
if is_simulator:
- self.assertIn(model, {"iPhone", "iPad"})
+ self.assertIn(model, devices)
else:
self.assertTrue(
- (model.startswith("iPhone") or model.startswith("iPad"))
+ any(model.startswith(d) for d in devices)
and "," in model
)
diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py
index 82f14ca968f266b..52e06832e6a6974 100644
--- a/Lib/test/test_webbrowser.py
+++ b/Lib/test/test_webbrowser.py
@@ -254,7 +254,8 @@ def test_open_new_tab(self):
arguments=[f'openURL({URL},new-tab)'])
-@unittest.skipUnless(sys.platform == "ios", "Test only applicable to iOS")
+@unittest.skipUnless(sys.platform in {"ios", "visionOS"},
+ "Test only applicable to iOS and visionOS")
class IOSBrowserTest(unittest.TestCase):
def _obj_ref(self, *args):
# Construct a string representation of the arguments that can be used
diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py
index ec8b544a6b05235..260208440230dca 100644
--- a/Lib/webbrowser.py
+++ b/Lib/webbrowser.py
@@ -505,7 +505,8 @@ def register_standard_browsers():
# macOS can use below Unix support (but we prefer using the macOS
# specific stuff)
- if sys.platform == "ios":
+ if sys.platform in {"ios", "visionos"}:
+ # iOS and visionOS provide a browser; tvOS and watchOS don't.
register("iosbrowser", None, IOSBrowser(), preferred=True)
if sys.platform == "serenityos":
@@ -744,9 +745,10 @@ def open(self, url, new=0, autoraise=True):
return not rc
#
-# Platform support for iOS
+# Platform support for Apple Mobile platforms that provide a browser
+# (i.e., iOS and visionOS)
#
-if sys.platform == "ios":
+if sys.platform in {"ios", "visionos"}:
from _ios_support import objc
if objc:
# If objc exists, we know ctypes is also importable.
diff --git a/Makefile.pre.in b/Makefile.pre.in
index cae9cae9d779bea..46cbb6598506412 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -217,6 +217,12 @@ IPHONEOS_DEPLOYMENT_TARGET=@IPHONEOS_DEPLOYMENT_TARGET@
BUILD_DETAILS=@BUILD_DETAILS@
+# visionOS Deployment target is *actually* used during the build, by the
+# compiler shims; export.
+XROS_DEPLOYMENT_TARGET=@XROS_DEPLOYMENT_TARGET@
+@EXPORT_XROS_DEPLOYMENT_TARGET@export XROS_DEPLOYMENT_TARGET
+
+
# Option to install to strip binaries
STRIPFLAG=-s
@@ -2292,30 +2298,31 @@ testuniversal: all
$(RUNSHARED) /usr/libexec/oah/translate \
./$(BUILDPYTHON) -E -m test -j 0 -u all $(TESTOPTS)
-# Run the test suite on the iOS simulator. Must be run on a macOS machine with
-# a full Xcode install that has an iPhone SE (3rd edition) simulator available.
+# Run the test suite on an Apple Mobile (i.e., iOS/tvOS/watchOS/visionOS)
+# device simulator. Must be run on a macOS machine with a full Xcode install
+# that has an SE-class simulator available for the chosen platform.
# This must be run *after* a `make install` has completed the build. The
# testbed is configured for the framework name used to configure the build;
# that name is expected to be `Python`, optionally followed by uppercased ABI
# flags (e.g., `PythonT`).
-XCFOLDER:=iOSTestbed.$(MULTIARCH).$(shell date +%s).$$PPID
+XCFOLDER:=AppleTestbed.$(MULTIARCH).$(shell date +%s).$$PPID
.PHONY: testios
testios:
- @if test "$(MACHDEP)" != "ios"; then \
- echo "Cannot run the iOS testbed for a non-iOS build."; \
+ @if test "$(MACHDEP)" != "ios" -a "$(MACHDEP)" != "tvos" -a "$(MACHDEP)" != "visionos" -a "$(MACHDEP)" != "watchos" ; then \
+ echo "Cannot run the Apple mobile testbed for a $(MACHDEP) build."; \
exit 1;\
fi
- @if test "$(findstring -iphonesimulator,$(MULTIARCH))" != "-iphonesimulator"; then \
- echo "Cannot run the iOS testbed for non-simulator builds."; \
+ @if test "$(findstring simulator,$(MULTIARCH))" != "simulator"; then \
+ echo "Cannot run the Apple mobile testbed for non-simulator builds."; \
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 Python.framework. Have you run 'make install' to finalize the framework build?"; \
exit 1;\
fi
# Clone the testbed project into the XCFOLDER
- $(PYTHON_FOR_BUILD) $(srcdir)/Platforms/Apple/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER)"
+ $(PYTHON_FOR_BUILD) $(srcdir)/Platforms/Apple/testbed clone --platform $(MACHDEP) --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER)"
# Run the testbed project
$(PYTHON_FOR_BUILD) "$(XCFOLDER)" run --verbose -- test -uall --single-process --rerun -W --pythoninfo
diff --git a/Misc/NEWS.d/next/Build/2026-10-20-12-06-22.gh-issue-131999.OWoYGM.rst b/Misc/NEWS.d/next/Build/2026-10-20-12-06-22.gh-issue-131999.OWoYGM.rst
new file mode 100644
index 000000000000000..8f282fa2d14c891
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2026-10-20-12-06-22.gh-issue-131999.OWoYGM.rst
@@ -0,0 +1 @@
+Platform support for Apple's tvOS, watchOS and visionOS was added.
diff --git a/Misc/platform_triplet.c b/Misc/platform_triplet.c
index f5cd73bdea83335..6c1863c943b3539 100644
--- a/Misc/platform_triplet.c
+++ b/Misc/platform_triplet.c
@@ -257,6 +257,32 @@ PLATFORM_TRIPLET=arm64-iphonesimulator
# else
PLATFORM_TRIPLET=arm64-iphoneos
# endif
+# elif defined(TARGET_OS_TV) && TARGET_OS_TV
+# if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR
+# if __x86_64__
+PLATFORM_TRIPLET=x86_64-appletvsimulator
+# else
+PLATFORM_TRIPLET=arm64-appletvsimulator
+# endif
+# else
+PLATFORM_TRIPLET=arm64-appletvos
+# endif
+# elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH
+# if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR
+# if __x86_64__
+PLATFORM_TRIPLET=x86_64-watchsimulator
+# else
+PLATFORM_TRIPLET=arm64-watchsimulator
+# endif
+# else
+PLATFORM_TRIPLET=arm64_32-watchos
+# endif
+# elif defined(TARGET_OS_VISION) && TARGET_OS_VISION
+# if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR
+PLATFORM_TRIPLET=arm64-xrsimulator
+# else
+PLATFORM_TRIPLET=arm64-xros
+# endif
// Older macOS SDKs do not define TARGET_OS_OSX
# elif !defined(TARGET_OS_OSX) || TARGET_OS_OSX
PLATFORM_TRIPLET=darwin
diff --git a/Platforms/Apple/__main__.py b/Platforms/Apple/__main__.py
index fa40f45ae2805cc..b31b20c2c26f34e 100644
--- a/Platforms/Apple/__main__.py
+++ b/Platforms/Apple/__main__.py
@@ -5,17 +5,20 @@
# This script simplifies the process of configuring, compiling and packaging an
# XCframework for an Apple platform.
#
-# At present, it only supports iOS, but it has been constructed so that it
-# could be used on any Apple platform.
+# At present, it supports iOS, tvOS, visionOS and watchOS, but it has been
+# constructed so that it could be used on any Apple platform.
#
# The simplest entry point is:
#
# $ python Platforms/Apple ci iOS
#
+# (replace iOS with tvOS, visionOS or watchOS as required.)
+#
# which will:
# * Clean any pre-existing build artefacts
# * Configure and make a Python that can be used for the build
-# * Configure and make a Python for each supported iOS architecture and ABI
+# * Configure and make a Python for each supported iOS/tvOS/watchOS/visionOS
+# architecture and ABI
# * Combine the outputs of the builds from the previous step into a single
# XCframework, merging binaries into a "fat" binary if necessary
# * Clone a copy of the testbed, configured to use the XCframework
@@ -75,6 +78,32 @@
"x86_64-apple-ios-simulator": "x86_64-iphonesimulator",
},
},
+ "tvOS": {
+ "tvos-arm64": {
+ "arm64-apple-tvos": "arm64-appletvos",
+ },
+ "tvos-arm64_x86_64-simulator": {
+ "arm64-apple-tvos-simulator": "arm64-appletvsimulator",
+ "x86_64-apple-tvos-simulator": "x86_64-appletvsimulator",
+ },
+ },
+ "visionOS": {
+ "xros-arm64": {
+ "arm64-apple-xros": "arm64-xros",
+ },
+ "xros-arm64-simulator": {
+ "arm64-apple-xros-simulator": "arm64-xrsimulator",
+ },
+ },
+ "watchOS": {
+ "watchos-arm64_32": {
+ "arm64_32-apple-watchos": "arm64_32-watchos",
+ },
+ "watchos-arm64_x86_64-simulator": {
+ "arm64-apple-watchos-simulator": "arm64-watchsimulator",
+ "x86_64-apple-watchos-simulator": "x86_64-watchsimulator",
+ },
+ },
}
# The configure arguments needed to produce each ABI flag. Flags are listed in
@@ -86,6 +115,11 @@
}
+def platform_name(value):
+ """Return the canonical spelling for a platform name."""
+ return {p.lower(): p for p in HOSTS.keys()}.get(value.lower(), value)
+
+
def validate_abiflags(value: str) -> str:
"""Validate an `--abiflags` value (for use as an argparse type)."""
known = "".join(ABIFLAG_CONFIGURE_ARGS)
@@ -175,11 +209,24 @@ def print_env(env: EnvironmentT) -> None:
print(f"export {key}={shlex.quote(value)}")
+def platform_for_host(host):
+ """Determine the platform for a given host triple."""
+ for plat, slices in HOSTS.items():
+ for _, candidates in slices.items():
+ for candidate in candidates:
+ if candidate == host:
+ return plat
+ raise KeyError(host)
+
+
def apple_env(host: str) -> EnvironmentT:
"""Construct an Apple development environment for the given host."""
env = {
"PATH": ":".join([
- str(PYTHON_DIR / "Platforms/Apple/iOS/Resources/bin"),
+ str(
+ PYTHON_DIR
+ / f"Platforms/Apple/{platform_for_host(host)}/Resources/bin"
+ ),
str(subdir(host) / "prefix"),
"/usr/bin",
"/bin",
@@ -354,8 +401,8 @@ def unpack_deps(
Downloads binaries if they aren't already present. Downloads will be stored
in provided cache directory.
- On iOS, as a safety mechanism, any dynamic libraries will be purged from
- the unpacked dependencies.
+ On non-macOS platforms, as a safety mechanism, any dynamic libraries will
+ be purged from the unpacked dependencies.
"""
# To create new builds of these dependencies, usually all that's necessary
# is to push a tag to the cpython-apple-source-deps repository, and GitHub
@@ -380,9 +427,9 @@ def unpack_deps(
)
shutil.unpack_archive(archive_path, prefix_dir)
- # Dynamic libraries will be preferentially linked over static;
- # On iOS, ensure that no dylibs are available in the prefix folder.
- if platform == "iOS":
+ # Dynamic libraries will be preferentially linked over static; On non-macOS
+ # platforms, ensure that no dylibs are available in the prefix folder.
+ if platform != "macOS":
for dylib in prefix_dir.glob("**/*.dylib"):
dylib.unlink()
@@ -448,6 +495,7 @@ def configure_host_python(
f"--host={host}",
f"--build={sysconfig.get_config_var('BUILD_GNU_TYPE')}",
f"--with-build-python={build_python_path()}",
+ "--enable-ipv6",
"--enable-framework",
# Dependent libraries.
f"--with-openssl={prefix_dir}",
@@ -495,7 +543,8 @@ def framework_path(host_triple: str, multiarch: str) -> Path:
"""
return (
CROSS_BUILD_DIR
- / f"{host_triple}/Platforms/Apple/iOS/Frameworks/{multiarch}"
+ / f"{host_triple}/Platforms/Apple/{platform_for_host(host_triple)}"
+ / f"Frameworks/{multiarch}"
)
@@ -722,7 +771,7 @@ def create_xcframework(platform: str, abiflags: str) -> str:
host_path = (
CROSS_BUILD_DIR
/ host_triple
- / "Platforms/Apple/iOS/Frameworks"
+ / f"Platforms/Apple/{platform}/Frameworks"
/ multiarch
)
host_framework = host_path / f"{fw_name}.framework"
@@ -1010,6 +1059,7 @@ def parse_args() -> argparse.Namespace:
cmd.add_argument(
"platform",
choices=HOSTS.keys(),
+ type=platform_name,
help="The target platform to build",
)
diff --git a/Platforms/Apple/iOS/Resources/Info.plist.in b/Platforms/Apple/iOS/Resources/Info.plist.in
index 032f6aa362224d3..1756208de405b13 100644
--- a/Platforms/Apple/iOS/Resources/Info.plist.in
+++ b/Platforms/Apple/iOS/Resources/Info.plist.in
@@ -17,13 +17,13 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- @VERSION@
+ %VERSION%
CFBundleLongVersionString
%VERSION%, (c) 2001-2024 Python Software Foundation.
CFBundleSignature
????
CFBundleVersion
- 1
+ %VERSION%
CFBundleSupportedPlatforms
iPhoneOS
diff --git a/Platforms/Apple/testbed/Python.xcframework/Info.plist b/Platforms/Apple/testbed/Python.xcframework/Info.plist
index 653a5386e4601e0..fa9784c43303b7c 100644
--- a/Platforms/Apple/testbed/Python.xcframework/Info.plist
+++ b/Platforms/Apple/testbed/Python.xcframework/Info.plist
@@ -35,6 +35,98 @@
SupportedPlatformVariant
simulator
+
+ BinaryPath
+ Python.framework/Python
+ LibraryIdentifier
+ tvos-arm64
+ LibraryPath
+ Python.framework
+ SupportedArchitectures
+
+ arm64
+
+ SupportedPlatform
+ tvos
+
+
+ BinaryPath
+ Python.framework/Python
+ LibraryIdentifier
+ tvos-arm64_x86_64-simulator
+ LibraryPath
+ Python.framework
+ SupportedArchitectures
+
+ arm64
+ x86_64
+
+ SupportedPlatform
+ tvos
+ SupportedPlatformVariant
+ simulator
+
+
+ BinaryPath
+ Python.framework/Python
+ LibraryIdentifier
+ xros-arm64-simulator
+ LibraryPath
+ Python.framework
+ SupportedArchitectures
+
+ arm64
+
+ SupportedPlatform
+ xros
+ SupportedPlatformVariant
+ simulator
+
+
+ BinaryPath
+ Python.framework/Python
+ LibraryIdentifier
+ xros-arm64
+ LibraryPath
+ Python.framework
+ SupportedArchitectures
+
+ arm64
+
+ SupportedPlatform
+ xros
+
+
+ BinaryPath
+ Python.framework/Python
+ LibraryIdentifier
+ watchos-arm64_x86_64-simulator
+ LibraryPath
+ Python.framework
+ SupportedArchitectures
+
+ arm64
+ x86_64
+
+ SupportedPlatform
+ watchos
+ SupportedPlatformVariant
+ simulator
+
+
+ BinaryPath
+ Python.framework/Python
+ LibraryIdentifier
+ watchos-arm64_32
+ LibraryPath
+ Python.framework
+ SupportedArchitectures
+
+ arm64_32
+
+ SupportedPlatform
+ watchos
+
CFBundlePackageType
XFWK
diff --git a/Platforms/Apple/testbed/Python.xcframework/build/tvOS-dylib-Info-template.plist b/Platforms/Apple/testbed/Python.xcframework/build/tvOS-dylib-Info-template.plist
new file mode 100644
index 000000000000000..a20d476fa7b5524
--- /dev/null
+++ b/Platforms/Apple/testbed/Python.xcframework/build/tvOS-dylib-Info-template.plist
@@ -0,0 +1,26 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+
+ CFBundleIdentifier
+
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSupportedPlatforms
+
+ tvOS
+
+ MinimumOSVersion
+ 9.0
+ CFBundleVersion
+ 1
+
+
diff --git a/Platforms/Apple/testbed/Python.xcframework/build/utils.sh b/Platforms/Apple/testbed/Python.xcframework/build/utils.sh
index ad3e62f9f53bd5a..bbe3620a1397311 100755
--- a/Platforms/Apple/testbed/Python.xcframework/build/utils.sh
+++ b/Platforms/Apple/testbed/Python.xcframework/build/utils.sh
@@ -34,9 +34,38 @@ install_stdlib() {
else
SLICE_FOLDER="ios-arm64_x86_64-simulator"
fi
- else
+ elif [ "$EFFECTIVE_PLATFORM_NAME" = "-iphoneos" ]; then
echo "Installing Python modules for iOS Device"
SLICE_FOLDER="ios-arm64"
+ elif [ "$EFFECTIVE_PLATFORM_NAME" = "-appletvsimulator" ]; then
+ echo "Installing Python modules for tvOS Simulator"
+ if [ -d "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/tvos-arm64-simulator" ]; then
+ SLICE_FOLDER="tvos-arm64-simulator"
+ else
+ SLICE_FOLDER="tvos-arm64_x86_64-simulator"
+ fi
+ elif [ "$EFFECTIVE_PLATFORM_NAME" = "-appletvos" ]; then
+ echo "Installing Python modules for tvOS Device"
+ SLICE_FOLDER="tvos-arm64"
+ elif [ "$EFFECTIVE_PLATFORM_NAME" = "-watchsimulator" ]; then
+ echo "Installing Python modules for watchOS Simulator"
+ if [ -d "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/watchos-arm64-simulator" ]; then
+ SLICE_FOLDER="watchos-arm64-simulator"
+ else
+ SLICE_FOLDER="watchos-arm64_x86_64-simulator"
+ fi
+ elif [ "$EFFECTIVE_PLATFORM_NAME" = "-watchos" ]; then
+ echo "Installing Python modules for watchOS Device"
+ SLICE_FOLDER="watchos-arm64_32"
+ elif [ "$EFFECTIVE_PLATFORM_NAME" = "-xrsimulator" ]; then
+ echo "Installing Python modules for visionOS Simulator"
+ SLICE_FOLDER="xros-arm64-simulator"
+ elif [ "$EFFECTIVE_PLATFORM_NAME" = "-xros" ]; then
+ echo "Installing Python modules for visionOS Device"
+ SLICE_FOLDER="xros-arm64"
+ else
+ echo "Unsupported platform name $EFFECTIVE_PLATFORM_NAME"
+ exit 1
fi
# If the XCframework has a shared lib folder, then it's a full framework.
diff --git a/Platforms/Apple/testbed/Python.xcframework/build/watchOS-dylib-Info-template.plist b/Platforms/Apple/testbed/Python.xcframework/build/watchOS-dylib-Info-template.plist
new file mode 100644
index 000000000000000..6f8c0bc20959555
--- /dev/null
+++ b/Platforms/Apple/testbed/Python.xcframework/build/watchOS-dylib-Info-template.plist
@@ -0,0 +1,26 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+
+ CFBundleIdentifier
+
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSupportedPlatforms
+
+ watchOS
+
+ MinimumOSVersion
+ 4.0
+ CFBundleVersion
+ 1
+
+
diff --git a/Platforms/Apple/testbed/Python.xcframework/build/xrOS-dylib-Info-template.plist b/Platforms/Apple/testbed/Python.xcframework/build/xrOS-dylib-Info-template.plist
new file mode 100644
index 000000000000000..e91673b4fbcbc45
--- /dev/null
+++ b/Platforms/Apple/testbed/Python.xcframework/build/xrOS-dylib-Info-template.plist
@@ -0,0 +1,30 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleExecutable
+
+ CFBundleIdentifier
+
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSupportedPlatforms
+
+ XROS
+
+ CFBundleVersion
+ 1
+ MinimumOSVersion
+ 2.0
+ UIDeviceFamily
+
+ 7
+
+
+
diff --git a/Platforms/Apple/testbed/Python.xcframework/tvos-arm64/README b/Platforms/Apple/testbed/Python.xcframework/tvos-arm64/README
new file mode 100644
index 000000000000000..ebd648d04bd6df8
--- /dev/null
+++ b/Platforms/Apple/testbed/Python.xcframework/tvos-arm64/README
@@ -0,0 +1,4 @@
+This directory is intentionally empty.
+
+It should be used as a target for `--enable-framework` when compiling a tvOS
+on-device build for testing purposes.
diff --git a/Platforms/Apple/testbed/Python.xcframework/tvos-arm64_x86_64-simulator/README b/Platforms/Apple/testbed/Python.xcframework/tvos-arm64_x86_64-simulator/README
new file mode 100644
index 000000000000000..f8163468d8c557e
--- /dev/null
+++ b/Platforms/Apple/testbed/Python.xcframework/tvos-arm64_x86_64-simulator/README
@@ -0,0 +1,4 @@
+This directory is intentionally empty.
+
+It should be used as a target for `--enable-framework` when compiling a tvOS
+simulator build for testing purposes (either x86_64 or ARM64).
diff --git a/Platforms/Apple/testbed/Python.xcframework/watchos-arm64_32/README b/Platforms/Apple/testbed/Python.xcframework/watchos-arm64_32/README
new file mode 100644
index 000000000000000..696af231df39d79
--- /dev/null
+++ b/Platforms/Apple/testbed/Python.xcframework/watchos-arm64_32/README
@@ -0,0 +1,4 @@
+This directory is intentionally empty.
+
+It should be used as a target for `--enable-framework` when compiling a watchOS on-device
+build for testing purposes.
diff --git a/Platforms/Apple/testbed/Python.xcframework/watchos-arm64_x86_64-simulator/README b/Platforms/Apple/testbed/Python.xcframework/watchos-arm64_x86_64-simulator/README
new file mode 100644
index 000000000000000..d38e1e982766ad1
--- /dev/null
+++ b/Platforms/Apple/testbed/Python.xcframework/watchos-arm64_x86_64-simulator/README
@@ -0,0 +1,4 @@
+This directory is intentionally empty.
+
+It should be used as a target for `--enable-framework` when compiling a watchOS
+simulator build for testing purposes (either x86_64 or ARM64).
diff --git a/Platforms/Apple/testbed/Python.xcframework/xros-arm64-simulator/README b/Platforms/Apple/testbed/Python.xcframework/xros-arm64-simulator/README
new file mode 100644
index 000000000000000..7bb0ad4b6baa9c2
--- /dev/null
+++ b/Platforms/Apple/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).
diff --git a/Platforms/Apple/testbed/Python.xcframework/xros-arm64/README b/Platforms/Apple/testbed/Python.xcframework/xros-arm64/README
new file mode 100644
index 000000000000000..2fc2112e47757ab
--- /dev/null
+++ b/Platforms/Apple/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.
diff --git a/Platforms/Apple/testbed/__main__.py b/Platforms/Apple/testbed/__main__.py
index 697f5d64b835b01..7ae7d8e710373cb 100644
--- a/Platforms/Apple/testbed/__main__.py
+++ b/Platforms/Apple/testbed/__main__.py
@@ -10,6 +10,9 @@
TEST_SLICES = {
"iOS": "ios-arm64_x86_64-simulator",
+ "tvOS": "tvos-arm64_x86_64-simulator",
+ "visionOS": "xros-arm64-simulator",
+ "watchOS": "watchos-arm64_x86_64-simulator",
}
# The checked-in testbed is a template. Any file containing this placeholder
@@ -30,7 +33,7 @@
LOG_PREFIX_REGEX = re.compile(
r"^\d{4}-\d{2}-\d{2}" # YYYY-MM-DD
r"\s+\d+:\d{2}:\d{2}\.\d+\+\d{4}" # HH:MM:SS.ssssss+ZZZZ
- r"\s+iOSTestbed\[\d+:\w+\] " # Process/thread ID
+ r"\s+.*Testbed\[\d+:\w+\] " # Process/thread ID
)
@@ -63,6 +66,34 @@ def select_simulator_device(platform):
)
)
simulator = se_simulators[-1][1]
+ elif platform == "tvOS":
+ # Find the most recent tvOS release.
+ simulators = sorted(
+ (devicetype["minRuntimeVersion"], devicetype["name"])
+ for devicetype in json_data["devicetypes"]
+ if devicetype["productFamily"] == "Apple TV"
+ )
+ simulator = simulators[-1][1]
+ elif platform == "visionOS":
+ # Find the most recent visionOS release.
+ simulators = sorted(
+ (devicetype["minRuntimeVersion"], devicetype["name"])
+ for devicetype in json_data["devicetypes"]
+ if devicetype["productFamily"] == "Apple Vision"
+ )
+ simulator = simulators[-1][1]
+ elif platform == "watchOS":
+ # Any watchOS device will do; we'll look for "SE" devices. Select the
+ # one with the highest minimum runtime version - this is an indicator
+ # of the "newest" released device, which should always be supported
+ # on the "most recent" watchOS version.
+ se_simulators = sorted(
+ (devicetype["minRuntimeVersion"], devicetype["name"])
+ for devicetype in json_data["devicetypes"]
+ if devicetype["productFamily"] == "Apple Watch"
+ and "Apple Watch SE" in devicetype["name"]
+ )
+ simulator = se_simulators[-1][1]
else:
raise ValueError(f"Unknown platform {platform}")
@@ -454,10 +485,16 @@ def main():
# many platforms, but when cloned, only one platform is preserved.
available_platforms = [
platform
- for platform in ["iOS"]
+ for platform in ["iOS", "tvOS", "visionOS", "watchOS"]
if (Path(__file__).parent / f"{platform}Testbed").is_dir()
]
+ def platform_name(value):
+ """Return the canonical spelling for a platform name."""
+ return {p.lower(): p for p in available_platforms}.get(
+ value.lower(), value
+ )
+
parser = argparse.ArgumentParser(
description=(
"Manages the process of testing an Apple Python project "
@@ -488,6 +525,7 @@ def main():
dest="platform",
choices=available_platforms,
default=available_platforms[0],
+ type=platform_name,
help=f"The platform to target (default: {available_platforms[0]})",
)
clone.add_argument(
@@ -510,7 +548,7 @@ def main():
),
description=(
"Run a testbed project. The arguments provided after `--` will be "
- "passed to the running iOS process as if they were arguments to "
+ "passed to the running test process as if they were arguments to "
"`python -m`."
),
help="Run a testbed project",
@@ -520,6 +558,7 @@ def main():
dest="platform",
choices=available_platforms,
default=available_platforms[0],
+ type=platform_name,
help=f"The platform to target (default: {available_platforms[0]})",
)
run.add_argument(
diff --git a/Platforms/Apple/testbed/tvOSTestbed.xcodeproj/project.pbxproj b/Platforms/Apple/testbed/tvOSTestbed.xcodeproj/project.pbxproj
new file mode 100644
index 000000000000000..e14489ad0770a0f
--- /dev/null
+++ b/Platforms/Apple/testbed/tvOSTestbed.xcodeproj/project.pbxproj
@@ -0,0 +1,506 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 77;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ EE7C8A1E2DCD6FF3003206DB /* Python{{abiflags}}.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE7C8A1C2DCD6FF3003206DB /* Python{{abiflags}}.xcframework */; };
+ EE7C8A1F2DCD70CD003206DB /* Python{{abiflags}}.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE7C8A1C2DCD6FF3003206DB /* Python{{abiflags}}.xcframework */; };
+ EE7C8A202DCD70CD003206DB /* Python{{abiflags}}.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EE7C8A1C2DCD6FF3003206DB /* Python{{abiflags}}.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ EE989E662DCD6E7A0036B268 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = EE989E462DCD6E780036B268 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = EE989E4D2DCD6E780036B268;
+ remoteInfo = tvOSTestbed;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ EE7C8A212DCD70CD003206DB /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ EE7C8A202DCD70CD003206DB /* Python{{abiflags}}.xcframework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 6077B3802E82A4BE00E3D6A3 /* tvOSTestbed.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = tvOSTestbed.xctestplan; sourceTree = ""; };
+ EE7C8A1C2DCD6FF3003206DB /* Python{{abiflags}}.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Python{{abiflags}}.xcframework; sourceTree = ""; };
+ EE989E4E2DCD6E780036B268 /* tvOSTestbed.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tvOSTestbed.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ EE989E652DCD6E7A0036B268 /* TestbedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestbedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
+ 6077B37F2E81892A00E3D6A3 /* Exceptions for "tvOSTestbed" folder in "tvOSTestbed" target */ = {
+ isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
+ membershipExceptions = (
+ "tvOSTestbed-Info.plist",
+ );
+ target = EE989E4D2DCD6E780036B268 /* tvOSTestbed */;
+ };
+/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
+
+/* Begin PBXFileSystemSynchronizedRootGroup section */
+ EE989E502DCD6E780036B268 /* tvOSTestbed */ = {
+ isa = PBXFileSystemSynchronizedRootGroup;
+ exceptions = (
+ 6077B37F2E81892A00E3D6A3 /* Exceptions for "tvOSTestbed" folder in "tvOSTestbed" target */,
+ );
+ explicitFolders = (
+ app,
+ app_packages,
+ );
+ path = tvOSTestbed;
+ sourceTree = "";
+ };
+ EE989E682DCD6E7A0036B268 /* TestbedTests */ = {
+ isa = PBXFileSystemSynchronizedRootGroup;
+ path = TestbedTests;
+ sourceTree = "";
+ };
+/* End PBXFileSystemSynchronizedRootGroup section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ EE989E4B2DCD6E780036B268 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EE7C8A1F2DCD70CD003206DB /* Python{{abiflags}}.xcframework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EE989E622DCD6E7A0036B268 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EE7C8A1E2DCD6FF3003206DB /* Python{{abiflags}}.xcframework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ EE989E452DCD6E780036B268 = {
+ isa = PBXGroup;
+ children = (
+ 6077B3802E82A4BE00E3D6A3 /* tvOSTestbed.xctestplan */,
+ EE7C8A1C2DCD6FF3003206DB /* Python{{abiflags}}.xcframework */,
+ EE989E502DCD6E780036B268 /* tvOSTestbed */,
+ EE989E682DCD6E7A0036B268 /* TestbedTests */,
+ EE989E4F2DCD6E780036B268 /* Products */,
+ );
+ sourceTree = "";
+ };
+ EE989E4F2DCD6E780036B268 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ EE989E4E2DCD6E780036B268 /* tvOSTestbed.app */,
+ EE989E652DCD6E7A0036B268 /* TestbedTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ EE989E4D2DCD6E780036B268 /* tvOSTestbed */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = EE989E792DCD6E7A0036B268 /* Build configuration list for PBXNativeTarget "tvOSTestbed" */;
+ buildPhases = (
+ EE989E4A2DCD6E780036B268 /* Sources */,
+ EE989E4B2DCD6E780036B268 /* Frameworks */,
+ EE989E4C2DCD6E780036B268 /* Resources */,
+ EE7C8A222DCD70F4003206DB /* Process Python libraries */,
+ EE7C8A212DCD70CD003206DB /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ fileSystemSynchronizedGroups = (
+ EE989E502DCD6E780036B268 /* tvOSTestbed */,
+ );
+ name = tvOSTestbed;
+ packageProductDependencies = (
+ );
+ productName = tvOSTestbed;
+ productReference = EE989E4E2DCD6E780036B268 /* tvOSTestbed.app */;
+ productType = "com.apple.product-type.application";
+ };
+ EE989E642DCD6E7A0036B268 /* TestbedTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = EE989E7C2DCD6E7A0036B268 /* Build configuration list for PBXNativeTarget "TestbedTests" */;
+ buildPhases = (
+ EE989E612DCD6E7A0036B268 /* Sources */,
+ EE989E622DCD6E7A0036B268 /* Frameworks */,
+ EE989E632DCD6E7A0036B268 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ EE989E672DCD6E7A0036B268 /* PBXTargetDependency */,
+ );
+ fileSystemSynchronizedGroups = (
+ EE989E682DCD6E7A0036B268 /* TestbedTests */,
+ );
+ name = TestbedTests;
+ packageProductDependencies = (
+ );
+ productName = TestbedTests;
+ productReference = EE989E652DCD6E7A0036B268 /* TestbedTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ EE989E462DCD6E780036B268 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = 1;
+ LastUpgradeCheck = 1620;
+ TargetAttributes = {
+ EE989E4D2DCD6E780036B268 = {
+ CreatedOnToolsVersion = 16.2;
+ };
+ EE989E642DCD6E7A0036B268 = {
+ CreatedOnToolsVersion = 16.2;
+ TestTargetID = EE989E4D2DCD6E780036B268;
+ };
+ };
+ };
+ buildConfigurationList = EE989E492DCD6E780036B268 /* Build configuration list for PBXProject "tvOSTestbed" */;
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = EE989E452DCD6E780036B268;
+ minimizedProjectReferenceProxies = 1;
+ preferredProjectObjectVersion = 77;
+ productRefGroup = EE989E4F2DCD6E780036B268 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ EE989E4D2DCD6E780036B268 /* tvOSTestbed */,
+ EE989E642DCD6E7A0036B268 /* TestbedTests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ EE989E4C2DCD6E780036B268 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EE989E632DCD6E7A0036B268 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ EE7C8A222DCD70F4003206DB /* Process Python libraries */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ name = "Process Python libraries";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "set -e\n\nsource $PROJECT_DIR/Python{{abiflags}}.xcframework/build/utils.sh\n\ninstall_python Python{{abiflags}}.xcframework app app_packages\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ EE989E4A2DCD6E780036B268 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EE989E612DCD6E7A0036B268 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ EE989E672DCD6E7A0036B268 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = EE989E4D2DCD6E780036B268 /* tvOSTestbed */;
+ targetProxy = EE989E662DCD6E7A0036B268 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ EE989E772DCD6E7A0036B268 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
+ GCC_C_LANGUAGE_STANDARD = gnu17;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)/Python{{abiflags}}.framework/Headers";
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = appletvos;
+ TVOS_DEPLOYMENT_TARGET = 18.2;
+ };
+ name = Debug;
+ };
+ EE989E782DCD6E7A0036B268 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
+ GCC_C_LANGUAGE_STANDARD = gnu17;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)/Python{{abiflags}}.framework/Headers";
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = appletvos;
+ TVOS_DEPLOYMENT_TARGET = 18.2;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ EE989E7A2DCD6E7A0036B268 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = NO;
+ INFOPLIST_FILE = "tvOSTestbed/tvOSTestbed-Info.plist";
+ INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
+ INFOPLIST_KEY_UIMainStoryboardFile = Main;
+ INFOPLIST_KEY_UIUserInterfaceStyle = Automatic;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = org.python.tvOSTestbed;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Debug;
+ };
+ EE989E7B2DCD6E7A0036B268 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = NO;
+ INFOPLIST_FILE = "tvOSTestbed/tvOSTestbed-Info.plist";
+ INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
+ INFOPLIST_KEY_UIMainStoryboardFile = Main;
+ INFOPLIST_KEY_UIUserInterfaceStyle = Automatic;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = org.python.tvOSTestbed;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Release;
+ };
+ EE989E7D2DCD6E7A0036B268 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = org.python.TestbedTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ TARGETED_DEVICE_FAMILY = 3;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/tvOSTestbed.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/tvOSTestbed";
+ TVOS_DEPLOYMENT_TARGET = 18.2;
+ };
+ name = Debug;
+ };
+ EE989E7E2DCD6E7A0036B268 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = org.python.TestbedTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ TARGETED_DEVICE_FAMILY = 3;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/tvOSTestbed.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/tvOSTestbed";
+ TVOS_DEPLOYMENT_TARGET = 18.2;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ EE989E492DCD6E780036B268 /* Build configuration list for PBXProject "tvOSTestbed" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ EE989E772DCD6E7A0036B268 /* Debug */,
+ EE989E782DCD6E7A0036B268 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ EE989E792DCD6E7A0036B268 /* Build configuration list for PBXNativeTarget "tvOSTestbed" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ EE989E7A2DCD6E7A0036B268 /* Debug */,
+ EE989E7B2DCD6E7A0036B268 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ EE989E7C2DCD6E7A0036B268 /* Build configuration list for PBXNativeTarget "TestbedTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ EE989E7D2DCD6E7A0036B268 /* Debug */,
+ EE989E7E2DCD6E7A0036B268 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = EE989E462DCD6E780036B268 /* Project object */;
+}
diff --git a/Platforms/Apple/testbed/tvOSTestbed.xcodeproj/xcshareddata/xcschemes/tvOSTestbed.xcscheme b/Platforms/Apple/testbed/tvOSTestbed.xcodeproj/xcshareddata/xcschemes/tvOSTestbed.xcscheme
new file mode 100644
index 000000000000000..c3f3f894a1ff95a
--- /dev/null
+++ b/Platforms/Apple/testbed/tvOSTestbed.xcodeproj/xcshareddata/xcschemes/tvOSTestbed.xcscheme
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Platforms/Apple/testbed/tvOSTestbed.xctestplan b/Platforms/Apple/testbed/tvOSTestbed.xctestplan
new file mode 100644
index 000000000000000..f996facc1782b7d
--- /dev/null
+++ b/Platforms/Apple/testbed/tvOSTestbed.xctestplan
@@ -0,0 +1,46 @@
+{
+ "configurations" : [
+ {
+ "id" : "F5A95CE4-1ADE-4A6E-A0E1-CDBAE26DF0C5",
+ "name" : "Test Scheme Action",
+ "options" : {
+
+ }
+ }
+ ],
+ "defaultOptions" : {
+ "commandLineArgumentEntries" : [
+ {
+ "argument" : "test"
+ },
+ {
+ "argument" : "-uall"
+ },
+ {
+ "argument" : "--single-process"
+ },
+ {
+ "argument" : "--rerun"
+ },
+ {
+ "argument" : "-W"
+ }
+ ],
+ "targetForVariableExpansion" : {
+ "containerPath" : "container:tvOSTestbed.xcodeproj",
+ "identifier" : "607A66112B0EFA380010BFC8",
+ "name" : "tvOSTestbed"
+ }
+ },
+ "testTargets" : [
+ {
+ "parallelizable" : false,
+ "target" : {
+ "containerPath" : "container:tvOSTestbed.xcodeproj",
+ "identifier" : "EE989E642DCD6E7A0036B268",
+ "name" : "TestbedTests"
+ }
+ }
+ ],
+ "version" : 1
+}
\ No newline at end of file
diff --git a/Platforms/Apple/testbed/tvOSTestbed/AppDelegate.h b/Platforms/Apple/testbed/tvOSTestbed/AppDelegate.h
new file mode 100644
index 000000000000000..112c9ed64b83fb4
--- /dev/null
+++ b/Platforms/Apple/testbed/tvOSTestbed/AppDelegate.h
@@ -0,0 +1,11 @@
+//
+// AppDelegate.h
+// tvOSTestbed
+//
+
+#import
+
+@interface AppDelegate : UIResponder
+
+
+@end
diff --git a/Platforms/Apple/testbed/tvOSTestbed/AppDelegate.m b/Platforms/Apple/testbed/tvOSTestbed/AppDelegate.m
new file mode 100644
index 000000000000000..7501ec7b6ef6338
--- /dev/null
+++ b/Platforms/Apple/testbed/tvOSTestbed/AppDelegate.m
@@ -0,0 +1,24 @@
+//
+// AppDelegate.m
+// tvOSTestbed
+//
+
+#import "AppDelegate.h"
+#import "SceneDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
+ UISceneConfiguration *configuration = [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
+ configuration.delegateClass = [SceneDelegate class];
+ return configuration;
+}
+
+- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions {
+}
+
+@end
diff --git a/Platforms/Apple/testbed/tvOSTestbed/Base.lproj/LaunchScreen.storyboard b/Platforms/Apple/testbed/tvOSTestbed/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 000000000000000..660ba53de4f73d9
--- /dev/null
+++ b/Platforms/Apple/testbed/tvOSTestbed/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Platforms/Apple/testbed/tvOSTestbed/SceneDelegate.h b/Platforms/Apple/testbed/tvOSTestbed/SceneDelegate.h
new file mode 100644
index 000000000000000..264aacadca16e5d
--- /dev/null
+++ b/Platforms/Apple/testbed/tvOSTestbed/SceneDelegate.h
@@ -0,0 +1,12 @@
+//
+// SceneDelegate.h
+// iOSTestbed
+//
+
+#import
+
+@interface SceneDelegate : UIResponder
+
+@property (strong, nonatomic) UIWindow *window;
+
+@end
diff --git a/Platforms/Apple/testbed/tvOSTestbed/SceneDelegate.m b/Platforms/Apple/testbed/tvOSTestbed/SceneDelegate.m
new file mode 100644
index 000000000000000..e82e447985d2e90
--- /dev/null
+++ b/Platforms/Apple/testbed/tvOSTestbed/SceneDelegate.m
@@ -0,0 +1,21 @@
+//
+// SceneDelegate.m
+// iOSTestbed
+//
+
+#import "SceneDelegate.h"
+
+@interface SceneDelegate ()
+
+@end
+
+@implementation SceneDelegate
+
+- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
+ UIWindowScene *windowScene = (UIWindowScene *)scene;
+ self.window = [[UIWindow alloc] initWithWindowScene:windowScene];
+ self.window.rootViewController = [[UIViewController alloc] init];
+ [self.window makeKeyAndVisible];
+}
+
+@end
diff --git a/Platforms/Apple/testbed/tvOSTestbed/app/README b/Platforms/Apple/testbed/tvOSTestbed/app/README
new file mode 100644
index 000000000000000..46c0e8e2a29a1cc
--- /dev/null
+++ b/Platforms/Apple/testbed/tvOSTestbed/app/README
@@ -0,0 +1,7 @@
+This folder can contain any Python application code.
+
+During the build, any binary modules found in this folder will be processed into
+Framework form.
+
+When the test suite runs, this folder will be on the PYTHONPATH, and will be the
+working directory for the test suite.
diff --git a/Platforms/Apple/testbed/tvOSTestbed/app_packages/README b/Platforms/Apple/testbed/tvOSTestbed/app_packages/README
new file mode 100644
index 000000000000000..02c2beccfbdaed2
--- /dev/null
+++ b/Platforms/Apple/testbed/tvOSTestbed/app_packages/README
@@ -0,0 +1,7 @@
+This folder can be a target for installing any Python dependencies needed by the
+test suite.
+
+During the build, any binary modules found in this folder will be processed into
+Framework form.
+
+When the test suite runs, this folder will be on the PYTHONPATH.
diff --git a/Platforms/Apple/testbed/tvOSTestbed/main.m b/Platforms/Apple/testbed/tvOSTestbed/main.m
new file mode 100644
index 000000000000000..d5808fbb9331b71
--- /dev/null
+++ b/Platforms/Apple/testbed/tvOSTestbed/main.m
@@ -0,0 +1,16 @@
+//
+// main.m
+// tvOSTestbed
+//
+
+#import
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ NSString * appDelegateClassName;
+ @autoreleasepool {
+ appDelegateClassName = NSStringFromClass([AppDelegate class]);
+
+ return UIApplicationMain(argc, argv, nil, appDelegateClassName);
+ }
+}
diff --git a/Platforms/Apple/testbed/tvOSTestbed/tvOSTestbed-Info.plist b/Platforms/Apple/testbed/tvOSTestbed/tvOSTestbed-Info.plist
new file mode 100644
index 000000000000000..6d84447c031ebd7
--- /dev/null
+++ b/Platforms/Apple/testbed/tvOSTestbed/tvOSTestbed-Info.plist
@@ -0,0 +1,62 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleDisplayName
+ ${PRODUCT_NAME}
+ CFBundleExecutable
+ ${EXECUTABLE_NAME}
+ CFBundleIdentifier
+ org.python.tvOSTestbed
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ ${PRODUCT_NAME}
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UIRequiresFullScreen
+
+ UILaunchStoryboardName
+ Launch Screen
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+
+ UISceneConfigurations
+
+ UIWindowSceneSessionRoleApplication
+
+
+ UISceneDelegateClassName
+ SceneDelegate
+ UISceneConfigurationName
+ Default Configuration
+
+
+
+
+
+
diff --git a/Platforms/Apple/testbed/visionOSTestbed.xcodeproj/project.pbxproj b/Platforms/Apple/testbed/visionOSTestbed.xcodeproj/project.pbxproj
new file mode 100644
index 000000000000000..ee19e22d533cc83
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed.xcodeproj/project.pbxproj
@@ -0,0 +1,550 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 77;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ EEB367CE2DADF5C900B9A1D7 /* Python{{abiflags}}.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EEE9C80C2DAB5ECA0056F8C6 /* Python{{abiflags}}.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ EEB367CF2DADF5D300B9A1D7 /* Python{{abiflags}}.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EEE9C80C2DAB5ECA0056F8C6 /* Python{{abiflags}}.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ EEE9C80D2DAB5ECA0056F8C6 /* Python{{abiflags}}.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EEE9C80C2DAB5ECA0056F8C6 /* Python{{abiflags}}.xcframework */; };
+ EEE9C80E2DAB5ECA0056F8C6 /* Python{{abiflags}}.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EEE9C80C2DAB5ECA0056F8C6 /* Python{{abiflags}}.xcframework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 607A662E2B0EFA3A0010BFC8 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 607A660A2B0EFA380010BFC8 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 607A66112B0EFA380010BFC8;
+ remoteInfo = iOSTestbed;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 607A664E2B0EFC080010BFC8 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ EEB367CF2DADF5D300B9A1D7 /* Python{{abiflags}}.xcframework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 607A66522B0EFFE00010BFC8 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ EEB367CE2DADF5C900B9A1D7 /* Python{{abiflags}}.xcframework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 6077B3D62E82E60C00E3D6A3 /* visionOSTestbed.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = visionOSTestbed.xctestplan; sourceTree = ""; };
+ 607A66122B0EFA380010BFC8 /* visionOSTestbed.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = visionOSTestbed.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 607A662D2B0EFA3A0010BFC8 /* TestbedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestbedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ EEE9C80C2DAB5ECA0056F8C6 /* Python{{abiflags}}.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Python{{abiflags}}.xcframework; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
+ 4172389B57E3372C38B3DB88 /* Exceptions for "visionOSTestbed" folder in "visionOSTestbed" target */ = {
+ isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
+ membershipExceptions = (
+ "visionOSTestbed-Info.plist",
+ );
+ target = 607A66112B0EFA380010BFC8 /* visionOSTestbed */;
+ };
+/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
+
+/* Begin PBXFileSystemSynchronizedRootGroup section */
+ 607A66142B0EFA380010BFC8 /* visionOSTestbed */ = {
+ isa = PBXFileSystemSynchronizedRootGroup;
+ exceptions = (
+ 4172389B57E3372C38B3DB88 /* Exceptions for "visionOSTestbed" folder in "visionOSTestbed" target */,
+ );
+ explicitFolders = (
+ app,
+ app_packages,
+ );
+ path = visionOSTestbed;
+ sourceTree = "";
+ };
+ 607A66302B0EFA3A0010BFC8 /* TestbedTests */ = {
+ isa = PBXFileSystemSynchronizedRootGroup;
+ path = TestbedTests;
+ sourceTree = "";
+ };
+/* End PBXFileSystemSynchronizedRootGroup section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 607A660F2B0EFA380010BFC8 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EEE9C80D2DAB5ECA0056F8C6 /* Python{{abiflags}}.xcframework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 607A662A2B0EFA3A0010BFC8 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EEE9C80E2DAB5ECA0056F8C6 /* Python{{abiflags}}.xcframework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 607A66092B0EFA380010BFC8 = {
+ isa = PBXGroup;
+ children = (
+ 6077B3D62E82E60C00E3D6A3 /* visionOSTestbed.xctestplan */,
+ EEE9C80C2DAB5ECA0056F8C6 /* Python{{abiflags}}.xcframework */,
+ 607A66142B0EFA380010BFC8 /* visionOSTestbed */,
+ 607A66302B0EFA3A0010BFC8 /* TestbedTests */,
+ 607A66132B0EFA380010BFC8 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 607A66132B0EFA380010BFC8 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 607A66122B0EFA380010BFC8 /* visionOSTestbed.app */,
+ 607A662D2B0EFA3A0010BFC8 /* TestbedTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 607A66112B0EFA380010BFC8 /* visionOSTestbed */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 607A66412B0EFA3A0010BFC8 /* Build configuration list for PBXNativeTarget "visionOSTestbed" */;
+ buildPhases = (
+ 607A660E2B0EFA380010BFC8 /* Sources */,
+ 607A660F2B0EFA380010BFC8 /* Frameworks */,
+ 607A66102B0EFA380010BFC8 /* Resources */,
+ 607A66552B0F061D0010BFC8 /* Process Python libraries */,
+ 607A664E2B0EFC080010BFC8 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ fileSystemSynchronizedGroups = (
+ 607A66142B0EFA380010BFC8 /* visionOSTestbed */,
+ );
+ name = visionOSTestbed;
+ packageProductDependencies = (
+ );
+ productName = iOSTestbed;
+ productReference = 607A66122B0EFA380010BFC8 /* visionOSTestbed.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 607A662C2B0EFA3A0010BFC8 /* TestbedTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 607A66442B0EFA3A0010BFC8 /* Build configuration list for PBXNativeTarget "TestbedTests" */;
+ buildPhases = (
+ 607A66292B0EFA3A0010BFC8 /* Sources */,
+ 607A662A2B0EFA3A0010BFC8 /* Frameworks */,
+ 607A662B2B0EFA3A0010BFC8 /* Resources */,
+ 607A66522B0EFFE00010BFC8 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 607A662F2B0EFA3A0010BFC8 /* PBXTargetDependency */,
+ );
+ fileSystemSynchronizedGroups = (
+ 607A66302B0EFA3A0010BFC8 /* TestbedTests */,
+ );
+ name = TestbedTests;
+ packageProductDependencies = (
+ );
+ productName = iOSTestbedTests;
+ productReference = 607A662D2B0EFA3A0010BFC8 /* TestbedTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 607A660A2B0EFA380010BFC8 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = 1;
+ LastUpgradeCheck = 1500;
+ TargetAttributes = {
+ 607A66112B0EFA380010BFC8 = {
+ CreatedOnToolsVersion = 15.0.1;
+ };
+ 607A662C2B0EFA3A0010BFC8 = {
+ CreatedOnToolsVersion = 15.0.1;
+ TestTargetID = 607A66112B0EFA380010BFC8;
+ };
+ };
+ };
+ buildConfigurationList = 607A660D2B0EFA380010BFC8 /* Build configuration list for PBXProject "visionOSTestbed" */;
+ compatibilityVersion = "Xcode 14.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 607A66092B0EFA380010BFC8;
+ minimizedProjectReferenceProxies = 1;
+ preferredProjectObjectVersion = 77;
+ productRefGroup = 607A66132B0EFA380010BFC8 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 607A66112B0EFA380010BFC8 /* visionOSTestbed */,
+ 607A662C2B0EFA3A0010BFC8 /* TestbedTests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 607A66102B0EFA380010BFC8 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 607A662B2B0EFA3A0010BFC8 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 607A66552B0F061D0010BFC8 /* Process Python libraries */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ name = "Process Python libraries";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "set -e\n\nsource $PROJECT_DIR/Python{{abiflags}}.xcframework/build/utils.sh\n\ninstall_python Python{{abiflags}}.xcframework app app_packages\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 607A660E2B0EFA380010BFC8 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 607A66292B0EFA3A0010BFC8 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 607A662F2B0EFA3A0010BFC8 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 607A66112B0EFA380010BFC8 /* visionOSTestbed */;
+ targetProxy = 607A662E2B0EFA3A0010BFC8 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 607A663F2B0EFA3A0010BFC8 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu17;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = xros;
+ };
+ name = Debug;
+ };
+ 607A66402B0EFA3A0010BFC8 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu17;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = xros;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 607A66422B0EFA3A0010BFC8 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = "";
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python{{abiflags}}.framework/Headers\"";
+ INFOPLIST_FILE = "visionOSTestbed/visionOSTestbed-Info.plist";
+ INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+ INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
+ INFOPLIST_KEY_UIMainStoryboardFile = Main;
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MARKETING_VERSION = 3.13.0a1;
+ PRODUCT_BUNDLE_IDENTIFIER = org.python.visionOSTestbed;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SUPPORTED_PLATFORMS = "xros xrsimulator";
+ SUPPORTS_MACCATALYST = NO;
+ SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
+ SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ TARGETED_DEVICE_FAMILY = 7;
+ XROS_DEPLOYMENT_TARGET = 2.0;
+ };
+ name = Debug;
+ };
+ 607A66432B0EFA3A0010BFC8 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = "";
+ ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python{{abiflags}}.framework/Headers\"";
+ INFOPLIST_FILE = "visionOSTestbed/visionOSTestbed-Info.plist";
+ INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+ INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
+ INFOPLIST_KEY_UIMainStoryboardFile = Main;
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MARKETING_VERSION = 3.13.0a1;
+ PRODUCT_BUNDLE_IDENTIFIER = org.python.visionOSTestbed;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SUPPORTED_PLATFORMS = "xros xrsimulator";
+ SUPPORTS_MACCATALYST = NO;
+ SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
+ SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ TARGETED_DEVICE_FAMILY = 7;
+ XROS_DEPLOYMENT_TARGET = 2.0;
+ };
+ name = Release;
+ };
+ 607A66452B0EFA3A0010BFC8 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 3HEZE76D99;
+ GENERATE_INFOPLIST_FILE = YES;
+ HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python{{abiflags}}.framework/Headers\"";
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = org.python.TestbedTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SUPPORTED_PLATFORMS = "xros xrsimulator";
+ SUPPORTS_MACCATALYST = NO;
+ SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
+ SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ TARGETED_DEVICE_FAMILY = 7;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/visionOSTestbed.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/visionOSTestbed";
+ };
+ name = Debug;
+ };
+ 607A66462B0EFA3A0010BFC8 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 3HEZE76D99;
+ GENERATE_INFOPLIST_FILE = YES;
+ HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python{{abiflags}}.framework/Headers\"";
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = org.python.TestbedTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SUPPORTED_PLATFORMS = "xros xrsimulator";
+ SUPPORTS_MACCATALYST = NO;
+ SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
+ SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ TARGETED_DEVICE_FAMILY = 7;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/visionOSTestbed.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/visionOSTestbed";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 607A660D2B0EFA380010BFC8 /* Build configuration list for PBXProject "visionOSTestbed" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 607A663F2B0EFA3A0010BFC8 /* Debug */,
+ 607A66402B0EFA3A0010BFC8 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 607A66412B0EFA3A0010BFC8 /* Build configuration list for PBXNativeTarget "visionOSTestbed" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 607A66422B0EFA3A0010BFC8 /* Debug */,
+ 607A66432B0EFA3A0010BFC8 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 607A66442B0EFA3A0010BFC8 /* Build configuration list for PBXNativeTarget "TestbedTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 607A66452B0EFA3A0010BFC8 /* Debug */,
+ 607A66462B0EFA3A0010BFC8 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 607A660A2B0EFA380010BFC8 /* Project object */;
+}
diff --git a/Platforms/Apple/testbed/visionOSTestbed.xcodeproj/xcshareddata/xcschemes/visionOSTestbed.xcscheme b/Platforms/Apple/testbed/visionOSTestbed.xcodeproj/xcshareddata/xcschemes/visionOSTestbed.xcscheme
new file mode 100644
index 000000000000000..b8397ea7cf116d6
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed.xcodeproj/xcshareddata/xcschemes/visionOSTestbed.xcscheme
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Platforms/Apple/testbed/visionOSTestbed.xctestplan b/Platforms/Apple/testbed/visionOSTestbed.xctestplan
new file mode 100644
index 000000000000000..73a2be8c22a70c5
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed.xctestplan
@@ -0,0 +1,46 @@
+{
+ "configurations" : [
+ {
+ "id" : "C17FA044-0B70-48CA-AFF8-BC252081002F",
+ "name" : "Test Scheme Action",
+ "options" : {
+
+ }
+ }
+ ],
+ "defaultOptions" : {
+ "commandLineArgumentEntries" : [
+ {
+ "argument" : "test"
+ },
+ {
+ "argument" : "-uall"
+ },
+ {
+ "argument" : "--single-process"
+ },
+ {
+ "argument" : "--rerun"
+ },
+ {
+ "argument" : "-W"
+ }
+ ],
+ "targetForVariableExpansion" : {
+ "containerPath" : "container:visionOSTestbed.xcodeproj",
+ "identifier" : "607A66112B0EFA380010BFC8",
+ "name" : "visionOSTestbed"
+ }
+ },
+ "testTargets" : [
+ {
+ "parallelizable" : false,
+ "target" : {
+ "containerPath" : "container:visionOSTestbed.xcodeproj",
+ "identifier" : "607A662C2B0EFA3A0010BFC8",
+ "name" : "TestbedTests"
+ }
+ }
+ ],
+ "version" : 1
+}
\ No newline at end of file
diff --git a/Platforms/Apple/testbed/visionOSTestbed/AppDelegate.h b/Platforms/Apple/testbed/visionOSTestbed/AppDelegate.h
new file mode 100644
index 000000000000000..8fe7ec8e64eeb29
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed/AppDelegate.h
@@ -0,0 +1,11 @@
+//
+// AppDelegate.h
+// visionOSTestbed
+//
+
+#import
+
+@interface AppDelegate : UIResponder
+
+
+@end
diff --git a/Platforms/Apple/testbed/visionOSTestbed/AppDelegate.m b/Platforms/Apple/testbed/visionOSTestbed/AppDelegate.m
new file mode 100644
index 000000000000000..f46c65a3834db9c
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed/AppDelegate.m
@@ -0,0 +1,24 @@
+//
+// AppDelegate.m
+// visionOSTestbed
+//
+
+#import "AppDelegate.h"
+#import "SceneDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
+ UISceneConfiguration *configuration = [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
+ configuration.delegateClass = [SceneDelegate class];
+ return configuration;
+}
+
+- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions {
+}
+
+@end
diff --git a/Platforms/Apple/testbed/visionOSTestbed/Assets.xcassets/AccentColor.colorset/Contents.json b/Platforms/Apple/testbed/visionOSTestbed/Assets.xcassets/AccentColor.colorset/Contents.json
new file mode 100644
index 000000000000000..eb8789700816459
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed/Assets.xcassets/AccentColor.colorset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "colors" : [
+ {
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Platforms/Apple/testbed/visionOSTestbed/Assets.xcassets/AppIcon.appiconset/Contents.json b/Platforms/Apple/testbed/visionOSTestbed/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 000000000000000..13613e3ee1a9348
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,13 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Platforms/Apple/testbed/visionOSTestbed/Assets.xcassets/Contents.json b/Platforms/Apple/testbed/visionOSTestbed/Assets.xcassets/Contents.json
new file mode 100644
index 000000000000000..73c00596a7fca3f
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Platforms/Apple/testbed/visionOSTestbed/SceneDelegate.h b/Platforms/Apple/testbed/visionOSTestbed/SceneDelegate.h
new file mode 100644
index 000000000000000..264aacadca16e5d
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed/SceneDelegate.h
@@ -0,0 +1,12 @@
+//
+// SceneDelegate.h
+// iOSTestbed
+//
+
+#import
+
+@interface SceneDelegate : UIResponder
+
+@property (strong, nonatomic) UIWindow *window;
+
+@end
diff --git a/Platforms/Apple/testbed/visionOSTestbed/SceneDelegate.m b/Platforms/Apple/testbed/visionOSTestbed/SceneDelegate.m
new file mode 100644
index 000000000000000..e82e447985d2e90
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed/SceneDelegate.m
@@ -0,0 +1,21 @@
+//
+// SceneDelegate.m
+// iOSTestbed
+//
+
+#import "SceneDelegate.h"
+
+@interface SceneDelegate ()
+
+@end
+
+@implementation SceneDelegate
+
+- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
+ UIWindowScene *windowScene = (UIWindowScene *)scene;
+ self.window = [[UIWindow alloc] initWithWindowScene:windowScene];
+ self.window.rootViewController = [[UIViewController alloc] init];
+ [self.window makeKeyAndVisible];
+}
+
+@end
diff --git a/Platforms/Apple/testbed/visionOSTestbed/app/README b/Platforms/Apple/testbed/visionOSTestbed/app/README
new file mode 100644
index 000000000000000..af22c685f87976a
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed/app/README
@@ -0,0 +1,7 @@
+This folder can contain any Python application code.
+
+During the build, any binary modules found in this folder will be processed into
+iOS Framework form.
+
+When the test suite runs, this folder will be on the PYTHONPATH, and will be the
+working directory for the test suite.
diff --git a/Platforms/Apple/testbed/visionOSTestbed/app_packages/README b/Platforms/Apple/testbed/visionOSTestbed/app_packages/README
new file mode 100644
index 000000000000000..42d7fdeb813250f
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed/app_packages/README
@@ -0,0 +1,7 @@
+This folder can be a target for installing any Python dependencies needed by the
+test suite.
+
+During the build, any binary modules found in this folder will be processed into
+iOS Framework form.
+
+When the test suite runs, this folder will be on the PYTHONPATH.
diff --git a/Platforms/Apple/testbed/visionOSTestbed/main.m b/Platforms/Apple/testbed/visionOSTestbed/main.m
new file mode 100644
index 000000000000000..2bb491f25c851bd
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed/main.m
@@ -0,0 +1,16 @@
+//
+// main.m
+// visionOSTestbed
+//
+
+#import
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ NSString * appDelegateClassName;
+ @autoreleasepool {
+ appDelegateClassName = NSStringFromClass([AppDelegate class]);
+
+ return UIApplicationMain(argc, argv, nil, appDelegateClassName);
+ }
+}
diff --git a/Platforms/Apple/testbed/visionOSTestbed/visionOSTestbed-Info.plist b/Platforms/Apple/testbed/visionOSTestbed/visionOSTestbed-Info.plist
new file mode 100644
index 000000000000000..11a8230d1d2cc0c
--- /dev/null
+++ b/Platforms/Apple/testbed/visionOSTestbed/visionOSTestbed-Info.plist
@@ -0,0 +1,66 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleDisplayName
+ ${PRODUCT_NAME}
+ CFBundleExecutable
+ ${EXECUTABLE_NAME}
+ CFBundleIdentifier
+ org.python.visionOSTestbed
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ ${PRODUCT_NAME}
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ TestArgs
+
+ test
+ -uall
+ --single-process
+ --rerun
+ -W
+
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+
+ UISceneConfigurations
+
+ UIWindowSceneSessionRoleApplication
+
+
+ UISceneDelegateClassName
+ SceneDelegate
+ UISceneConfigurationName
+ Default Configuration
+
+
+
+
+ UIRequiresFullScreen
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/Platforms/Apple/testbed/watchOSTestbed.xcodeproj/project.pbxproj b/Platforms/Apple/testbed/watchOSTestbed.xcodeproj/project.pbxproj
new file mode 100644
index 000000000000000..d5220c60e65c441
--- /dev/null
+++ b/Platforms/Apple/testbed/watchOSTestbed.xcodeproj/project.pbxproj
@@ -0,0 +1,490 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 77;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 60F7C0012EB0000000A1B2C3 /* Python{{abiflags}}.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 60F7C0072EB0000000A1B2C3 /* Python{{abiflags}}.xcframework */; };
+ 60F7C0022EB0000000A1B2C3 /* Python{{abiflags}}.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 60F7C0072EB0000000A1B2C3 /* Python{{abiflags}}.xcframework */; };
+ 60F7C0032EB0000000A1B2C3 /* Python{{abiflags}}.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 60F7C0072EB0000000A1B2C3 /* Python{{abiflags}}.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 60F7C0042EB0000000A1B2C3 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 60F7C0132EB0000000A1B2C3 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 60F7C0112EB0000000A1B2C3;
+ remoteInfo = watchOSTestbed;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 60F7C0052EB0000000A1B2C3 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 60F7C0032EB0000000A1B2C3 /* Python{{abiflags}}.xcframework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 60F7C0062EB0000000A1B2C3 /* watchOSTestbed.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = watchOSTestbed.xctestplan; sourceTree = ""; };
+ 60F7C0072EB0000000A1B2C3 /* Python{{abiflags}}.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Python{{abiflags}}.xcframework; sourceTree = ""; };
+ 60F7C0082EB0000000A1B2C3 /* watchOSTestbed.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = watchOSTestbed.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 60F7C0092EB0000000A1B2C3 /* TestbedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestbedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
+ 60F7C00A2EB0000000A1B2C3 /* Exceptions for "watchOSTestbed" folder in "watchOSTestbed" target */ = {
+ isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
+ membershipExceptions = (
+ "watchOSTestbed-Info.plist",
+ );
+ target = 60F7C0112EB0000000A1B2C3 /* watchOSTestbed */;
+ };
+/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
+
+/* Begin PBXFileSystemSynchronizedRootGroup section */
+ 60F7C00B2EB0000000A1B2C3 /* watchOSTestbed */ = {
+ isa = PBXFileSystemSynchronizedRootGroup;
+ exceptions = (
+ 60F7C00A2EB0000000A1B2C3 /* Exceptions for "watchOSTestbed" folder in "watchOSTestbed" target */,
+ );
+ explicitFolders = (
+ app,
+ app_packages,
+ );
+ path = watchOSTestbed;
+ sourceTree = "";
+ };
+ 60F7C00C2EB0000000A1B2C3 /* TestbedTests */ = {
+ isa = PBXFileSystemSynchronizedRootGroup;
+ path = TestbedTests;
+ sourceTree = "";
+ };
+/* End PBXFileSystemSynchronizedRootGroup section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 60F7C00D2EB0000000A1B2C3 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 60F7C0022EB0000000A1B2C3 /* Python{{abiflags}}.xcframework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 60F7C00E2EB0000000A1B2C3 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 60F7C0012EB0000000A1B2C3 /* Python{{abiflags}}.xcframework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 60F7C00F2EB0000000A1B2C3 = {
+ isa = PBXGroup;
+ children = (
+ 60F7C0062EB0000000A1B2C3 /* watchOSTestbed.xctestplan */,
+ 60F7C0072EB0000000A1B2C3 /* Python{{abiflags}}.xcframework */,
+ 60F7C00B2EB0000000A1B2C3 /* watchOSTestbed */,
+ 60F7C00C2EB0000000A1B2C3 /* TestbedTests */,
+ 60F7C0102EB0000000A1B2C3 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 60F7C0102EB0000000A1B2C3 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 60F7C0082EB0000000A1B2C3 /* watchOSTestbed.app */,
+ 60F7C0092EB0000000A1B2C3 /* TestbedTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 60F7C0112EB0000000A1B2C3 /* watchOSTestbed */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 60F7C0212EB0000000A1B2C3 /* Build configuration list for PBXNativeTarget "watchOSTestbed" */;
+ buildPhases = (
+ 60F7C0172EB0000000A1B2C3 /* Sources */,
+ 60F7C00D2EB0000000A1B2C3 /* Frameworks */,
+ 60F7C0142EB0000000A1B2C3 /* Resources */,
+ 60F7C0162EB0000000A1B2C3 /* Process Python libraries */,
+ 60F7C0052EB0000000A1B2C3 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ fileSystemSynchronizedGroups = (
+ 60F7C00B2EB0000000A1B2C3 /* watchOSTestbed */,
+ );
+ name = watchOSTestbed;
+ packageProductDependencies = (
+ );
+ productName = watchOSTestbed;
+ productReference = 60F7C0082EB0000000A1B2C3 /* watchOSTestbed.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 60F7C0122EB0000000A1B2C3 /* TestbedTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 60F7C0222EB0000000A1B2C3 /* Build configuration list for PBXNativeTarget "TestbedTests" */;
+ buildPhases = (
+ 60F7C0182EB0000000A1B2C3 /* Sources */,
+ 60F7C00E2EB0000000A1B2C3 /* Frameworks */,
+ 60F7C0152EB0000000A1B2C3 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 60F7C0192EB0000000A1B2C3 /* PBXTargetDependency */,
+ );
+ fileSystemSynchronizedGroups = (
+ 60F7C00C2EB0000000A1B2C3 /* TestbedTests */,
+ );
+ name = TestbedTests;
+ packageProductDependencies = (
+ );
+ productName = TestbedTests;
+ productReference = 60F7C0092EB0000000A1B2C3 /* TestbedTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 60F7C0132EB0000000A1B2C3 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = 1;
+ LastUpgradeCheck = 1620;
+ TargetAttributes = {
+ 60F7C0112EB0000000A1B2C3 = {
+ CreatedOnToolsVersion = 16.2;
+ };
+ 60F7C0122EB0000000A1B2C3 = {
+ CreatedOnToolsVersion = 16.2;
+ TestTargetID = 60F7C0112EB0000000A1B2C3;
+ };
+ };
+ };
+ buildConfigurationList = 60F7C0202EB0000000A1B2C3 /* Build configuration list for PBXProject "watchOSTestbed" */;
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 60F7C00F2EB0000000A1B2C3;
+ minimizedProjectReferenceProxies = 1;
+ preferredProjectObjectVersion = 77;
+ productRefGroup = 60F7C0102EB0000000A1B2C3 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 60F7C0112EB0000000A1B2C3 /* watchOSTestbed */,
+ 60F7C0122EB0000000A1B2C3 /* TestbedTests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 60F7C0142EB0000000A1B2C3 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 60F7C0152EB0000000A1B2C3 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 60F7C0162EB0000000A1B2C3 /* Process Python libraries */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ name = "Process Python libraries";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "set -e\n\nsource $PROJECT_DIR/Python{{abiflags}}.xcframework/build/utils.sh\n\ninstall_python Python{{abiflags}}.xcframework app app_packages\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 60F7C0172EB0000000A1B2C3 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 60F7C0182EB0000000A1B2C3 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 60F7C0192EB0000000A1B2C3 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 60F7C0112EB0000000A1B2C3 /* watchOSTestbed */;
+ targetProxy = 60F7C0042EB0000000A1B2C3 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 60F7C01A2EB0000000A1B2C3 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
+ GCC_C_LANGUAGE_STANDARD = gnu17;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)/Python{{abiflags}}.framework/Headers";
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = watchos;
+ WATCHOS_DEPLOYMENT_TARGET = 9.0;
+ };
+ name = Debug;
+ };
+ 60F7C01B2EB0000000A1B2C3 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
+ GCC_C_LANGUAGE_STANDARD = gnu17;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)/Python{{abiflags}}.framework/Headers";
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = watchos;
+ VALIDATE_PRODUCT = YES;
+ WATCHOS_DEPLOYMENT_TARGET = 9.0;
+ };
+ name = Release;
+ };
+ 60F7C01C2EB0000000A1B2C3 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = NO;
+ INFOPLIST_FILE = "watchOSTestbed/watchOSTestbed-Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = org.python.watchOSTestbed;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = 4;
+ };
+ name = Debug;
+ };
+ 60F7C01D2EB0000000A1B2C3 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = NO;
+ INFOPLIST_FILE = "watchOSTestbed/watchOSTestbed-Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = org.python.watchOSTestbed;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = 4;
+ };
+ name = Release;
+ };
+ 60F7C01E2EB0000000A1B2C3 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = org.python.TestbedTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = 4;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/watchOSTestbed.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/watchOSTestbed";
+ WATCHOS_DEPLOYMENT_TARGET = 9.0;
+ };
+ name = Debug;
+ };
+ 60F7C01F2EB0000000A1B2C3 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = org.python.TestbedTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = 4;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/watchOSTestbed.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/watchOSTestbed";
+ WATCHOS_DEPLOYMENT_TARGET = 9.0;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 60F7C0202EB0000000A1B2C3 /* Build configuration list for PBXProject "watchOSTestbed" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 60F7C01A2EB0000000A1B2C3 /* Debug */,
+ 60F7C01B2EB0000000A1B2C3 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 60F7C0212EB0000000A1B2C3 /* Build configuration list for PBXNativeTarget "watchOSTestbed" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 60F7C01C2EB0000000A1B2C3 /* Debug */,
+ 60F7C01D2EB0000000A1B2C3 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 60F7C0222EB0000000A1B2C3 /* Build configuration list for PBXNativeTarget "TestbedTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 60F7C01E2EB0000000A1B2C3 /* Debug */,
+ 60F7C01F2EB0000000A1B2C3 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 60F7C0132EB0000000A1B2C3 /* Project object */;
+}
diff --git a/Platforms/Apple/testbed/watchOSTestbed.xcodeproj/xcshareddata/xcschemes/watchOSTestbed.xcscheme b/Platforms/Apple/testbed/watchOSTestbed.xcodeproj/xcshareddata/xcschemes/watchOSTestbed.xcscheme
new file mode 100644
index 000000000000000..96689416946110d
--- /dev/null
+++ b/Platforms/Apple/testbed/watchOSTestbed.xcodeproj/xcshareddata/xcschemes/watchOSTestbed.xcscheme
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Platforms/Apple/testbed/watchOSTestbed.xctestplan b/Platforms/Apple/testbed/watchOSTestbed.xctestplan
new file mode 100644
index 000000000000000..f83ff3a5595074c
--- /dev/null
+++ b/Platforms/Apple/testbed/watchOSTestbed.xctestplan
@@ -0,0 +1,46 @@
+{
+ "configurations" : [
+ {
+ "id" : "8E3B1C52-4F0A-4D7E-9B61-2C5A7E0D9F14",
+ "name" : "Test Scheme Action",
+ "options" : {
+
+ }
+ }
+ ],
+ "defaultOptions" : {
+ "commandLineArgumentEntries" : [
+ {
+ "argument" : "test"
+ },
+ {
+ "argument" : "-uall"
+ },
+ {
+ "argument" : "--single-process"
+ },
+ {
+ "argument" : "--rerun"
+ },
+ {
+ "argument" : "-W"
+ }
+ ],
+ "targetForVariableExpansion" : {
+ "containerPath" : "container:watchOSTestbed.xcodeproj",
+ "identifier" : "60F7C0112EB0000000A1B2C3",
+ "name" : "watchOSTestbed"
+ }
+ },
+ "testTargets" : [
+ {
+ "parallelizable" : false,
+ "target" : {
+ "containerPath" : "container:watchOSTestbed.xcodeproj",
+ "identifier" : "60F7C0122EB0000000A1B2C3",
+ "name" : "TestbedTests"
+ }
+ }
+ ],
+ "version" : 1
+}
diff --git a/Platforms/Apple/testbed/watchOSTestbed/AppDelegate.h b/Platforms/Apple/testbed/watchOSTestbed/AppDelegate.h
new file mode 100644
index 000000000000000..cc7359048ae4c41
--- /dev/null
+++ b/Platforms/Apple/testbed/watchOSTestbed/AppDelegate.h
@@ -0,0 +1,11 @@
+//
+// AppDelegate.h
+// watchOSTestbed
+//
+
+#import
+
+@interface AppDelegate : NSObject
+
+
+@end
diff --git a/Platforms/Apple/testbed/watchOSTestbed/AppDelegate.m b/Platforms/Apple/testbed/watchOSTestbed/AppDelegate.m
new file mode 100644
index 000000000000000..3390d2efc879f70
--- /dev/null
+++ b/Platforms/Apple/testbed/watchOSTestbed/AppDelegate.m
@@ -0,0 +1,21 @@
+//
+// AppDelegate.m
+// watchOSTestbed
+//
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+// The testbed has no storyboard (Interface.plist), so WatchKit requires the
+// delegate to provide a root interface controller class, or the app crashes
+// on launch.
+- (Class)applicationRootInterfaceControllerClass {
+ return [WKInterfaceController class];
+}
+
+@end
diff --git a/Platforms/Apple/testbed/watchOSTestbed/app/README b/Platforms/Apple/testbed/watchOSTestbed/app/README
new file mode 100644
index 000000000000000..46c0e8e2a29a1cc
--- /dev/null
+++ b/Platforms/Apple/testbed/watchOSTestbed/app/README
@@ -0,0 +1,7 @@
+This folder can contain any Python application code.
+
+During the build, any binary modules found in this folder will be processed into
+Framework form.
+
+When the test suite runs, this folder will be on the PYTHONPATH, and will be the
+working directory for the test suite.
diff --git a/Platforms/Apple/testbed/watchOSTestbed/app_packages/README b/Platforms/Apple/testbed/watchOSTestbed/app_packages/README
new file mode 100644
index 000000000000000..02c2beccfbdaed2
--- /dev/null
+++ b/Platforms/Apple/testbed/watchOSTestbed/app_packages/README
@@ -0,0 +1,7 @@
+This folder can be a target for installing any Python dependencies needed by the
+test suite.
+
+During the build, any binary modules found in this folder will be processed into
+Framework form.
+
+When the test suite runs, this folder will be on the PYTHONPATH.
diff --git a/Platforms/Apple/testbed/watchOSTestbed/main.m b/Platforms/Apple/testbed/watchOSTestbed/main.m
new file mode 100644
index 000000000000000..b0e43f1a06f59eb
--- /dev/null
+++ b/Platforms/Apple/testbed/watchOSTestbed/main.m
@@ -0,0 +1,16 @@
+//
+// main.m
+// watchOSTestbed
+//
+
+#import
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ NSString * appDelegateClassName;
+ @autoreleasepool {
+ appDelegateClassName = NSStringFromClass([AppDelegate class]);
+
+ return WKApplicationMain(argc, argv, appDelegateClassName);
+ }
+}
diff --git a/Platforms/Apple/testbed/watchOSTestbed/watchOSTestbed-Info.plist b/Platforms/Apple/testbed/watchOSTestbed/watchOSTestbed-Info.plist
new file mode 100644
index 000000000000000..4f25642a8e22b47
--- /dev/null
+++ b/Platforms/Apple/testbed/watchOSTestbed/watchOSTestbed-Info.plist
@@ -0,0 +1,30 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleDisplayName
+ ${PRODUCT_NAME}
+ CFBundleExecutable
+ ${EXECUTABLE_NAME}
+ CFBundleIdentifier
+ org.python.watchOSTestbed
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ ${PRODUCT_NAME}
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ WKApplication
+
+ WKWatchOnly
+
+
+
diff --git a/Platforms/Apple/tvOS/README.md b/Platforms/Apple/tvOS/README.md
new file mode 100644
index 000000000000000..de4d5e209bf9ff9
--- /dev/null
+++ b/Platforms/Apple/tvOS/README.md
@@ -0,0 +1,30 @@
+# Python on tvOS README
+
+This document provides a quick overview of some tvOS specific features in the
+Python distribution.
+
+Python on tvOS is largely the same as Python on iOS; most of the instructions in
+the [iOS README](../iOS/README.md) can be used for tvOS builds, substituting:
+
+- `tvOS` as the identifier for `Platforms/Apple` invocations; e.g.,
+ - `python Platforms/Apple build tvOS`
+ - `python Platforms/Apple ci tvOS`
+ - `python Platforms/Apple test tvOS`
+
+- tvOS resources are stored in the `Platforms/Apple/tvOS/Resources` directory.
+
+- The tvOS SDK version is controlled with the `TVOS_SDK_VERSION` environment
+ variable.
+
+- The minimum supported tvOS SDK version is controlled with the
+ `TVOS_DEPLOYMENT_TARGET` environment variable.
+
+- When referencing platforms, the tvOS compiler triples are:
+ - `arm64-apple-tvos` for AppleTV devices
+ - `arm64-apple-tvos-simulator` for AppleTV simulators on ARM64 hardware
+ - `x86_64-apple-tvos-simulator` for AppleTV simulators on x86-64 hardware
+
+- The tvOS testbed Xcode template project is stored in
+ `Platforms/Apple/testbed/tvOSTestbed`.
+
+- `platform.ios_ver()` will return tvOS-relevant version information.
diff --git a/Platforms/Apple/tvOS/Resources/Info.plist.in b/Platforms/Apple/tvOS/Resources/Info.plist.in
new file mode 100644
index 000000000000000..b913504d69e096a
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/Info.plist.in
@@ -0,0 +1,34 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ @PYTHONFRAMEWORK@
+ CFBundleGetInfoString
+ Python Runtime and Library
+ CFBundleIdentifier
+ @PYTHONFRAMEWORKIDENTIFIER@
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ @PYTHONFRAMEWORK@
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ %VERSION%
+ CFBundleLongVersionString
+ %VERSION%, (c) 2001-2024 Python Software Foundation.
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ CFBundleSupportedPlatforms
+
+ tvOS
+
+ MinimumOSVersion
+ @TVOS_DEPLOYMENT_TARGET@
+
+
diff --git a/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-ar b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-ar
new file mode 100755
index 000000000000000..482a8da6c64b9cd
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-ar
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvos${TVOS_SDK_VERSION} ar "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang
new file mode 100755
index 000000000000000..c08cefd6067e381
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvos${TVOS_SDK_VERSION} clang -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET} "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang++ b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang++
new file mode 100755
index 000000000000000..3425d57aafa5e02
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang++
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvos${TVOS_SDK_VERSION} clang++ -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET} "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-cpp b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-cpp
new file mode 100755
index 000000000000000..8466e9ada39c454
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-cpp
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvos${TVOS_SDK_VERSION} clang -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET} -E "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-ar b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-ar
new file mode 100755
index 000000000000000..a0b20edc7a9e67f
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-ar
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} ar "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang
new file mode 100755
index 000000000000000..fa5e7cbd5bcd03d
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang++ b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang++
new file mode 100755
index 000000000000000..b3f82e8ca360692
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang++
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang++ -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-cpp b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-cpp
new file mode 100755
index 000000000000000..aba485f1e239a79
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-cpp
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator -E "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-strip b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-strip
new file mode 100755
index 000000000000000..a8cce95233e75f5
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-strip
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} strip -arch arm64 "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-strip b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-strip
new file mode 100755
index 000000000000000..ee1d2b95ff1bb49
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/arm64-apple-tvos-strip
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk iphoneos${TVOS_SDK_VERSION} strip -arch arm64 "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-ar b/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-ar
new file mode 100755
index 000000000000000..a0b20edc7a9e67f
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-ar
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} ar "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang b/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang
new file mode 100755
index 000000000000000..6c1a538b64df9e2
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target x86_64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang++ b/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang++
new file mode 100755
index 000000000000000..efa76909c374234
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang++
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang++ -target x86_64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-cpp b/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-cpp
new file mode 100755
index 000000000000000..f6ad1a5c2e2a543
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-cpp
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target x86_64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator -E "$@"
diff --git a/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-strip b/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-strip
new file mode 100755
index 000000000000000..f6a884b4aef6204
--- /dev/null
+++ b/Platforms/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-strip
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} strip -arch x86_64 "$@"
diff --git a/Platforms/Apple/tvOS/Resources/pyconfig.h b/Platforms/Apple/tvOS/Resources/pyconfig.h
new file mode 100644
index 000000000000000..4acff2c60516377
--- /dev/null
+++ b/Platforms/Apple/tvOS/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/Platforms/Apple/visionOS/README.md b/Platforms/Apple/visionOS/README.md
new file mode 100644
index 000000000000000..45bf0157137f28c
--- /dev/null
+++ b/Platforms/Apple/visionOS/README.md
@@ -0,0 +1,30 @@
+# Python on visionOS README
+
+This document provides a quick overview of some visionOS specific features in the
+Python distribution.
+
+Python on visionOS is largely the same as Python on iOS; most of the instructions in
+the [iOS README](../iOS/README.md) can be used for visionOS builds, substituting:
+
+- `visionOS` as the identifier for `Platforms/Apple` invocations; e.g.,
+ - `python Platforms/Apple build visionOS`
+ - `python Platforms/Apple ci visionOS`
+ - `python Platforms/Apple test visionOS`
+
+- visionOS resources are stored in the `Platforms/Apple/visionOS/Resources`
+ directory.
+
+- The visionOS SDK version is controlled with the `XROS_SDK_VERSION` environment
+ variable.
+
+- The minimum supported visionOS SDK version is controlled with the
+ `XROS_DEPLOYMENT_TARGET` environment variable.
+
+- When referencing platforms, the visionOS compiler triples are:
+ - `arm64-apple-xros` for Apple Vision devices
+ - `arm64-apple-xros-simulator` for Apple Vision simulators
+
+- The visionOS testbed Xcode template project is stored in
+ `Platforms/Apple/testbed/visionOSTestbed`.
+
+- `platform.ios_ver()` will return visionOS-relevant version information.
diff --git a/Platforms/Apple/visionOS/Resources/Info.plist.in b/Platforms/Apple/visionOS/Resources/Info.plist.in
new file mode 100644
index 000000000000000..c3dd63ced8df89f
--- /dev/null
+++ b/Platforms/Apple/visionOS/Resources/Info.plist.in
@@ -0,0 +1,34 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ @PYTHONFRAMEWORK@
+ CFBundleGetInfoString
+ Python Runtime and Library
+ CFBundleIdentifier
+ @PYTHONFRAMEWORKIDENTIFIER@
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ @PYTHONFRAMEWORK@
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ %VERSION%
+ CFBundleLongVersionString
+ %VERSION%, (c) 2001-2023 Python Software Foundation.
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ %VERSION%
+ CFBundleSupportedPlatforms
+
+ XROS
+
+ MinimumOSVersion
+ @XROS_DEPLOYMENT_TARGET@
+
+
diff --git a/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-ar b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-ar
new file mode 100755
index 000000000000000..f31c0fc3b89abd4
--- /dev/null
+++ b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-ar
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk xros${XROS_SDK_VERSION} ar "$@"
diff --git a/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-clang b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-clang
new file mode 100755
index 000000000000000..d2405ac3405a860
--- /dev/null
+++ b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-clang
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk xros${XROS_SDK_VERSION} clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET} "$@"
diff --git a/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-clang++ b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-clang++
new file mode 100755
index 000000000000000..9063f19ef9a9d5f
--- /dev/null
+++ b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-clang++
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk xros${XROS_SDK_VERSION} clang++ -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET} "$@"
diff --git a/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-cpp b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-cpp
new file mode 100755
index 000000000000000..17a40cbbee1b425
--- /dev/null
+++ b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-cpp
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk xros${XROS_SDK_VERSION} clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET} -E "$@"
diff --git a/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-ar b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-ar
new file mode 100755
index 000000000000000..cf0468377b3386b
--- /dev/null
+++ b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-ar
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk xrsimulator${XROS_SDK_VERSION} ar "$@"
diff --git a/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-clang b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-clang
new file mode 100755
index 000000000000000..ef57a9b76101038
--- /dev/null
+++ b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-clang
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk xrsimulator${XROS_SDK_VERSION} clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET}-simulator "$@"
diff --git a/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-clang++ b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-clang++
new file mode 100755
index 000000000000000..0cc3ec328658624
--- /dev/null
+++ b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-clang++
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk xrsimulator${XROS_SDK_VERSION} clang++ -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET}-simulator "$@"
diff --git a/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-cpp b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-cpp
new file mode 100755
index 000000000000000..835a54a0f9ead1d
--- /dev/null
+++ b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-cpp
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk xrsimulator${XROS_SDK_VERSION} clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET}-simulator -E "$@"
diff --git a/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-strip b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-strip
new file mode 100644
index 000000000000000..376aff61a232ef4
--- /dev/null
+++ b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-strip
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk xrsimulator${XROS_SDK_VERSION} strip -arch arm64 "$@"
diff --git a/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-strip b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-strip
new file mode 100644
index 000000000000000..2de3ba5d31cb10c
--- /dev/null
+++ b/Platforms/Apple/visionOS/Resources/bin/arm64-apple-xros-strip
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk xros${XROS_SDK_VERSION} strip -arch arm64 "$@"
diff --git a/Platforms/Apple/visionOS/Resources/pyconfig.h b/Platforms/Apple/visionOS/Resources/pyconfig.h
new file mode 100644
index 000000000000000..2a4330784006dd5
--- /dev/null
+++ b/Platforms/Apple/visionOS/Resources/pyconfig.h
@@ -0,0 +1,3 @@
+#ifdef __arm64__
+#include "pyconfig-arm64.h"
+#endif
diff --git a/Platforms/Apple/watchOS/README.md b/Platforms/Apple/watchOS/README.md
new file mode 100644
index 000000000000000..6d96ac4855628ee
--- /dev/null
+++ b/Platforms/Apple/watchOS/README.md
@@ -0,0 +1,31 @@
+# Python on watchOS README
+
+This document provides a quick overview of some watchOS specific features in the
+Python distribution.
+
+Python on watchOS is largely the same as Python on iOS; most of the instructions in
+the [iOS README](../iOS/README.md) can be used for watchOS builds, substituting:
+
+- `watchOS` as the identifier for `Platforms/Apple` invocations; e.g.,
+ - `python Platforms/Apple build watchOS`
+ - `python Platforms/Apple ci watchOS`
+ - `python Platforms/Apple test watchOS`
+
+- watchOS resources are stored in the `Platforms/Apple/watchOS/Resources`
+ directory
+
+- The watchOS SDK version is controlled with the `WATCHOS_SDK_VERSION` environment
+ variable.
+
+- The minimum supported watchOS SDK version is controlled with the
+ `WATCHOS_DEPLOYMENT_TARGET` environment variable.
+
+- When referencing platforms, the watchOS compiler triples are:
+ - `arm64_32-apple-watchos` for Apple Watch devices
+ - `arm64-apple-watchos-simulator` for Apple Watch simulators on ARM64 hardware
+ - `x86_64-apple-watchos-simulator` for Apple Watch simulators on x86_64 hardware
+
+- The watchOS testbed Xcode template project is stored in
+ `Platforms/Apple/testbed/watchOSTestbed`.
+
+- `platform.ios_ver()` will return watchOS-relevant version information.
diff --git a/Platforms/Apple/watchOS/Resources/Info.plist.in b/Platforms/Apple/watchOS/Resources/Info.plist.in
new file mode 100644
index 000000000000000..b2f64710d704cdc
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/Info.plist.in
@@ -0,0 +1,34 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ @PYTHONFRAMEWORK@
+ CFBundleGetInfoString
+ Python Runtime and Library
+ CFBundleIdentifier
+ @PYTHONFRAMEWORKIDENTIFIER@
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ @PYTHONFRAMEWORK@
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ %VERSION%
+ CFBundleLongVersionString
+ %VERSION%, (c) 2001-2023 Python Software Foundation.
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ %VERSION%
+ CFBundleSupportedPlatforms
+
+ watchOS
+
+ MinimumOSVersion
+ @WATCHOS_DEPLOYMENT_TARGET@
+
+
diff --git a/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-ar b/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-ar
new file mode 100755
index 000000000000000..0e1b948633ef814
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-ar
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} ar "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang b/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang
new file mode 100755
index 000000000000000..6911a2e3bf38848
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target arm64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang++ b/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang++
new file mode 100755
index 000000000000000..7dacb3d858557c4
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang++
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang++ -target arm64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-cpp b/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-cpp
new file mode 100755
index 000000000000000..a31bc3fb7e49dd8
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-cpp
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchsimulator clang -target arm64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator -E "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-strip b/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-strip
new file mode 100755
index 000000000000000..e28e3f7597a83d1
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-strip
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} strip -arch arm64 "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-strip b/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-strip
new file mode 100755
index 000000000000000..efe5a1260ad910a
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/arm64-apple-watchos-strip
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchos${WATCHOS_SDK_VERSION} strip -arch arm64 "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-ar b/Platforms/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-ar
new file mode 100755
index 000000000000000..78b647b78e5b86c
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-ar
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchos${WATCHOS_SDK_VERSION} ar "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang b/Platforms/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang
new file mode 100755
index 000000000000000..cf7c175b1b0a370
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang -target arm64_32-apple-watchos${WATCHOS_DEPLOYMENT_TARGET} "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang++ b/Platforms/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang++
new file mode 100755
index 000000000000000..c3e6ddfa1fe353e
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang++
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang++ -target arm64_32-apple-watchos${WATCHOS_DEPLOYMENT_TARGET} "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-cpp b/Platforms/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-cpp
new file mode 100755
index 000000000000000..d038450a901a176
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-cpp
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang -target arm64_32-apple-watchos${WATCHOS_DEPLOYMENT_TARGET} -E "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-ar b/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-ar
new file mode 100755
index 000000000000000..0e1b948633ef814
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-ar
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} ar "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang b/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang
new file mode 100755
index 000000000000000..a839a93ab4711c4
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target x86_64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang++ b/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang++
new file mode 100755
index 000000000000000..f0ecc650dfdbbde
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang++
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang++ -target x86_64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-cpp b/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-cpp
new file mode 100755
index 000000000000000..1fe12659baf3e97
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-cpp
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target x86_64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator -E "$@"
diff --git a/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-strip b/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-strip
new file mode 100755
index 000000000000000..105c78281f9b345
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-strip
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} strip -arch x86_64 "$@"
diff --git a/Platforms/Apple/watchOS/Resources/pyconfig.h b/Platforms/Apple/watchOS/Resources/pyconfig.h
new file mode 100644
index 000000000000000..f842b987b2edba1
--- /dev/null
+++ b/Platforms/Apple/watchOS/Resources/pyconfig.h
@@ -0,0 +1,11 @@
+#ifdef __arm64__
+# ifdef __LP64__
+#include "pyconfig-arm64.h"
+# else
+#include "pyconfig-arm64_32.h"
+# endif
+#endif
+
+#ifdef __x86_64__
+#include "pyconfig-x86_64.h"
+#endif
diff --git a/config.sub b/config.sub
index 1bb6a05dc11026c..49febd56a37cc00 100755
--- a/config.sub
+++ b/config.sub
@@ -1743,7 +1743,7 @@ case $os in
| hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
| sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
| hiux* | abug | nacl* | netware* | windows* \
- | os9* | macos* | osx* | ios* | tvos* | watchos* \
+ | os9* | macos* | osx* | ios* | tvos* | watchos* | xros* \
| mpw* | magic* | mmixware* | mon960* | lnews* \
| amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
| aos* | aros* | cloudabi* | sortix* | twizzler* \
@@ -1867,7 +1867,7 @@ case $kernel-$os-$obj in
;;
*-eabi*- | *-gnueabi*-)
;;
- ios*-simulator- | tvos*-simulator- | watchos*-simulator- )
+ ios*-simulator- | tvos*-simulator- | watchos*-simulator- | xros*-simulator-)
;;
none--*)
# None (no kernel, i.e. freestanding / bare metal),
diff --git a/configure b/configure
index 04260d2c4b58344..c0923c8f37a9012 100755
--- a/configure
+++ b/configure
@@ -994,6 +994,10 @@ LDFLAGS
CFLAGS
CC
HAS_XCRUN
+EXPORT_XROS_DEPLOYMENT_TARGET
+WATCHOS_DEPLOYMENT_TARGET
+XROS_DEPLOYMENT_TARGET
+TVOS_DEPLOYMENT_TARGET
IPHONEOS_DEPLOYMENT_TARGET
EXPORT_MACOSX_DEPLOYMENT_TARGET
CONFIGURE_MACOSX_DEPLOYMENT_TARGET
@@ -4188,6 +4192,15 @@ then
*-apple-ios*)
ac_sys_system=iOS
;;
+ *-apple-tvos*)
+ ac_sys_system=tvOS
+ ;;
+ *-apple-xros*)
+ ac_sys_system=visionOS
+ ;;
+ *-apple-watchos*)
+ ac_sys_system=watchOS
+ ;;
*-*-darwin*)
ac_sys_system=Darwin
;;
@@ -4272,7 +4285,7 @@ fi
# On cross-compile builds, configure will look for a host-specific compiler by
# prepending the user-provided host triple to the required binary name.
#
-# On iOS, this results in binaries like "arm64-apple-ios13.0-simulator-gcc",
+# On iOS/tvOS/visionOS/watchOS, this results in binaries like "arm64-apple-ios13.0-simulator-gcc",
# 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
@@ -4287,6 +4300,17 @@ if test -z "$AR"; then
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 ;;
+
+ aarch64-apple-tvos*-simulator) AR=arm64-apple-tvos-simulator-ar ;;
+ aarch64-apple-tvos*) AR=arm64-apple-tvos-ar ;;
+ x86_64-apple-tvos*-simulator) AR=x86_64-apple-tvos-simulator-ar ;;
+
+ aarch64-apple-xros*-simulator) AR=arm64-apple-xros-simulator-ar ;;
+ aarch64-apple-xros*) AR=arm64-apple-xros-ar ;;
+
+ aarch64-apple-watchos*-simulator) AR=arm64-apple-watchos-simulator-ar ;;
+ aarch64-apple-watchos*) AR=arm64_32-apple-watchos-ar ;;
+ x86_64-apple-watchos*-simulator) AR=x86_64-apple-watchos-simulator-ar ;;
*)
esac
fi
@@ -4295,6 +4319,17 @@ if test -z "$CC"; then
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 ;;
+
+ aarch64-apple-tvos*-simulator) CC=arm64-apple-tvos-simulator-clang ;;
+ aarch64-apple-tvos*) CC=arm64-apple-tvos-clang ;;
+ x86_64-apple-tvos*-simulator) CC=x86_64-apple-tvos-simulator-clang ;;
+
+ aarch64-apple-xros*-simulator) CC=arm64-apple-xros-simulator-clang ;;
+ aarch64-apple-xros*) CC=arm64-apple-xros-clang ;;
+
+ aarch64-apple-watchos*-simulator) CC=arm64-apple-watchos-simulator-clang ;;
+ aarch64-apple-watchos*) CC=arm64_32-apple-watchos-clang ;;
+ x86_64-apple-watchos*-simulator) CC=x86_64-apple-watchos-simulator-clang ;;
*)
esac
fi
@@ -4303,6 +4338,17 @@ if test -z "$CPP"; then
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 ;;
+
+ aarch64-apple-tvos*-simulator) CPP=arm64-apple-tvos-simulator-cpp ;;
+ aarch64-apple-tvos*) CPP=arm64-apple-tvos-cpp ;;
+ x86_64-apple-tvos*-simulator) CPP=x86_64-apple-tvos-simulator-cpp ;;
+
+ aarch64-apple-xros*-simulator) CPP=arm64-apple-xros-simulator-cpp ;;
+ aarch64-apple-xros*) CPP=arm64-apple-xros-cpp ;;
+
+ aarch64-apple-watchos*-simulator) CPP=arm64-apple-watchos-simulator-cpp ;;
+ aarch64-apple-watchos*) CPP=arm64_32-apple-watchos-cpp ;;
+ x86_64-apple-watchos*-simulator) CPP=x86_64-apple-watchos-simulator-cpp ;;
*)
esac
fi
@@ -4311,6 +4357,17 @@ if test -z "$CXX"; then
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++ ;;
+
+ aarch64-apple-tvos*-simulator) CXX=arm64-apple-tvos-simulator-clang++ ;;
+ aarch64-apple-tvos*) CXX=arm64-apple-tvos-clang++ ;;
+ x86_64-apple-tvos*-simulator) CXX=x86_64-apple-tvos-simulator-clang++ ;;
+
+ aarch64-apple-xros*-simulator) CXX=arm64-apple-xros-simulator-clang++ ;;
+ aarch64-apple-xros*) CXX=arm64-apple-xros-clang++ ;;
+
+ aarch64-apple-watchos*-simulator) CXX=arm64-apple-watchos-simulator-clang++ ;;
+ aarch64-apple-watchos*) CXX=arm64_32-apple-watchos-clang++ ;;
+ x86_64-apple-watchos*-simulator) CXX=x86_64-apple-watchos-simulator-clang++ ;;
*)
esac
fi
@@ -4433,8 +4490,11 @@ then :
case $enableval in
yes)
case $ac_sys_system in
- Darwin) enableval=/Library/Frameworks ;;
- iOS) enableval=Platforms/Apple/iOS/Frameworks/\$\(MULTIARCH\) ;;
+ Darwin) enableval=/Library/Frameworks ;;
+ iOS) enableval=Platforms/Apple/iOS/Frameworks/\$\(MULTIARCH\) ;;
+ tvOS) enableval=Platforms/Apple/tvOS/Frameworks/\$\(MULTIARCH\) ;;
+ visionOS) enableval=Platforms/Apple/visionOS/Frameworks/\$\(MULTIARCH\) ;;
+ watchOS) enableval=Platforms/Apple/watchOS/Frameworks/\$\(MULTIARCH\) ;;
*) as_fn_error $? "Unknown platform for framework build" "$LINENO" 5
esac
esac
@@ -4545,6 +4605,51 @@ then :
ac_config_files="$ac_config_files Platforms/Apple/iOS/Resources/Info.plist"
+ ;;
+ tvOS) :
+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure"
+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure "
+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKPYTHONW=
+ INSTALLTARGETS="libinstall inclinstall sharedinstall"
+
+ prefix=$PYTHONFRAMEWORKPREFIX
+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR"
+ RESSRCDIR=Platforms/Apple/tvOS/Resources
+
+ ac_config_files="$ac_config_files Platforms/Apple/tvOS/Resources/Info.plist"
+
+ ;;
+ visionOS) :
+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure"
+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure "
+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKPYTHONW=
+ INSTALLTARGETS="libinstall inclinstall sharedinstall"
+
+ prefix=$PYTHONFRAMEWORKPREFIX
+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR"
+ RESSRCDIR=Platforms/Apple/visionOS/Resources
+
+ ac_config_files="$ac_config_files Platforms/Apple/visionOS/Resources/Info.plist"
+
+ ;;
+ watchOS) :
+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure"
+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure "
+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKPYTHONW=
+ INSTALLTARGETS="libinstall inclinstall sharedinstall"
+
+ prefix=$PYTHONFRAMEWORKPREFIX
+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR"
+ RESSRCDIR=Platforms/Apple/watchOS/Resources
+
+ ac_config_files="$ac_config_files Platforms/Apple/watchOS/Resources/Info.plist"
+
;;
*)
as_fn_error $? "Unknown platform for framework build" "$LINENO" 5
@@ -4606,8 +4711,8 @@ then :
case "$withval" in
yes)
case $ac_sys_system in
- Darwin|iOS)
- # iOS is able to share the macOS patch
+ Darwin|iOS|tvOS|visionOS|watchOS)
+ # iOS/tvOS/visionOS/watchOS is able to share the macOS patch
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 ;;
@@ -4625,8 +4730,8 @@ printf "%s\n" "applying custom app store compliance patch" >&6; }
else case e in #(
e)
case $ac_sys_system in
- iOS)
- # Always apply the compliance patch on iOS; we can use the macOS patch
+ iOS|tvOS|visionOS|watchOS)
+ # Always apply the compliance patch on iOS/tvOS/visionOS/watchOS; we can use the macOS patch
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; }
@@ -4644,6 +4749,8 @@ fi
+EXPORT_XROS_DEPLOYMENT_TARGET='#'
+
if test "$cross_compiling" = yes; then
case "$host" in
@@ -4684,6 +4791,78 @@ printf "%s\n" "$IPHONEOS_DEPLOYMENT_TARGET" >&6; }
;;
esac
;;
+ *-apple-tvos*)
+ _host_os=`echo $host | cut -d '-' -f3`
+ _host_device=`echo $host | cut -d '-' -f4`
+ _host_device=${_host_device:=os}
+
+ # TVOS_DEPLOYMENT_TARGET is the minimum supported tvOS version
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking tvOS deployment target" >&5
+printf %s "checking tvOS deployment target... " >&6; }
+ TVOS_DEPLOYMENT_TARGET=${_host_os:4}
+ TVOS_DEPLOYMENT_TARGET=${TVOS_DEPLOYMENT_TARGET:=12.0}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TVOS_DEPLOYMENT_TARGET" >&5
+printf "%s\n" "$TVOS_DEPLOYMENT_TARGET" >&6; }
+
+ case "$host_cpu" in
+ aarch64)
+ _host_ident=${TVOS_DEPLOYMENT_TARGET}-arm64-appletv${_host_device}
+ ;;
+ *)
+ _host_ident=${TVOS_DEPLOYMENT_TARGET}-$host_cpu-appletv${_host_device}
+ ;;
+ esac
+ ;;
+ *-apple-xros*)
+ _host_os=`echo $host | cut -d '-' -f3`
+ _host_device=`echo $host | cut -d '-' -f4`
+ _host_device=${_host_device:=os}
+
+ # XROS_DEPLOYMENT_TARGET is the minimum supported visionOS version
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking visionOS deployment target" >&5
+printf %s "checking visionOS deployment target... " >&6; }
+ XROS_DEPLOYMENT_TARGET=${_host_os:8}
+ XROS_DEPLOYMENT_TARGET=${XROS_DEPLOYMENT_TARGET:=2.0}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $XROS_DEPLOYMENT_TARGET" >&5
+printf "%s\n" "$XROS_DEPLOYMENT_TARGET" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking exporting flag of visionOS deployment target" >&5
+printf %s "checking exporting flag of visionOS deployment target... " >&6; }
+ export XROS_DEPLOYMENT_TARGET
+ EXPORT_XROS_DEPLOYMENT_TARGET=''
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $EXPORT_XROS_DEPLOYMENT_TARGET" >&5
+printf "%s\n" "$EXPORT_XROS_DEPLOYMENT_TARGET" >&6; }
+
+ case "$host_cpu" in
+ aarch64)
+ _host_ident=${XROS_DEPLOYMENT_TARGET}-arm64-xr${_host_device}
+ ;;
+ *)
+ _host_ident=${XROS_DEPLOYMENT_TARGET}-$host_cpu-xr${_host_device}
+ ;;
+ esac
+ ;;
+ *-apple-watchos*)
+ _host_os=`echo $host | cut -d '-' -f3`
+ _host_device=`echo $host | cut -d '-' -f4`
+ _host_device=${_host_device:=os}
+
+ # WATCHOS_DEPLOYMENT_TARGET is the minimum supported watchOS version
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking watchOS deployment target" >&5
+printf %s "checking watchOS deployment target... " >&6; }
+ WATCHOS_DEPLOYMENT_TARGET=${_host_os:7}
+ WATCHOS_DEPLOYMENT_TARGET=${WATCHOS_DEPLOYMENT_TARGET:=9.0}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WATCHOS_DEPLOYMENT_TARGET" >&5
+printf "%s\n" "$WATCHOS_DEPLOYMENT_TARGET" >&6; }
+
+ case "$host_cpu" in
+ aarch64)
+ _host_ident=${WATCHOS_DEPLOYMENT_TARGET}-arm64-watch${_host_device}
+ ;;
+ *)
+ _host_ident=${WATCHOS_DEPLOYMENT_TARGET}-$host_cpu-watch${_host_device}
+ ;;
+ esac
+ ;;
*-*-darwin*)
case "$host_cpu" in
arm*)
@@ -4771,9 +4950,15 @@ printf "%s\n" "#define _BSD_SOURCE 1" >>confdefs.h
define_xopen_source=no;;
Darwin/[12][0-9].*)
define_xopen_source=no;;
- # On iOS, defining _POSIX_C_SOURCE also disables platform specific features.
+ # On iOS/tvOS/visionOS/watchOS, defining _POSIX_C_SOURCE also disables platform specific features.
iOS/*)
define_xopen_source=no;;
+ tvOS/*)
+ define_xopen_source=no;;
+ visionOS/*)
+ define_xopen_source=no;;
+ watchOS/*)
+ define_xopen_source=no;;
# On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from
# defining NI_NUMERICHOST.
QNX/6.3.2)
@@ -4852,7 +5037,14 @@ fi
CONFIGURE_MACOSX_DEPLOYMENT_TARGET=
EXPORT_MACOSX_DEPLOYMENT_TARGET='#'
-# Record the value of IPHONEOS_DEPLOYMENT_TARGET enforced by the selected host triple.
+# Record the value of IPHONEOS_DEPLOYMENT_TARGET / TVOS_DEPLOYMENT_TARGET /
+# XROS_DEPLOYMENT_TARGET / WATCHOS_DEPLOYMENT_TARGET enforced by the selected host triple.
+
+
+
+
+
+# XROS_DEPLOYMENT_TARGET should get exported
# checks for alternative programs
@@ -4898,6 +5090,26 @@ case $host in #(
as_fn_append CFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"
as_fn_append LDFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"
;; #(
+ *-apple-tvos*-simulator) :
+
+ as_fn_append CFLAGS " -mtvos-simulator-version-min=${TVOS_DEPLOYMENT_TARGET}"
+ as_fn_append LDFLAGS " -mtvos-simulator-version-min=${TVOS_DEPLOYMENT_TARGET}"
+ ;; #(
+ *-apple-tvos*) :
+
+ as_fn_append CFLAGS " -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"
+ as_fn_append LDFLAGS " -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"
+ ;; #(
+ *-apple-watchos*-simulator) :
+
+ as_fn_append CFLAGS " -mwatchos-simulator-version-min=${WATCHOS_DEPLOYMENT_TARGET}"
+ as_fn_append LDFLAGS " -mwatchos-simulator-version-min=${WATCHOS_DEPLOYMENT_TARGET}"
+ ;; #(
+ *-apple-watchos*) :
+
+ as_fn_append CFLAGS " -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"
+ as_fn_append LDFLAGS " -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"
+ ;; #(
*) :
;;
esac
@@ -7379,6 +7591,12 @@ case $ac_sys_system in #(
MULTIARCH="" ;; #(
iOS) :
MULTIARCH="" ;; #(
+ tvOS) :
+ MULTIARCH="" ;; #(
+ visionOS) :
+ MULTIARCH="" ;; #(
+ watchOS) :
+ MULTIARCH="" ;; #(
FreeBSD*) :
MULTIARCH="" ;; #(
OpenBSD*) :
@@ -7401,7 +7619,7 @@ fi
printf "%s\n" "$MULTIARCH" >&6; }
case $ac_sys_system in #(
- iOS) :
+ iOS|tvOS|visionOS|watchOS) :
SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2` ;; #(
*) :
SOABI_PLATFORM=$PLATFORM_TRIPLET
@@ -7952,7 +8170,7 @@ then
case $ac_sys_system in
Darwin)
LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)';;
- iOS)
+ iOS|tvOS|visionOS|watchOS)
LDLIBRARY='$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)';;
*)
as_fn_error $? "Unknown platform for framework build" "$LINENO" 5;;
@@ -8018,7 +8236,7 @@ printf "%s\n" "#define Py_ENABLE_SHARED 1" >>confdefs.h
BLDLIBRARY='-L. -lpython$(LDVERSION)'
RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}}
;;
- iOS)
+ iOS|tvOS|visionOS|watchOS)
if test -z "$PYTHONFRAMEWORK"; then
as_fn_error $? "iOS shared builds must use --enable-framework; an iOS app can only load a signed framework, never a bare dylib" "$LINENO" 5
fi
@@ -14497,7 +14715,7 @@ then
BLDSHARED="$LDSHARED"
fi
;;
- iOS/*)
+ iOS/*|tvOS/*|visionOS/*|watchOS/*)
LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)'
LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)'
BLDSHARED="$LDSHARED"
@@ -14630,7 +14848,7 @@ then
Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";;
Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";;
# -u libsys_s pulls in all symbols in libsys
- Darwin/*|iOS/*)
+ Darwin/*|iOS/*|tvOS/*|visionOS/*|watchOS/*)
LINKFORSHARED="$extra_undefs -framework CoreFoundation"
# Issue #18075: the default maximum stack size (8MBytes) is too
@@ -14654,7 +14872,7 @@ printf "%s\n" "#define THREAD_STACK_SIZE 0x$stack_size" >>confdefs.h
LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)'
fi
LINKFORSHARED="$LINKFORSHARED"
- elif test $ac_sys_system = "iOS"; then
+ elif test "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "visionOS" -o "$ac_sys_system" = "watchOS"; then
LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED"
if test "$enable_framework"; then
@@ -16598,7 +16816,7 @@ then :
ctypes_malloc_closure=yes
;; #(
- iOS) :
+ iOS|tvOS|visionOS|watchOS) :
ctypes_malloc_closure=yes
;; #(
@@ -20634,12 +20852,6 @@ if test "x$ac_cv_func_dup" = xyes
then :
printf "%s\n" "#define HAVE_DUP 1" >>confdefs.h
-fi
-ac_fn_c_check_func "$LINENO" "execv" "ac_cv_func_execv"
-if test "x$ac_cv_func_execv" = xyes
-then :
- printf "%s\n" "#define HAVE_EXECV 1" >>confdefs.h
-
fi
ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero"
if test "x$ac_cv_func_explicit_bzero" = xyes
@@ -20700,18 +20912,6 @@ if test "x$ac_cv_func_fexecve" = xyes
then :
printf "%s\n" "#define HAVE_FEXECVE 1" >>confdefs.h
-fi
-ac_fn_c_check_func "$LINENO" "fork" "ac_cv_func_fork"
-if test "x$ac_cv_func_fork" = xyes
-then :
- printf "%s\n" "#define HAVE_FORK 1" >>confdefs.h
-
-fi
-ac_fn_c_check_func "$LINENO" "fork1" "ac_cv_func_fork1"
-if test "x$ac_cv_func_fork1" = xyes
-then :
- printf "%s\n" "#define HAVE_FORK1 1" >>confdefs.h
-
fi
ac_fn_c_check_func "$LINENO" "fpathconf" "ac_cv_func_fpathconf"
if test "x$ac_cv_func_fpathconf" = xyes
@@ -21186,24 +21386,6 @@ if test "x$ac_cv_func_posix_openpt" = xyes
then :
printf "%s\n" "#define HAVE_POSIX_OPENPT 1" >>confdefs.h
-fi
-ac_fn_c_check_func "$LINENO" "posix_spawn" "ac_cv_func_posix_spawn"
-if test "x$ac_cv_func_posix_spawn" = xyes
-then :
- printf "%s\n" "#define HAVE_POSIX_SPAWN 1" >>confdefs.h
-
-fi
-ac_fn_c_check_func "$LINENO" "posix_spawnp" "ac_cv_func_posix_spawnp"
-if test "x$ac_cv_func_posix_spawnp" = xyes
-then :
- printf "%s\n" "#define HAVE_POSIX_SPAWNP 1" >>confdefs.h
-
-fi
-ac_fn_c_check_func "$LINENO" "posix_spawn_file_actions_addclosefrom_np" "ac_cv_func_posix_spawn_file_actions_addclosefrom_np"
-if test "x$ac_cv_func_posix_spawn_file_actions_addclosefrom_np" = xyes
-then :
- printf "%s\n" "#define HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP 1" >>confdefs.h
-
fi
ac_fn_c_check_func "$LINENO" "pread" "ac_cv_func_pread"
if test "x$ac_cv_func_pread" = xyes
@@ -21522,12 +21704,6 @@ if test "x$ac_cv_func_sigaction" = xyes
then :
printf "%s\n" "#define HAVE_SIGACTION 1" >>confdefs.h
-fi
-ac_fn_c_check_func "$LINENO" "sigaltstack" "ac_cv_func_sigaltstack"
-if test "x$ac_cv_func_sigaltstack" = xyes
-then :
- printf "%s\n" "#define HAVE_SIGALTSTACK 1" >>confdefs.h
-
fi
ac_fn_c_check_func "$LINENO" "sigfillset" "ac_cv_func_sigfillset"
if test "x$ac_cv_func_sigfillset" = xyes
@@ -21947,14 +22123,14 @@ fi
fi
-# iOS defines some system methods that can be linked (so they are
+# iOS/tvOS/visionOS/watchOS define some system methods that can be linked (so they are
# found by configure), but either raise a compilation error (because the
# header definition prevents usage - autoconf doesn't use the headers), or
# raise an error if used at runtime. Force these symbols off.
-# In particular, dup3 and pipe2 are available as of iOS 27 but were
+# In particular, dup3 and pipe2 are available as of iOS/tvOS/watchOS/visionOS 27 but were
# incorrectly detected in older simulator versions.
case "$ac_sys_system" in
- iOS)
+ iOS|tvOS|watchOS|visionOS)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if iOS SDK is older than 27" >&5
printf %s "checking if iOS SDK is older than 27... " >&6; }
ios_sdk_version=$(xcrun --sdk iphoneos --show-sdk-version 2>/dev/null | cut -d. -f1)
@@ -21980,7 +22156,7 @@ printf "%s\n" "yes" >&6; }
fi
;;
*)
- # not iOS
+ # not iOS/tvOS/watchOS/visionOS
ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
if test "x$ac_cv_func_dup3" = xyes
then :
@@ -22015,6 +22191,53 @@ fi
;;
esac
+# tvOS/watchOS have some additional methods that can be found, but not used.
+if test "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then
+ ac_fn_c_check_func "$LINENO" "execv" "ac_cv_func_execv"
+if test "x$ac_cv_func_execv" = xyes
+then :
+ printf "%s\n" "#define HAVE_EXECV 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "fork" "ac_cv_func_fork"
+if test "x$ac_cv_func_fork" = xyes
+then :
+ printf "%s\n" "#define HAVE_FORK 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "fork1" "ac_cv_func_fork1"
+if test "x$ac_cv_func_fork1" = xyes
+then :
+ printf "%s\n" "#define HAVE_FORK1 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "posix_spawn" "ac_cv_func_posix_spawn"
+if test "x$ac_cv_func_posix_spawn" = xyes
+then :
+ printf "%s\n" "#define HAVE_POSIX_SPAWN 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "posix_spawnp" "ac_cv_func_posix_spawnp"
+if test "x$ac_cv_func_posix_spawnp" = xyes
+then :
+ printf "%s\n" "#define HAVE_POSIX_SPAWNP 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "posix_spawn_file_actions_addclosefrom_np" "ac_cv_func_posix_spawn_file_actions_addclosefrom_np"
+if test "x$ac_cv_func_posix_spawn_file_actions_addclosefrom_np" = xyes
+then :
+ printf "%s\n" "#define HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "sigaltstack" "ac_cv_func_sigaltstack"
+if test "x$ac_cv_func_sigaltstack" = xyes
+then :
+ printf "%s\n" "#define HAVE_SIGALTSTACK 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include
#include
" "$ac_c_undeclared_builtin_options" "CFLAGS"
@@ -25633,7 +25856,8 @@ fi
;;
esac
# check for openpty, login_tty, and forkpty
-
+# tvOS/watchOS have functions for tty, but can't use them
+if test "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then
for ac_func in openpty
do :
@@ -25747,7 +25971,7 @@ esac
fi
done
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing login_tty" >&5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing login_tty" >&5
printf %s "checking for library containing login_tty... " >&6; }
if test ${ac_cv_search_login_tty+y}
then :
@@ -25930,6 +26154,7 @@ esac
fi
done
+fi
# check for long file support functions
ac_fn_c_check_func "$LINENO" "fseek64" "ac_cv_func_fseek64"
@@ -26195,10 +26420,10 @@ fi
done
-# On Android and iOS, clock_settime can be linked (so it is found by
+# On Android, iOS, tvOS, visionOS, and watchOS, clock_settime can be linked (so it is found by
# configure), but when used in an unprivileged process, it crashes rather than
# returning an error. Force the symbol off.
-if test "$ac_sys_system" != "Linux-android" && test "$ac_sys_system" != "iOS"
+if test "$ac_sys_system" != "Linux-android" -a "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "visionOS" -a "$ac_sys_system" != "watchOS"
then
for ac_func in clock_settime
@@ -26515,7 +26740,7 @@ else case e in #(
e) if test "$cross_compiling" = yes
then :
-if test "$ac_sys_system" = "Linux-android" || test "$ac_sys_system" = "iOS"; then
+if test "$ac_sys_system" = "Linux-android" || test "$ac_sys_system" = "iOS" || test "$ac_sys_system" = "tvOS" || test "$ac_sys_system" = "visionOS" || test "$ac_sys_system" = "watchOS"; then
ac_cv_buggy_getaddrinfo="no"
elif test "${enable_ipv6+set}" = set; then
ac_cv_buggy_getaddrinfo="no -- configured with --(en|dis)able-ipv6"
@@ -28888,8 +29113,8 @@ if test "$PY_ENABLE_SHARED" = "1" && ( test -n "$ANDROID_API_LEVEL" || test "$MA
LIBPYTHON="-lpython${VERSION}${ABIFLAGS}"
fi
-# On iOS the shared libraries must be linked with the framework, when built
-if test "$ac_sys_system" = "iOS" && test "$enable_framework"; then
+# On iOS/tvOS/watchOS the shared libraries must be linked with the framework, when built
+if test "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "visionOS" -o "$ac_sys_system" = "watchOS" && test "$enable_framework"; then
MODULE_DEPS_SHARED="$MODULE_DEPS_SHARED \$(PYTHONFRAMEWORKDIR)/\$(PYTHONFRAMEWORK)"
fi
@@ -34337,7 +34562,7 @@ LIBS=$save_LIBS
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for device files" >&5
printf "%s\n" "$as_me: checking for device files" >&6;}
-if test "$ac_sys_system" = "Linux-android" || test "$ac_sys_system" = "iOS"; then
+if test "$ac_sys_system" = "Linux-android" -o "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "visionOS" -o "$ac_sys_system" = "watchOS" ; then
ac_cv_file__dev_ptmx=no
ac_cv_file__dev_ptc=no
else
@@ -34890,7 +35115,7 @@ else case e in #(
with_ensurepip=no ;; #(
WASI) :
with_ensurepip=no ;; #(
- iOS) :
+ iOS|tvOS|visionOS|watchOS) :
with_ensurepip=no ;; #(
*) :
with_ensurepip=upgrade
@@ -35895,6 +36120,9 @@ case "$ac_sys_system" in
NetBSD*) _PYTHREAD_NAME_MAXLEN=15;; # gh-131268
Darwin) _PYTHREAD_NAME_MAXLEN=63;;
iOS) _PYTHREAD_NAME_MAXLEN=63;;
+ tvOS) _PYTHREAD_NAME_MAXLEN=63;;
+ visionOS) _PYTHREAD_NAME_MAXLEN=63;;
+ watchOS) _PYTHREAD_NAME_MAXLEN=63;;
FreeBSD*) _PYTHREAD_NAME_MAXLEN=19;; # gh-131268
OpenBSD*) _PYTHREAD_NAME_MAXLEN=23;; # gh-131268
CYGWIN*) _PYTHREAD_NAME_MAXLEN=16;;
@@ -35927,7 +36155,7 @@ case $ac_sys_system in #(
;; #(
Darwin) :
;; #(
- iOS) :
+ iOS|tvOS|visionOS|watchOS) :
@@ -40242,6 +40470,9 @@ do
"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" ;;
"Platforms/Apple/iOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES Platforms/Apple/iOS/Resources/Info.plist" ;;
+ "Platforms/Apple/tvOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES Platforms/Apple/tvOS/Resources/Info.plist" ;;
+ "Platforms/Apple/visionOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES Platforms/Apple/visionOS/Resources/Info.plist" ;;
+ "Platforms/Apple/watchOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES Platforms/Apple/watchOS/Resources/Info.plist" ;;
"Makefile.pre") CONFIG_FILES="$CONFIG_FILES Makefile.pre" ;;
"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 b53247194fc9003..e4600addbe3303a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -345,6 +345,15 @@ then
*-apple-ios*)
ac_sys_system=iOS
;;
+ *-apple-tvos*)
+ ac_sys_system=tvOS
+ ;;
+ *-apple-xros*)
+ ac_sys_system=visionOS
+ ;;
+ *-apple-watchos*)
+ ac_sys_system=watchOS
+ ;;
*-*-darwin*)
ac_sys_system=Darwin
;;
@@ -423,7 +432,7 @@ AC_SUBST([host_exec_prefix])
# On cross-compile builds, configure will look for a host-specific compiler by
# prepending the user-provided host triple to the required binary name.
#
-# On iOS, this results in binaries like "arm64-apple-ios13.0-simulator-gcc",
+# On iOS/tvOS/visionOS/watchOS, this results in binaries like "arm64-apple-ios13.0-simulator-gcc",
# 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
@@ -438,6 +447,17 @@ if test -z "$AR"; then
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 ;;
+
+ aarch64-apple-tvos*-simulator) AR=arm64-apple-tvos-simulator-ar ;;
+ aarch64-apple-tvos*) AR=arm64-apple-tvos-ar ;;
+ x86_64-apple-tvos*-simulator) AR=x86_64-apple-tvos-simulator-ar ;;
+
+ aarch64-apple-xros*-simulator) AR=arm64-apple-xros-simulator-ar ;;
+ aarch64-apple-xros*) AR=arm64-apple-xros-ar ;;
+
+ aarch64-apple-watchos*-simulator) AR=arm64-apple-watchos-simulator-ar ;;
+ aarch64-apple-watchos*) AR=arm64_32-apple-watchos-ar ;;
+ x86_64-apple-watchos*-simulator) AR=x86_64-apple-watchos-simulator-ar ;;
*)
esac
fi
@@ -446,6 +466,17 @@ if test -z "$CC"; then
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 ;;
+
+ aarch64-apple-tvos*-simulator) CC=arm64-apple-tvos-simulator-clang ;;
+ aarch64-apple-tvos*) CC=arm64-apple-tvos-clang ;;
+ x86_64-apple-tvos*-simulator) CC=x86_64-apple-tvos-simulator-clang ;;
+
+ aarch64-apple-xros*-simulator) CC=arm64-apple-xros-simulator-clang ;;
+ aarch64-apple-xros*) CC=arm64-apple-xros-clang ;;
+
+ aarch64-apple-watchos*-simulator) CC=arm64-apple-watchos-simulator-clang ;;
+ aarch64-apple-watchos*) CC=arm64_32-apple-watchos-clang ;;
+ x86_64-apple-watchos*-simulator) CC=x86_64-apple-watchos-simulator-clang ;;
*)
esac
fi
@@ -454,6 +485,17 @@ if test -z "$CPP"; then
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 ;;
+
+ aarch64-apple-tvos*-simulator) CPP=arm64-apple-tvos-simulator-cpp ;;
+ aarch64-apple-tvos*) CPP=arm64-apple-tvos-cpp ;;
+ x86_64-apple-tvos*-simulator) CPP=x86_64-apple-tvos-simulator-cpp ;;
+
+ aarch64-apple-xros*-simulator) CPP=arm64-apple-xros-simulator-cpp ;;
+ aarch64-apple-xros*) CPP=arm64-apple-xros-cpp ;;
+
+ aarch64-apple-watchos*-simulator) CPP=arm64-apple-watchos-simulator-cpp ;;
+ aarch64-apple-watchos*) CPP=arm64_32-apple-watchos-cpp ;;
+ x86_64-apple-watchos*-simulator) CPP=x86_64-apple-watchos-simulator-cpp ;;
*)
esac
fi
@@ -462,6 +504,17 @@ if test -z "$CXX"; then
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++ ;;
+
+ aarch64-apple-tvos*-simulator) CXX=arm64-apple-tvos-simulator-clang++ ;;
+ aarch64-apple-tvos*) CXX=arm64-apple-tvos-clang++ ;;
+ x86_64-apple-tvos*-simulator) CXX=x86_64-apple-tvos-simulator-clang++ ;;
+
+ aarch64-apple-xros*-simulator) CXX=arm64-apple-xros-simulator-clang++ ;;
+ aarch64-apple-xros*) CXX=arm64-apple-xros-clang++ ;;
+
+ aarch64-apple-watchos*-simulator) CXX=arm64-apple-watchos-simulator-clang++ ;;
+ aarch64-apple-watchos*) CXX=arm64_32-apple-watchos-clang++ ;;
+ x86_64-apple-watchos*-simulator) CXX=x86_64-apple-watchos-simulator-clang++ ;;
*)
esac
fi
@@ -576,8 +629,11 @@ AC_ARG_ENABLE([framework],
case $enableval in
yes)
case $ac_sys_system in
- Darwin) enableval=/Library/Frameworks ;;
- iOS) enableval=Platforms/Apple/iOS/Frameworks/\$\(MULTIARCH\) ;;
+ Darwin) enableval=/Library/Frameworks ;;
+ iOS) enableval=Platforms/Apple/iOS/Frameworks/\$\(MULTIARCH\) ;;
+ tvOS) enableval=Platforms/Apple/tvOS/Frameworks/\$\(MULTIARCH\) ;;
+ visionOS) enableval=Platforms/Apple/visionOS/Frameworks/\$\(MULTIARCH\) ;;
+ watchOS) enableval=Platforms/Apple/watchOS/Frameworks/\$\(MULTIARCH\) ;;
*) AC_MSG_ERROR([Unknown platform for framework build])
esac
esac
@@ -684,6 +740,48 @@ AC_ARG_ENABLE([framework],
AC_CONFIG_FILES([Platforms/Apple/iOS/Resources/Info.plist])
;;
+ tvOS) :
+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure"
+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure "
+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKPYTHONW=
+ INSTALLTARGETS="libinstall inclinstall sharedinstall"
+
+ prefix=$PYTHONFRAMEWORKPREFIX
+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR"
+ RESSRCDIR=Platforms/Apple/tvOS/Resources
+
+ AC_CONFIG_FILES([Platforms/Apple/tvOS/Resources/Info.plist])
+ ;;
+ visionOS) :
+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure"
+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure "
+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKPYTHONW=
+ INSTALLTARGETS="libinstall inclinstall sharedinstall"
+
+ prefix=$PYTHONFRAMEWORKPREFIX
+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR"
+ RESSRCDIR=Platforms/Apple/visionOS/Resources
+
+ AC_CONFIG_FILES([Platforms/Apple/visionOS/Resources/Info.plist])
+ ;;
+ watchOS) :
+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure"
+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure "
+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKPYTHONW=
+ INSTALLTARGETS="libinstall inclinstall sharedinstall"
+
+ prefix=$PYTHONFRAMEWORKPREFIX
+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR"
+ RESSRCDIR=Platforms/Apple/watchOS/Resources
+
+ AC_CONFIG_FILES([Platforms/Apple/watchOS/Resources/Info.plist])
+ ;;
*)
AC_MSG_ERROR([Unknown platform for framework build])
;;
@@ -740,8 +838,8 @@ AC_ARG_WITH(
case "$withval" in
yes)
case $ac_sys_system in
- Darwin|iOS)
- # iOS is able to share the macOS patch
+ Darwin|iOS|tvOS|visionOS|watchOS)
+ # iOS/tvOS/visionOS/watchOS is able to share the macOS patch
APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch"
;;
*) AC_MSG_ERROR([no default app store compliance patch available for $ac_sys_system]) ;;
@@ -755,8 +853,8 @@ AC_ARG_WITH(
esac
],[
case $ac_sys_system in
- iOS)
- # Always apply the compliance patch on iOS; we can use the macOS patch
+ iOS|tvOS|visionOS|watchOS)
+ # Always apply the compliance patch on iOS/tvOS/visionOS/watchOS; we can use the macOS patch
APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch"
AC_MSG_RESULT([applying default app store compliance patch])
;;
@@ -769,6 +867,8 @@ AC_ARG_WITH(
])
AC_SUBST([APP_STORE_COMPLIANCE_PATCH])
+EXPORT_XROS_DEPLOYMENT_TARGET='#'
+
AC_SUBST([_PYTHON_HOST_PLATFORM])
if test "$cross_compiling" = yes; then
case "$host" in
@@ -807,6 +907,70 @@ if test "$cross_compiling" = yes; then
;;
esac
;;
+ *-apple-tvos*)
+ _host_os=`echo $host | cut -d '-' -f3`
+ _host_device=`echo $host | cut -d '-' -f4`
+ _host_device=${_host_device:=os}
+
+ # TVOS_DEPLOYMENT_TARGET is the minimum supported tvOS version
+ AC_MSG_CHECKING([tvOS deployment target])
+ TVOS_DEPLOYMENT_TARGET=${_host_os:4}
+ TVOS_DEPLOYMENT_TARGET=${TVOS_DEPLOYMENT_TARGET:=12.0}
+ AC_MSG_RESULT([$TVOS_DEPLOYMENT_TARGET])
+
+ case "$host_cpu" in
+ aarch64)
+ _host_ident=${TVOS_DEPLOYMENT_TARGET}-arm64-appletv${_host_device}
+ ;;
+ *)
+ _host_ident=${TVOS_DEPLOYMENT_TARGET}-$host_cpu-appletv${_host_device}
+ ;;
+ esac
+ ;;
+ *-apple-xros*)
+ _host_os=`echo $host | cut -d '-' -f3`
+ _host_device=`echo $host | cut -d '-' -f4`
+ _host_device=${_host_device:=os}
+
+ # XROS_DEPLOYMENT_TARGET is the minimum supported visionOS version
+ AC_MSG_CHECKING([visionOS deployment target])
+ XROS_DEPLOYMENT_TARGET=${_host_os:8}
+ XROS_DEPLOYMENT_TARGET=${XROS_DEPLOYMENT_TARGET:=2.0}
+ AC_MSG_RESULT([$XROS_DEPLOYMENT_TARGET])
+ AC_MSG_CHECKING([exporting flag of visionOS deployment target])
+ export XROS_DEPLOYMENT_TARGET
+ EXPORT_XROS_DEPLOYMENT_TARGET=''
+ AC_MSG_RESULT([$EXPORT_XROS_DEPLOYMENT_TARGET])
+
+ case "$host_cpu" in
+ aarch64)
+ _host_ident=${XROS_DEPLOYMENT_TARGET}-arm64-xr${_host_device}
+ ;;
+ *)
+ _host_ident=${XROS_DEPLOYMENT_TARGET}-$host_cpu-xr${_host_device}
+ ;;
+ esac
+ ;;
+ *-apple-watchos*)
+ _host_os=`echo $host | cut -d '-' -f3`
+ _host_device=`echo $host | cut -d '-' -f4`
+ _host_device=${_host_device:=os}
+
+ # WATCHOS_DEPLOYMENT_TARGET is the minimum supported watchOS version
+ AC_MSG_CHECKING([watchOS deployment target])
+ WATCHOS_DEPLOYMENT_TARGET=${_host_os:7}
+ WATCHOS_DEPLOYMENT_TARGET=${WATCHOS_DEPLOYMENT_TARGET:=9.0}
+ AC_MSG_RESULT([$WATCHOS_DEPLOYMENT_TARGET])
+
+ case "$host_cpu" in
+ aarch64)
+ _host_ident=${WATCHOS_DEPLOYMENT_TARGET}-arm64-watch${_host_device}
+ ;;
+ *)
+ _host_ident=${WATCHOS_DEPLOYMENT_TARGET}-$host_cpu-watch${_host_device}
+ ;;
+ esac
+ ;;
*-*-darwin*)
case "$host_cpu" in
arm*)
@@ -893,9 +1057,15 @@ case $ac_sys_system/$ac_sys_release in
define_xopen_source=no;;
Darwin/@<:@[12]@:>@@<:@0-9@:>@.*)
define_xopen_source=no;;
- # On iOS, defining _POSIX_C_SOURCE also disables platform specific features.
+ # On iOS/tvOS/visionOS/watchOS, defining _POSIX_C_SOURCE also disables platform specific features.
iOS/*)
define_xopen_source=no;;
+ tvOS/*)
+ define_xopen_source=no;;
+ visionOS/*)
+ define_xopen_source=no;;
+ watchOS/*)
+ define_xopen_source=no;;
# On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from
# defining NI_NUMERICHOST.
QNX/6.3.2)
@@ -968,8 +1138,15 @@ AC_SUBST([EXPORT_MACOSX_DEPLOYMENT_TARGET])
CONFIGURE_MACOSX_DEPLOYMENT_TARGET=
EXPORT_MACOSX_DEPLOYMENT_TARGET='#'
-# Record the value of IPHONEOS_DEPLOYMENT_TARGET enforced by the selected host triple.
+# Record the value of IPHONEOS_DEPLOYMENT_TARGET / TVOS_DEPLOYMENT_TARGET /
+# XROS_DEPLOYMENT_TARGET / WATCHOS_DEPLOYMENT_TARGET enforced by the selected host triple.
AC_SUBST([IPHONEOS_DEPLOYMENT_TARGET])
+AC_SUBST([TVOS_DEPLOYMENT_TARGET])
+AC_SUBST([XROS_DEPLOYMENT_TARGET])
+AC_SUBST([WATCHOS_DEPLOYMENT_TARGET])
+
+# XROS_DEPLOYMENT_TARGET should get exported
+AC_SUBST([EXPORT_XROS_DEPLOYMENT_TARGET])
# checks for alternative programs
@@ -1003,15 +1180,28 @@ AS_CASE([$host],
],
)
-dnl Add the compiler flag for the iOS minimum supported OS version.
+dnl Add the compiler flag for the iOS/tvOS/watchOS minimum supported OS
+dnl version. visionOS doesn't use an explicit -mxros-version-min option -
+dnl it encodes the min version into the target triple.
AS_CASE([$host],
[*-apple-ios*-simulator], [
AS_VAR_APPEND([CFLAGS], [" -mios-simulator-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"])
AS_VAR_APPEND([LDFLAGS], [" -mios-simulator-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"])
- ],
- [*-apple-ios*], [
+ ],[*-apple-ios*], [
AS_VAR_APPEND([CFLAGS], [" -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"])
AS_VAR_APPEND([LDFLAGS], [" -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"])
+ ],[*-apple-tvos*-simulator], [
+ AS_VAR_APPEND([CFLAGS], [" -mtvos-simulator-version-min=${TVOS_DEPLOYMENT_TARGET}"])
+ AS_VAR_APPEND([LDFLAGS], [" -mtvos-simulator-version-min=${TVOS_DEPLOYMENT_TARGET}"])
+ ],[*-apple-tvos*], [
+ AS_VAR_APPEND([CFLAGS], [" -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"])
+ AS_VAR_APPEND([LDFLAGS], [" -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"])
+ ],[*-apple-watchos*-simulator], [
+ AS_VAR_APPEND([CFLAGS], [" -mwatchos-simulator-version-min=${WATCHOS_DEPLOYMENT_TARGET}"])
+ AS_VAR_APPEND([LDFLAGS], [" -mwatchos-simulator-version-min=${WATCHOS_DEPLOYMENT_TARGET}"])
+ ],[*-apple-watchos*], [
+ AS_VAR_APPEND([CFLAGS], [" -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"])
+ AS_VAR_APPEND([LDFLAGS], [" -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"])
],
)
@@ -1203,6 +1393,9 @@ AC_MSG_CHECKING([for multiarch])
AS_CASE([$ac_sys_system],
[Darwin*], [MULTIARCH=""],
[iOS], [MULTIARCH=""],
+ [tvOS], [MULTIARCH=""],
+ [visionOS], [MULTIARCH=""],
+ [watchOS], [MULTIARCH=""],
[FreeBSD*], [MULTIARCH=""],
[OpenBSD*], [MULTIARCH=""],
[MULTIARCH=$($CC --print-multiarch 2>/dev/null)]
@@ -1225,7 +1418,7 @@ dnl will have multiple sysconfig modules (one for each CPU architecture), but
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],
- [iOS], [SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2`],
+ [iOS|tvOS|visionOS|watchOS], [SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2`],
[SOABI_PLATFORM=$PLATFORM_TRIPLET]
)
@@ -1608,7 +1801,7 @@ then
case $ac_sys_system in
Darwin)
LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)';;
- iOS)
+ iOS|tvOS|visionOS|watchOS)
LDLIBRARY='$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)';;
*)
AC_MSG_ERROR([Unknown platform for framework build]);;
@@ -1673,7 +1866,7 @@ if test $enable_shared = "yes"; then
BLDLIBRARY='-L. -lpython$(LDVERSION)'
RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}}
;;
- iOS)
+ iOS|tvOS|visionOS|watchOS)
if test -z "$PYTHONFRAMEWORK"; then
AC_MSG_ERROR([iOS shared builds must use --enable-framework; an iOS app can only load a signed framework, never a bare dylib])
fi
@@ -3732,7 +3925,7 @@ then
BLDSHARED="$LDSHARED"
fi
;;
- iOS/*)
+ iOS/*|tvOS/*|visionOS/*|watchOS/*)
LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)'
LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)'
BLDSHARED="$LDSHARED"
@@ -3856,7 +4049,7 @@ then
Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";;
Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";;
# -u libsys_s pulls in all symbols in libsys
- Darwin/*|iOS/*)
+ Darwin/*|iOS/*|tvOS/*|visionOS/*|watchOS/*)
LINKFORSHARED="$extra_undefs -framework CoreFoundation"
# Issue #18075: the default maximum stack size (8MBytes) is too
@@ -3880,7 +4073,7 @@ then
LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)'
fi
LINKFORSHARED="$LINKFORSHARED"
- elif test $ac_sys_system = "iOS"; then
+ elif test "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "visionOS" -o "$ac_sys_system" = "watchOS"; then
LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED"
if test "$enable_framework"; then
@@ -4453,7 +4646,7 @@ AS_VAR_IF([have_libffi], [yes], [
dnl when do we need USING_APPLE_OS_LIBFFI?
ctypes_malloc_closure=yes
],
- [iOS], [
+ [iOS|tvOS|visionOS|watchOS], [
ctypes_malloc_closure=yes
],
[sunos5], [AS_VAR_APPEND([LIBFFI_LIBS], [" -mimpure-text"])]
@@ -5582,9 +5775,9 @@ fi
AC_CHECK_FUNCS([ \
accept4 alarm bind_textdomain_codeset chmod chown clearenv \
clock closefrom close_range confstr \
- copy_file_range ctermid dladdr dup execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dladdr dup explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
- fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
+ fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getdents64 getegid geteuid getgid getgrent getgrgid getgrgid_r \
getgrnam_r getgrouplist gethostname getitimer getloadavg getlogin getlogin_r \
getpeername getpgid getpid getppid getpriority _getpty \
@@ -5594,8 +5787,7 @@ AC_CHECK_FUNCS([ \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause \
pidfd_open pidfd_getfd pidfd_send_signal pipe \
- plock poll ppoll posix_fadvise posix_fallocate posix_openpt posix_spawn posix_spawnp \
- posix_spawn_file_actions_addclosefrom_np \
+ plock poll ppoll posix_fadvise posix_fallocate posix_openpt \
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 \
@@ -5605,7 +5797,7 @@ AC_CHECK_FUNCS([ \
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 \
- setresuid setreuid setsid setuid setvbuf shutdown sigaction sigaltstack \
+ setresuid setreuid setsid setuid setvbuf shutdown sigaction \
sigfillset siginterrupt sigpending sigrelse sigtimedwait sigwait \
sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \
sysconf sysctlbyname tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \
@@ -5632,14 +5824,14 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS([lchmod])
fi
-# iOS defines some system methods that can be linked (so they are
+# iOS/tvOS/visionOS/watchOS define some system methods that can be linked (so they are
# found by configure), but either raise a compilation error (because the
# header definition prevents usage - autoconf doesn't use the headers), or
# raise an error if used at runtime. Force these symbols off.
-# In particular, dup3 and pipe2 are available as of iOS 27 but were
+# In particular, dup3 and pipe2 are available as of iOS/tvOS/watchOS/visionOS 27 but were
# incorrectly detected in older simulator versions.
case "$ac_sys_system" in
- iOS)
+ iOS|tvOS|watchOS|visionOS)
AC_MSG_CHECKING([if iOS SDK is older than 27])
ios_sdk_version=$(xcrun --sdk iphoneos --show-sdk-version 2>/dev/null | cut -d. -f1)
if test -n "$ios_sdk_version" && test "$ios_sdk_version" -ge 27; then
@@ -5650,11 +5842,19 @@ case "$ac_sys_system" in
fi
;;
*)
- # not iOS
+ # not iOS/tvOS/watchOS/visionOS
AC_CHECK_FUNCS([dup3 getentropy getgroups pipe2 system])
;;
esac
+# tvOS/watchOS have some additional methods that can be found, but not used.
+if test "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then
+ AC_CHECK_FUNCS([ \
+ execv fork fork1 posix_spawn posix_spawnp posix_spawn_file_actions_addclosefrom_np \
+ sigaltstack \
+ ])
+fi
+
AC_CHECK_DECL([dirfd],
[AC_DEFINE([HAVE_DIRFD], [1],
[Define if you have the 'dirfd' function or macro.])],
@@ -6048,20 +6248,22 @@ AS_CASE([$host],
@%:@include ])]
)
# check for openpty, login_tty, and forkpty
-
-AC_CHECK_FUNCS([openpty], [],
- [AC_CHECK_LIB([util], [openpty],
- [AC_DEFINE([HAVE_OPENPTY]) LIBS="$LIBS -lutil"],
- [AC_CHECK_LIB([bsd], [openpty],
- [AC_DEFINE([HAVE_OPENPTY]) LIBS="$LIBS -lbsd"])])])
-AC_SEARCH_LIBS([login_tty], [util],
- [AC_DEFINE([HAVE_LOGIN_TTY], [1], [Define to 1 if you have the `login_tty' function.])]
-)
-AC_CHECK_FUNCS([forkpty], [],
- [AC_CHECK_LIB([util], [forkpty],
- [AC_DEFINE([HAVE_FORKPTY]) LIBS="$LIBS -lutil"],
- [AC_CHECK_LIB([bsd], [forkpty],
- [AC_DEFINE([HAVE_FORKPTY]) LIBS="$LIBS -lbsd"])])])
+# tvOS/watchOS have functions for tty, but can't use them
+if test "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then
+ AC_CHECK_FUNCS([openpty], [],
+ [AC_CHECK_LIB([util], [openpty],
+ [AC_DEFINE([HAVE_OPENPTY]) LIBS="$LIBS -lutil"],
+ [AC_CHECK_LIB([bsd], [openpty],
+ [AC_DEFINE([HAVE_OPENPTY]) LIBS="$LIBS -lbsd"])])])
+ AC_SEARCH_LIBS([login_tty], [util],
+ [AC_DEFINE([HAVE_LOGIN_TTY], [1], [Define to 1 if you have the `login_tty' function.])]
+ )
+ AC_CHECK_FUNCS([forkpty], [],
+ [AC_CHECK_LIB([util], [forkpty],
+ [AC_DEFINE([HAVE_FORKPTY]) LIBS="$LIBS -lutil"],
+ [AC_CHECK_LIB([bsd], [forkpty],
+ [AC_DEFINE([HAVE_FORKPTY]) LIBS="$LIBS -lbsd"])])])
+fi
# check for long file support functions
AC_CHECK_FUNCS([fseek64 fseeko fstatvfs ftell64 ftello statvfs])
@@ -6100,10 +6302,10 @@ AC_CHECK_FUNCS([clock_getres], [], [
])
])
-# On Android and iOS, clock_settime can be linked (so it is found by
+# On Android, iOS, tvOS, visionOS, and watchOS, clock_settime can be linked (so it is found by
# configure), but when used in an unprivileged process, it crashes rather than
# returning an error. Force the symbol off.
-if test "$ac_sys_system" != "Linux-android" && test "$ac_sys_system" != "iOS"
+if test "$ac_sys_system" != "Linux-android" -a "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "visionOS" -a "$ac_sys_system" != "watchOS"
then
AC_CHECK_FUNCS([clock_settime], [], [
AC_CHECK_LIB([rt], [clock_settime], [
@@ -6261,7 +6463,7 @@ int main(void)
[ac_cv_buggy_getaddrinfo=no],
[ac_cv_buggy_getaddrinfo=yes],
[
-if test "$ac_sys_system" = "Linux-android" || test "$ac_sys_system" = "iOS"; then
+if test "$ac_sys_system" = "Linux-android" || test "$ac_sys_system" = "iOS" || test "$ac_sys_system" = "tvOS" || test "$ac_sys_system" = "visionOS" || test "$ac_sys_system" = "watchOS"; then
ac_cv_buggy_getaddrinfo="no"
elif test "${enable_ipv6+set}" = set; then
ac_cv_buggy_getaddrinfo="no -- configured with --(en|dis)able-ipv6"
@@ -6873,8 +7075,8 @@ if test "$PY_ENABLE_SHARED" = "1" && ( test -n "$ANDROID_API_LEVEL" || test "$MA
LIBPYTHON="-lpython${VERSION}${ABIFLAGS}"
fi
-# On iOS the shared libraries must be linked with the framework, when built
-if test "$ac_sys_system" = "iOS" && test "$enable_framework"; then
+# On iOS/tvOS/watchOS the shared libraries must be linked with the framework, when built
+if test "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "visionOS" -o "$ac_sys_system" = "watchOS" && test "$enable_framework"; then
MODULE_DEPS_SHARED="$MODULE_DEPS_SHARED \$(PYTHONFRAMEWORKDIR)/\$(PYTHONFRAMEWORK)"
fi
@@ -7625,7 +7827,7 @@ AC_MSG_NOTICE([checking for device files])
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.
-if test "$ac_sys_system" = "Linux-android" || test "$ac_sys_system" = "iOS"; then
+if test "$ac_sys_system" = "Linux-android" -o "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "visionOS" -o "$ac_sys_system" = "watchOS" ; then
ac_cv_file__dev_ptmx=no
ac_cv_file__dev_ptc=no
else
@@ -7953,7 +8155,7 @@ AC_ARG_WITH([ensurepip],
AS_CASE([$ac_sys_system],
[Emscripten], [with_ensurepip=no],
[WASI], [with_ensurepip=no],
- [iOS], [with_ensurepip=no],
+ [iOS|tvOS|visionOS|watchOS], [with_ensurepip=no],
[with_ensurepip=upgrade]
)
])
@@ -8384,6 +8586,9 @@ case "$ac_sys_system" in
NetBSD*) _PYTHREAD_NAME_MAXLEN=15;; # gh-131268
Darwin) _PYTHREAD_NAME_MAXLEN=63;;
iOS) _PYTHREAD_NAME_MAXLEN=63;;
+ tvOS) _PYTHREAD_NAME_MAXLEN=63;;
+ visionOS) _PYTHREAD_NAME_MAXLEN=63;;
+ watchOS) _PYTHREAD_NAME_MAXLEN=63;;
FreeBSD*) _PYTHREAD_NAME_MAXLEN=19;; # gh-131268
OpenBSD*) _PYTHREAD_NAME_MAXLEN=23;; # gh-131268
CYGWIN*) _PYTHREAD_NAME_MAXLEN=16;;
@@ -8409,7 +8614,7 @@ AS_CASE([$ac_sys_system],
[VxWorks*], [PY_STDLIB_MOD_SET_NA([_scproxy], [termios], [grp])],
dnl The _scproxy module is available on macOS
[Darwin], [],
- [iOS], [
+ [iOS|tvOS|visionOS|watchOS], [
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