diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 924ce56..791943b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -29,6 +29,9 @@ on: XZ_VERSION: description: "The XZ version used for the build." value: ${{ jobs.config.outputs.XZ_VERSION }} + ZSTD_VERSION: + description: "The Zstandard version used for the build." + value: ${{ jobs.config.outputs.ZSTD_VERSION }} env: FORCE_COLOR: "1" @@ -54,9 +57,10 @@ jobs: MPDECIMAL_VERSION: ${{ steps.extract.outputs.MPDECIMAL_VERSION }} OPENSSL_VERSION: ${{ steps.extract.outputs.OPENSSL_VERSION }} XZ_VERSION: ${{ steps.extract.outputs.XZ_VERSION }} + ZSTD_VERSION: ${{ steps.extract.outputs.ZSTD_VERSION }} steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v5 - name: Extract config variables id: extract @@ -68,6 +72,7 @@ jobs: MPDECIMAL_VERSION=$(make config | grep "MPDECIMAL_VERSION=" | cut -d "=" -f 2) OPENSSL_VERSION=$(make config | grep "OPENSSL_VERSION=" | cut -d "=" -f 2) XZ_VERSION=$(make config | grep "XZ_VERSION=" | cut -d "=" -f 2) + ZSTD_VERSION=$(make config | grep "ZSTD_VERSION=" | cut -d "=" -f 2) if [ -z "${{ inputs.build-number }}" ]; then BUILD_NUMBER=custom else @@ -82,30 +87,30 @@ jobs: echo "MPDECIMAL_VERSION=${MPDECIMAL_VERSION}" | tee -a ${GITHUB_OUTPUT} echo "OPENSSL_VERSION=${OPENSSL_VERSION}" | tee -a ${GITHUB_OUTPUT} echo "XZ_VERSION=${XZ_VERSION}" | tee -a ${GITHUB_OUTPUT} + echo "ZSTD_VERSION=${ZSTD_VERSION}" | tee -a ${GITHUB_OUTPUT} build: - runs-on: macOS-latest + runs-on: macOS-15 needs: [ config ] strategy: fail-fast: false matrix: - target: ['macOS', 'iOS', 'tvOS', 'watchOS', 'visionOS'] - include: - - briefcase-run-args: - - run-tests: false - - - target: macOS - run-tests: true - - - target: iOS - briefcase-run-args: ' -d "iPhone SE (3rd generation)"' - run-tests: true + platform: ['macOS', 'iOS', 'tvOS', 'watchOS', 'visionOS'] steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v5 + + - name: Set up Xcode + # GitHub recommends explicitly selecting the desired Xcode version: + # https://github.com/actions/runner-images/issues/12541#issuecomment-3083850140 + # This became a necessity as a result of + # https://github.com/actions/runner-images/issues/12541 and + # https://github.com/actions/runner-images/issues/12751. + run: | + sudo xcode-select --switch /Applications/Xcode_16.4.app - name: Set up Python - uses: actions/setup-python@v5.6.0 + uses: actions/setup-python@v6.0.0 with: # Appending -dev ensures that we can always build the dev release. # It's a no-op for versions that have been published. @@ -114,31 +119,194 @@ jobs: # It's an edge case, but when a new alpha is released, we need to use it ASAP. check-latest: true - - name: Build ${{ matrix.target }} + - name: Build ${{ matrix.platform }} run: | - # Do the build for the requested target. - make ${{ matrix.target }} BUILD_NUMBER=${{ needs.config.outputs.BUILD_NUMBER }} + # Do the build for the requested platform. + make ${{ matrix.platform }} BUILD_NUMBER=${{ needs.config.outputs.BUILD_NUMBER }} - name: Upload build artefacts uses: actions/upload-artifact@v4.6.2 with: - name: Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.target }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz - path: dist/Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.target }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + name: Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + path: dist/Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + + briefcase-testbed: + name: Briefcase testbed (${{ matrix.platform }}) + runs-on: macOS-15 + needs: [ config, build ] + strategy: + fail-fast: false + matrix: + platform: ["macOS", "iOS"] + include: + - briefcase-run-args: + + - platform: iOS + briefcase-run-args: ' -d "iPhone 16e::iOS 18.5"' + + steps: + - uses: actions/checkout@v5 + + - name: Set up Xcode + # GitHub recommends explicitly selecting the desired Xcode version: + # https://github.com/actions/runner-images/issues/12541#issuecomment-3083850140 + # This became a necessity as a result of + # https://github.com/actions/runner-images/issues/12541 and + # https://github.com/actions/runner-images/issues/12751. + run: | + sudo xcode-select --switch /Applications/Xcode_16.4.app + + - name: Get build artifact + uses: actions/download-artifact@v5.0.0 + with: + pattern: Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + path: dist + merge-multiple: true - - uses: actions/checkout@v4.1.7 - if: matrix.run-tests + - name: Set up Python + uses: actions/setup-python@v6.0.0 + with: + # Appending -dev ensures that we can always build the dev release. + # It's a no-op for versions that have been published. + python-version: ${{ needs.config.outputs.PYTHON_VER }}-dev + # Ensure that we *always* use the latest build, not a cached version. + # It's an edge case, but when a new alpha is released, we need to use it ASAP. + check-latest: true + + - uses: actions/checkout@v5 with: repository: beeware/Python-support-testbed path: Python-support-testbed - name: Install dependencies - if: matrix.run-tests run: | # Use the development version of Briefcase python -m pip install git+https://github.com/beeware/briefcase.git - name: Run support testbed check - if: matrix.run-tests - timeout-minutes: 10 + timeout-minutes: 15 working-directory: Python-support-testbed - run: briefcase run ${{ matrix.target }} Xcode --test ${{ matrix.briefcase-run-args }} -C support_package=\'../dist/Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.target }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz\' + run: briefcase run ${{ matrix.platform }} Xcode --test ${{ matrix.briefcase-run-args }} -C support_package=\'../dist/Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz\' + + cpython-testbed: + name: CPython testbed (${{ matrix.platform }}) + runs-on: macOS-15 + needs: [ config, build ] + strategy: + fail-fast: false + matrix: + platform: ["iOS", "tvOS", "visionOS"] + include: + # Needed to disambiguate simulator options. + - platform: "visionOS" + testbed-args: '--simulator "Apple Vision Pro,arch=arm64,OS=2.5"' + + steps: + - uses: actions/checkout@v5 + + - name: Get build artifact + uses: actions/download-artifact@v5.0.0 + with: + pattern: Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + path: dist + merge-multiple: true + + - name: Set up Xcode + # GitHub recommends explicitly selecting the desired Xcode version: + # https://github.com/actions/runner-images/issues/12541#issuecomment-3083850140 + # This became a necessity as a result of + # https://github.com/actions/runner-images/issues/12541 and + # https://github.com/actions/runner-images/issues/12751. + run: | + sudo xcode-select --switch /Applications/Xcode_16.4.app + + - name: Set up Python + uses: actions/setup-python@v6.0.0 + with: + # Appending -dev ensures that we can always build the dev release. + # It's a no-op for versions that have been published. + python-version: ${{ needs.config.outputs.PYTHON_VER }}-dev + # Ensure that we *always* use the latest build, not a cached version. + # It's an edge case, but when a new alpha is released, we need to use it ASAP. + check-latest: true + + - name: Unpack support package + run: | + mkdir -p support/${{ needs.config.outputs.PYTHON_VER }}/${{ matrix.platform }} + cd support/${{ needs.config.outputs.PYTHON_VER }}/${{ matrix.platform }} + tar zxvf ../../../dist/Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + + - name: Run CPython testbed + timeout-minutes: 15 + working-directory: support/${{ needs.config.outputs.PYTHON_VER }}/${{ matrix.platform }} + run: | + # Run a representative subset of CPython core tests: + # - test_builtin as a test of core language tools + # - test_grammar as a test of core language features + # - test_os as a test of system library calls + # - test_bz2 as a simple test of third party libraries + # - test_ctypes as a test of FFI + python -m testbed run --verbose ${{ matrix.testbed-args }} -- test --single-process --rerun -W test_builtin test_grammar test_os test_bz2 test_ctypes + + crossenv-test: + name: Cross-platform env test (${{ matrix.multiarch }}) + runs-on: macOS-latest + needs: [ config, build ] + strategy: + fail-fast: false + matrix: + include: + - platform: iOS + slice: ios-arm64_x86_64-simulator + multiarch: arm64-iphonesimulator + - platform: iOS + slice: ios-arm64_x86_64-simulator + multiarch: x86_64-iphonesimulator + - platform: iOS + slice: ios-arm64 + multiarch: arm64-iphoneos + + steps: + - uses: actions/checkout@v5 + + - name: Get build artifact + uses: actions/download-artifact@v5.0.0 + with: + pattern: Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + path: dist + merge-multiple: true + + - name: Set up Python + uses: actions/setup-python@v6.0.0 + with: + # Appending -dev ensures that we can always build the dev release. + # It's a no-op for versions that have been published. + python-version: ${{ needs.config.outputs.PYTHON_VER }}-dev + # Ensure that we *always* use the latest build, not a cached version. + # It's an edge case, but when a new alpha is released, we need to use it ASAP. + check-latest: true + + - name: Unpack support package + run: | + mkdir -p support/${{ needs.config.outputs.PYTHON_VER }}/${{ matrix.platform }} + cd support/${{ needs.config.outputs.PYTHON_VER }}/${{ matrix.platform }} + tar zxvf ../../../dist/Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + + - name: Run cross-platform environment test + env: + PYTHON_CROSS_PLATFORM: ${{ matrix.platform }} + PYTHON_CROSS_SLICE: ${{ matrix.slice }} + PYTHON_CROSS_MULTIARCH: ${{ matrix.multiarch }} + run: | + # Create and activate a native virtual environment + python${{ needs.config.outputs.PYTHON_VER }} -m venv cross-venv + source cross-venv/bin/activate + + # Install pytest + python -m pip install pytest + + # Convert venv into cross-venv + python support/${{ needs.config.outputs.PYTHON_VER }}/${{ matrix.platform }}/Python.xcframework/${{ matrix.slice }}/platform-config/${{ matrix.multiarch }}/make_cross_venv.py cross-venv + + # Run the test suite + python -m pytest tests diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 587abe8..9b45abb 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -8,10 +8,10 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python environment - uses: actions/setup-python@v5.6.0 + uses: actions/setup-python@v6.0.0 with: python-version: "3.X" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index fd78eee..a2c9069 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -40,14 +40,14 @@ jobs: needs: [ config, ci ] steps: - name: Get build artifacts - uses: actions/download-artifact@v4.3.0 + uses: actions/download-artifact@v5.0.0 with: pattern: Python-* path: dist merge-multiple: true - name: Create Release - uses: ncipollo/release-action@v1.16.0 + uses: ncipollo/release-action@v1.20.0 with: name: ${{ needs.ci.outputs.PYTHON_VER }}-${{ needs.config.outputs.BUILD_NUMBER }} tag: ${{ needs.ci.outputs.PYTHON_VER }}-${{ needs.config.outputs.BUILD_NUMBER }} @@ -62,4 +62,5 @@ jobs: * mpdecimal ${{ needs.ci.outputs.MPDECIMAL_VERSION }} * OpenSSL ${{ needs.ci.outputs.OPENSSL_VERSION }} * XZ ${{ needs.ci.outputs.XZ_VERSION }} + * Zstandard ${{ needs.ci.outputs.ZSTD_VERSION }} artifacts: "dist/*" diff --git a/.gitignore b/.gitignore index f805393..a87e3e2 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ tests/testbed/iOS *.log *.gz *.DS_Store +cross-venv/ +temp diff --git a/Makefile b/Makefile index 3796f84..88a32cc 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ BUILD_NUMBER=custom # of a release cycle, as official binaries won't be published. # PYTHON_MICRO_VERSION is the full version number, without any alpha/beta/rc suffix. (e.g., 3.10.0) # PYTHON_VER is the major/minor version (e.g., 3.10) -PYTHON_VERSION=3.14.0a7 +PYTHON_VERSION=3.14.0 PYTHON_PKG_VERSION=$(PYTHON_VERSION) PYTHON_MICRO_VERSION=$(shell echo $(PYTHON_VERSION) | grep -Eo "\d+\.\d+\.\d+") PYTHON_PKG_MICRO_VERSION=$(shell echo $(PYTHON_PKG_VERSION) | grep -Eo "\d+\.\d+\.\d+") @@ -30,8 +30,9 @@ PYTHON_VER=$(basename $(PYTHON_VERSION)) BZIP2_VERSION=1.0.8-2 LIBFFI_VERSION=3.4.7-2 MPDECIMAL_VERSION=4.0.0-2 -OPENSSL_VERSION=3.0.16-2 +OPENSSL_VERSION=3.0.18-1 XZ_VERSION=5.6.4-2 +ZSTD_VERSION=1.5.7-1 # Supported OS OS_LIST=macOS iOS tvOS watchOS visionOS @@ -41,25 +42,30 @@ CURL_FLAGS=--disable --fail --location --create-dirs --progress-bar # macOS targets TARGETS-macOS=macosx.x86_64 macosx.arm64 TRIPLE_OS-macOS=macos +PLATFORM_NAME-macOS=macOS VERSION_MIN-macOS=11.0 # iOS targets TARGETS-iOS=iphonesimulator.x86_64 iphonesimulator.arm64 iphoneos.arm64 TRIPLE_OS-iOS=ios +PLATFORM_NAME-iOS=iOS VERSION_MIN-iOS=13.0 # tvOS targets TARGETS-tvOS=appletvsimulator.x86_64 appletvsimulator.arm64 appletvos.arm64 TRIPLE_OS-tvOS=tvos +PLATFORM_NAME-tvOS=tvOS VERSION_MIN-tvOS=12.0 # watchOS targets TARGETS-watchOS=watchsimulator.x86_64 watchsimulator.arm64 watchos.arm64_32 TRIPLE_OS-watchOS=watchos +PLATFORM_NAME-watchOS=watchOS VERSION_MIN-watchOS=4.0 TARGETS-visionOS=xrsimulator.arm64 xros.arm64 TRIPLE_OS-visionOS=xros +PLATFORM_NAME-visionOS=xrOS VERSION_MIN-visionOS=2.0 # The architecture of the machine doing the build @@ -89,13 +95,13 @@ update-patch: # comparing between the current state of the 3.X branch against the v3.X.Y # tag associated with the release being built. This allows you to # maintain a branch that contains custom patches against the default Python. - # The patch archived in this respository is based on github.com/freakboy3742/cpython + # The patch archived in this repository is based on github.com/freakboy3742/cpython # Requires patchutils (installable via `brew install patchutils`); this # also means we need to re-introduce homebrew to the path for the filterdiff # call if [ -z "$(PYTHON_REPO_DIR)" ]; then echo "\n\nPYTHON_REPO_DIR must be set to the root of your Python github checkout\n\n"; fi cd $(PYTHON_REPO_DIR) && \ - git diff -D v$(PYTHON_VERSION) $(PYTHON_VER)-patched \ + git diff --no-renames -D v$(PYTHON_VERSION) $(PYTHON_VER)-patched \ | PATH="/usr/local/bin:/opt/homebrew/bin:$(PATH)" filterdiff \ -X $(PROJECT_DIR)/patch/Python/diff.exclude -p 1 --clean \ > $(PROJECT_DIR)/patch/Python/Python.patch @@ -187,6 +193,26 @@ $$(XZ_LIB-$(target)): downloads/xz-$(XZ_VERSION)-$(target).tar.gz # Ensure the target is marked as clean. touch $$(XZ_LIB-$(target)) +########################################################################### +# Target: zstd (ZStandard) +########################################################################### + +ZSTD_INSTALL-$(target)=$(PROJECT_DIR)/install/$(os)/$(target)/zstd-$(ZSTD_VERSION) +ZSTD_LIB-$(target)=$$(ZSTD_INSTALL-$(target))/lib/libzstd.a + +downloads/zstd-$(ZSTD_VERSION)-$(target).tar.gz: + @echo ">>> Download zstd for $(target)" + mkdir -p downloads + curl $(CURL_FLAGS) -o $$@ \ + https://github.com/beeware/cpython-apple-source-deps/releases/download/zstd-$(ZSTD_VERSION)/zstd-$(ZSTD_VERSION)-$(target).tar.gz + +$$(ZSTD_LIB-$(target)): downloads/zstd-$(ZSTD_VERSION)-$(target).tar.gz + @echo ">>> Install zstd for $(target)" + mkdir -p $$(ZSTD_INSTALL-$(target)) + cd $$(ZSTD_INSTALL-$(target)) && tar zxvf $(PROJECT_DIR)/downloads/zstd-$(ZSTD_VERSION)-$(target).tar.gz --exclude="*.dylib" + # Ensure the target is marked as clean. + touch $$(ZSTD_LIB-$(target)) + ########################################################################### # Target: mpdecimal ########################################################################### @@ -280,14 +306,15 @@ $$(PYTHON_SRCDIR-$(target))/configure: \ $$(LIBFFI_LIB-$(target)) \ $$(MPDECIMAL_LIB-$(target)) \ $$(OPENSSL_SSL_LIB-$(target)) \ - $$(XZ_LIB-$(target)) + $$(XZ_LIB-$(target)) \ + $$(ZSTD_LIB-$(target)) @echo ">>> Unpack and configure Python for $(target)" mkdir -p $$(PYTHON_SRCDIR-$(target)) tar zxf downloads/Python-$(PYTHON_VERSION).tar.gz --strip-components 1 -C $$(PYTHON_SRCDIR-$(target)) # Apply target Python patches cd $$(PYTHON_SRCDIR-$(target)) && patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch # Make sure the binary scripts are executable - chmod 755 $$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin/* + chmod 755 $$(PYTHON_SRCDIR-$(target))/Apple/$(os)/Resources/bin/* # Touch the configure script to ensure that Make identifies it as up to date. touch $$(PYTHON_SRCDIR-$(target))/configure @@ -295,7 +322,7 @@ $$(PYTHON_SRCDIR-$(target))/Makefile: \ $$(PYTHON_SRCDIR-$(target))/configure # Configure target Python cd $$(PYTHON_SRCDIR-$(target)) && \ - PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin:$(PATH)" \ + PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/Apple/$(os)/Resources/bin:$(PATH)" \ ./configure \ LIBLZMA_CFLAGS="-I$$(XZ_INSTALL-$(target))/include" \ LIBLZMA_LIBS="-L$$(XZ_INSTALL-$(target))/lib -llzma" \ @@ -305,6 +332,8 @@ $$(PYTHON_SRCDIR-$(target))/Makefile: \ LIBMPDEC_LIBS="-L$$(MPDECIMAL_INSTALL-$(target))/lib -lmpdec" \ LIBFFI_CFLAGS="-I$$(LIBFFI_INSTALL-$(target))/include" \ LIBFFI_LIBS="-L$$(LIBFFI_INSTALL-$(target))/lib -lffi" \ + LIBZSTD_CFLAGS="-I$$(ZSTD_INSTALL-$(target))/include" \ + LIBZSTD_LIBS="-L$$(ZSTD_INSTALL-$(target))/lib -lzstd" \ --host=$$(TARGET_TRIPLE-$(target)) \ --build=$(HOST_ARCH)-apple-darwin \ --with-build-python=$(HOST_PYTHON) \ @@ -317,14 +346,14 @@ $$(PYTHON_SRCDIR-$(target))/Makefile: \ $$(PYTHON_SRCDIR-$(target))/python.exe: $$(PYTHON_SRCDIR-$(target))/Makefile @echo ">>> Build Python for $(target)" cd $$(PYTHON_SRCDIR-$(target)) && \ - PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin:$(PATH)" \ + PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/Apple/$(os)/Resources/bin:$(PATH)" \ make -j8 all \ 2>&1 | tee -a ../python-$(PYTHON_VERSION).build.log $$(PYTHON_LIB-$(target)): $$(PYTHON_SRCDIR-$(target))/python.exe @echo ">>> Install Python for $(target)" cd $$(PYTHON_SRCDIR-$(target)) && \ - PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin:$(PATH)" \ + PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/Apple/$(os)/Resources/bin:$(PATH)" \ make install \ 2>&1 | tee -a ../python-$(PYTHON_VERSION).install.log @@ -333,7 +362,7 @@ $$(PYTHON_LIB-$(target)): $$(PYTHON_SRCDIR-$(target))/python.exe $$(PYTHON_PLATFORM_SITECUSTOMIZE-$(target)): - @echo ">>> Create cross-plaform config for $(target)" + @echo ">>> Create cross-platform config for $(target)" mkdir -p $$(PYTHON_PLATFORM_CONFIG-$(target)) # Create the cross-platform site definition echo "import _cross_$$(ARCH-$(target))_$$(SDK-$(target)); import _cross_venv;" \ @@ -457,6 +486,8 @@ $$(PYTHON_LIB-$(sdk)): $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_LIB-$$ mkdir -p $$(dir $$(PYTHON_LIB-$(sdk))) lipo -create -output $$@ $$^ \ 2>&1 | tee -a install/$(os)/$(sdk)/python-$(PYTHON_VERSION).lipo.log + # Disable dSYM production (for now) + # dsymutil $$@ -o $$(PYTHON_INSTALL-$(sdk))/Python.dSYM $$(PYTHON_FRAMEWORK-$(sdk))/Info.plist: $$(PYTHON_LIB-$(sdk)) @echo ">>> Install Info.plist for the $(sdk) SDK" @@ -488,15 +519,11 @@ $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h: $$(PYTHON_LIB-$(sdk)) mkdir -p $$(PYTHON_INSTALL-$(sdk))/include ln -si ../Python.framework/Headers $$(PYTHON_INSTALL-$(sdk))/include/python$(PYTHON_VER) -ifeq ($(os), visionOS) - echo "Skipping arch-specific header copying for visionOS" -else # Add the individual headers from each target in an arch-specific name $$(foreach target,$$(SDK_TARGETS-$(sdk)),cp $$(PYTHON_INCLUDE-$$(target))/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig-$$(ARCH-$$(target)).h; ) # Copy the cross-target header from the source folder of the first target in the $(sdk) SDK - cp $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$(sdk))))/$(os)/Resources/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h -endif + cp $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$(sdk))))/Apple/$(os)/Resources/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Info.plist $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) @@ -523,6 +550,15 @@ $$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK- # Merge the binary modules from each target in the $(sdk) SDK into a single binary $$(foreach module,$$(wildcard $$(PYTHON_STDLIB-$$(firstword $$(SDK_TARGETS-$(sdk))))/lib-dynload/*),lipo -create -output $$(PYTHON_STDLIB-$(sdk))/lib-dynload/$$(notdir $$(module)) $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_STDLIB-$$(target))/lib-dynload/$$(notdir $$(module))); ) + # # Disable dSYM production (for now) + # # Create dSYM files for each module + # $$(foreach module,$$(wildcard $$(PYTHON_STDLIB-$$(firstword $$(SDK_TARGETS-$(sdk))))/lib-dynload/*),dsymutil $$(PYTHON_STDLIB-$(sdk))/lib-dynload/$$(notdir $$(module)); ) + + # Copy in known-required xcprivacy files. + # Libraries linking OpenSSL must provide a privacy manifest. The one in this repository + # has been sourced from https://github.com/openssl/openssl/blob/openssl-3.0/os-dep/Apple/PrivacyInfo.xcprivacy + cp $(PROJECT_DIR)/patch/Python/OpenSSL.xcprivacy $$(PYTHON_STDLIB-$(sdk))/lib-dynload/_hashlib.xcprivacy + cp $(PROJECT_DIR)/patch/Python/OpenSSL.xcprivacy $$(PYTHON_STDLIB-$(sdk))/lib-dynload/_ssl.xcprivacy endif $(sdk): $$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT @@ -655,15 +691,22 @@ $$(PYTHON_XCFRAMEWORK-$(os))/Info.plist: \ -output $$(PYTHON_XCFRAMEWORK-$(os)) $$(foreach sdk,$$(SDKS-$(os)),-framework $$(PYTHON_FRAMEWORK-$$(sdk))) \ 2>&1 | tee -a support/$(PYTHON_VER)/python-$(os).xcframework.log + @echo ">>> Install build tools for $(os)" + mkdir $$(PYTHON_XCFRAMEWORK-$(os))/build + cp $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/Apple/testbed/Python.xcframework/build/utils.sh $$(PYTHON_XCFRAMEWORK-$(os))/build + cp $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/Apple/testbed/Python.xcframework/build/$$(PLATFORM_NAME-$(os))-dylib-Info-template.plist $$(PYTHON_XCFRAMEWORK-$(os))/build + @echo ">>> Install PYTHONHOME for $(os)" $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/include $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/bin $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/lib $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/platform-config $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) + # Disable dSYM production (for now) + # $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/Python.dSYM $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) -ifeq ($(filter $(os),iOS visionOS),$(os)) +ifeq ($(filter $(os),iOS tvOS visionOS),$(os)) @echo ">>> Clone testbed project for $(os)" - $(HOST_PYTHON) $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/$(os)/testbed clone --framework $$(PYTHON_XCFRAMEWORK-$(os)) support/$(PYTHON_VER)/$(os)/testbed + $(HOST_PYTHON) $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/Apple/testbed clone --platform $(os) --framework $$(PYTHON_XCFRAMEWORK-$(os)) support/$(PYTHON_VER)/$(os)/testbed endif @echo ">>> Create VERSIONS file for $(os)" @@ -676,6 +719,7 @@ endif echo "mpdecimal: $(MPDECIMAL_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS echo "OpenSSL: $(OPENSSL_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS echo "XZ: $(XZ_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS + echo "Zstandard: $(ZSTD_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS dist/Python-$(PYTHON_VER)-$(os)-support.$(BUILD_NUMBER).tar.gz: \ $$(PYTHON_XCFRAMEWORK-$(os))/Info.plist \ @@ -744,6 +788,7 @@ config: @echo "MPDECIMAL_VERSION=$(MPDECIMAL_VERSION)" @echo "OPENSSL_VERSION=$(OPENSSL_VERSION)" @echo "XZ_VERSION=$(XZ_VERSION)" + @echo "ZSTD_VERSION=$(ZSTD_VERSION)" # Expand cross-platform build and clean targets for each output product clean: $(foreach os,$(OS_LIST),clean-$(os)) diff --git a/README.md b/README.md new file mode 100644 index 0000000..3da329c --- /dev/null +++ b/README.md @@ -0,0 +1,169 @@ +# Python Apple Support + +This is a meta-package for building a version of Python that can be +embedded into a macOS, iOS, tvOS, watchOS, or visionOS project. + +**This branch builds a packaged version of Python 3.14**. Other Python +versions are available by cloning other branches of the main repository: + +- [Python + 3.10](https://github.com/beeware/Python-Apple-support/tree/3.10) +- [Python + 3.11](https://github.com/beeware/Python-Apple-support/tree/3.11) +- [Python + 3.12](https://github.com/beeware/Python-Apple-support/tree/3.12) +- [Python + 3.13](https://github.com/beeware/Python-Apple-support/tree/3.13) + +It works by downloading, patching, and building a fat binary of Python +and selected pre-requisites, and packaging them as frameworks that can +be incorporated into an Xcode project. The binary modules in the Python +standard library are distributed as binaries that can be dynamically +loaded at runtime. + +The macOS package is a re-bundling of the official macOS binary, +modified so that it is relocatable, with the IDLE, Tkinter and turtle +packages removed, and the App Store compliance patch applied. + +The iOS, tvOS, watchOS, and visionOS packages compiled by this project +use the official [PEP 730](https://peps.python.org/pep-0730/) code that +is part of Python 3.13 to provide iOS support; the relevant patches have +been backported to 3.10-3.12. Additional patches have been applied to add +tvOS, watchOS, and visionOS support. + +The binaries support x86_64 and arm64 for macOS; arm64 for iOS and +appleTV devices; arm64_32 for watchOS devices; and arm64 for visionOS +devices. It also supports device simulators on both x86_64 and M1 +hardware, except for visionOS, for which x86_64 simulators are +officially unsupported. This should enable the code to run on: + +- macOS 11 (Big Sur) or later, on: + - MacBook (including MacBooks using Apple Silicon) + - iMac (including iMacs using Apple Silicon) + - Mac Mini (including Apple Silicon Mac minis) + - Mac Studio (all models) + - Mac Pro (all models) + +- iOS 13.0 or later, on: + - iPhone (6s or later) + - iPad (5th gen or later) + - iPad Air (all models) + - iPad Mini (2 or later) + - iPad Pro (all models) + - iPod Touch (7th gen or later) + +- tvOS 12.0 or later, on: + - Apple TV (4th gen or later) + +- watchOS 4.0 or later, on: + - Apple Watch (4th gen or later) + +- visionOS 2.0 or later, on: + - Apple Vision Pro + +## Quickstart + +The easist way to use these packages is by creating a project with +[Briefcase](https://github.com/beeware/briefcase). Briefcase will +download pre-compiled versions of these support packages, and add them +to an Xcode project (or pre-build stub application, in the case of +macOS). + +Pre-built versions of the frameworks can be downloaded from the [Github +releases page](https://github.com/beeware/Python-Apple-support/releases) +and added to your project. + +Alternatively, to build the frameworks on your own, download/clone this +repository, and then in the root directory, and run: + +- `make` (or `make all`) to build everything. +- `make macOS` to build everything for macOS. +- `make iOS` to build everything for iOS. +- `make tvOS` to build everything for tvOS. +- `make watchOS` to build everything for watchOS. +- `make visionOS` to build everything for visionOS. + +This should: + +1. Download the original source packages +2. Patch them as required for compatibility with the selected OS +3. Build the packages as Xcode-compatible XCFrameworks. + +The resulting support packages will be packaged as `.tar.gz` files in +the `dist` folder. + +Each support package contains: + +- `VERSIONS`, a text file describing the specific versions of code used + to build the support package; +- `Python.xcframework`, a multi-architecture build of the Python runtime + library. + +On iOS/tvOS/watchOS/visionOS, the `Python.xcframework` contains a slice +for each supported ABI (device and simulator). The folder containing the +slice can also be used as a `PYTHONHOME`, as it contains a `bin`, +`include` and `lib` directory. + +The `bin` folder does not contain Python executables (as they can't be +invoked). However, it *does* contain shell aliases for the compilers +that are needed to build packages. This is required because Xcode uses +the `xcrun` alias to dynamically generate the name of binaries, but a +lot of C tooling expects that `CC` will not contain spaces. + +Each slice of an iOS/tvOS/watchOS/visionOS XCframework also contains a +`platform-config` folder with a subfolder for each supported +architecture in that slice. These subfolders can be used to make a macOS +Python environment behave as if it were on an iOS/tvOS/watchOS/visionOS +device. This works in one of two ways: + +1. **A sitecustomize.py script**. If the `platform-config` subfolder is + on your `PYTHONPATH` when a Python interpreter is started, a site + customization will be applied that patches methods in `sys`, + `sysconfig` and `platform` that are used to identify the system. +2. **A make_cross_venv.py script**. If you call `make_cross_venv.py`, + providing the location of a virtual environment, the script will add + some files to the `site-packages` folder of that environment that + will automatically apply the same set of patches as the + `sitecustomize.py` script whenever the environment is activated, + without any need to modify `PYTHONPATH`. If you use `build` to + create an isolated PEP 517 environment to build a wheel, these + patches will also be applied to the isolated build environment that + is created. + +iOS and visionOS distributions also contain a copy of the iOS or +visionOS `testbed` project - an Xcode project that can be used to run +test suites of Python code. See the [CPython documentation on testing +packages](https://docs.python.org/3/using/ios.html#testing-a-python-package) +for details on how to use this testbed. + +For a detailed instructions on using the support package in your own +project, see the [usage guide](./USAGE.md) + +## Building binary wheels + +This project packages the Python standard library, but does not address +building binary wheels. Binary wheels for macOS can be obtained from +PyPI. [Mobile Forge](https://github.com/beeware/mobile-forge) is a +project that provides the tooling to build build binary wheels for iOS +(and potentially for tvOS, watchOS, and visionOS, although that hasn't +been tested). + +## Historical support + +The following versions were supported in the past, but are no longer +maintained: + +- [Python 2.7](https://github.com/beeware/Python-Apple-support/tree/2.7) + (EOL January 2020) +- [Python 3.4](https://github.com/beeware/Python-Apple-support/tree/3.4) + (EOL March 2019) +- [Python 3.5](https://github.com/beeware/Python-Apple-support/tree/3.5) + (EOL February 2021) +- [Python 3.6](https://github.com/beeware/Python-Apple-support/tree/3.6) + (EOL December 2021) +- [Python 3.7](https://github.com/beeware/Python-Apple-support/tree/3.7) + (EOL September 2022) +- [Python 3.8](https://github.com/beeware/Python-Apple-support/tree/3.8) + (EOL October 2024) +- [Python 3.9](https://github.com/beeware/Python-Apple-support/tree/3.9) + (EOL October 2025) diff --git a/README.rst b/README.rst deleted file mode 100644 index 06fde6c..0000000 --- a/README.rst +++ /dev/null @@ -1,154 +0,0 @@ -Python Apple Support -==================== - -This is a meta-package for building a version of Python that can be embedded -into a macOS, iOS, tvOS, watchOS, or visionOS project. - -**This branch builds a packaged version of Python 3.14**. -Other Python versions are available by cloning other branches of the main -repository: - -* `Python 3.9 `__ -* `Python 3.10 `__ -* `Python 3.11 `__ -* `Python 3.12 `__ -* `Python 3.13 `__ - -It works by downloading, patching, and building a fat binary of Python and -selected pre-requisites, and packaging them as frameworks that can be -incorporated into an Xcode project. The binary modules in the Python standard -library are distributed as binaries that can be dynamically loaded at runtime. - -The macOS package is a re-bundling of the official macOS binary, modified so that -it is relocatable, with the IDLE, Tkinter and turtle packages removed, and the -App Store compliance patch applied. - -The iOS, tvOS, watchOS, and visionOS packages compiled by this project use the -official `PEP 730 `__ code that is part of -Python 3.13 to provide iOS support; the relevant patches have been backported -to 3.9-3.12. Additional patches have been applied to add tvOS, watchOS, and -visionOS support. - -The binaries support x86_64 and arm64 for macOS; arm64 for iOS and appleTV -devices; arm64_32 for watchOS devices; and arm64 for visionOS devices. It also -supports device simulators on both x86_64 and M1 hardware, except for visionOS, -for which x86_64 simulators are officially unsupported. This should enable the -code to run on: - -* macOS 11 (Big Sur) or later, on: - * MacBook (including MacBooks using Apple Silicon) - * iMac (including iMacs using Apple Silicon) - * Mac Mini (including Apple Silicon Mac minis) - * Mac Studio (all models) - * Mac Pro (all models) -* iOS 13.0 or later, on: - * iPhone (6s or later) - * iPad (5th gen or later) - * iPad Air (all models) - * iPad Mini (2 or later) - * iPad Pro (all models) - * iPod Touch (7th gen or later) -* tvOS 12.0 or later, on: - * Apple TV (4th gen or later) -* watchOS 4.0 or later, on: - * Apple Watch (4th gen or later) -* visionOS 2.0 or later, on: - * Apple Vision Pro - -Quickstart ----------- - -The easist way to use these packages is by creating a project with `Briefcase -`__. Briefcase will download pre-compiled -versions of these support packages, and add them to an Xcode project (or -pre-build stub application, in the case of macOS). - -Pre-built versions of the frameworks can be downloaded from the `Github releases page -`__ and added to your project. - -Alternatively, to build the frameworks on your own, download/clone this -repository, and then in the root directory, and run: - -* ``make`` (or ``make all``) to build everything. -* ``make macOS`` to build everything for macOS. -* ``make iOS`` to build everything for iOS. -* ``make tvOS`` to build everything for tvOS. -* ``make watchOS`` to build everything for watchOS. -* ``make visionOS`` to build everything for visionOS. - -This should: - -1. Download the original source packages -2. Patch them as required for compatibility with the selected OS -3. Build the packages as Xcode-compatible XCFrameworks. - -The resulting support packages will be packaged as ``.tar.gz`` files -in the ``dist`` folder. - -Each support package contains: - -* ``VERSIONS``, a text file describing the specific versions of code used to build the - support package; -* ``Python.xcframework``, a multi-architecture build of the Python runtime library. - -On iOS/tvOS/watchOS/visionOS, the ``Python.xcframework`` contains a -slice for each supported ABI (device and simulator). The folder containing the -slice can also be used as a ``PYTHONHOME``, as it contains a ``bin``, ``include`` -and ``lib`` directory. - -The ``bin`` folder does not contain Python executables (as they can't be -invoked). However, it *does* contain shell aliases for the compilers that are -needed to build packages. This is required because Xcode uses the ``xcrun`` -alias to dynamically generate the name of binaries, but a lot of C tooling -expects that ``CC`` will not contain spaces. - -Each slice of an iOS/tvOS/watchOS/visionOS XCframework also contains a -``platform-config`` folder with a subfolder for each supported architecture in -that slice. These subfolders can be used to make a macOS Python environment -behave as if it were on an iOS/tvOS/watchOS/visionOS device. This works in one -of two ways: - -1. **A sitecustomize.py script**. If the ``platform-config`` subfolder is on - your ``PYTHONPATH`` when a Python interpreter is started, a site - customization will be applied that patches methods in ``sys``, ``sysconfig`` - and ``platform`` that are used to identify the system. - -2. **A make_cross_venv.py script**. If you call ``make_cross_venv.py``, - providing the location of a virtual environment, the script will add some - files to the ``site-packages`` folder of that environment that will - automatically apply the same set of patches as the ``sitecustomize.py`` - script whenever the environment is activated, without any need to modify - ``PYTHONPATH``. If you use ``build`` to create an isolated PEP 517 - environment to build a wheel, these patches will also be applied to the - isolated build environment that is created. - -iOS and visionOS distributions also contain a copy of the iOS or visionOS -``testbed`` project - an Xcode project that can be used to run test suites of -Python code. See the `CPython documentation on testing packages -`__ for -details on how to use this testbed. - -For a detailed instructions on using the support package in your own project, -see the `usage guide <./USAGE.md>`__ - -Building binary wheels ----------------------- - -This project packages the Python standard library, but does not address building -binary wheels. Binary wheels for macOS can be obtained from PyPI. `Mobile Forge -`__ is a project that provides the -tooling to build build binary wheels for iOS (and potentially for tvOS, watchOS, -and visionOS, although that hasn't been tested). - -Historical support ------------------- - -The following versions were supported in the past, but are no longer -maintained: - -* `Python 2.7 `__ (EOL January 2020) -* `Python 3.4 `__ (EOL March 2019) -* `Python 3.5 `__ (EOL February 2021) -* `Python 3.6 `__ (EOL December 2021) -* `Python 3.7 `__ (EOL September 2022) -* `Python 3.8 `__ (EOL October 2024) diff --git a/USAGE.md b/USAGE.md index 072ae1e..b205cdc 100644 --- a/USAGE.md +++ b/USAGE.md @@ -2,15 +2,15 @@ ## The easy way -The easist way to use these packages is by creating a project with -(Briefcase)[https://github.com/beeware/briefcase]. Briefcase will download +The easiest way to use these packages is by creating a project with +[Briefcase](https://github.com/beeware/briefcase). Briefcase will download pre-compiled versions of these support packages, and add them to an Xcode project (or pre-build stub application, in the case of macOS). ## The manual way **NOTE** Briefcase usage is the officially supported approach for using this -support package. If you are experiencing diffculties, one approach for debugging +support package. If you are experiencing difficulties, one approach for debugging is to generate a "Hello World" project with Briefcase, and compare the project that Briefcase has generated with your own project. @@ -28,7 +28,7 @@ generated on iOS and visionOS may be used as rough references as well. ### Using Objective C -Once you've added the Python XCframework to your project, you'll need to +Once you've added the Python XCFramework to your project, you'll need to initialize the Python runtime in your Objective C code (This is step 10 of the iOS guide linked above). This initialization should generally be done as early as possible in the application's lifecycle, but definitely needs to be done @@ -97,7 +97,7 @@ There are 2 ways to access the Python runtime in your project code. You can use the [Python Embedded C API](https://docs.python.org/3/extending/embedding.html) to invoke Python code -and interact with Python objects. This is a raw C API that is accesible to both +and interact with Python objects. This is a raw C API that is accessible to both Objective C and Swift. ### PythonKit diff --git a/patch/Python/OpenSSL.xcprivacy b/patch/Python/OpenSSL.xcprivacy new file mode 100644 index 0000000..95780a0 --- /dev/null +++ b/patch/Python/OpenSSL.xcprivacy @@ -0,0 +1,23 @@ + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyCollectedDataTypes + + NSPrivacyTrackingDomains + + NSPrivacyTracking + + + diff --git a/patch/Python/Python.patch b/patch/Python/Python.patch index 270bf5c..e40920c 100644 --- a/patch/Python/Python.patch +++ b/patch/Python/Python.patch @@ -1,1855 +1,2278 @@ -diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py -index bba08b99b95..8d03017c223 100644 ---- a/Lib/ctypes/__init__.py -+++ b/Lib/ctypes/__init__.py -@@ -361,7 +361,7 @@ - if name: - name = _os.fspath(name) +diff --git a/Apple/__main__.py b/Apple/__main__.py +index 96c2d34fbe0..eea74ee2209 100644 +--- a/Apple/__main__.py ++++ b/Apple/__main__.py +@@ -5,17 +5,19 @@ + # 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 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 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 +@@ -76,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", ++ }, ++ }, + } -- # If the filename that has been provided is an iOS/tvOS/watchOS -+ # If the filename that has been provided is an iOS/tvOS/watchOS/visionOS - # .fwork file, dereference the location to the true origin of the - # binary. - if name.endswith(".fwork"): -diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py -index 99504911a3d..527c2f36dd0 100644 ---- a/Lib/ctypes/util.py -+++ b/Lib/ctypes/util.py -@@ -126,7 +126,7 @@ - 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", "watchos", "visionos"}: - from ctypes.macholib.dyld import dyld_find as _dyld_find - def find_library(name): - possible = ['lib%s.dylib' % name, -@@ -425,7 +425,7 @@ - # https://man.openbsd.org/dl_iterate_phdr - # https://docs.oracle.com/cd/E88353_01/html/E37843/dl-iterate-phdr-3c.html - if (os.name == "posix" and -- sys.platform not in {"darwin", "ios", "tvos", "watchos"}): -+ sys.platform not in {"darwin", "ios", "tvos", "watchos", "visionos"}): - import ctypes - if hasattr((_libc := ctypes.CDLL(None)), "dl_iterate_phdr"): +@@ -137,12 +165,25 @@ + print(f"export {key}={shlex.quote(value)}") -diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py -index 8bcd741c446..d8a6f28edba 100644 ---- a/Lib/importlib/_bootstrap_external.py -+++ b/Lib/importlib/_bootstrap_external.py -@@ -52,7 +52,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', 'watchos', 'visionos' - _CASE_INSENSITIVE_PLATFORMS = (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY - + _CASE_INSENSITIVE_PLATFORMS_STR_KEY) ++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 / "Apple/iOS/Resources/bin"), ++ str( ++ PYTHON_DIR ++ / f"Apple/{platform_for_host(host)}/Resources/bin" ++ ), + str(subdir(host) / "prefix"), + "/usr/bin", + "/bin", +@@ -309,8 +350,8 @@ + Downloads binaries if they aren't already present. Downloads will be stored + in provided cache directory. -@@ -1535,7 +1535,7 @@ +- 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. """ - extension_loaders = [] - if hasattr(_imp, 'create_dynamic'): -- if sys.platform in {"ios", "tvos", "watchos"}: -+ if sys.platform in {"ios", "tvos", "watchos", "visionos"}: - extension_loaders = [(AppleFrameworkLoader, [ - suffix.replace(".so", ".fwork") - for suffix in _imp.extension_suffixes() -diff --git a/Lib/platform.py b/Lib/platform.py -index a62192589af..31f18b026b7 100644 ---- a/Lib/platform.py -+++ b/Lib/platform.py -@@ -528,6 +528,78 @@ - return IOSVersionInfo(system, release, model, is_simulator) - + # 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 +@@ -335,9 +376,9 @@ + ) + shutil.unpack_archive(archive_path, prefix_dir) -+# A namedtuple for tvOS version information. -+TVOSVersionInfo = collections.namedtuple( -+ "TVOSVersionInfo", -+ ["system", "release", "model", "is_simulator"] -+) -+ -+ -+def tvos_ver(system="", release="", model="", is_simulator=False): -+ """Get tvOS 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 == "tvos": -+ # TODO: Can the iOS implementation be used here? -+ import _ios_support -+ result = _ios_support.get_platform_ios() -+ if result is not None: -+ return TVOSVersionInfo(*result) -+ -+ return TVOSVersionInfo(system, release, model, is_simulator) -+ -+ -+# A namedtuple for watchOS version information. -+WatchOSVersionInfo = collections.namedtuple( -+ "WatchOSVersionInfo", -+ ["system", "release", "model", "is_simulator"] -+) -+ -+ -+def watchos_ver(system="", release="", model="", is_simulator=False): -+ """Get watchOS 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 == "watchos": -+ # TODO: Can the iOS implementation be used here? -+ import _ios_support -+ result = _ios_support.get_platform_ios() -+ if result is not None: -+ return WatchOSVersionInfo(*result) -+ -+ return WatchOSVersionInfo(system, release, model, is_simulator) -+ -+ -+# A namedtuple for visionOS version information. -+VisionOSVersionInfo = collections.namedtuple( -+ "VisionOSVersionInfo", -+ ["system", "release", "model", "is_simulator"] -+) -+ -+ -+def visionos_ver(system="", release="", model="", is_simulator=False): -+ """Get 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 == "visionos": -+ # TODO: Can the iOS implementation be used here? -+ import _ios_support -+ result = _ios_support.get_platform_ios() -+ if result is not None: -+ return VisionOSVersionInfo(*result) -+ -+ return VisionOSVersionInfo(system, release, model, is_simulator) -+ -+ - def _java_getprop(name, default): - """This private helper is deprecated in 3.13 and will be removed in 3.15""" - from java.lang import System -@@ -727,7 +799,7 @@ - default in case the command should fail. +- # 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() +@@ -401,6 +442,7 @@ + f"--build={sysconfig.get_config_var('BUILD_GNU_TYPE')}", + f"--with-build-python={build_python_path()}", + "--with-system-libmpdec", ++ "--enable-ipv6", + "--enable-framework", + # Dependent libraries. + f"--with-openssl={prefix_dir}", +@@ -441,7 +483,10 @@ + :param host_triple: The host triple (e.g., arm64-apple-ios-simulator) + :param multiarch: The multiarch identifier (e.g., arm64-simulator) """ -- if sys.platform in {'dos', 'win32', 'win16', 'ios', 'tvos', 'watchos'}: -+ if sys.platform in {'dos', 'win32', 'win16', 'ios', 'tvos', 'watchos', 'visionos'}: - # XXX Others too ? - return default - -@@ -891,14 +963,30 @@ - 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/watchOS/visionOS 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_watchos(): -+ if sys.implementation._multiarch.endswith("simulator"): -+ return os.uname().machine -+ return 'arm64_32' -+ -+ def get_visionos(): -+ if sys.implementation._multiarch.endswith("simulator"): -+ return os.uname().machine -+ return 'arm64' -+ - def from_subprocess(): - """ - Fall back to `uname -p` -@@ -1058,9 +1146,15 @@ - system = 'Android' - release = android_ver().release - -- # Normalize responses on iOS -+ # Normalize responses on Apple mobile platforms - if sys.platform == 'ios': - system, release, _, _ = ios_ver() -+ if sys.platform == 'tvos': -+ system, release, _, _ = tvos_ver() -+ if sys.platform == 'watchos': -+ system, release, _, _ = watchos_ver() -+ if sys.platform == 'visionos': -+ system, release, _, _ = visionos_ver() - - vals = system, node, release, version, machine - # Replace 'unknown' values with the more portable '' -@@ -1350,6 +1444,12 @@ - # macOS and iOS both report as a "Darwin" kernel - if sys.platform == "ios": - system, release, _, _ = ios_ver() -+ elif sys.platform == "tvos": -+ system, release, _, _ = tvos_ver() -+ elif sys.platform == "watchos": -+ system, release, _, _ = watchos_ver() -+ elif sys.platform == "visionos": -+ system, release, _, _ = visionos_ver() - else: - macos_release = mac_ver()[0] - if macos_release: -diff --git a/Lib/site.py b/Lib/site.py -index 9da8b6724e1..345f55a5bde 100644 ---- a/Lib/site.py -+++ b/Lib/site.py -@@ -297,8 +297,8 @@ - if env_base: - return env_base +- return CROSS_BUILD_DIR / f"{host_triple}/Apple/iOS/Frameworks/{multiarch}" ++ return ( ++ CROSS_BUILD_DIR ++ / f"{host_triple}/Apple/{platform_for_host(host_triple)}/Frameworks/{multiarch}" ++ ) -- # 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 da5f5729e09..7401ffbc987 100644 ---- a/Lib/subprocess.py -+++ b/Lib/subprocess.py -@@ -75,7 +75,7 @@ - _mswindows = True + def package_version(prefix_path: Path) -> str: +@@ -468,8 +513,7 @@ - # some platforms do not support subprocesses --_can_fork_exec = sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos"} -+_can_fork_exec = sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos", "visionos"} - if _mswindows: - import _winapi -diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py -index 18e6b8d25e5..64603fb1bb1 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', - } + def lib_platform_files(dirname, names): +- """A file filter that ignores platform-specific files in the lib directory. +- """ ++ """A file filter that ignores platform-specific files in the lib directory.""" + path = Path(dirname) + if ( + path.parts[-3] == "lib" +@@ -499,7 +543,9 @@ + """ + path = Path(dirname) + if path.parts[-2] == "lib" and path.parts[-1].startswith("python"): +- return set(names) - lib_platform_files(dirname, names) - {"lib-dynload"} ++ return ( ++ set(names) - lib_platform_files(dirname, names) - {"lib-dynload"} ++ ) + else: + return set() - _INSTALL_SCHEMES = { -@@ -119,7 +122,7 @@ - # 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 +@@ -646,7 +692,7 @@ + host_path = ( + CROSS_BUILD_DIR + / host_triple +- / "Apple/iOS/Frameworks" ++ / f"Apple/{platform}/Frameworks" + / multiarch + ) + host_framework = host_path / "Python.framework" +@@ -659,7 +705,8 @@ + # statically link those libraries into a Framework, you become + # responsible for providing a privacy manifest for that framework. + xcprivacy_file = { +- "OpenSSL": subdir(host_triple) / "prefix/share/OpenSSL.xcprivacy" ++ "OpenSSL": subdir(host_triple) ++ / "prefix/share/OpenSSL.xcprivacy" + } + print(f" - {multiarch} xcprivacy files") + for module, lib in [ +@@ -690,20 +737,22 @@ + # Create an XCframework + version = create_xcframework(context.platform) - def joinuser(*args): -@@ -719,6 +722,18 @@ - 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", "9.0") -+ osname = sys.platform -+ machine = sys.implementation._multiarch -+ elif sys.platform == "watchos": -+ release = get_config_vars().get("WATCHOS_DEPLOYMENT_TARGET", "4.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 ecb37250ceb..67d04491072 100644 ---- a/Lib/test/datetimetester.py -+++ b/Lib/test/datetimetester.py -@@ -7155,9 +7155,9 @@ - self.assertEqual(dt_orig, dt_rt) +- # Clone testbed +- print() +- run( +- [ +- sys.executable, +- "Apple/testbed", +- "clone", +- "--platform", +- context.platform, +- "--framework", +- CROSS_BUILD_DIR / context.platform / "Python.xcframework", +- CROSS_BUILD_DIR / context.platform / "testbed", +- ] +- ) ++ # watchOS doesn't have a testbed (yet!) ++ if context.platform != "watchOS": ++ # Clone testbed ++ print() ++ run( ++ [ ++ sys.executable, ++ "Apple/testbed", ++ "clone", ++ "--platform", ++ context.platform, ++ "--framework", ++ CROSS_BUILD_DIR / context.platform / "Python.xcframework", ++ CROSS_BUILD_DIR / context.platform / "testbed", ++ ] ++ ) - 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/support/__init__.py b/Lib/test/support/__init__.py -index 6d670a575b0..8d7d68d1ee1 100644 ---- a/Lib/test/support/__init__.py -+++ b/Lib/test/support/__init__.py -@@ -551,7 +551,7 @@ - sys.platform == "android", f"Android blocks {name} with SELinux" - ) + # Build the final archive + archive_name = ( +diff --git a/Apple/iOS/Resources/Info.plist.in b/Apple/iOS/Resources/Info.plist.in +index c3e261ecd9e..26ef7a95de4 100644 +--- a/Apple/iOS/Resources/Info.plist.in ++++ b/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/Apple/testbed/Python.xcframework/Info.plist b/Apple/testbed/Python.xcframework/Info.plist +index c6418de6e74..0587f4735f7 100644 +--- a/Apple/testbed/Python.xcframework/Info.plist ++++ b/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 +--- /dev/null ++++ b/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/Apple/testbed/Python.xcframework/build/utils.sh b/Apple/testbed/Python.xcframework/build/utils.sh +index 961c46d014b..76172162487 100755 +--- a/Apple/testbed/Python.xcframework/build/utils.sh ++++ b/Apple/testbed/Python.xcframework/build/utils.sh +@@ -34,9 +34,38 @@ + 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" ++ 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 sys.platform not in {"win32", "vxworks", "ios", "tvos", "watchos"}: -+if sys.platform not in {"win32", "vxworks", "ios", "tvos", "watchos", "visionos"}: - unix_shell = '/system/bin/sh' if is_android else '/bin/sh' - else: - unix_shell = None -@@ -567,7 +567,7 @@ - def skip_wasi_stack_overflow(): - return unittest.skipIf(is_wasi, "Exhausts stack on WASI") + # If the XCframework has a shared lib folder, then it's a full framework. +--- /dev/null ++++ b/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 ++ ++ +--- /dev/null ++++ b/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 ++ ++ ++ +--- /dev/null ++++ b/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. +--- /dev/null ++++ b/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). +--- /dev/null ++++ b/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. +--- /dev/null ++++ b/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). +--- /dev/null ++++ b/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). +--- /dev/null ++++ b/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/Apple/testbed/__main__.py b/Apple/testbed/__main__.py +index 4a1333380cd..41877db5b4f 100644 +--- a/Apple/testbed/__main__.py ++++ b/Apple/testbed/__main__.py +@@ -8,6 +8,9 @@ --is_apple_mobile = sys.platform in {"ios", "tvos", "watchos"} -+is_apple_mobile = sys.platform in {"ios", "tvos", "watchos", "visionos"} - is_apple = is_apple_mobile or sys.platform == "darwin" + TEST_SLICES = { + "iOS": "ios-arm64_x86_64-simulator", ++ "tvOS": "tvos-arm64_x86_64-simulator", ++ "visionOS": "xros-arm64-simulator", ++ "watchOS": "watchos-arm64_x86_64-simulator", + } - has_fork_support = hasattr(os, "fork") and not ( -diff --git a/Lib/test/support/os_helper.py b/Lib/test/support/os_helper.py -index d82093e375c..2c45fe2369e 100644 ---- a/Lib/test/support/os_helper.py -+++ b/Lib/test/support/os_helper.py -@@ -657,7 +657,7 @@ - """ - if sys.platform.startswith(('linux', 'android', 'freebsd', 'emscripten')): - fd_path = "/proc/self/fd" -- elif sys.platform == "darwin": -+ elif support.is_apple: - fd_path = "/dev/fd" - else: - fd_path = None -diff --git a/Lib/test/test_ctypes/test_dllist.py b/Lib/test/test_ctypes/test_dllist.py -index 15603dc3d77..bff6c0fb95f 100644 ---- a/Lib/test/test_ctypes/test_dllist.py -+++ b/Lib/test/test_ctypes/test_dllist.py -@@ -7,7 +7,7 @@ + DECODE_ARGS = ("UTF-8", "backslashreplace") +@@ -19,7 +22,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 + ) - WINDOWS = os.name == "nt" --APPLE = sys.platform in {"darwin", "ios", "tvos", "watchos"} -+APPLE = sys.platform in {"darwin", "ios", "tvos", "watchos", "visionos"} +@@ -52,6 +55,24 @@ + ) + ) + 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": ++ raise NotImplementedError(f"Don't know how to launch watchOS (yet)") + else: + raise ValueError(f"Unknown platform {platform}") - if WINDOWS: - KNOWN_LIBRARIES = ["KERNEL32.DLL"] -diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py -index 6ba630ad527..7b447744d12 100644 ---- a/Lib/test/test_platform.py -+++ b/Lib/test/test_platform.py -@@ -268,13 +268,21 @@ - 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"}) -- self.assertEqual(res.release, platform.ios_ver().release) -+ 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) -+ # Use the platform-specific version method -+ platform_ver = getattr(platform, f"{sys.platform}_ver") -+ self.assertEqual(res.release, platform_ver().release) - else: - self.assertEqual(res.system, "") - self.assertEqual(res.release, "") -diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py -index 4c3ea1cd8df..04a210e5c86 100644 ---- a/Lib/test/test_webbrowser.py -+++ b/Lib/test/test_webbrowser.py -@@ -236,7 +236,8 @@ - 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 232d3c3a9c5..e042c20ea54 100644 ---- a/Lib/webbrowser.py -+++ b/Lib/webbrowser.py -@@ -488,7 +488,8 @@ - # OS X can use below Unix support (but we prefer using the OS X - # 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": -@@ -640,9 +641,10 @@ - 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 e10c78d6403..920e707ab26 100644 ---- a/Makefile.pre.in -+++ b/Makefile.pre.in -@@ -209,6 +209,12 @@ - # the build, and is only listed here so it will be included in sysconfigdata. - IPHONEOS_DEPLOYMENT_TARGET=@IPHONEOS_DEPLOYMENT_TARGET@ - -+# 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 +@@ -279,7 +300,7 @@ + # 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() + ] -@@ -2243,7 +2249,7 @@ - # a full Xcode install that has an iPhone SE (3rd edition) simulator available. - # This must be run *after* a `make install` has completed the build. The - # `--with-framework-name` argument *cannot* be used when configuring the build. --XCFOLDER:=iOSTestbed.$(MULTIARCH).$(shell date +%s).$$PPID -+XCFOLDER-iOS:=iOSTestbed.$(MULTIARCH).$(shell date +%s).$$PPID - .PHONY: testios - testios: - @if test "$(MACHDEP)" != "ios"; then \ -@@ -2263,11 +2269,41 @@ - exit 1;\ - fi - -- # Clone the testbed project into the XCFOLDER -- $(PYTHON_FOR_BUILD) $(srcdir)/iOS/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER)" -+ # Clone the testbed project into the XCFOLDER-iOS -+ $(PYTHON_FOR_BUILD) $(srcdir)/iOS/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER-iOS)" -+ -+ # Run the testbed project -+ $(PYTHON_FOR_BUILD) "$(XCFOLDER-iOS)" run --verbose -- test -uall --single-process --rerun -W -+ -+# Run the test suite on the visionOS simulator. Must be run on a macOS machine with -+# a full Xcode install that has an Apple Vision Pro simulator available. -+# This must be run *after* a `make install` has completed the build. The -+# `--with-framework-name` argument *cannot* be used when configuring the build. -+XCFOLDER-visionOS:=visionOSTestbed.$(MULTIARCH).$(shell date +%s).$$PPID -+.PHONY: testvisionos -+testvisionos: -+ @if test "$(MACHDEP)" != "visionos"; then \ -+ echo "Cannot run the visionOS testbed for a non-visionOS build."; \ -+ exit 1;\ -+ fi -+ @if test "$(findstring -xrsimulator,$(MULTIARCH))" != "-xrsimulator"; then \ -+ echo "Cannot run the visionOS testbed for non-simulator builds."; \ -+ exit 1;\ -+ fi -+ @if test $(PYTHONFRAMEWORK) != "Python"; then \ -+ echo "Cannot run the visionOS testbed with a non-default framework name."; \ -+ exit 1;\ -+ fi -+ @if ! test -d $(PYTHONFRAMEWORKPREFIX); then \ -+ echo "Cannot find a finalized visionOS Python.framework. Have you run 'make install' to finalize the framework build?"; \ -+ exit 1;\ -+ fi -+ -+ # Clone the testbed project into the XCFOLDER-visionOS -+ $(PYTHON_FOR_BUILD) $(srcdir)/visionOS/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER-visionOS)" - - # Run the testbed project -- $(PYTHON_FOR_BUILD) "$(XCFOLDER)" run --verbose -- test -uall --single-process --rerun -W -+ $(PYTHON_FOR_BUILD) "$(XCFOLDER-visionOS)" run --verbose -- test -uall --single-process --rerun -W - - # Like test, but using --slow-ci which enables all test resources and use - # longer timeout. Run an optional pybuildbot.identify script to include -diff --git a/Misc/platform_triplet.c b/Misc/platform_triplet.c -index ec0857a4a99..e52f486cdb3 100644 ---- a/Misc/platform_triplet.c -+++ b/Misc/platform_triplet.c -@@ -257,6 +257,32 @@ - # 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/config.sub b/config.sub -index 1bb6a05dc11..49febd56a37 100755 ---- a/config.sub -+++ b/config.sub -@@ -1743,7 +1743,7 @@ - | 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 @@ - ;; - *-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 1b75ddfa26d..7b79dfc424c 100755 ---- a/configure -+++ b/configure -@@ -978,6 +978,10 @@ - CFLAGS - CC - HAS_XCRUN -+EXPORT_XROS_DEPLOYMENT_TARGET -+XROS_DEPLOYMENT_TARGET -+WATCHOS_DEPLOYMENT_TARGET -+TVOS_DEPLOYMENT_TARGET - IPHONEOS_DEPLOYMENT_TARGET - EXPORT_MACOSX_DEPLOYMENT_TARGET - CONFIGURE_MACOSX_DEPLOYMENT_TARGET -@@ -4106,6 +4110,15 @@ - *-apple-ios*) - ac_sys_system=iOS - ;; -+ *-apple-tvos*) -+ ac_sys_system=tvOS -+ ;; -+ *-apple-watchos*) -+ ac_sys_system=watchOS -+ ;; -+ *-apple-xros*) -+ ac_sys_system=visionOS -+ ;; - *-*-darwin*) - ac_sys_system=Darwin - ;; -@@ -4187,7 +4200,7 @@ - # On cross-compile builds, configure will look for a host-specific compiler by - # prepending the user-provided host triple to the required binary name. - # --# On iOS, this results in binaries like "arm64-apple-ios13.0-simulator-gcc", -+# On iOS/tvOS/watchOS/visionOS, 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 -@@ -4202,6 +4215,17 @@ - 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 ;; +@@ -329,7 +350,7 @@ + usage="%(prog)s [-h] [--simulator SIMULATOR] -- [ ...]", + 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", +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed.xcodeproj/project.pbxproj +@@ -0,0 +1,505 @@ ++// !$*UTF8*$! ++{ ++ archiveVersion = 1; ++ classes = { ++ }; ++ objectVersion = 77; ++ objects = { + -+ 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 ;; ++/* Begin PBXBuildFile section */ ++ EE7C8A1E2DCD6FF3003206DB /* Python.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE7C8A1C2DCD6FF3003206DB /* Python.xcframework */; }; ++ EE7C8A1F2DCD70CD003206DB /* Python.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE7C8A1C2DCD6FF3003206DB /* Python.xcframework */; }; ++ EE7C8A202DCD70CD003206DB /* Python.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EE7C8A1C2DCD6FF3003206DB /* Python.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; ++/* End PBXBuildFile section */ + -+ 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 ;; ++/* Begin PBXContainerItemProxy section */ ++ EE989E662DCD6E7A0036B268 /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = EE989E462DCD6E780036B268 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = EE989E4D2DCD6E780036B268; ++ remoteInfo = tvOSTestbed; ++ }; ++/* End PBXContainerItemProxy section */ + -+ aarch64-apple-xros*-simulator) AR=arm64-apple-xros-simulator-ar ;; -+ aarch64-apple-xros*) AR=arm64-apple-xros-ar ;; - *) - esac - fi -@@ -4210,6 +4234,17 @@ - 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 ;; ++/* Begin PBXCopyFilesBuildPhase section */ ++ EE7C8A212DCD70CD003206DB /* Embed Frameworks */ = { ++ isa = PBXCopyFilesBuildPhase; ++ buildActionMask = 2147483647; ++ dstPath = ""; ++ dstSubfolderSpec = 10; ++ files = ( ++ EE7C8A202DCD70CD003206DB /* Python.xcframework in Embed Frameworks */, ++ ); ++ name = "Embed Frameworks"; ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXCopyFilesBuildPhase section */ + -+ 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 ;; ++/* Begin PBXFileReference section */ ++ 6077B3802E82A4BE00E3D6A3 /* tvOSTestbed.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = tvOSTestbed.xctestplan; sourceTree = ""; }; ++ EE7C8A1C2DCD6FF3003206DB /* Python.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Python.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 */ + -+ 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 ;; ++/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ ++ 6077B37F2E81892A00E3D6A3 /* Exceptions for "tvOSTestbed" folder in "tvOSTestbed" target */ = { ++ isa = PBXFileSystemSynchronizedBuildFileExceptionSet; ++ membershipExceptions = ( ++ "tvOSTestbed-Info.plist", ++ ); ++ target = EE989E4D2DCD6E780036B268 /* tvOSTestbed */; ++ }; ++/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + -+ aarch64-apple-xros*-simulator) CC=arm64-apple-xros-simulator-clang ;; -+ aarch64-apple-xros*) CC=arm64-apple-xros-clang ;; - *) - esac - fi -@@ -4218,6 +4253,17 @@ - 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 ;; ++/* 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 */ + -+ 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 ;; ++/* Begin PBXFrameworksBuildPhase section */ ++ EE989E4B2DCD6E780036B268 /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ EE7C8A1F2DCD70CD003206DB /* Python.xcframework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ EE989E622DCD6E7A0036B268 /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ EE7C8A1E2DCD6FF3003206DB /* Python.xcframework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXFrameworksBuildPhase section */ + -+ 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 ;; ++/* Begin PBXGroup section */ ++ EE989E452DCD6E780036B268 = { ++ isa = PBXGroup; ++ children = ( ++ 6077B3802E82A4BE00E3D6A3 /* tvOSTestbed.xctestplan */, ++ EE7C8A1C2DCD6FF3003206DB /* Python.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 */ + -+ aarch64-apple-xros*-simulator) CPP=arm64-apple-xros-simulator-cpp ;; -+ aarch64-apple-xros*) CPP=arm64-apple-xros-cpp ;; - *) - esac - fi -@@ -4226,6 +4272,17 @@ - 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-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++ ;; -+ -+ aarch64-apple-xros*-simulator) CXX=arm64-apple-xros-simulator-clang++ ;; -+ aarch64-apple-xros*) CXX=arm64-apple-xros-clang++ ;; - *) - esac - fi -@@ -4348,8 +4405,11 @@ - case $enableval in - yes) - case $ac_sys_system in -- Darwin) enableval=/Library/Frameworks ;; -- iOS) enableval=iOS/Frameworks/\$\(MULTIARCH\) ;; -+ Darwin) enableval=/Library/Frameworks ;; -+ iOS) enableval=iOS/Frameworks/\$\(MULTIARCH\) ;; -+ tvOS) enableval=tvOS/Frameworks/\$\(MULTIARCH\) ;; -+ watchOS) enableval=watchOS/Frameworks/\$\(MULTIARCH\) ;; -+ visionOS) enableval=visionOS/Frameworks/\$\(MULTIARCH\) ;; - *) as_fn_error $? "Unknown platform for framework build" "$LINENO" 5 - esac - esac -@@ -4358,6 +4418,9 @@ - no) - case $ac_sys_system in - iOS) as_fn_error $? "iOS builds must use --enable-framework" "$LINENO" 5 ;; -+ tvOS) as_fn_error $? "tvOS builds must use --enable-framework" "$LINENO" 5 ;; -+ watchOS) as_fn_error $? "watchOS builds must use --enable-framework" "$LINENO" 5 ;; -+ visionOS) as_fn_error $? "visionOS builds must use --enable-framework" "$LINENO" 5 ;; - *) - PYTHONFRAMEWORK= - PYTHONFRAMEWORKDIR=no-framework -@@ -4464,6 +4527,51 @@ - - ac_config_files="$ac_config_files iOS/Resources/Info.plist" - -+ ;; -+ tvOS) : -+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " -+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKPYTHONW= -+ INSTALLTARGETS="libinstall inclinstall sharedinstall" -+ -+ prefix=$PYTHONFRAMEWORKPREFIX -+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" -+ RESSRCDIR=tvOS/Resources -+ -+ ac_config_files="$ac_config_files tvOS/Resources/Info.plist" -+ -+ ;; -+ watchOS) : -+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " -+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKPYTHONW= -+ INSTALLTARGETS="libinstall inclinstall sharedinstall" -+ -+ prefix=$PYTHONFRAMEWORKPREFIX -+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" -+ RESSRCDIR=watchOS/Resources -+ -+ ac_config_files="$ac_config_files watchOS/Resources/Info.plist" -+ -+ ;; -+ visionOS) : -+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " -+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKPYTHONW= -+ INSTALLTARGETS="libinstall inclinstall sharedinstall" -+ -+ prefix=$PYTHONFRAMEWORKPREFIX -+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" -+ RESSRCDIR=visionOS/Resources -+ -+ ac_config_files="$ac_config_files visionOS/Resources/Info.plist" -+ - ;; - *) - as_fn_error $? "Unknown platform for framework build" "$LINENO" 5 -@@ -4475,6 +4583,9 @@ - e) - case $ac_sys_system in - iOS) as_fn_error $? "iOS builds must use --enable-framework" "$LINENO" 5 ;; -+ tvOS) as_fn_error $? "tvOS builds must use --enable-framework" "$LINENO" 5 ;; -+ watchOS) as_fn_error $? "watchOS builds must use --enable-framework" "$LINENO" 5 ;; -+ visionOS) as_fn_error $? "visionOS builds must use --enable-framework" "$LINENO" 5 ;; - *) - PYTHONFRAMEWORK= - PYTHONFRAMEWORKDIR=no-framework -@@ -4529,8 +4640,8 @@ - case "$withval" in - yes) - case $ac_sys_system in -- Darwin|iOS) -- # iOS is able to share the macOS patch -+ Darwin|iOS|tvOS|watchOS|visionOS) -+ # iOS/tvOS/watchOS/visionOS 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 ;; -@@ -4548,8 +4659,8 @@ - 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|watchOS|visionOS) -+ # Always apply the compliance patch on iOS/tvOS/watchOS/visionOS; 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; } -@@ -4567,6 +4678,8 @@ - - - -+EXPORT_XROS_DEPLOYMENT_TARGET='#' ++/* 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 */ + - - if test "$cross_compiling" = yes; then - case "$host" in -@@ -4604,6 +4717,78 @@ - ;; - esac - ;; -+ *-apple-tvos*) -+ _host_os=`echo $host | cut -d '-' -f3` -+ _host_device=`echo $host | cut -d '-' -f4` -+ _host_device=${_host_device:=os} ++/* 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 */ + -+ # 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; } ++/* Begin PBXResourcesBuildPhase section */ ++ EE989E4C2DCD6E780036B268 /* Resources */ = { ++ isa = PBXResourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ EE989E632DCD6E7A0036B268 /* Resources */ = { ++ isa = PBXResourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXResourcesBuildPhase section */ + -+ 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-watchos*) -+ _host_os=`echo $host | cut -d '-' -f3` -+ _host_device=`echo $host | cut -d '-' -f4` -+ _host_device=${_host_device:=os} ++/* 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.xcframework/build/utils.sh\n\ninstall_python Python.xcframework app app_packages\n"; ++ }; ++/* End PBXShellScriptBuildPhase section */ + -+ # 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:=4.0} -+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WATCHOS_DEPLOYMENT_TARGET" >&5 -+printf "%s\n" "$WATCHOS_DEPLOYMENT_TARGET" >&6; } ++/* Begin PBXSourcesBuildPhase section */ ++ EE989E4A2DCD6E780036B268 /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ EE989E612DCD6E7A0036B268 /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXSourcesBuildPhase section */ + -+ 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 -+ ;; -+ *-apple-xros*) -+ _host_os=`echo $host | cut -d '-' -f3` -+ _host_device=`echo $host | cut -d '-' -f4` -+ _host_device=${_host_device:=os} ++/* Begin PBXTargetDependency section */ ++ EE989E672DCD6E7A0036B268 /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = EE989E4D2DCD6E780036B268 /* tvOSTestbed */; ++ targetProxy = EE989E662DCD6E7A0036B268 /* PBXContainerItemProxy */; ++ }; ++/* End PBXTargetDependency section */ + -+ # 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; } ++/* 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.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.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 */ + -+ 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 -+ ;; - *-*-darwin*) - case "$host_cpu" in - arm*) -@@ -4694,9 +4879,15 @@ - 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/watchOS/visionOS, defining _POSIX_C_SOURCE also disables platform specific features. - iOS/*) - define_xopen_source=no;; -+ tvOS/*) -+ define_xopen_source=no;; -+ watchOS/*) -+ define_xopen_source=no;; -+ visionOS/*) -+ define_xopen_source=no;; - # On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from - # defining NI_NUMERICHOST. - QNX/6.3.2) -@@ -4759,7 +4950,13 @@ - 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 / -+# WATCHOS_DEPLOYMENT_TARGET / XROS_DEPLOYMENT_TARGET enforced by the selected host triple. ++/* 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 */; ++} +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed.xcodeproj/xcshareddata/xcschemes/tvOSTestbed.xcscheme +@@ -0,0 +1,97 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +--- /dev/null ++++ b/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 +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/AppDelegate.h +@@ -0,0 +1,11 @@ ++// ++// AppDelegate.h ++// tvOSTestbed ++// + ++#import + ++@interface AppDelegate : UIResponder + -+# XROS_DEPLOYMENT_TARGET should get exported - - - # checks for alternative programs -@@ -4800,6 +4997,16 @@ - as_fn_append CFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}" - as_fn_append LDFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}" - ;; #( -+ tvOS) : + -+ as_fn_append CFLAGS " -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}" -+ as_fn_append LDFLAGS " -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}" -+ ;; #( -+ watchOS) : ++@end +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/AppDelegate.m +@@ -0,0 +1,19 @@ ++// ++// AppDelegate.m ++// tvOSTestbed ++// + -+ as_fn_append CFLAGS " -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}" -+ as_fn_append LDFLAGS " -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}" -+ ;; #( - *) : - ;; - esac -@@ -7169,6 +7376,12 @@ - MULTIARCH="" ;; #( - iOS) : - MULTIARCH="" ;; #( -+ tvOS) : -+ MULTIARCH="" ;; #( -+ watchOS) : -+ MULTIARCH="" ;; #( -+ visionOS) : -+ MULTIARCH="" ;; #( - FreeBSD*) : - MULTIARCH="" ;; #( - *) : -@@ -7189,7 +7402,7 @@ - printf "%s\n" "$MULTIARCH" >&6; } - - case $ac_sys_system in #( -- iOS) : -+ iOS|tvOS|watchOS|visionOS) : - SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2` ;; #( - *) : - SOABI_PLATFORM=$PLATFORM_TRIPLET -@@ -7240,6 +7453,18 @@ - PY_SUPPORT_TIER=3 ;; #( - aarch64-apple-ios*/clang) : - PY_SUPPORT_TIER=3 ;; #( -+ aarch64-apple-tvos*-simulator/clang) : -+ PY_SUPPORT_TIER=3 ;; #( -+ aarch64-apple-tvos*/clang) : -+ PY_SUPPORT_TIER=3 ;; #( -+ aarch64-apple-watchos*-simulator/clang) : -+ PY_SUPPORT_TIER=3 ;; #( -+ arm64_32-apple-watchos*/clang) : -+ PY_SUPPORT_TIER=3 ;; #( -+ aarch64-apple-xros*-simulator/clang) : -+ PY_SUPPORT_TIER=3 ;; #( -+ aarch64-apple-xros*/clang) : -+ PY_SUPPORT_TIER=3 ;; #( - aarch64-*-linux-android/clang) : - PY_SUPPORT_TIER=3 ;; #( - x86_64-*-linux-android/clang) : -@@ -7676,7 +7901,7 @@ - case $ac_sys_system in - Darwin) - LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)';; -- iOS) -+ iOS|tvOS|watchOS|visionOS) - LDLIBRARY='$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)';; - *) - as_fn_error $? "Unknown platform for framework build" "$LINENO" 5;; -@@ -7742,7 +7967,7 @@ - BLDLIBRARY='-L. -lpython$(LDVERSION)' - RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} - ;; -- iOS) -+ iOS|tvOS|watchOS|visionOS) - LDLIBRARY='libpython$(LDVERSION).dylib' - ;; - AIX*) -@@ -13550,7 +13775,7 @@ - BLDSHARED="$LDSHARED" - fi - ;; -- iOS/*) -+ iOS/*|tvOS/*|watchOS/*|visionOS/*) - LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' - LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' - BLDSHARED="$LDSHARED" -@@ -13683,7 +13908,7 @@ - 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/*|watchOS/*|visionOS/*) - LINKFORSHARED="$extra_undefs -framework CoreFoundation" - - # Issue #18075: the default maximum stack size (8MBytes) is too -@@ -13707,7 +13932,7 @@ - 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" = "watchOS" -o "$ac_sys_system" = "visionOS"; then - LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' - fi - ;; -@@ -15292,7 +15517,7 @@ - - ctypes_malloc_closure=yes - ;; #( -- iOS) : -+ iOS|tvOS|watchOS|visionOS) : - - ctypes_malloc_closure=yes - ;; #( -@@ -19044,12 +19269,6 @@ - then : - printf "%s\n" "#define HAVE_DUP3 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 -@@ -19110,18 +19329,6 @@ - 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 -@@ -19548,24 +19755,6 @@ - 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 -@@ -19884,12 +20073,6 @@ - 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 -@@ -20158,11 +20341,11 @@ - - fi - --# iOS defines some system methods that can be linked (so they are -+# iOS/tvOS/watchOS/visionOS 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. --if test "$ac_sys_system" != "iOS" ; then -+if test "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" -a "$ac_sys_system" != "visionOS" ; then - ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy" - if test "x$ac_cv_func_getentropy" = xyes - then : -@@ -20184,6 +20367,53 @@ - - fi - -+# 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 ++#import "AppDelegate.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 ++@interface AppDelegate () + -+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 ++@end + -+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 ++@implementation AppDelegate + -+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 ++- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ++ return YES; ++} + -+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 ++@end +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/Base.lproj/LaunchScreen.storyboard +@@ -0,0 +1,24 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/app/README +@@ -0,0 +1,7 @@ ++This folder can contain any Python application code. + -+fi ++During the build, any binary modules found in this folder will be processed into ++Framework form. + -+fi ++When the test suite runs, this folder will be on the PYTHONPATH, and will be the ++working directory for the test suite. +--- /dev/null ++++ b/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. + - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 - printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } - if test ${ac_cv_c_undeclared_builtin_options+y} -@@ -23266,7 +23496,8 @@ - - - # 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 : -@@ -23380,7 +23611,7 @@ - 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 : -@@ -23563,6 +23794,7 @@ - fi - - done -+fi - - # check for long file support functions - ac_fn_c_check_func "$LINENO" "fseek64" "ac_cv_func_fseek64" -@@ -23828,10 +24060,10 @@ - - done - --# On Android and iOS, clock_settime can be linked (so it is found by -+# On Android, iOS, tvOS, watchOS, and visionOS, 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" != "watchOS" -a "$ac_sys_system" != "visionOS" - then - - for ac_func in clock_settime -@@ -24148,7 +24380,7 @@ - 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" = "watchOS" || test "$ac_sys_system" = "visionOS"; then - ac_cv_buggy_getaddrinfo="no" - elif test "${enable_ipv6+set}" = set; then - ac_cv_buggy_getaddrinfo="no -- configured with --(en|dis)able-ipv6" -@@ -26170,8 +26402,8 @@ - LIBPYTHON="\$(BLDLIBRARY)" - fi - --# On iOS the shared libraries must be linked with the Python framework --if test "$ac_sys_system" = "iOS"; then -+# On iOS/tvOS/watchOS the shared libraries must be linked with the Python framework -+if test "$ac_sys_system" = "iOS" -o $ac_sys_system = "tvOS" -o $ac_sys_system = "watchOS" -o $ac_sys_system = "visionOS"; then - MODULE_DEPS_SHARED="$MODULE_DEPS_SHARED \$(PYTHONFRAMEWORKDIR)/\$(PYTHONFRAMEWORK)" - fi - -@@ -29041,7 +29273,7 @@ - { 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" = "watchOS" -o "$ac_sys_system" = "visionOS" ; then - ac_cv_file__dev_ptmx=no - ac_cv_file__dev_ptc=no - else -@@ -29550,7 +29782,7 @@ - with_ensurepip=no ;; #( - WASI) : - with_ensurepip=no ;; #( -- iOS) : -+ iOS|tvOS|watchOS|visionOS) : - with_ensurepip=no ;; #( - *) : - with_ensurepip=upgrade -@@ -30499,7 +30731,7 @@ - SunOS*) _PYTHREAD_NAME_MAXLEN=31;; - NetBSD*) _PYTHREAD_NAME_MAXLEN=15;; # gh-131268 - Darwin) _PYTHREAD_NAME_MAXLEN=63;; -- iOS) _PYTHREAD_NAME_MAXLEN=63;; -+ iOS|tvOS|watchOS|visionOS) _PYTHREAD_NAME_MAXLEN=63;; - FreeBSD*) _PYTHREAD_NAME_MAXLEN=19;; # gh-131268 - OpenBSD*) _PYTHREAD_NAME_MAXLEN=23;; # gh-131268 - *) _PYTHREAD_NAME_MAXLEN=;; -@@ -30531,7 +30763,7 @@ - ;; #( - Darwin) : - ;; #( -- iOS) : -+ iOS|tvOS|watchOS|visionOS) : - - - -@@ -34605,6 +34837,9 @@ - "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" ;; - "iOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES iOS/Resources/Info.plist" ;; -+ "tvOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES tvOS/Resources/Info.plist" ;; -+ "watchOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES watchOS/Resources/Info.plist" ;; -+ "visionOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES visionOS/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 c449bb5ebb3..29b9a82374b 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -330,6 +330,15 @@ - *-apple-ios*) - ac_sys_system=iOS - ;; -+ *-apple-tvos*) -+ ac_sys_system=tvOS -+ ;; -+ *-apple-watchos*) -+ ac_sys_system=watchOS -+ ;; -+ *-apple-xros*) -+ ac_sys_system=visionOS -+ ;; - *-*-darwin*) - ac_sys_system=Darwin - ;; -@@ -405,7 +414,7 @@ - # On cross-compile builds, configure will look for a host-specific compiler by - # prepending the user-provided host triple to the required binary name. - # --# On iOS, this results in binaries like "arm64-apple-ios13.0-simulator-gcc", -+# On iOS/tvOS/watchOS/visionOS, 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 -@@ -420,6 +429,17 @@ - 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 ;; ++During the build, any binary modules found in this folder will be processed into ++Framework form. + -+ 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 ;; ++When the test suite runs, this folder will be on the PYTHONPATH. +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/main.m +@@ -0,0 +1,16 @@ ++// ++// main.m ++// tvOSTestbed ++// + -+ aarch64-apple-xros*-simulator) AR=arm64-apple-xros-simulator-ar ;; -+ aarch64-apple-xros*) AR=arm64-apple-xros-ar ;; - *) - esac - fi -@@ -428,6 +448,17 @@ - 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 ;; ++#import ++#import "AppDelegate.h" + -+ 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 ;; ++int main(int argc, char * argv[]) { ++ NSString * appDelegateClassName; ++ @autoreleasepool { ++ appDelegateClassName = NSStringFromClass([AppDelegate class]); + -+ 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 ;; ++ return UIApplicationMain(argc, argv, nil, appDelegateClassName); ++ } ++} +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/tvOSTestbed-Info.plist +@@ -0,0 +1,52 @@ ++ ++ ++ ++ ++ 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 ++ ++ ++ ++ +--- /dev/null ++++ b/Apple/testbed/visionOSTestbed.xcodeproj/project.pbxproj +@@ -0,0 +1,558 @@ ++// !$*UTF8*$! ++{ ++ archiveVersion = 1; ++ classes = { ++ }; ++ objectVersion = 56; ++ objects = { + -+ aarch64-apple-xros*-simulator) CC=arm64-apple-xros-simulator-clang ;; -+ aarch64-apple-xros*) CC=arm64-apple-xros-clang ;; - *) - esac - fi -@@ -436,6 +467,17 @@ - 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 ;; ++/* Begin PBXBuildFile section */ ++ 607A66172B0EFA380010BFC8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 607A66162B0EFA380010BFC8 /* AppDelegate.m */; }; ++ 607A66222B0EFA390010BFC8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607A66212B0EFA390010BFC8 /* Assets.xcassets */; }; ++ 607A66282B0EFA390010BFC8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 607A66272B0EFA390010BFC8 /* main.m */; }; ++ 607A66322B0EFA3A0010BFC8 /* TestbedTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 607A66312B0EFA3A0010BFC8 /* TestbedTests.m */; }; ++ 608619542CB77BA900F46182 /* app_packages in Resources */ = {isa = PBXBuildFile; fileRef = 608619532CB77BA900F46182 /* app_packages */; }; ++ 608619562CB7819B00F46182 /* app in Resources */ = {isa = PBXBuildFile; fileRef = 608619552CB7819B00F46182 /* app */; }; ++ EEB367CE2DADF5C900B9A1D7 /* Python.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EEE9C80C2DAB5ECA0056F8C6 /* Python.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; ++ EEB367CF2DADF5D300B9A1D7 /* Python.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EEE9C80C2DAB5ECA0056F8C6 /* Python.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; ++ EEE9C80D2DAB5ECA0056F8C6 /* Python.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EEE9C80C2DAB5ECA0056F8C6 /* Python.xcframework */; }; ++ EEE9C80E2DAB5ECA0056F8C6 /* Python.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EEE9C80C2DAB5ECA0056F8C6 /* Python.xcframework */; }; ++/* End PBXBuildFile section */ + -+ 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 ;; ++/* Begin PBXContainerItemProxy section */ ++ 607A662E2B0EFA3A0010BFC8 /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 607A660A2B0EFA380010BFC8 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = 607A66112B0EFA380010BFC8; ++ remoteInfo = iOSTestbed; ++ }; ++/* End PBXContainerItemProxy section */ + -+ 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 ;; ++/* Begin PBXCopyFilesBuildPhase section */ ++ 607A664E2B0EFC080010BFC8 /* Embed Frameworks */ = { ++ isa = PBXCopyFilesBuildPhase; ++ buildActionMask = 2147483647; ++ dstPath = ""; ++ dstSubfolderSpec = 10; ++ files = ( ++ EEB367CF2DADF5D300B9A1D7 /* Python.xcframework in Embed Frameworks */, ++ ); ++ name = "Embed Frameworks"; ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ 607A66522B0EFFE00010BFC8 /* Embed Frameworks */ = { ++ isa = PBXCopyFilesBuildPhase; ++ buildActionMask = 2147483647; ++ dstPath = ""; ++ dstSubfolderSpec = 10; ++ files = ( ++ EEB367CE2DADF5C900B9A1D7 /* Python.xcframework in Embed Frameworks */, ++ ); ++ name = "Embed Frameworks"; ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXCopyFilesBuildPhase section */ + -+ aarch64-apple-xros*-simulator) CPP=arm64-apple-xros-simulator-cpp ;; -+ aarch64-apple-xros*) CPP=arm64-apple-xros-cpp ;; - *) - esac - fi -@@ -444,6 +486,17 @@ - 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-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++ ;; ++/* 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; }; ++ 607A66152B0EFA380010BFC8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; ++ 607A66162B0EFA380010BFC8 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; ++ 607A66212B0EFA390010BFC8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; ++ 607A66272B0EFA390010BFC8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; ++ 607A662D2B0EFA3A0010BFC8 /* TestbedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestbedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; ++ 607A66312B0EFA3A0010BFC8 /* TestbedTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestbedTests.m; sourceTree = ""; }; ++ 607A66592B0F08600010BFC8 /* visionOSTestbed-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "visionOSTestbed-Info.plist"; sourceTree = ""; }; ++ 608619532CB77BA900F46182 /* app_packages */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app_packages; sourceTree = ""; }; ++ 608619552CB7819B00F46182 /* app */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app; sourceTree = ""; }; ++ EEE9C80C2DAB5ECA0056F8C6 /* Python.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Python.xcframework; sourceTree = ""; }; ++/* End PBXFileReference section */ + -+ aarch64-apple-xros*-simulator) CXX=arm64-apple-xros-simulator-clang++ ;; -+ aarch64-apple-xros*) CXX=arm64-apple-xros-clang++ ;; - *) - esac - fi -@@ -558,8 +611,11 @@ - case $enableval in - yes) - case $ac_sys_system in -- Darwin) enableval=/Library/Frameworks ;; -- iOS) enableval=iOS/Frameworks/\$\(MULTIARCH\) ;; -+ Darwin) enableval=/Library/Frameworks ;; -+ iOS) enableval=iOS/Frameworks/\$\(MULTIARCH\) ;; -+ tvOS) enableval=tvOS/Frameworks/\$\(MULTIARCH\) ;; -+ watchOS) enableval=watchOS/Frameworks/\$\(MULTIARCH\) ;; -+ visionOS) enableval=visionOS/Frameworks/\$\(MULTIARCH\) ;; - *) AC_MSG_ERROR([Unknown platform for framework build]) - esac - esac -@@ -568,6 +624,9 @@ - no) - case $ac_sys_system in - iOS) AC_MSG_ERROR([iOS builds must use --enable-framework]) ;; -+ tvOS) AC_MSG_ERROR([tvOS builds must use --enable-framework]) ;; -+ watchOS) AC_MSG_ERROR([watchOS builds must use --enable-framework]) ;; -+ visionOS) AC_MSG_ERROR([visionOS builds must use --enable-framework]) ;; - *) - PYTHONFRAMEWORK= - PYTHONFRAMEWORKDIR=no-framework -@@ -670,6 +729,48 @@ - - AC_CONFIG_FILES([iOS/Resources/Info.plist]) - ;; -+ tvOS) : -+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " -+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKPYTHONW= -+ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++/* Begin PBXFrameworksBuildPhase section */ ++ 607A660F2B0EFA380010BFC8 /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ EEE9C80D2DAB5ECA0056F8C6 /* Python.xcframework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ 607A662A2B0EFA3A0010BFC8 /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ EEE9C80E2DAB5ECA0056F8C6 /* Python.xcframework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXFrameworksBuildPhase section */ + -+ prefix=$PYTHONFRAMEWORKPREFIX -+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" -+ RESSRCDIR=tvOS/Resources ++/* Begin PBXGroup section */ ++ 607A66092B0EFA380010BFC8 = { ++ isa = PBXGroup; ++ children = ( ++ 6077B3D62E82E60C00E3D6A3 /* visionOSTestbed.xctestplan */, ++ EEE9C80C2DAB5ECA0056F8C6 /* Python.xcframework */, ++ 607A66142B0EFA380010BFC8 /* visionOSTestbed */, ++ 607A66302B0EFA3A0010BFC8 /* TestbedTests */, ++ 607A66132B0EFA380010BFC8 /* Products */, ++ 607A664F2B0EFFE00010BFC8 /* Frameworks */, ++ ); ++ sourceTree = ""; ++ }; ++ 607A66132B0EFA380010BFC8 /* Products */ = { ++ isa = PBXGroup; ++ children = ( ++ 607A66122B0EFA380010BFC8 /* visionOSTestbed.app */, ++ 607A662D2B0EFA3A0010BFC8 /* TestbedTests.xctest */, ++ ); ++ name = Products; ++ sourceTree = ""; ++ }; ++ 607A66142B0EFA380010BFC8 /* visionOSTestbed */ = { ++ isa = PBXGroup; ++ children = ( ++ 608619552CB7819B00F46182 /* app */, ++ 608619532CB77BA900F46182 /* app_packages */, ++ 607A66592B0F08600010BFC8 /* visionOSTestbed-Info.plist */, ++ 607A66152B0EFA380010BFC8 /* AppDelegate.h */, ++ 607A66162B0EFA380010BFC8 /* AppDelegate.m */, ++ 607A66212B0EFA390010BFC8 /* Assets.xcassets */, ++ 607A66272B0EFA390010BFC8 /* main.m */, ++ ); ++ path = visionOSTestbed; ++ sourceTree = ""; ++ }; ++ 607A66302B0EFA3A0010BFC8 /* TestbedTests */ = { ++ isa = PBXGroup; ++ children = ( ++ 607A66312B0EFA3A0010BFC8 /* TestbedTests.m */, ++ ); ++ path = TestbedTests; ++ sourceTree = ""; ++ }; ++ 607A664F2B0EFFE00010BFC8 /* Frameworks */ = { ++ isa = PBXGroup; ++ children = ( ++ ); ++ name = Frameworks; ++ sourceTree = ""; ++ }; ++/* End PBXGroup section */ + -+ AC_CONFIG_FILES([tvOS/Resources/Info.plist]) -+ ;; -+ watchOS) : -+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " -+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKPYTHONW= -+ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++/* 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 = ( ++ ); ++ name = visionOSTestbed; ++ 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 */, ++ ); ++ name = TestbedTests; ++ productName = iOSTestbedTests; ++ productReference = 607A662D2B0EFA3A0010BFC8 /* TestbedTests.xctest */; ++ productType = "com.apple.product-type.bundle.unit-test"; ++ }; ++/* End PBXNativeTarget section */ + -+ prefix=$PYTHONFRAMEWORKPREFIX -+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" -+ RESSRCDIR=watchOS/Resources ++/* 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; ++ productRefGroup = 607A66132B0EFA380010BFC8 /* Products */; ++ projectDirPath = ""; ++ projectRoot = ""; ++ targets = ( ++ 607A66112B0EFA380010BFC8 /* visionOSTestbed */, ++ 607A662C2B0EFA3A0010BFC8 /* TestbedTests */, ++ ); ++ }; ++/* End PBXProject section */ + -+ AC_CONFIG_FILES([watchOS/Resources/Info.plist]) -+ ;; -+ visionOS) : -+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " -+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKPYTHONW= -+ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++/* Begin PBXResourcesBuildPhase section */ ++ 607A66102B0EFA380010BFC8 /* Resources */ = { ++ isa = PBXResourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ 608619562CB7819B00F46182 /* app in Resources */, ++ 607A66222B0EFA390010BFC8 /* Assets.xcassets in Resources */, ++ 608619542CB77BA900F46182 /* app_packages in Resources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ 607A662B2B0EFA3A0010BFC8 /* Resources */ = { ++ isa = PBXResourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXResourcesBuildPhase section */ + -+ prefix=$PYTHONFRAMEWORKPREFIX -+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" -+ RESSRCDIR=visionOS/Resources ++/* 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.xcframework/build/utils.sh\n\ninstall_python Python.xcframework app app_packages\n"; ++ showEnvVarsInLog = 0; ++ }; ++/* End PBXShellScriptBuildPhase section */ + -+ AC_CONFIG_FILES([visionOS/Resources/Info.plist]) -+ ;; - *) - AC_MSG_ERROR([Unknown platform for framework build]) - ;; -@@ -678,6 +779,9 @@ - ],[ - case $ac_sys_system in - iOS) AC_MSG_ERROR([iOS builds must use --enable-framework]) ;; -+ tvOS) AC_MSG_ERROR([tvOS builds must use --enable-framework]) ;; -+ watchOS) AC_MSG_ERROR([watchOS builds must use --enable-framework]) ;; -+ visionOS) AC_MSG_ERROR([visionOS builds must use --enable-framework]) ;; - *) - PYTHONFRAMEWORK= - PYTHONFRAMEWORKDIR=no-framework -@@ -730,8 +834,8 @@ - case "$withval" in - yes) - case $ac_sys_system in -- Darwin|iOS) -- # iOS is able to share the macOS patch -+ Darwin|iOS|tvOS|watchOS|visionOS) -+ # iOS/tvOS/watchOS/visionOS 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]) ;; -@@ -745,8 +849,8 @@ - esac - ],[ - case $ac_sys_system in -- iOS) -- # Always apply the compliance patch on iOS; we can use the macOS patch -+ iOS|tvOS|watchOS|visionOS) -+ # Always apply the compliance patch on iOS/tvOS/watchOS/visionOS; 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]) - ;; -@@ -759,6 +863,8 @@ - ]) - AC_SUBST([APP_STORE_COMPLIANCE_PATCH]) - -+EXPORT_XROS_DEPLOYMENT_TARGET='#' -+ - AC_SUBST([_PYTHON_HOST_PLATFORM]) - if test "$cross_compiling" = yes; then - case "$host" in -@@ -794,6 +900,70 @@ - ;; - 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-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:=4.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 -+ ;; -+ *-apple-xros*) -+ _host_os=`echo $host | cut -d '-' -f3` -+ _host_device=`echo $host | cut -d '-' -f4` -+ _host_device=${_host_device:=os} ++/* Begin PBXSourcesBuildPhase section */ ++ 607A660E2B0EFA380010BFC8 /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ 607A66172B0EFA380010BFC8 /* AppDelegate.m in Sources */, ++ 607A66282B0EFA390010BFC8 /* main.m in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ 607A66292B0EFA3A0010BFC8 /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ 607A66322B0EFA3A0010BFC8 /* TestbedTests.m in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXSourcesBuildPhase section */ + -+ # 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]) ++/* Begin PBXTargetDependency section */ ++ 607A662F2B0EFA3A0010BFC8 /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = 607A66112B0EFA380010BFC8 /* visionOSTestbed */; ++ targetProxy = 607A662E2B0EFA3A0010BFC8 /* PBXContainerItemProxy */; ++ }; ++/* End PBXTargetDependency section */ + -+ 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 -+ ;; - *-*-darwin*) - case "$host_cpu" in - arm*) -@@ -883,9 +1053,15 @@ - 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/watchOS/visionOS, defining _POSIX_C_SOURCE also disables platform specific features. - iOS/*) - define_xopen_source=no;; -+ tvOS/*) -+ define_xopen_source=no;; -+ watchOS/*) -+ define_xopen_source=no;; -+ visionOS/*) -+ define_xopen_source=no;; - # On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from - # defining NI_NUMERICHOST. - QNX/6.3.2) -@@ -944,8 +1120,14 @@ - 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 / -+# WATCHOS_DEPLOYMENT_TARGET / XROS_DEPLOYMENT_TARGET enforced by the selected host triple. - AC_SUBST([IPHONEOS_DEPLOYMENT_TARGET]) -+AC_SUBST([TVOS_DEPLOYMENT_TARGET]) -+AC_SUBST([WATCHOS_DEPLOYMENT_TARGET]) -+AC_SUBST([XROS_DEPLOYMENT_TARGET]) -+# XROS_DEPLOYMENT_TARGET should get exported -+AC_SUBST([EXPORT_XROS_DEPLOYMENT_TARGET]) - - # checks for alternative programs - -@@ -979,11 +1161,19 @@ - ], - ) - --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([$ac_sys_system], - [iOS], [ - AS_VAR_APPEND([CFLAGS], [" -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"]) - AS_VAR_APPEND([LDFLAGS], [" -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"]) -+ ],[tvOS], [ -+ AS_VAR_APPEND([CFLAGS], [" -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"]) -+ AS_VAR_APPEND([LDFLAGS], [" -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"]) -+ ],[watchOS], [ -+ AS_VAR_APPEND([CFLAGS], [" -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"]) -+ AS_VAR_APPEND([LDFLAGS], [" -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"]) - ], - ) - -@@ -1172,6 +1362,9 @@ - AS_CASE([$ac_sys_system], - [Darwin*], [MULTIARCH=""], - [iOS], [MULTIARCH=""], -+ [tvOS], [MULTIARCH=""], -+ [watchOS], [MULTIARCH=""], -+ [visionOS], [MULTIARCH=""], - [FreeBSD*], [MULTIARCH=""], - [MULTIARCH=$($CC --print-multiarch 2>/dev/null)] - ) -@@ -1193,7 +1386,7 @@ - dnl use a single "fat" binary at runtime. SOABI_PLATFORM is the component of - dnl the PLATFORM_TRIPLET that will be used in binary module extensions. - AS_CASE([$ac_sys_system], -- [iOS], [SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2`], -+ [iOS|tvOS|watchOS|visionOS], [SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2`], - [SOABI_PLATFORM=$PLATFORM_TRIPLET] - ) - -@@ -1227,6 +1420,12 @@ - [x86_64-*-freebsd*/clang], [PY_SUPPORT_TIER=3], dnl FreeBSD on AMD64 - [aarch64-apple-ios*-simulator/clang], [PY_SUPPORT_TIER=3], dnl iOS Simulator on arm64 - [aarch64-apple-ios*/clang], [PY_SUPPORT_TIER=3], dnl iOS on ARM64 -+ [aarch64-apple-tvos*-simulator/clang], [PY_SUPPORT_TIER=3], dnl tvOS Simulator on arm64 -+ [aarch64-apple-tvos*/clang], [PY_SUPPORT_TIER=3], dnl tvOS on ARM64 -+ [aarch64-apple-watchos*-simulator/clang], [PY_SUPPORT_TIER=3], dnl watchOS Simulator on arm64 -+ [arm64_32-apple-watchos*/clang], [PY_SUPPORT_TIER=3], dnl watchOS on ARM64 -+ [aarch64-apple-xros*-simulator/clang], [PY_SUPPORT_TIER=3], dnl visionOS Simulator on arm64 -+ [aarch64-apple-xros*/clang], [PY_SUPPORT_TIER=3], dnl visionOS on ARM64 - [aarch64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on ARM64 - [x86_64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on AMD64 - -@@ -1536,7 +1735,7 @@ - case $ac_sys_system in - Darwin) - LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)';; -- iOS) -+ iOS|tvOS|watchOS|visionOS) - LDLIBRARY='$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)';; - *) - AC_MSG_ERROR([Unknown platform for framework build]);; -@@ -1601,7 +1800,7 @@ - BLDLIBRARY='-L. -lpython$(LDVERSION)' - RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} - ;; -- iOS) -+ iOS|tvOS|watchOS|visionOS) - LDLIBRARY='libpython$(LDVERSION).dylib' - ;; - AIX*) -@@ -3456,7 +3655,7 @@ - BLDSHARED="$LDSHARED" - fi - ;; -- iOS/*) -+ iOS/*|tvOS/*|watchOS/*|visionOS/*) - LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' - LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' - BLDSHARED="$LDSHARED" -@@ -3580,7 +3779,7 @@ - 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/*|watchOS/*|visionOS/*) - LINKFORSHARED="$extra_undefs -framework CoreFoundation" - - # Issue #18075: the default maximum stack size (8MBytes) is too -@@ -3604,7 +3803,7 @@ - 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" = "watchOS" -o "$ac_sys_system" = "visionOS"; then - LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' - fi - ;; -@@ -4024,7 +4223,7 @@ - dnl when do we need USING_APPLE_OS_LIBFFI? - ctypes_malloc_closure=yes - ], -- [iOS], [ -+ [iOS|tvOS|watchOS|visionOS], [ - ctypes_malloc_closure=yes - ], - [sunos5], [AS_VAR_APPEND([LIBFFI_LIBS], [" -mimpure-text"])] -@@ -5133,9 +5332,9 @@ - # checks for library functions - AC_CHECK_FUNCS([ \ - accept4 alarm bind_textdomain_codeset chmod chown clock closefrom close_range confstr \ -- copy_file_range ctermid dladdr dup dup3 execv explicit_bzero explicit_memset \ -+ copy_file_range ctermid dladdr dup dup3 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 getegid geteuid getgid getgrent getgrgid getgrgid_r \ - getgrnam_r getgrouplist gethostname getitimer getloadavg getlogin \ - getpeername getpgid getpid getppid getpriority _getpty \ -@@ -5143,8 +5342,7 @@ - getspnam getuid getwd grantpt if_nameindex initgroups kill killpg lchown linkat \ - lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \ - mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \ -- pipe2 plock poll posix_fadvise posix_fallocate posix_openpt posix_spawn posix_spawnp \ -- posix_spawn_file_actions_addclosefrom_np \ -+ pipe2 plock poll 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 -@@ -5154,7 +5352,7 @@ - sched_setparam sched_setscheduler sem_clockwait sem_getvalue sem_open \ - sem_timedwait sem_unlink sendfile setegid seteuid setgid sethostname \ - setitimer setlocale setpgid setpgrp setpriority setregid setresgid \ -- 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 tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \ -@@ -5169,12 +5367,20 @@ - AC_CHECK_FUNCS([lchmod]) - fi - --# iOS defines some system methods that can be linked (so they are -+# iOS/tvOS/watchOS/visionOS 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. --if test "$ac_sys_system" != "iOS" ; then -- AC_CHECK_FUNCS([getentropy getgroups system]) -+if test "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" -a "$ac_sys_system" != "visionOS" ; then -+ AC_CHECK_FUNCS([ getentropy getgroups system ]) -+fi ++/* 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.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.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.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.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 */ + -+# 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], -@@ -5428,20 +5634,22 @@ - ]) - - # 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]) -@@ -5480,10 +5688,10 @@ - ]) - ]) - --# On Android and iOS, clock_settime can be linked (so it is found by -+# On Android, iOS, tvOS, watchOS, and visionOS, 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" != "watchOS" -a "$ac_sys_system" != "visionOS" - then - AC_CHECK_FUNCS([clock_settime], [], [ - AC_CHECK_LIB([rt], [clock_settime], [ -@@ -5641,7 +5849,7 @@ - [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" = "watchOS" || test "$ac_sys_system" = "visionOS"; then - ac_cv_buggy_getaddrinfo="no" - elif test "${enable_ipv6+set}" = set; then - ac_cv_buggy_getaddrinfo="no -- configured with --(en|dis)able-ipv6" -@@ -6234,8 +6442,8 @@ - LIBPYTHON="\$(BLDLIBRARY)" - fi - --# On iOS the shared libraries must be linked with the Python framework --if test "$ac_sys_system" = "iOS"; then -+# On iOS/tvOS/watchOS the shared libraries must be linked with the Python framework -+if test "$ac_sys_system" = "iOS" -o $ac_sys_system = "tvOS" -o $ac_sys_system = "watchOS" -o $ac_sys_system = "visionOS"; then - MODULE_DEPS_SHARED="$MODULE_DEPS_SHARED \$(PYTHONFRAMEWORKDIR)/\$(PYTHONFRAMEWORK)" - fi - -@@ -6894,7 +7102,7 @@ - dnl NOTE: Inform user how to proceed with files when cross compiling. - dnl Some cross-compile builds are predictable; they won't ever - dnl have /dev/ptmx or /dev/ptc, so we can set them explicitly. --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" = "watchOS" -o "$ac_sys_system" = "visionOS" ; then - ac_cv_file__dev_ptmx=no - ac_cv_file__dev_ptc=no - else -@@ -7195,7 +7403,7 @@ - AS_CASE([$ac_sys_system], - [Emscripten], [with_ensurepip=no], - [WASI], [with_ensurepip=no], -- [iOS], [with_ensurepip=no], -+ [iOS|tvOS|watchOS|visionOS], [with_ensurepip=no], - [with_ensurepip=upgrade] - ) - ]) -@@ -7582,7 +7790,7 @@ - SunOS*) _PYTHREAD_NAME_MAXLEN=31;; - NetBSD*) _PYTHREAD_NAME_MAXLEN=15;; # gh-131268 - Darwin) _PYTHREAD_NAME_MAXLEN=63;; -- iOS) _PYTHREAD_NAME_MAXLEN=63;; -+ iOS|tvOS|watchOS|visionOS) _PYTHREAD_NAME_MAXLEN=63;; - FreeBSD*) _PYTHREAD_NAME_MAXLEN=19;; # gh-131268 - OpenBSD*) _PYTHREAD_NAME_MAXLEN=23;; # gh-131268 - *) _PYTHREAD_NAME_MAXLEN=;; -@@ -7607,7 +7815,7 @@ - [VxWorks*], [PY_STDLIB_MOD_SET_NA([_scproxy], [termios], [grp])], - dnl The _scproxy module is available on macOS - [Darwin], [], -- [iOS], [ -+ [iOS|tvOS|watchOS|visionOS], [ - 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 -diff --git a/iOS/Resources/Info.plist.in b/iOS/Resources/Info.plist.in -index c3e261ecd9e..26ef7a95de4 100644 ---- a/iOS/Resources/Info.plist.in -+++ b/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 ++/* 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 */; ++} +--- /dev/null ++++ b/Apple/testbed/visionOSTestbed.xcodeproj/xcshareddata/xcschemes/visionOSTestbed.xcscheme +@@ -0,0 +1,97 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +--- /dev/null ++++ b/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 +--- /dev/null ++++ b/Apple/testbed/visionOSTestbed/AppDelegate.h +@@ -0,0 +1,11 @@ ++// ++// AppDelegate.h ++// visionOSTestbed ++// ++ ++#import ++ ++@interface AppDelegate : UIResponder ++ ++ ++@end +--- /dev/null ++++ b/Apple/testbed/visionOSTestbed/AppDelegate.m +@@ -0,0 +1,19 @@ ++// ++// AppDelegate.m ++// visionOSTestbed ++// ++ ++#import "AppDelegate.h" ++ ++@interface AppDelegate () ++ ++@end ++ ++@implementation AppDelegate ++ ++ ++- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ++ return YES; ++} ++ ++@end +--- /dev/null ++++ b/Apple/testbed/visionOSTestbed/Assets.xcassets/AccentColor.colorset/Contents.json +@@ -0,0 +1,11 @@ ++{ ++ "colors" : [ ++ { ++ "idiom" : "universal" ++ } ++ ], ++ "info" : { ++ "author" : "xcode", ++ "version" : 1 ++ } ++} +--- /dev/null ++++ b/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 ++ } ++} +--- /dev/null ++++ b/Apple/testbed/visionOSTestbed/Assets.xcassets/Contents.json +@@ -0,0 +1,6 @@ ++{ ++ "info" : { ++ "author" : "xcode", ++ "version" : 1 ++ } ++} +--- /dev/null ++++ b/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. --- /dev/null -+++ b/tvOS/README.rst ++++ b/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. +--- /dev/null ++++ b/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); ++ } ++} +--- /dev/null ++++ b/Apple/testbed/visionOSTestbed/visionOSTestbed-Info.plist +@@ -0,0 +1,56 @@ ++ ++ ++ ++ ++ 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 ++ ++ ++ UIRequiresFullScreen ++ ++ UISupportedInterfaceOrientations ++ ++ UIInterfaceOrientationPortrait ++ UIInterfaceOrientationLandscapeLeft ++ UIInterfaceOrientationLandscapeRight ++ ++ UISupportedInterfaceOrientations~ipad ++ ++ UIInterfaceOrientationPortrait ++ UIInterfaceOrientationPortraitUpsideDown ++ UIInterfaceOrientationLandscapeLeft ++ UIInterfaceOrientationLandscapeRight ++ ++ ++ +--- /dev/null ++++ b/Apple/tvOS/README.rst @@ -0,0 +1,108 @@ +===================== +Python on tvOS README @@ -1960,7 +2383,7 @@ index c3e261ecd9e..26ef7a95de4 100644 +Using a framework-based Python on tvOS +====================================== --- /dev/null -+++ b/tvOS/Resources/Info.plist.in ++++ b/Apple/tvOS/Resources/Info.plist.in @@ -0,0 +1,34 @@ + + @@ -1997,106 +2420,296 @@ index c3e261ecd9e..26ef7a95de4 100644 + + --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-ar ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-ar @@ -0,0 +1,2 @@ +#!/bin/bash +xcrun --sdk appletvos${TVOS_SDK_VERSION} ar "$@" --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-clang ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvos${TVOS_SDK_VERSION} clang -target arm64-apple-tvos "$@" ++xcrun --sdk appletvos${TVOS_SDK_VERSION} clang -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET} "$@" --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-clang++ ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang++ @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvos${TVOS_SDK_VERSION} clang++ -target arm64-apple-tvos "$@" ++xcrun --sdk appletvos${TVOS_SDK_VERSION} clang++ -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET} "$@" --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-cpp ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-cpp @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvos${TVOS_SDK_VERSION} clang -target arm64-apple-tvos -E "$@" ++xcrun --sdk appletvos${TVOS_SDK_VERSION} clang -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET} -E "$@" --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-simulator-ar ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-ar @@ -0,0 +1,2 @@ +#!/bin/bash +xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} ar "$@" --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target arm64-apple-tvos-simulator "$@" ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator "$@" --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang++ ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang++ @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang++ -target arm64-apple-tvos-simulator "$@" ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang++ -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator "$@" --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-simulator-cpp ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-cpp @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target arm64-apple-tvos-simulator -E "$@" ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator -E "$@" +--- /dev/null ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} strip -arch arm64 "$@" +--- /dev/null ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphoneos${TVOS_SDK_VERSION} strip -arch arm64 "$@" --- /dev/null -+++ b/tvOS/Resources/bin/x86_64-apple-tvos-simulator-ar ++++ b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-ar @@ -0,0 +1,2 @@ +#!/bin/bash +xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} ar "$@" --- /dev/null -+++ b/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang ++++ b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target x86_64-apple-tvos-simulator "$@" ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target x86_64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator "$@" --- /dev/null -+++ b/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang++ ++++ b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang++ @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang++ -target x86_64-apple-tvos-simulator "$@" ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang++ -target x86_64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator "$@" --- /dev/null -+++ b/tvOS/Resources/bin/x86_64-apple-tvos-simulator-cpp ++++ b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-cpp @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target x86_64-apple-tvos-simulator -E "$@" ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target x86_64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator -E "$@" --- /dev/null -+++ b/tvOS/Resources/dylib-Info-template.plist -@@ -0,0 +1,26 @@ ++++ b/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 "$@" +--- /dev/null ++++ b/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 +--- /dev/null ++++ b/Apple/visionOS/Resources/Info.plist.in +@@ -0,0 +1,34 @@ + -+ -+ ++ ++ + + CFBundleDevelopmentRegion + en + CFBundleExecutable -+ ++ Python ++ CFBundleGetInfoString ++ Python Runtime and Library + CFBundleIdentifier -+ ++ @PYTHONFRAMEWORKIDENTIFIER@ + CFBundleInfoDictionaryVersion + 6.0 ++ CFBundleName ++ Python + CFBundlePackageType -+ APPL ++ FMWK + CFBundleShortVersionString -+ 1.0 ++ %VERSION% ++ CFBundleLongVersionString ++ %VERSION%, (c) 2001-2023 Python Software Foundation. ++ CFBundleSignature ++ ???? ++ CFBundleVersion ++ %VERSION% + CFBundleSupportedPlatforms + -+ tvOS ++ XROS + + MinimumOSVersion -+ 9.0 -+ CFBundleVersion -+ 1 ++ @XROS_DEPLOYMENT_TARGET@ + + --- /dev/null -+++ b/tvOS/Resources/pyconfig.h -@@ -0,0 +1,7 @@ ++++ b/Apple/visionOS/Resources/bin/arm64-apple-xros-ar +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk xros${XROS_SDK_VERSION} ar "$@" +--- /dev/null ++++ b/Apple/visionOS/Resources/bin/arm64-apple-xros-clang +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk xros${XROS_SDK_VERSION} clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET} "$@" +--- /dev/null ++++ b/Apple/visionOS/Resources/bin/arm64-apple-xros-clang++ +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk xros${XROS_SDK_VERSION} clang++ -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET} "$@" +--- /dev/null ++++ b/Apple/visionOS/Resources/bin/arm64-apple-xros-cpp +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk xros${XROS_SDK_VERSION} clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET} -E "$@" +--- /dev/null ++++ b/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-ar +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk xrsimulator${XROS_SDK_VERSION} ar "$@" +--- /dev/null ++++ b/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-clang +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk xrsimulator${XROS_SDK_VERSION} clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET}-simulator "$@" +--- /dev/null ++++ b/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-clang++ +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk xrsimulator${XROS_SDK_VERSION} clang++ -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET}-simulator "$@" +--- /dev/null ++++ b/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-cpp +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk xrsimulator${XROS_SDK_VERSION} clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET}-simulator -E "$@" +--- /dev/null ++++ b/Apple/visionOS/Resources/bin/arm64-apple-xros-simulator-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk xrsimulator${XROS_SDK_VERSION} strip -arch arm64 "$@" +--- /dev/null ++++ b/Apple/visionOS/Resources/bin/arm64-apple-xros-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk xros${XROS_SDK_VERSION} strip -arch arm64 "$@" +--- /dev/null ++++ b/Apple/visionOS/Resources/pyconfig.h +@@ -0,0 +1,3 @@ +#ifdef __arm64__ +#include "pyconfig-arm64.h" +#endif +--- /dev/null ++++ b/Apple/watchOS/README.rst +@@ -0,0 +1,108 @@ ++======================== ++Python on watchOS README ++======================== ++ ++:Authors: ++ Russell Keith-Magee (2023-11) ++ ++This document provides a quick overview of some watchOS specific features in the ++Python distribution. ++ ++Compilers for building on watchOS ++================================= ++ ++Building for watchOS requires the use of Apple's Xcode tooling. It is strongly ++recommended that you use the most recent stable release of Xcode, on the ++most recently released macOS. ++ ++watchOS specific arguments to configure ++======================================= ++ ++* ``--enable-framework[=DIR]`` ++ ++ This argument specifies the location where the Python.framework will ++ be installed. ++ ++* ``--with-framework-name=NAME`` ++ ++ Specify the name for the python framework, defaults to ``Python``. ++ ++ ++Building and using Python on watchOS ++==================================== ++ ++ABIs and Architectures ++---------------------- ++ ++watchOS apps can be deployed on physical devices, and on the watchOS simulator. ++Although the API used on these devices is identical, the ABI is different - you ++need to link against different libraries for an watchOS device build ++(``watchos``) or an watchOS simulator build (``watchsimulator``). Apple uses the ++XCframework format to allow specifying a single dependency that supports ++multiple ABIs. An XCframework is a wrapper around multiple ABI-specific ++frameworks. ++ ++watchOS can also support different CPU architectures within each ABI. At present, ++there is only a single support ed architecture on physical devices - ARM64. ++However, the *simulator* supports 2 architectures - ARM64 (for running on Apple ++Silicon machines), and x86_64 (for running on older Intel-based machines.) ++ ++To support multiple CPU architectures on a single platform, Apple uses a "fat ++binary" format - a single physical file that contains support for multiple ++architectures. ++ ++How do I build Python for watchOS? ++------------------------------- ++ ++The Python build system will build a ``Python.framework`` that supports a ++*single* ABI with a *single* architecture. If you want to use Python in an watchOS ++project, you need to: ++ ++1. Produce multiple ``Python.framework`` builds, one for each ABI and architecture; ++2. Merge the binaries for each architecture on a given ABI into a single "fat" binary; ++3. Merge the "fat" frameworks for each ABI into a single XCframework. ++ ++watchOS builds of Python *must* be constructed as framework builds. To support this, ++you must provide the ``--enable-framework`` flag when configuring the build. ++ ++The build also requires the use of cross-compilation. The commands for building ++Python for watchOS will look somethign like:: ++ ++ $ ./configure \ ++ --enable-framework=/path/to/install \ ++ --host=aarch64-apple-watchos \ ++ --build=aarch64-apple-darwin \ ++ --with-build-python=/path/to/python.exe ++ $ make ++ $ make install ++ ++In this invocation: ++ ++* ``/path/to/install`` is the location where the final Python.framework will be ++ output. ++ ++* ``--host`` is the architecture and ABI that you want to build, in GNU compiler ++ triple format. This will be one of: ++ ++ - ``arm64_32-apple-watchos`` for ARM64-32 watchOS devices. ++ - ``aarch64-apple-watchos-simulator`` for the watchOS simulator running on Apple ++ Silicon devices. ++ - ``x86_64-apple-watchos-simulator`` for the watchOS simulator running on Intel ++ devices. + -+#ifdef __x86_64__ -+#include "pyconfig-x86_64.h" -+#endif ++* ``--build`` is the GNU compiler triple for the machine that will be running ++ the compiler. This is one of: ++ ++ - ``aarch64-apple-darwin`` for Apple Silicon devices. ++ - ``x86_64-apple-darwin`` for Intel devices. ++ ++* ``/path/to/python.exe`` is the path to a Python binary on the machine that ++ will be running the compiler. This is needed because the Python compilation ++ process involves running some Python code. On a normal desktop build of ++ Python, you can compile a python interpreter and then use that interpreter to ++ run Python code. However, the binaries produced for watchOS won't run on macOS, so ++ you need to provide an external Python interpreter. This interpreter must be ++ the version as the Python that is being compiled. ++ ++Using a framework-based Python on watchOS ++====================================== --- /dev/null -+++ b/visionOS/Resources/Info.plist.in ++++ b/Apple/watchOS/Resources/Info.plist.in @@ -0,0 +1,34 @@ + + @@ -2126,1849 +2739,1901 @@ index c3e261ecd9e..26ef7a95de4 100644 + %VERSION% + CFBundleSupportedPlatforms + -+ XROS ++ watchOS + + MinimumOSVersion -+ @XROS_DEPLOYMENT_TARGET@ ++ @WATCHOS_DEPLOYMENT_TARGET@ + + --- /dev/null -+++ b/visionOS/Resources/bin/arm64-apple-xros-ar ++++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-ar @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk xros${XROS_SDK_VERSION} ar "$@" ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} ar "$@" --- /dev/null -+++ b/visionOS/Resources/bin/arm64-apple-xros-clang ++++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk xros${XROS_SDK_VERSION} clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET} "$@" ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target arm64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator "$@" --- /dev/null -+++ b/visionOS/Resources/bin/arm64-apple-xros-clang++ ++++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang++ @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk xros${XROS_SDK_VERSION} clang++ -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET} "$@" ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang++ -target arm64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator "$@" --- /dev/null -+++ b/visionOS/Resources/bin/arm64-apple-xros-cpp ++++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-cpp @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk xros${XROS_SDK_VERSION} clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET} -E "$@" ++xcrun --sdk watchsimulator clang -target arm64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator -E "$@" +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} strip -arch arm64 "$@" +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk watchos${WATCHOS_SDK_VERSION} strip -arch arm64 "$@" --- /dev/null -+++ b/visionOS/Resources/bin/arm64-apple-xros-simulator-ar ++++ b/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-ar @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk xrsimulator${XROS_SDK_VERSION} ar "$@" ++xcrun --sdk watchos${WATCHOS_SDK_VERSION} ar "$@" --- /dev/null -+++ b/visionOS/Resources/bin/arm64-apple-xros-simulator-clang ++++ b/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk xrsimulator${XROS_SDK_VERSION} clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET}-simulator "$@" ++xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang -target arm64_32-apple-watchos${WATCHOS_DEPLOYMENT_TARGET} "$@" --- /dev/null -+++ b/visionOS/Resources/bin/arm64-apple-xros-simulator-clang++ ++++ b/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang++ @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk xrsimulator${XROS_SDK_VERSION} clang++ -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET}-simulator "$@" ++xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang++ -target arm64_32-apple-watchos${WATCHOS_DEPLOYMENT_TARGET} "$@" --- /dev/null -+++ b/visionOS/Resources/bin/arm64-apple-xros-simulator-cpp ++++ b/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-cpp @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk xrsimulator clang -target arm64-apple-xros${XROS_DEPLOYMENT_TARGET}-simulator -E "$@" ++xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang -target arm64_32-apple-watchos${WATCHOS_DEPLOYMENT_TARGET} -E "$@" --- /dev/null -+++ b/visionOS/Resources/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 -+ -+ -+ ++++ b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-ar +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} ar "$@" --- /dev/null -+++ b/visionOS/testbed/Python.xcframework/Info.plist -@@ -0,0 +1,43 @@ -+ -+ -+ -+ -+ AvailableLibraries -+ -+ -+ 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 -+ -+ -+ CFBundlePackageType -+ XFWK -+ XCFrameworkFormatVersion -+ 1.0 -+ -+ ++++ b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target x86_64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator "$@" --- /dev/null -+++ b/visionOS/testbed/__main__.py -@@ -0,0 +1,512 @@ -+import argparse -+import asyncio -+import fcntl -+import json -+import os -+import plistlib -+import re -+import shutil -+import subprocess -+import sys -+import tempfile -+from contextlib import asynccontextmanager -+from datetime import datetime -+from pathlib import Path -+ -+ -+DECODE_ARGS = ("UTF-8", "backslashreplace") -+ -+# The system log prefixes each line: -+# 2025-01-17 16:14:29.090 Df visionOSTestbed[23987:1fd393b4] (Python) ... -+# 2025-01-17 16:14:29.090 E visionOSTestbed[23987:1fd393b4] (Python) ... -+ -+LOG_PREFIX_REGEX = re.compile( -+ r"^\d{4}-\d{2}-\d{2}" # YYYY-MM-DD -+ r"\s+\d+:\d{2}:\d{2}\.\d+" # HH:MM:SS.sss -+ r"\s+\w+" # Df/E -+ r"\s+visionOSTestbed\[\d+:\w+\]" # Process/thread ID -+ r"\s+\(Python\)\s" # Logger name -+) -+ ++++ b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang++ +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang++ -target x86_64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator "$@" +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-cpp +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target x86_64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator -E "$@" +--- /dev/null ++++ b/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 "$@" +--- /dev/null ++++ b/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 + -+# Work around a bug involving sys.exit and TaskGroups -+# (https://github.com/python/cpython/issues/101515). -+def exit(*args): -+ raise MySystemExit(*args) -+ -+ -+class MySystemExit(Exception): -+ pass -+ -+ -+class SimulatorLock: -+ # An fcntl-based filesystem lock that can be used to ensure that -+ def __init__(self, timeout): -+ self.filename = Path(tempfile.gettempdir()) / "python-visionos-testbed" -+ self.timeout = timeout -+ -+ self.fd = None -+ -+ async def acquire(self): -+ # Ensure the lockfile exists -+ self.filename.touch(exist_ok=True) -+ -+ # Try `timeout` times to acquire the lock file, with a 1 second pause -+ # between each attempt. Report status every 10 seconds. -+ for i in range(0, self.timeout): -+ try: -+ fd = os.open(self.filename, os.O_RDWR | os.O_TRUNC, 0o644) -+ fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) -+ except OSError: -+ os.close(fd) -+ if i % 10 == 0: -+ print("... waiting", flush=True) -+ await asyncio.sleep(1) -+ else: -+ self.fd = fd -+ return -+ -+ # If we reach the end of the loop, we've exceeded the allowed number of -+ # attempts. -+ raise ValueError("Unable to obtain lock on visionOS simulator creation") -+ -+ def release(self): -+ # If a lock is held, release it. -+ if self.fd is not None: -+ # Release the lock. -+ fcntl.flock(self.fd, fcntl.LOCK_UN) -+ os.close(self.fd) -+ self.fd = None -+ -+ -+# All subprocesses are executed through this context manager so that no matter -+# what happens, they can always be cancelled from another task, and they will -+# always be cleaned up on exit. -+@asynccontextmanager -+async def async_process(*args, **kwargs): -+ process = await asyncio.create_subprocess_exec(*args, **kwargs) -+ try: -+ yield process -+ finally: -+ if process.returncode is None: -+ # Allow a reasonably long time for Xcode to clean itself up, -+ # because we don't want stale emulators left behind. -+ timeout = 10 -+ process.terminate() -+ try: -+ await asyncio.wait_for(process.wait(), timeout) -+ except TimeoutError: -+ print( -+ f"Command {args} did not terminate after {timeout} seconds " -+ f" - sending SIGKILL" -+ ) -+ process.kill() -+ -+ # Even after killing the process we must still wait for it, -+ # otherwise we'll get the warning "Exception ignored in __del__". -+ await asyncio.wait_for(process.wait(), timeout=1) -+ -+ -+async def async_check_output(*args, **kwargs): -+ async with async_process( -+ *args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs -+ ) as process: -+ stdout, stderr = await process.communicate() -+ if process.returncode == 0: -+ return stdout.decode(*DECODE_ARGS) -+ else: -+ raise subprocess.CalledProcessError( -+ process.returncode, -+ args, -+ stdout.decode(*DECODE_ARGS), -+ stderr.decode(*DECODE_ARGS), -+ ) ++#ifdef __x86_64__ ++#include "pyconfig-x86_64.h" ++#endif +diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py +index 823a3692fd1..69550af2087 100644 +--- a/Lib/ctypes/__init__.py ++++ b/Lib/ctypes/__init__.py +@@ -419,9 +419,9 @@ + if name: + name = _os.fspath(name) + +- # 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.endswith(".fwork"): + with open(name) as f: + name = _os.path.join( +diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py +index 378f12167c6..591c69adfb7 100644 +--- a/Lib/ctypes/util.py ++++ b/Lib/ctypes/util.py +@@ -126,7 +126,7 @@ + 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, +@@ -444,7 +444,7 @@ + # https://man.openbsd.org/dl_iterate_phdr + # https://docs.oracle.com/cd/E88353_01/html/E37843/dl-iterate-phdr-3c.html + if (os.name == "posix" and +- sys.platform not in {"darwin", "ios", "tvos", "watchos"}): ++ sys.platform not in {"darwin", "ios", "tvos", "watchos", "visionos"}): + import ctypes + if hasattr((_libc := ctypes.CDLL(None)), "dl_iterate_phdr"): + +diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py +index 8bcd741c446..db11cbe0945 100644 +--- a/Lib/importlib/_bootstrap_external.py ++++ b/Lib/importlib/_bootstrap_external.py +@@ -52,7 +52,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) + +@@ -1535,7 +1535,7 @@ + """ + 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 784b6b749b7..4d3be1aca18 100644 +--- a/Lib/platform.py ++++ b/Lib/platform.py +@@ -539,6 +539,78 @@ + return IOSVersionInfo(system, release, model, is_simulator) + + ++# A namedtuple for tvOS version information. ++TVOSVersionInfo = collections.namedtuple( ++ "TVOSVersionInfo", ++ ["system", "release", "model", "is_simulator"] ++) + + -+# Return a list of UDIDs associated with booted simulators -+async def list_devices(): -+ try: -+ # List the testing simulators, in JSON format -+ raw_json = await async_check_output( -+ "xcrun", "simctl", "--set", "testing", "list", "-j" -+ ) -+ json_data = json.loads(raw_json) -+ -+ # Filter out the booted visionOS simulators -+ return [ -+ simulator["udid"] -+ for runtime, simulators in json_data["devices"].items() -+ for simulator in simulators -+ if runtime.split(".")[-1].startswith("xrOS") and simulator["state"] == "Booted" -+ ] -+ except subprocess.CalledProcessError as e: -+ # If there's no ~/Library/Developer/XCTestDevices folder (which is the -+ # case on fresh installs, and in some CI environments), `simctl list` -+ # returns error code 1, rather than an empty list. Handle that case, -+ # but raise all other errors. -+ if e.returncode == 1: -+ return [] -+ else: -+ raise -+ -+ -+async def find_device(initial_devices, lock): -+ while True: -+ new_devices = set(await list_devices()).difference(initial_devices) -+ if len(new_devices) == 0: -+ await asyncio.sleep(1) -+ elif len(new_devices) == 1: -+ udid = new_devices.pop() -+ print(f"{datetime.now():%Y-%m-%d %H:%M:%S}: New test simulator detected") -+ print(f"UDID: {udid}", flush=True) -+ lock.release() -+ return udid -+ else: -+ exit(f"Found more than one new device: {new_devices}") -+ -+ -+async def log_stream_task(initial_devices, lock): -+ # Wait up to 5 minutes for the build to complete and the simulator to boot. -+ udid = await asyncio.wait_for(find_device(initial_devices, lock), 5 * 60) -+ -+ # Stream the visionOS device's logs, filtering out messages that come from the -+ # XCTest test suite (catching NSLog messages from the test method), or -+ # Python itself (catching stdout/stderr content routed to the system log -+ # with config->use_system_logger). -+ args = [ -+ "xcrun", -+ "simctl", -+ "--set", -+ "testing", -+ "spawn", -+ udid, -+ "log", -+ "stream", -+ "--style", -+ "compact", -+ "--predicate", -+ ( -+ 'senderImagePath ENDSWITH "/visionOSTestbedTests.xctest/visionOSTestbedTests"' -+ ' OR senderImagePath ENDSWITH "/Python.framework/Python"' -+ ), -+ ] -+ -+ async with async_process( -+ *args, -+ stdout=subprocess.PIPE, -+ stderr=subprocess.STDOUT, -+ ) as process: -+ suppress_dupes = False -+ while line := (await process.stdout.readline()).decode(*DECODE_ARGS): -+ # Strip the prefix from each log line -+ line = LOG_PREFIX_REGEX.sub("", line) -+ # The visionOS log streamer can sometimes lag; when it does, it outputs -+ # a warning about messages being dropped... often multiple times. -+ # Only print the first of these duplicated warnings. -+ if line.startswith("=== Messages dropped "): -+ if not suppress_dupes: -+ suppress_dupes = True -+ sys.stdout.write(line) -+ else: -+ suppress_dupes = False -+ sys.stdout.write(line) -+ sys.stdout.flush() -+ -+ -+async def xcode_test(location, simulator, verbose): -+ # Run the test suite on the named simulator -+ print("Starting xcodebuild...", flush=True) -+ args = [ -+ "xcodebuild", -+ "test", -+ "-project", -+ str(location / "visionOSTestbed.xcodeproj"), -+ "-scheme", -+ "visionOSTestbed", -+ "-destination", -+ f"platform=visionOS Simulator,name={simulator}", -+ "-resultBundlePath", -+ str(location / f"{datetime.now():%Y%m%d-%H%M%S}.xcresult"), -+ "-derivedDataPath", -+ str(location / "DerivedData"), -+ ] -+ if not verbose: -+ args += ["-quiet"] -+ -+ async with async_process( -+ *args, -+ stdout=subprocess.PIPE, -+ stderr=subprocess.STDOUT, -+ ) as process: -+ while line := (await process.stdout.readline()).decode(*DECODE_ARGS): -+ sys.stdout.write(line) -+ sys.stdout.flush() -+ -+ status = await asyncio.wait_for(process.wait(), timeout=1) -+ exit(status) -+ -+ -+def clone_testbed( -+ source: Path, -+ target: Path, -+ framework: Path, -+ apps: list[Path], -+) -> None: -+ if target.exists(): -+ print(f"{target} already exists; aborting without creating project.") -+ sys.exit(10) -+ -+ if framework is None: -+ if not ( -+ source / "Python.xcframework/xros-arm64-simulator/bin" -+ ).is_dir(): -+ print( -+ f"The testbed being cloned ({source}) does not contain " -+ f"a simulator framework. Re-run with --framework" -+ ) -+ sys.exit(11) -+ else: -+ if not framework.is_dir(): -+ print(f"{framework} does not exist.") -+ sys.exit(12) -+ elif not ( -+ framework.suffix == ".xcframework" -+ or (framework / "Python.framework").is_dir() -+ ): -+ print( -+ f"{framework} is not an XCframework, " -+ f"or a simulator slice of a framework build." -+ ) -+ sys.exit(13) -+ -+ print("Cloning testbed project:") -+ print(f" Cloning {source}...", end="", flush=True) -+ shutil.copytree(source, target, symlinks=True) -+ print(" done") -+ -+ xc_framework_path = target / "Python.xcframework" -+ sim_framework_path = xc_framework_path / "xros-arm64-simulator" -+ if framework is not None: -+ if framework.suffix == ".xcframework": -+ print(" Installing XCFramework...", end="", flush=True) -+ if xc_framework_path.is_dir(): -+ shutil.rmtree(xc_framework_path) -+ else: -+ xc_framework_path.unlink(missing_ok=True) -+ xc_framework_path.symlink_to( -+ framework.relative_to(xc_framework_path.parent, walk_up=True) -+ ) -+ print(" done") -+ else: -+ print(" Installing simulator framework...", end="", flush=True) -+ if sim_framework_path.is_dir(): -+ shutil.rmtree(sim_framework_path) -+ else: -+ sim_framework_path.unlink(missing_ok=True) -+ sim_framework_path.symlink_to( -+ framework.relative_to(sim_framework_path.parent, walk_up=True) -+ ) -+ print(" done") -+ else: -+ if ( -+ xc_framework_path.is_symlink() -+ and not xc_framework_path.readlink().is_absolute() -+ ): -+ # XCFramework is a relative symlink. Rewrite the symlink relative -+ # to the new location. -+ print(" Rewriting symlink to XCframework...", end="", flush=True) -+ orig_xc_framework_path = ( -+ source -+ / xc_framework_path.readlink() -+ ).resolve() -+ xc_framework_path.unlink() -+ xc_framework_path.symlink_to( -+ orig_xc_framework_path.relative_to( -+ xc_framework_path.parent, walk_up=True -+ ) -+ ) -+ print(" done") -+ elif ( -+ sim_framework_path.is_symlink() -+ and not sim_framework_path.readlink().is_absolute() -+ ): -+ print(" Rewriting symlink to simulator framework...", end="", flush=True) -+ # Simulator framework is a relative symlink. Rewrite the symlink -+ # relative to the new location. -+ orig_sim_framework_path = ( -+ source -+ / "Python.XCframework" -+ / sim_framework_path.readlink() -+ ).resolve() -+ sim_framework_path.unlink() -+ sim_framework_path.symlink_to( -+ orig_sim_framework_path.relative_to( -+ sim_framework_path.parent, walk_up=True -+ ) -+ ) -+ print(" done") -+ else: -+ print(" Using pre-existing visionOS framework.") -+ -+ for app_src in apps: -+ print(f" Installing app {app_src.name!r}...", end="", flush=True) -+ app_target = target / f"visionOSTestbed/app/{app_src.name}" -+ if app_target.is_dir(): -+ shutil.rmtree(app_target) -+ shutil.copytree(app_src, app_target) -+ print(" done") -+ -+ print(f"Successfully cloned testbed: {target.resolve()}") -+ -+ -+def update_plist(testbed_path, args): -+ # Add the test runner arguments to the testbed's Info.plist file. -+ info_plist = testbed_path / "visionOSTestbed" / "visionOSTestbed-Info.plist" -+ with info_plist.open("rb") as f: -+ info = plistlib.load(f) -+ -+ info["TestArgs"] = args -+ -+ with info_plist.open("wb") as f: -+ plistlib.dump(info, f) -+ -+ -+async def run_testbed(simulator: str, args: list[str], verbose: bool=False): -+ location = Path(__file__).parent -+ print("Updating plist...", end="", flush=True) -+ update_plist(location, args) -+ print(" done.", flush=True) -+ -+ # We need to get an exclusive lock on simulator creation, to avoid issues -+ # with multiple simulators starting and being unable to tell which -+ # simulator is due to which testbed instance. See -+ # https://github.com/python/cpython/issues/130294 for details. Wait up to -+ # 10 minutes for a simulator to boot. -+ print("Obtaining lock on simulator creation...", flush=True) -+ simulator_lock = SimulatorLock(timeout=10*60) -+ await simulator_lock.acquire() -+ print("Simulator lock acquired.", flush=True) -+ -+ # Get the list of devices that are booted at the start of the test run. -+ # The simulator started by the test suite will be detected as the new -+ # entry that appears on the device list. -+ initial_devices = await list_devices() -+ -+ try: -+ async with asyncio.TaskGroup() as tg: -+ tg.create_task(log_stream_task(initial_devices, simulator_lock)) -+ tg.create_task(xcode_test(location, simulator=simulator, verbose=verbose)) -+ except* MySystemExit as e: -+ raise SystemExit(*e.exceptions[0].args) from None -+ except* subprocess.CalledProcessError as e: -+ # Extract it from the ExceptionGroup so it can be handled by `main`. -+ raise e.exceptions[0] -+ finally: -+ simulator_lock.release() -+ -+ -+def main(): -+ parser = argparse.ArgumentParser( -+ description=( -+ "Manages the process of testing a Python project in the visionOS simulator." -+ ), -+ ) ++def tvos_ver(system="", release="", model="", is_simulator=False): ++ """Get tvOS version information, and return it as a namedtuple: ++ (system, release, model, is_simulator). + -+ subcommands = parser.add_subparsers(dest="subcommand") ++ If values can't be determined, they are set to values provided as ++ parameters. ++ """ ++ if sys.platform == "tvos": ++ # TODO: Can the iOS implementation be used here? ++ import _ios_support ++ result = _ios_support.get_platform_ios() ++ if result is not None: ++ return TVOSVersionInfo(*result) + -+ clone = subcommands.add_parser( -+ "clone", -+ description=( -+ "Clone the testbed project, copying in an visionOS Python framework and" -+ "any specified application code." -+ ), -+ help="Clone a testbed project to a new location.", -+ ) -+ clone.add_argument( -+ "--framework", -+ help=( -+ "The location of the XCFramework (or simulator-only slice of an " -+ "XCFramework) to use when running the testbed" -+ ), -+ ) -+ clone.add_argument( -+ "--app", -+ dest="apps", -+ action="append", -+ default=[], -+ help="The location of any code to include in the testbed project", -+ ) -+ clone.add_argument( -+ "location", -+ help="The path where the testbed will be cloned.", -+ ) ++ return TVOSVersionInfo(system, release, model, is_simulator) + -+ run = subcommands.add_parser( -+ "run", -+ usage="%(prog)s [-h] [--simulator SIMULATOR] -- [ ...]", -+ description=( -+ "Run a testbed project. The arguments provided after `--` will be " -+ "passed to the running visionOS process as if they were arguments to " -+ "`python -m`." -+ ), -+ help="Run a testbed project", -+ ) -+ run.add_argument( -+ "--simulator", -+ default="Apple Vision Pro", -+ help="The name of the simulator to use (default: 'Apple Vision Pro')", -+ ) -+ run.add_argument( -+ "-v", "--verbose", -+ action="store_true", -+ help="Enable verbose output", -+ ) + -+ try: -+ pos = sys.argv.index("--") -+ testbed_args = sys.argv[1:pos] -+ test_args = sys.argv[pos + 1 :] -+ except ValueError: -+ testbed_args = sys.argv[1:] -+ test_args = [] -+ -+ context = parser.parse_args(testbed_args) -+ -+ if context.subcommand == "clone": -+ clone_testbed( -+ source=Path(__file__).parent.resolve(), -+ target=Path(context.location).resolve(), -+ framework=Path(context.framework).resolve() if context.framework else None, -+ apps=[Path(app) for app in context.apps], -+ ) -+ elif context.subcommand == "run": -+ if test_args: -+ if not ( -+ Path(__file__).parent / "Python.xcframework/xros-arm64-simulator/bin" -+ ).is_dir(): -+ print( -+ f"Testbed does not contain a compiled visionOS framework. Use " -+ f"`python {sys.argv[0]} clone ...` to create a runnable " -+ f"clone of this testbed." -+ ) -+ sys.exit(20) -+ -+ asyncio.run( -+ run_testbed( -+ simulator=context.simulator, -+ verbose=context.verbose, -+ args=test_args, -+ ) -+ ) -+ else: -+ print(f"Must specify test arguments (e.g., {sys.argv[0]} run -- test)") -+ print() -+ parser.print_help(sys.stderr) -+ sys.exit(21) -+ else: -+ parser.print_help(sys.stderr) -+ sys.exit(1) ++# A namedtuple for watchOS version information. ++WatchOSVersionInfo = collections.namedtuple( ++ "WatchOSVersionInfo", ++ ["system", "release", "model", "is_simulator"] ++) + + -+if __name__ == "__main__": -+ main() ---- /dev/null -+++ b/visionOS/testbed/visionOSTestbed.xcodeproj/project.pbxproj -@@ -0,0 +1,581 @@ -+// !$*UTF8*$! -+{ -+ archiveVersion = 1; -+ classes = { -+ }; -+ objectVersion = 56; -+ objects = { ++def watchos_ver(system="", release="", model="", is_simulator=False): ++ """Get watchOS version information, and return it as a namedtuple: ++ (system, release, model, is_simulator). + -+/* Begin PBXBuildFile section */ -+ 607A66172B0EFA380010BFC8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 607A66162B0EFA380010BFC8 /* AppDelegate.m */; }; -+ 607A66222B0EFA390010BFC8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607A66212B0EFA390010BFC8 /* Assets.xcassets */; }; -+ 607A66282B0EFA390010BFC8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 607A66272B0EFA390010BFC8 /* main.m */; }; -+ 607A66322B0EFA3A0010BFC8 /* visionOSTestbedTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 607A66312B0EFA3A0010BFC8 /* visionOSTestbedTests.m */; }; -+ 607A66582B0F079F0010BFC8 /* dylib-Info-template.plist in Resources */ = {isa = PBXBuildFile; fileRef = 607A66572B0F079F0010BFC8 /* dylib-Info-template.plist */; }; -+ 608619542CB77BA900F46182 /* app_packages in Resources */ = {isa = PBXBuildFile; fileRef = 608619532CB77BA900F46182 /* app_packages */; }; -+ 608619562CB7819B00F46182 /* app in Resources */ = {isa = PBXBuildFile; fileRef = 608619552CB7819B00F46182 /* app */; }; -+ EEB367CE2DADF5C900B9A1D7 /* Python.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EEE9C80C2DAB5ECA0056F8C6 /* Python.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; -+ EEB367CF2DADF5D300B9A1D7 /* Python.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EEE9C80C2DAB5ECA0056F8C6 /* Python.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; -+ EEE9C80D2DAB5ECA0056F8C6 /* Python.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EEE9C80C2DAB5ECA0056F8C6 /* Python.xcframework */; }; -+ EEE9C80E2DAB5ECA0056F8C6 /* Python.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EEE9C80C2DAB5ECA0056F8C6 /* Python.xcframework */; }; -+/* End PBXBuildFile section */ ++ If values can't be determined, they are set to values provided as ++ parameters. ++ """ ++ if sys.platform == "watchos": ++ # TODO: Can the iOS implementation be used here? ++ import _ios_support ++ result = _ios_support.get_platform_ios() ++ if result is not None: ++ return WatchOSVersionInfo(*result) + -+/* Begin PBXContainerItemProxy section */ -+ 607A662E2B0EFA3A0010BFC8 /* PBXContainerItemProxy */ = { -+ isa = PBXContainerItemProxy; -+ containerPortal = 607A660A2B0EFA380010BFC8 /* Project object */; -+ proxyType = 1; -+ remoteGlobalIDString = 607A66112B0EFA380010BFC8; -+ remoteInfo = iOSTestbed; -+ }; -+/* End PBXContainerItemProxy section */ ++ return WatchOSVersionInfo(system, release, model, is_simulator) + -+/* Begin PBXCopyFilesBuildPhase section */ -+ 607A664E2B0EFC080010BFC8 /* Embed Frameworks */ = { -+ isa = PBXCopyFilesBuildPhase; -+ buildActionMask = 2147483647; -+ dstPath = ""; -+ dstSubfolderSpec = 10; -+ files = ( -+ EEB367CF2DADF5D300B9A1D7 /* Python.xcframework in Embed Frameworks */, -+ ); -+ name = "Embed Frameworks"; -+ runOnlyForDeploymentPostprocessing = 0; -+ }; -+ 607A66522B0EFFE00010BFC8 /* Embed Frameworks */ = { -+ isa = PBXCopyFilesBuildPhase; -+ buildActionMask = 2147483647; -+ dstPath = ""; -+ dstSubfolderSpec = 10; -+ files = ( -+ EEB367CE2DADF5C900B9A1D7 /* Python.xcframework in Embed Frameworks */, -+ ); -+ name = "Embed Frameworks"; -+ runOnlyForDeploymentPostprocessing = 0; -+ }; -+/* End PBXCopyFilesBuildPhase section */ + -+/* Begin PBXFileReference section */ -+ 607A66122B0EFA380010BFC8 /* visionOSTestbed.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = visionOSTestbed.app; sourceTree = BUILT_PRODUCTS_DIR; }; -+ 607A66152B0EFA380010BFC8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; -+ 607A66162B0EFA380010BFC8 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; -+ 607A66212B0EFA390010BFC8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; -+ 607A66272B0EFA390010BFC8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; -+ 607A662D2B0EFA3A0010BFC8 /* visionOSTestbedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = visionOSTestbedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; -+ 607A66312B0EFA3A0010BFC8 /* visionOSTestbedTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = visionOSTestbedTests.m; sourceTree = ""; }; -+ 607A66572B0F079F0010BFC8 /* dylib-Info-template.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "dylib-Info-template.plist"; sourceTree = ""; }; -+ 607A66592B0F08600010BFC8 /* visionOSTestbed-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "visionOSTestbed-Info.plist"; sourceTree = ""; }; -+ 608619532CB77BA900F46182 /* app_packages */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app_packages; sourceTree = ""; }; -+ 608619552CB7819B00F46182 /* app */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app; sourceTree = ""; }; -+ EEE9C80C2DAB5ECA0056F8C6 /* Python.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Python.xcframework; sourceTree = ""; }; -+/* End PBXFileReference section */ ++# A namedtuple for visionOS version information. ++VisionOSVersionInfo = collections.namedtuple( ++ "VisionOSVersionInfo", ++ ["system", "release", "model", "is_simulator"] ++) + -+/* Begin PBXFrameworksBuildPhase section */ -+ 607A660F2B0EFA380010BFC8 /* Frameworks */ = { -+ isa = PBXFrameworksBuildPhase; -+ buildActionMask = 2147483647; -+ files = ( -+ EEE9C80D2DAB5ECA0056F8C6 /* Python.xcframework in Frameworks */, -+ ); -+ runOnlyForDeploymentPostprocessing = 0; -+ }; -+ 607A662A2B0EFA3A0010BFC8 /* Frameworks */ = { -+ isa = PBXFrameworksBuildPhase; -+ buildActionMask = 2147483647; -+ files = ( -+ EEE9C80E2DAB5ECA0056F8C6 /* Python.xcframework in Frameworks */, -+ ); -+ runOnlyForDeploymentPostprocessing = 0; -+ }; -+/* End PBXFrameworksBuildPhase section */ + -+/* Begin PBXGroup section */ -+ 607A66092B0EFA380010BFC8 = { -+ isa = PBXGroup; -+ children = ( -+ EEE9C80C2DAB5ECA0056F8C6 /* Python.xcframework */, -+ 607A66142B0EFA380010BFC8 /* visionOSTestbed */, -+ 607A66302B0EFA3A0010BFC8 /* visionOSTestbedTests */, -+ 607A66132B0EFA380010BFC8 /* Products */, -+ 607A664F2B0EFFE00010BFC8 /* Frameworks */, -+ ); -+ sourceTree = ""; -+ }; -+ 607A66132B0EFA380010BFC8 /* Products */ = { -+ isa = PBXGroup; -+ children = ( -+ 607A66122B0EFA380010BFC8 /* visionOSTestbed.app */, -+ 607A662D2B0EFA3A0010BFC8 /* visionOSTestbedTests.xctest */, -+ ); -+ name = Products; -+ sourceTree = ""; -+ }; -+ 607A66142B0EFA380010BFC8 /* visionOSTestbed */ = { -+ isa = PBXGroup; -+ children = ( -+ 608619552CB7819B00F46182 /* app */, -+ 608619532CB77BA900F46182 /* app_packages */, -+ 607A66592B0F08600010BFC8 /* visionOSTestbed-Info.plist */, -+ 607A66572B0F079F0010BFC8 /* dylib-Info-template.plist */, -+ 607A66152B0EFA380010BFC8 /* AppDelegate.h */, -+ 607A66162B0EFA380010BFC8 /* AppDelegate.m */, -+ 607A66212B0EFA390010BFC8 /* Assets.xcassets */, -+ 607A66272B0EFA390010BFC8 /* main.m */, -+ ); -+ path = visionOSTestbed; -+ sourceTree = ""; -+ }; -+ 607A66302B0EFA3A0010BFC8 /* visionOSTestbedTests */ = { -+ isa = PBXGroup; -+ children = ( -+ 607A66312B0EFA3A0010BFC8 /* visionOSTestbedTests.m */, -+ ); -+ path = visionOSTestbedTests; -+ sourceTree = ""; -+ }; -+ 607A664F2B0EFFE00010BFC8 /* Frameworks */ = { -+ isa = PBXGroup; -+ children = ( -+ ); -+ name = Frameworks; -+ sourceTree = ""; -+ }; -+/* End PBXGroup section */ ++def visionos_ver(system="", release="", model="", is_simulator=False): ++ """Get visionOS version information, and return it as a namedtuple: ++ (system, release, model, is_simulator). + -+/* Begin PBXNativeTarget section */ -+ 607A66112B0EFA380010BFC8 /* visionOSTestbed */ = { -+ isa = PBXNativeTarget; -+ buildConfigurationList = 607A66412B0EFA3A0010BFC8 /* Build configuration list for PBXNativeTarget "visionOSTestbed" */; -+ buildPhases = ( -+ 607A660E2B0EFA380010BFC8 /* Sources */, -+ 607A660F2B0EFA380010BFC8 /* Frameworks */, -+ 607A66102B0EFA380010BFC8 /* Resources */, -+ 607A66552B0F061D0010BFC8 /* Install Target Specific Python Standard Library */, -+ 607A66562B0F06200010BFC8 /* Prepare Python Binary Modules */, -+ 607A664E2B0EFC080010BFC8 /* Embed Frameworks */, -+ ); -+ buildRules = ( -+ ); -+ dependencies = ( -+ ); -+ name = visionOSTestbed; -+ productName = iOSTestbed; -+ productReference = 607A66122B0EFA380010BFC8 /* visionOSTestbed.app */; -+ productType = "com.apple.product-type.application"; -+ }; -+ 607A662C2B0EFA3A0010BFC8 /* visionOSTestbedTests */ = { -+ isa = PBXNativeTarget; -+ buildConfigurationList = 607A66442B0EFA3A0010BFC8 /* Build configuration list for PBXNativeTarget "visionOSTestbedTests" */; -+ buildPhases = ( -+ 607A66292B0EFA3A0010BFC8 /* Sources */, -+ 607A662A2B0EFA3A0010BFC8 /* Frameworks */, -+ 607A662B2B0EFA3A0010BFC8 /* Resources */, -+ 607A66522B0EFFE00010BFC8 /* Embed Frameworks */, -+ ); -+ buildRules = ( -+ ); -+ dependencies = ( -+ 607A662F2B0EFA3A0010BFC8 /* PBXTargetDependency */, -+ ); -+ name = visionOSTestbedTests; -+ productName = iOSTestbedTests; -+ productReference = 607A662D2B0EFA3A0010BFC8 /* visionOSTestbedTests.xctest */; -+ productType = "com.apple.product-type.bundle.unit-test"; -+ }; -+/* End PBXNativeTarget section */ ++ If values can't be determined, they are set to values provided as ++ parameters. ++ """ ++ if sys.platform == "visionos": ++ # TODO: Can the iOS implementation be used here? ++ import _ios_support ++ result = _ios_support.get_platform_ios() ++ if result is not None: ++ return VisionOSVersionInfo(*result) + -+/* 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; -+ productRefGroup = 607A66132B0EFA380010BFC8 /* Products */; -+ projectDirPath = ""; -+ projectRoot = ""; -+ targets = ( -+ 607A66112B0EFA380010BFC8 /* visionOSTestbed */, -+ 607A662C2B0EFA3A0010BFC8 /* visionOSTestbedTests */, -+ ); -+ }; -+/* End PBXProject section */ ++ return VisionOSVersionInfo(system, release, model, is_simulator) + -+/* Begin PBXResourcesBuildPhase section */ -+ 607A66102B0EFA380010BFC8 /* Resources */ = { -+ isa = PBXResourcesBuildPhase; -+ buildActionMask = 2147483647; -+ files = ( -+ 607A66582B0F079F0010BFC8 /* dylib-Info-template.plist in Resources */, -+ 608619562CB7819B00F46182 /* app in Resources */, -+ 607A66222B0EFA390010BFC8 /* Assets.xcassets in Resources */, -+ 608619542CB77BA900F46182 /* app_packages in Resources */, -+ ); -+ runOnlyForDeploymentPostprocessing = 0; -+ }; -+ 607A662B2B0EFA3A0010BFC8 /* Resources */ = { -+ isa = PBXResourcesBuildPhase; -+ buildActionMask = 2147483647; -+ files = ( -+ ); -+ runOnlyForDeploymentPostprocessing = 0; -+ }; -+/* End PBXResourcesBuildPhase section */ + -+/* Begin PBXShellScriptBuildPhase section */ -+ 607A66552B0F061D0010BFC8 /* Install Target Specific Python Standard Library */ = { -+ isa = PBXShellScriptBuildPhase; -+ alwaysOutOfDate = 1; -+ buildActionMask = 2147483647; -+ files = ( -+ ); -+ inputFileListPaths = ( -+ ); -+ inputPaths = ( -+ ); -+ name = "Install Target Specific Python Standard Library"; -+ outputFileListPaths = ( -+ ); -+ outputPaths = ( -+ ); -+ runOnlyForDeploymentPostprocessing = 0; -+ shellPath = /bin/sh; -+ shellScript = "set -e\n\nmkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-xrsimulator\" ]; then\n echo \"Installing Python modules for xrOS Simulator\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/xros-arm64-simulator/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nelse\n echo \"Installing Python modules for xrOS Device\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/xros-arm64/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nfi\n"; -+ showEnvVarsInLog = 0; -+ }; -+ 607A66562B0F06200010BFC8 /* Prepare Python Binary Modules */ = { -+ isa = PBXShellScriptBuildPhase; -+ alwaysOutOfDate = 1; -+ buildActionMask = 2147483647; -+ files = ( -+ ); -+ inputFileListPaths = ( -+ ); -+ inputPaths = ( -+ ); -+ name = "Prepare Python Binary Modules"; -+ outputFileListPaths = ( -+ ); -+ outputPaths = ( -+ ); -+ runOnlyForDeploymentPostprocessing = 0; -+ shellPath = /bin/sh; -+ shellScript = "set -e\n\ninstall_dylib () {\n INSTALL_BASE=$1\n FULL_EXT=$2\n\n # The name of the extension file\n EXT=$(basename \"$FULL_EXT\")\n # The location of the extension file, relative to the bundle\n RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/} \n # The path to the extension file, relative to the install base\n PYTHON_EXT=${RELATIVE_EXT/$INSTALL_BASE/}\n # The full dotted name of the extension module, constructed from the file path.\n FULL_MODULE_NAME=$(echo $PYTHON_EXT | cut -d \".\" -f 1 | tr \"/\" \".\"); \n # A bundle identifier; not actually used, but required by Xcode framework packaging\n FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr \"_\" \"-\")\n # The name of the framework folder.\n FRAMEWORK_FOLDER=\"Frameworks/$FULL_MODULE_NAME.framework\"\n\n # If the framework folder doesn't exist, create it.\n if [ ! -d \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\" ]; then\n echo \"Creating framework for $RELATIVE_EXT\" \n mkdir -p \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\"\n cp \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleExecutable -string \"$FULL_MODULE_NAME\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleIdentifier -string \"$FRAMEWORK_BUNDLE_ID\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n fi\n \n echo \"Installing binary for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" \n mv \"$FULL_EXT\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\"\n # Create a placeholder .fwork file where the .so was\n echo \"$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" > ${FULL_EXT%.so}.fwork\n # Create a back reference to the .so file location in the framework\n echo \"${RELATIVE_EXT%.so}.fwork\" > \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin\" \n}\n\nPYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/python/lib\")\necho \"Install Python $PYTHON_VER standard library extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/python/lib/$PYTHON_VER/lib-dynload\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib python/lib/$PYTHON_VER/lib-dynload/ \"$FULL_EXT\"\ndone\necho \"Install app package extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/app_packages\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app_packages/ \"$FULL_EXT\"\ndone\necho \"Install app extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/app\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app/ \"$FULL_EXT\"\ndone\n\n# Clean up dylib template \nrm -f \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\"\necho \"Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)...\"\nfind \"$CODESIGNING_FOLDER_PATH/Frameworks\" -name \"*.framework\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der \"{}\" \\; \n"; -+ showEnvVarsInLog = 0; -+ }; -+/* End PBXShellScriptBuildPhase section */ + def _java_getprop(name, default): + """This private helper is deprecated in 3.13 and will be removed in 3.15""" + from java.lang import System +@@ -738,7 +810,7 @@ + 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 + +@@ -902,14 +974,30 @@ + 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' + -+/* Begin PBXSourcesBuildPhase section */ -+ 607A660E2B0EFA380010BFC8 /* Sources */ = { -+ isa = PBXSourcesBuildPhase; -+ buildActionMask = 2147483647; -+ files = ( -+ 607A66172B0EFA380010BFC8 /* AppDelegate.m in Sources */, -+ 607A66282B0EFA390010BFC8 /* main.m in Sources */, -+ ); -+ runOnlyForDeploymentPostprocessing = 0; -+ }; -+ 607A66292B0EFA3A0010BFC8 /* Sources */ = { -+ isa = PBXSourcesBuildPhase; -+ buildActionMask = 2147483647; -+ files = ( -+ 607A66322B0EFA3A0010BFC8 /* visionOSTestbedTests.m in Sources */, -+ ); -+ runOnlyForDeploymentPostprocessing = 0; -+ }; -+/* End PBXSourcesBuildPhase section */ ++ 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` +@@ -1069,9 +1157,15 @@ + system = 'Android' + release = android_ver().release + +- # Normalize responses on iOS ++ # Normalize responses on Apple mobile platforms + if sys.platform == 'ios': + system, release, _, _ = ios_ver() ++ if sys.platform == 'tvos': ++ system, release, _, _ = tvos_ver() ++ if sys.platform == 'visionos': ++ system, release, _, _ = visionos_ver() ++ if sys.platform == 'watchos': ++ system, release, _, _ = watchos_ver() + + vals = system, node, release, version, machine + # Replace 'unknown' values with the more portable '' +@@ -1361,6 +1455,12 @@ + # macOS and iOS both report as a "Darwin" kernel + if sys.platform == "ios": + system, release, _, _ = ios_ver() ++ elif sys.platform == "tvos": ++ system, release, _, _ = tvos_ver() ++ elif sys.platform == "visionos": ++ system, release, _, _ = visionos_ver() ++ elif sys.platform == "watchos": ++ system, release, _, _ = watchos_ver() + else: + macos_release = mac_ver()[0] + if macos_release: +diff --git a/Lib/site.py b/Lib/site.py +index f9327197159..74899abecb0 100644 +--- a/Lib/site.py ++++ b/Lib/site.py +@@ -298,8 +298,8 @@ + 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 54c2eb515b6..e02063aefea 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 2ecbff222fe..542d3f21cae 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 @@ + # 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): +@@ -734,6 +737,18 @@ + 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", "4.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 1c1cbd03d02..1378985de4a 100644 +--- a/Lib/test/datetimetester.py ++++ b/Lib/test/datetimetester.py +@@ -7159,9 +7159,9 @@ + 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/support/__init__.py b/Lib/test/support/__init__.py +index 88f61103512..4b44e03319c 100644 +--- a/Lib/test/support/__init__.py ++++ b/Lib/test/support/__init__.py +@@ -573,7 +573,7 @@ + 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 +@@ -592,7 +592,7 @@ + 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 a32d5d81d2b..f9421619e98 100644 +--- a/Lib/test/test__interpreters.py ++++ b/Lib/test/test__interpreters.py +@@ -612,6 +612,7 @@ + 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 15603dc3d77..bff6c0fb95f 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 187a3d54809..3c6195bea69 100644 +--- a/Lib/test/test_platform.py ++++ b/Lib/test/test_platform.py +@@ -271,13 +271,21 @@ + 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"}) +- self.assertEqual(res.release, platform.ios_ver().release) ++ 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) ++ # Use the platform-specific version method ++ platform_ver = getattr(platform, f"{sys.platform}_ver") ++ self.assertEqual(res.release, platform_ver().release) + else: + self.assertEqual(res.system, "") + self.assertEqual(res.release, "") +diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py +index 4c3ea1cd8df..04a210e5c86 100644 +--- a/Lib/test/test_webbrowser.py ++++ b/Lib/test/test_webbrowser.py +@@ -236,7 +236,8 @@ + 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 f2e2394089d..2efbbfb0014 100644 +--- a/Lib/webbrowser.py ++++ b/Lib/webbrowser.py +@@ -488,7 +488,8 @@ + # 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": +@@ -653,9 +654,10 @@ + 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 ba039794c88..19a332ffdcb 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -209,6 +209,12 @@ + # the build, and is only listed here so it will be included in sysconfigdata. + IPHONEOS_DEPLOYMENT_TARGET=@IPHONEOS_DEPLOYMENT_TARGET@ + ++# 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 + -+/* 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.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.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.framework/Headers\""; -+ IPHONEOS_DEPLOYMENT_TARGET = 12.0; -+ MARKETING_VERSION = 1.0; -+ PRODUCT_BUNDLE_IDENTIFIER = org.python.visionOSTestbedTests; -+ 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.framework/Headers\""; -+ IPHONEOS_DEPLOYMENT_TARGET = 12.0; -+ MARKETING_VERSION = 1.0; -+ PRODUCT_BUNDLE_IDENTIFIER = org.python.visionOSTestbedTests; -+ 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 */ + # Option to install to strip binaries + STRIPFLAG=-s + +diff --git a/Misc/platform_triplet.c b/Misc/platform_triplet.c +index f5cd73bdea8..6c1863c943b 100644 +--- a/Misc/platform_triplet.c ++++ b/Misc/platform_triplet.c +@@ -257,6 +257,32 @@ + # 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/config.sub b/config.sub +index 1bb6a05dc11..49febd56a37 100755 +--- a/config.sub ++++ b/config.sub +@@ -1743,7 +1743,7 @@ + | 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 @@ + ;; + *-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 d31c24dffa2..b177687b0bc 100755 +--- a/configure ++++ b/configure +@@ -982,6 +982,10 @@ + 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 +@@ -4116,6 +4120,15 @@ + *-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 + ;; +@@ -4197,7 +4210,7 @@ + # On cross-compile builds, configure will look for a host-specific compiler by + # prepending the user-provided host triple to the required binary name. + # +-# 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 +@@ -4212,6 +4225,17 @@ + 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 ;; + -+/* 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 "visionOSTestbedTests" */ = { -+ isa = XCConfigurationList; -+ buildConfigurations = ( -+ 607A66452B0EFA3A0010BFC8 /* Debug */, -+ 607A66462B0EFA3A0010BFC8 /* Release */, -+ ); -+ defaultConfigurationIsVisible = 0; -+ defaultConfigurationName = Release; -+ }; -+/* End XCConfigurationList section */ -+ }; -+ rootObject = 607A660A2B0EFA380010BFC8 /* Project object */; -+} ---- /dev/null -+++ b/visionOS/testbed/visionOSTestbed/AppDelegate.h -@@ -0,0 +1,11 @@ -+// -+// AppDelegate.h -+// visionOSTestbed -+// ++ 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 ;; + -+#import ++ aarch64-apple-xros*-simulator) AR=arm64-apple-xros-simulator-ar ;; ++ aarch64-apple-xros*) AR=arm64-apple-xros-ar ;; + -+@interface AppDelegate : UIResponder ++ 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 +@@ -4220,6 +4244,17 @@ + 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 ;; + -+@end ---- /dev/null -+++ b/visionOS/testbed/visionOSTestbed/AppDelegate.m -@@ -0,0 +1,19 @@ -+// -+// AppDelegate.m -+// visionOSTestbed -+// ++ aarch64-apple-xros*-simulator) CC=arm64-apple-xros-simulator-clang ;; ++ aarch64-apple-xros*) CC=arm64-apple-xros-clang ;; + -+#import "AppDelegate.h" ++ 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 +@@ -4228,6 +4263,17 @@ + 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 ;; + -+@interface AppDelegate () ++ 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 ;; + -+@end ++ aarch64-apple-xros*-simulator) CPP=arm64-apple-xros-simulator-cpp ;; ++ aarch64-apple-xros*) CPP=arm64-apple-xros-cpp ;; + -+@implementation AppDelegate ++ 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 +@@ -4236,6 +4282,17 @@ + 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++ ;; + -+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { -+ return YES; -+} ++ aarch64-apple-xros*-simulator) CXX=arm64-apple-xros-simulator-clang++ ;; ++ aarch64-apple-xros*) CXX=arm64-apple-xros-clang++ ;; + -+@end ---- /dev/null -+++ b/visionOS/testbed/visionOSTestbed/Assets.xcassets/AccentColor.colorset/Contents.json -@@ -0,0 +1,11 @@ -+{ -+ "colors" : [ -+ { -+ "idiom" : "universal" -+ } -+ ], -+ "info" : { -+ "author" : "xcode", -+ "version" : 1 -+ } -+} ---- /dev/null -+++ b/visionOS/testbed/visionOSTestbed/Assets.xcassets/AppIcon.appiconset/Contents.json -@@ -0,0 +1,13 @@ -+{ -+ "images" : [ -+ { -+ "idiom" : "universal", -+ "platform" : "ios", -+ "size" : "1024x1024" -+ } -+ ], -+ "info" : { -+ "author" : "xcode", -+ "version" : 1 -+ } -+} ---- /dev/null -+++ b/visionOS/testbed/visionOSTestbed/Assets.xcassets/Contents.json -@@ -0,0 +1,6 @@ -+{ -+ "info" : { -+ "author" : "xcode", -+ "version" : 1 -+ } -+} ---- /dev/null -+++ b/visionOS/testbed/visionOSTestbed/app/README -@@ -0,0 +1,7 @@ -+This folder can contain any Python application code. ++ 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 +@@ -4358,8 +4415,11 @@ + case $enableval in + yes) + case $ac_sys_system in +- Darwin) enableval=/Library/Frameworks ;; +- iOS) enableval=Apple/iOS/Frameworks/\$\(MULTIARCH\) ;; ++ Darwin) enableval=/Library/Frameworks ;; ++ iOS) enableval=Apple/iOS/Frameworks/\$\(MULTIARCH\) ;; ++ tvOS) enableval=Apple/tvOS/Frameworks/\$\(MULTIARCH\) ;; ++ visionOS) enableval=Apple/visionOS/Frameworks/\$\(MULTIARCH\) ;; ++ watchOS) enableval=Apple/watchOS/Frameworks/\$\(MULTIARCH\) ;; + *) as_fn_error $? "Unknown platform for framework build" "$LINENO" 5 + esac + esac +@@ -4368,6 +4428,9 @@ + no) + case $ac_sys_system in + iOS) as_fn_error $? "iOS builds must use --enable-framework" "$LINENO" 5 ;; ++ tvOS) as_fn_error $? "tvOS builds must use --enable-framework" "$LINENO" 5 ;; ++ visionOS) as_fn_error $? "visionOS builds must use --enable-framework" "$LINENO" 5 ;; ++ watchOS) as_fn_error $? "watchOS builds must use --enable-framework" "$LINENO" 5 ;; + *) + PYTHONFRAMEWORK= + PYTHONFRAMEWORKDIR=no-framework +@@ -4474,6 +4537,51 @@ + + ac_config_files="$ac_config_files Apple/iOS/Resources/Info.plist" + ++ ;; ++ tvOS) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" + -+During the build, any binary modules found in this folder will be processed into -+iOS Framework form. ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=Apple/tvOS/Resources + -+When the test suite runs, this folder will be on the PYTHONPATH, and will be the -+working directory for the test suite. ---- /dev/null -+++ b/visionOS/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. ++ ac_config_files="$ac_config_files Apple/tvOS/Resources/Info.plist" + -+During the build, any binary modules found in this folder will be processed into -+iOS Framework form. ++ ;; ++ visionOS) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" + -+When the test suite runs, this folder will be on the PYTHONPATH. ---- /dev/null -+++ b/visionOS/testbed/visionOSTestbed/dylib-Info-template.plist -@@ -0,0 +1,30 @@ -+ -+ -+ -+ -+ CFBundleDevelopmentRegion -+ en -+ CFBundleInfoDictionaryVersion -+ 6.0 -+ CFBundleExecutable -+ -+ CFBundleIdentifier -+ -+ CFBundlePackageType -+ FMWK -+ CFBundleShortVersionString -+ 1.0 -+ CFBundleSupportedPlatforms -+ -+ XROS -+ -+ CFBundleVersion -+ 1 -+ MinimumOSVersion -+ 2.0 -+ UIDeviceFamily -+ -+ 7 -+ -+ -+ ---- /dev/null -+++ b/visionOS/testbed/visionOSTestbed/main.m -@@ -0,0 +1,16 @@ -+// -+// main.m -+// visionOSTestbed -+// ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=Apple/visionOS/Resources + -+#import -+#import "AppDelegate.h" ++ ac_config_files="$ac_config_files Apple/visionOS/Resources/Info.plist" + -+int main(int argc, char * argv[]) { -+ NSString * appDelegateClassName; -+ @autoreleasepool { -+ appDelegateClassName = NSStringFromClass([AppDelegate class]); ++ ;; ++ watchOS) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" + -+ return UIApplicationMain(argc, argv, nil, appDelegateClassName); -+ } -+} ---- /dev/null -+++ b/visionOS/testbed/visionOSTestbed/visionOSTestbed-Info.plist -@@ -0,0 +1,56 @@ -+ -+ -+ -+ -+ 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 -+ -+ -+ UIRequiresFullScreen -+ -+ UISupportedInterfaceOrientations -+ -+ UIInterfaceOrientationPortrait -+ UIInterfaceOrientationLandscapeLeft -+ UIInterfaceOrientationLandscapeRight -+ -+ UISupportedInterfaceOrientations~ipad -+ -+ UIInterfaceOrientationPortrait -+ UIInterfaceOrientationPortraitUpsideDown -+ UIInterfaceOrientationLandscapeLeft -+ UIInterfaceOrientationLandscapeRight -+ -+ -+ ---- /dev/null -+++ b/visionOS/testbed/visionOSTestbedTests/visionOSTestbedTests.m -@@ -0,0 +1,162 @@ -+#import -+#import ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=Apple/watchOS/Resources + -+@interface visionOSTestbedTests : XCTestCase ++ ac_config_files="$ac_config_files Apple/watchOS/Resources/Info.plist" + -+@end + ;; + *) + as_fn_error $? "Unknown platform for framework build" "$LINENO" 5 +@@ -4485,6 +4593,9 @@ + e) + case $ac_sys_system in + iOS) as_fn_error $? "iOS builds must use --enable-framework" "$LINENO" 5 ;; ++ tvOS) as_fn_error $? "tvOS builds must use --enable-framework" "$LINENO" 5 ;; ++ visionOS) as_fn_error $? "visionOS builds must use --enable-framework" "$LINENO" 5 ;; ++ watchOS) as_fn_error $? "watchOS builds must use --enable-framework" "$LINENO" 5 ;; + *) + PYTHONFRAMEWORK= + PYTHONFRAMEWORKDIR=no-framework +@@ -4539,8 +4650,8 @@ + 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 ;; +@@ -4558,8 +4669,8 @@ + 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; } +@@ -4577,6 +4688,8 @@ + + + ++EXPORT_XROS_DEPLOYMENT_TARGET='#' + -+@implementation visionOSTestbedTests -+ -+ -+- (void)testPython { -+ const char **argv; -+ int exit_code; -+ int failed; -+ PyStatus status; -+ PyPreConfig preconfig; -+ PyConfig config; -+ PyObject *sys_module; -+ PyObject *sys_path_attr; -+ NSArray *test_args; -+ NSString *python_home; -+ NSString *path; -+ wchar_t *wtmp_str; -+ -+ NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; -+ -+ // Set some other common environment indicators to disable color, as the -+ // Xcode log can't display color. Stdout will report that it is *not* a -+ // TTY. -+ setenv("NO_COLOR", "1", true); -+ setenv("PYTHON_COLORS", "0", true); -+ -+ // Arguments to pass into the test suite runner. -+ // argv[0] must identify the process; any subsequent arg -+ // will be handled as if it were an argument to `python -m test` -+ test_args = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"TestArgs"]; -+ if (test_args == NULL) { -+ NSLog(@"Unable to identify test arguments."); -+ } -+ argv = malloc(sizeof(char *) * ([test_args count] + 1)); -+ argv[0] = "visionOSTestbed"; -+ for (int i = 1; i < [test_args count]; i++) { -+ argv[i] = [[test_args objectAtIndex:i] UTF8String]; -+ } -+ NSLog(@"Test command: %@", test_args); -+ -+ // Generate an isolated Python configuration. -+ NSLog(@"Configuring isolated Python..."); -+ PyPreConfig_InitIsolatedConfig(&preconfig); -+ PyConfig_InitIsolatedConfig(&config); -+ -+ // Configure the Python interpreter: -+ // Enforce UTF-8 encoding for stderr, stdout, file-system encoding and locale. -+ // See https://docs.python.org/3/library/os.html#python-utf-8-mode. -+ preconfig.utf8_mode = 1; -+ // Use the system logger for stdout/err -+ config.use_system_logger = 1; -+ // Don't buffer stdio. We want output to appears in the log immediately -+ config.buffered_stdio = 0; -+ // Don't write bytecode; we can't modify the app bundle -+ // after it has been signed. -+ config.write_bytecode = 0; -+ // Ensure that signal handlers are installed -+ config.install_signal_handlers = 1; -+ // Run the test module. -+ config.run_module = Py_DecodeLocale([[test_args objectAtIndex:0] UTF8String], NULL); -+ // For debugging - enable verbose mode. -+ // config.verbose = 1; -+ -+ NSLog(@"Pre-initializing Python runtime..."); -+ status = Py_PreInitialize(&preconfig); -+ if (PyStatus_Exception(status)) { -+ XCTFail(@"Unable to pre-initialize Python interpreter: %s", status.err_msg); -+ PyConfig_Clear(&config); -+ return; -+ } + + if test "$cross_compiling" = yes; then + case "$host" in +@@ -4614,6 +4727,78 @@ + ;; + esac + ;; ++ *-apple-tvos*) ++ _host_os=`echo $host | cut -d '-' -f3` ++ _host_device=`echo $host | cut -d '-' -f4` ++ _host_device=${_host_device:=os} + -+ // Set the home for the Python interpreter -+ python_home = [NSString stringWithFormat:@"%@/python", resourcePath, nil]; -+ NSLog(@"PythonHome: %@", python_home); -+ wtmp_str = Py_DecodeLocale([python_home UTF8String], NULL); -+ status = PyConfig_SetString(&config, &config.home, wtmp_str); -+ if (PyStatus_Exception(status)) { -+ XCTFail(@"Unable to set PYTHONHOME: %s", status.err_msg); -+ PyConfig_Clear(&config); -+ return; -+ } -+ PyMem_RawFree(wtmp_str); -+ -+ // Read the site config -+ status = PyConfig_Read(&config); -+ if (PyStatus_Exception(status)) { -+ XCTFail(@"Unable to read site config: %s", status.err_msg); -+ PyConfig_Clear(&config); -+ return; -+ } ++ # 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:=4.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*) +@@ -4704,9 +4889,15 @@ + 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) +@@ -4769,7 +4960,14 @@ + 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. + -+ NSLog(@"Configure argc/argv..."); -+ status = PyConfig_SetBytesArgv(&config, [test_args count], (char**) argv); -+ if (PyStatus_Exception(status)) { -+ XCTFail(@"Unable to configure argc/argv: %s", status.err_msg); -+ PyConfig_Clear(&config); -+ return; -+ } + -+ NSLog(@"Initializing Python runtime..."); -+ status = Py_InitializeFromConfig(&config); -+ if (PyStatus_Exception(status)) { -+ XCTFail(@"Unable to initialize Python interpreter: %s", status.err_msg); -+ PyConfig_Clear(&config); -+ return; -+ } + -+ sys_module = PyImport_ImportModule("sys"); -+ if (sys_module == NULL) { -+ XCTFail(@"Could not import sys module"); -+ return; -+ } + -+ sys_path_attr = PyObject_GetAttrString(sys_module, "path"); -+ if (sys_path_attr == NULL) { -+ XCTFail(@"Could not access sys.path"); -+ return; -+ } + -+ // Add the app packages path -+ path = [NSString stringWithFormat:@"%@/app_packages", resourcePath, nil]; -+ NSLog(@"App packages path: %@", path); -+ wtmp_str = Py_DecodeLocale([path UTF8String], NULL); -+ failed = PyList_Insert(sys_path_attr, 0, PyUnicode_FromString([path UTF8String])); -+ if (failed) { -+ XCTFail(@"Unable to add app packages to sys.path"); -+ return; -+ } -+ PyMem_RawFree(wtmp_str); -+ -+ path = [NSString stringWithFormat:@"%@/app", resourcePath, nil]; -+ NSLog(@"App path: %@", path); -+ wtmp_str = Py_DecodeLocale([path UTF8String], NULL); -+ failed = PyList_Insert(sys_path_attr, 0, PyUnicode_FromString([path UTF8String])); -+ if (failed) { -+ XCTFail(@"Unable to add app to sys.path"); -+ return; -+ } -+ PyMem_RawFree(wtmp_str); ++# XROS_DEPLOYMENT_TARGET should get exported + + + # checks for alternative programs +@@ -4810,6 +5008,16 @@ + as_fn_append CFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}" + as_fn_append LDFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}" + ;; #( ++ tvOS) : + -+ // Ensure the working directory is the app folder. -+ chdir([path UTF8String]); ++ as_fn_append CFLAGS " -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}" ++ as_fn_append LDFLAGS " -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}" ++ ;; #( ++ watchOS) : + -+ // Start the test suite. Print a separator to differentiate Python startup logs from app logs -+ NSLog(@"---------------------------------------------------------------------------"); ++ as_fn_append CFLAGS " -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}" ++ as_fn_append LDFLAGS " -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}" ++ ;; #( + *) : + ;; + esac +@@ -7179,6 +7387,12 @@ + MULTIARCH="" ;; #( + iOS) : + MULTIARCH="" ;; #( ++ tvOS) : ++ MULTIARCH="" ;; #( ++ visionOS) : ++ MULTIARCH="" ;; #( ++ watchOS) : ++ MULTIARCH="" ;; #( + FreeBSD*) : + MULTIARCH="" ;; #( + *) : +@@ -7199,7 +7413,7 @@ + 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 +@@ -7250,6 +7464,18 @@ + PY_SUPPORT_TIER=3 ;; #( + aarch64-apple-ios*/clang) : + PY_SUPPORT_TIER=3 ;; #( ++ aarch64-apple-tvos*-simulator/clang) : ++ PY_SUPPORT_TIER=3 ;; #( ++ aarch64-apple-tvos*/clang) : ++ PY_SUPPORT_TIER=3 ;; #( ++ aarch64-apple-xros*-simulator/clang) : ++ PY_SUPPORT_TIER=3 ;; #( ++ aarch64-apple-xros*/clang) : ++ PY_SUPPORT_TIER=3 ;; #( ++ aarch64-apple-watchos*-simulator/clang) : ++ PY_SUPPORT_TIER=3 ;; #( ++ arm64_32-apple-watchos*/clang) : ++ PY_SUPPORT_TIER=3 ;; #( + aarch64-*-linux-android/clang) : + PY_SUPPORT_TIER=3 ;; #( + x86_64-*-linux-android/clang) : +@@ -7688,7 +7914,7 @@ + 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;; +@@ -7754,7 +7980,7 @@ + BLDLIBRARY='-L. -lpython$(LDVERSION)' + RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} + ;; +- iOS) ++ iOS|tvOS|visionOS|watchOS) + LDLIBRARY='libpython$(LDVERSION).dylib' + ;; + AIX*) +@@ -13570,7 +13796,7 @@ + BLDSHARED="$LDSHARED" + fi + ;; +- iOS/*) ++ iOS/*|tvOS/*|visionOS/*|watchOS/*) + LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' + LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' + BLDSHARED="$LDSHARED" +@@ -13703,7 +13929,7 @@ + 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 +@@ -13727,7 +13953,7 @@ + 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 "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' + fi + ;; +@@ -15504,7 +15730,7 @@ + + ctypes_malloc_closure=yes + ;; #( +- iOS) : ++ iOS|tvOS|visionOS|watchOS) : + + ctypes_malloc_closure=yes + ;; #( +@@ -19256,12 +19482,6 @@ + then : + printf "%s\n" "#define HAVE_DUP3 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 +@@ -19322,18 +19542,6 @@ + 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 +@@ -19766,24 +19974,6 @@ + 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 +@@ -20102,12 +20292,6 @@ + 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 +@@ -20376,11 +20560,11 @@ + + 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. +-if test "$ac_sys_system" != "iOS" ; then ++if test "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "visionOS" -a "$ac_sys_system" != "watchOS" ; then + ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy" + if test "x$ac_cv_func_getentropy" = xyes + then : +@@ -20402,6 +20586,53 @@ + + fi + ++# 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 + -+ exit_code = Py_RunMain(); -+ XCTAssertEqual(exit_code, 0, @"Test suite did not pass"); ++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 + -+ NSLog(@"---------------------------------------------------------------------------"); ++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 + -+ Py_Finalize(); -+} ++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 + -+@end ---- /dev/null -+++ b/watchOS/README.rst -@@ -0,0 +1,108 @@ -+======================== -+Python on watchOS README -+======================== ++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 + -+:Authors: -+ Russell Keith-Magee (2023-11) ++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 + -+This document provides a quick overview of some watchOS specific features in the -+Python distribution. ++fi + -+Compilers for building on watchOS -+================================= ++fi + -+Building for watchOS requires the use of Apple's Xcode tooling. It is strongly -+recommended that you use the most recent stable release of Xcode, on the -+most recently released macOS. + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 + printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } + if test ${ac_cv_c_undeclared_builtin_options+y} +@@ -23873,7 +24104,8 @@ + + + # 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 : +@@ -23987,7 +24219,7 @@ + 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 : +@@ -24170,6 +24402,7 @@ + fi + + done ++fi + + # check for long file support functions + ac_fn_c_check_func "$LINENO" "fseek64" "ac_cv_func_fseek64" +@@ -24435,10 +24668,10 @@ + + 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 +@@ -24755,7 +24988,7 @@ + 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" +@@ -26777,8 +27010,8 @@ + LIBPYTHON="\$(BLDLIBRARY)" + fi + +-# On iOS the shared libraries must be linked with the Python framework +-if test "$ac_sys_system" = "iOS"; then ++# On iOS/tvOS/watchOS the shared libraries must be linked with the Python framework ++if test "$ac_sys_system" = "iOS" -o $ac_sys_system = "tvOS" -o $ac_sys_system = "visionOS" -o $ac_sys_system = "watchOS"; then + MODULE_DEPS_SHARED="$MODULE_DEPS_SHARED \$(PYTHONFRAMEWORKDIR)/\$(PYTHONFRAMEWORK)" + fi + +@@ -29648,7 +29881,7 @@ + { 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 +@@ -30155,7 +30388,7 @@ + with_ensurepip=no ;; #( + WASI) : + with_ensurepip=no ;; #( +- iOS) : ++ iOS|tvOS|visionOS|watchOS) : + with_ensurepip=no ;; #( + *) : + with_ensurepip=upgrade +@@ -31105,6 +31338,9 @@ + 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 + *) _PYTHREAD_NAME_MAXLEN=;; +@@ -31136,7 +31372,7 @@ + ;; #( + Darwin) : + ;; #( +- iOS) : ++ iOS|tvOS|visionOS|watchOS) : + + + +@@ -35304,6 +35540,9 @@ + "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" ;; + "Apple/iOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES Apple/iOS/Resources/Info.plist" ;; ++ "Apple/tvOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES Apple/tvOS/Resources/Info.plist" ;; ++ "Apple/visionOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES Apple/visionOS/Resources/Info.plist" ;; ++ "Apple/watchOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES 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 af7a9623d7b..4cf79576a55 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -330,6 +330,15 @@ + *-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 + ;; +@@ -405,7 +414,7 @@ + # On cross-compile builds, configure will look for a host-specific compiler by + # prepending the user-provided host triple to the required binary name. + # +-# 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 +@@ -420,6 +429,17 @@ + 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 ;; + -+watchOS specific arguments to configure -+======================================= ++ 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 ;; + -+* ``--enable-framework[=DIR]`` ++ aarch64-apple-xros*-simulator) AR=arm64-apple-xros-simulator-ar ;; ++ aarch64-apple-xros*) AR=arm64-apple-xros-ar ;; + -+ This argument specifies the location where the Python.framework will -+ be installed. ++ 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 +@@ -428,6 +448,17 @@ + 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 ;; + -+* ``--with-framework-name=NAME`` ++ 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 ;; + -+ Specify the name for the python framework, defaults to ``Python``. ++ 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 +@@ -436,6 +467,17 @@ + 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 ;; + -+Building and using Python on watchOS -+==================================== ++ 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 ;; + -+ABIs and Architectures -+---------------------- ++ aarch64-apple-xros*-simulator) CPP=arm64-apple-xros-simulator-cpp ;; ++ aarch64-apple-xros*) CPP=arm64-apple-xros-cpp ;; + -+watchOS apps can be deployed on physical devices, and on the watchOS simulator. -+Although the API used on these devices is identical, the ABI is different - you -+need to link against different libraries for an watchOS device build -+(``watchos``) or an watchOS simulator build (``watchsimulator``). Apple uses the -+XCframework format to allow specifying a single dependency that supports -+multiple ABIs. An XCframework is a wrapper around multiple ABI-specific -+frameworks. ++ 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 +@@ -444,6 +486,17 @@ + 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++ ;; + -+watchOS can also support different CPU architectures within each ABI. At present, -+there is only a single support ed architecture on physical devices - ARM64. -+However, the *simulator* supports 2 architectures - ARM64 (for running on Apple -+Silicon machines), and x86_64 (for running on older Intel-based machines.) ++ 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++ ;; + -+To support multiple CPU architectures on a single platform, Apple uses a "fat -+binary" format - a single physical file that contains support for multiple -+architectures. ++ aarch64-apple-xros*-simulator) CXX=arm64-apple-xros-simulator-clang++ ;; ++ aarch64-apple-xros*) CXX=arm64-apple-xros-clang++ ;; + -+How do I build Python for watchOS? -+------------------------------- ++ 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 +@@ -558,8 +611,11 @@ + case $enableval in + yes) + case $ac_sys_system in +- Darwin) enableval=/Library/Frameworks ;; +- iOS) enableval=Apple/iOS/Frameworks/\$\(MULTIARCH\) ;; ++ Darwin) enableval=/Library/Frameworks ;; ++ iOS) enableval=Apple/iOS/Frameworks/\$\(MULTIARCH\) ;; ++ tvOS) enableval=Apple/tvOS/Frameworks/\$\(MULTIARCH\) ;; ++ visionOS) enableval=Apple/visionOS/Frameworks/\$\(MULTIARCH\) ;; ++ watchOS) enableval=Apple/watchOS/Frameworks/\$\(MULTIARCH\) ;; + *) AC_MSG_ERROR([Unknown platform for framework build]) + esac + esac +@@ -568,6 +624,9 @@ + no) + case $ac_sys_system in + iOS) AC_MSG_ERROR([iOS builds must use --enable-framework]) ;; ++ tvOS) AC_MSG_ERROR([tvOS builds must use --enable-framework]) ;; ++ visionOS) AC_MSG_ERROR([visionOS builds must use --enable-framework]) ;; ++ watchOS) AC_MSG_ERROR([watchOS builds must use --enable-framework]) ;; + *) + PYTHONFRAMEWORK= + PYTHONFRAMEWORKDIR=no-framework +@@ -670,6 +729,48 @@ + + AC_CONFIG_FILES([Apple/iOS/Resources/Info.plist]) + ;; ++ tvOS) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" + -+The Python build system will build a ``Python.framework`` that supports a -+*single* ABI with a *single* architecture. If you want to use Python in an watchOS -+project, you need to: ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=Apple/tvOS/Resources + -+1. Produce multiple ``Python.framework`` builds, one for each ABI and architecture; -+2. Merge the binaries for each architecture on a given ABI into a single "fat" binary; -+3. Merge the "fat" frameworks for each ABI into a single XCframework. ++ AC_CONFIG_FILES([Apple/tvOS/Resources/Info.plist]) ++ ;; ++ visionOS) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" + -+watchOS builds of Python *must* be constructed as framework builds. To support this, -+you must provide the ``--enable-framework`` flag when configuring the build. ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=Apple/visionOS/Resources + -+The build also requires the use of cross-compilation. The commands for building -+Python for watchOS will look somethign like:: ++ AC_CONFIG_FILES([Apple/visionOS/Resources/Info.plist]) ++ ;; ++ watchOS) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" + -+ $ ./configure \ -+ --enable-framework=/path/to/install \ -+ --host=aarch64-apple-watchos \ -+ --build=aarch64-apple-darwin \ -+ --with-build-python=/path/to/python.exe -+ $ make -+ $ make install ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=Apple/watchOS/Resources + -+In this invocation: ++ AC_CONFIG_FILES([Apple/watchOS/Resources/Info.plist]) ++ ;; + *) + AC_MSG_ERROR([Unknown platform for framework build]) + ;; +@@ -678,6 +779,9 @@ + ],[ + case $ac_sys_system in + iOS) AC_MSG_ERROR([iOS builds must use --enable-framework]) ;; ++ tvOS) AC_MSG_ERROR([tvOS builds must use --enable-framework]) ;; ++ visionOS) AC_MSG_ERROR([visionOS builds must use --enable-framework]) ;; ++ watchOS) AC_MSG_ERROR([watchOS builds must use --enable-framework]) ;; + *) + PYTHONFRAMEWORK= + PYTHONFRAMEWORKDIR=no-framework +@@ -730,8 +834,8 @@ + 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]) ;; +@@ -745,8 +849,8 @@ + 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]) + ;; +@@ -759,6 +863,8 @@ + ]) + AC_SUBST([APP_STORE_COMPLIANCE_PATCH]) + ++EXPORT_XROS_DEPLOYMENT_TARGET='#' + -+* ``/path/to/install`` is the location where the final Python.framework will be -+ output. + AC_SUBST([_PYTHON_HOST_PLATFORM]) + if test "$cross_compiling" = yes; then + case "$host" in +@@ -794,6 +900,70 @@ + ;; + esac + ;; ++ *-apple-tvos*) ++ _host_os=`echo $host | cut -d '-' -f3` ++ _host_device=`echo $host | cut -d '-' -f4` ++ _host_device=${_host_device:=os} + -+* ``--host`` is the architecture and ABI that you want to build, in GNU compiler -+ triple format. This will be one of: ++ # 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]) + -+ - ``arm64_32-apple-watchos`` for ARM64-32 watchOS devices. -+ - ``aarch64-apple-watchos-simulator`` for the watchOS simulator running on Apple -+ Silicon devices. -+ - ``x86_64-apple-watchos-simulator`` for the watchOS simulator running on Intel -+ devices. ++ 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} + -+* ``--build`` is the GNU compiler triple for the machine that will be running -+ the compiler. This is one of: ++ # 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]) + -+ - ``aarch64-apple-darwin`` for Apple Silicon devices. -+ - ``x86_64-apple-darwin`` for Intel devices. ++ 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} + -+* ``/path/to/python.exe`` is the path to a Python binary on the machine that -+ will be running the compiler. This is needed because the Python compilation -+ process involves running some Python code. On a normal desktop build of -+ Python, you can compile a python interpreter and then use that interpreter to -+ run Python code. However, the binaries produced for watchOS won't run on macOS, so -+ you need to provide an external Python interpreter. This interpreter must be -+ the version as the Python that is being compiled. ++ # 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:=4.0} ++ AC_MSG_RESULT([$WATCHOS_DEPLOYMENT_TARGET]) + -+Using a framework-based Python on watchOS -+====================================== ---- /dev/null -+++ b/watchOS/Resources/Info.plist.in -@@ -0,0 +1,34 @@ -+ -+ -+ -+ -+ CFBundleDevelopmentRegion -+ en -+ CFBundleExecutable -+ Python -+ CFBundleGetInfoString -+ Python Runtime and Library -+ CFBundleIdentifier -+ @PYTHONFRAMEWORKIDENTIFIER@ -+ CFBundleInfoDictionaryVersion -+ 6.0 -+ CFBundleName -+ Python -+ CFBundlePackageType -+ FMWK -+ CFBundleShortVersionString -+ %VERSION% -+ CFBundleLongVersionString -+ %VERSION%, (c) 2001-2023 Python Software Foundation. -+ CFBundleSignature -+ ???? -+ CFBundleVersion -+ %VERSION% -+ CFBundleSupportedPlatforms -+ -+ watchOS -+ -+ MinimumOSVersion -+ @WATCHOS_DEPLOYMENT_TARGET@ -+ -+ ---- /dev/null -+++ b/watchOS/Resources/bin/arm64-apple-watchos-simulator-ar -@@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} ar "$@" ---- /dev/null -+++ b/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang -@@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target arm64-apple-watchos-simulator "$@" ---- /dev/null -+++ b/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang++ -@@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang++ -target arm64-apple-watchos-simulator "$@" ---- /dev/null -+++ b/watchOS/Resources/bin/arm64-apple-watchos-simulator-cpp -@@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator clang -target arm64-apple-watchos-simulator -E "$@" ---- /dev/null -+++ b/watchOS/Resources/bin/arm64_32-apple-watchos-ar -@@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchos${WATCHOS_SDK_VERSION} ar "$@" ---- /dev/null -+++ b/watchOS/Resources/bin/arm64_32-apple-watchos-clang -@@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang -target arm64_32-apple-watchos "$@" ---- /dev/null -+++ b/watchOS/Resources/bin/arm64_32-apple-watchos-clang++ -@@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang++ -target arm64_32-apple-watchos "$@" ---- /dev/null -+++ b/watchOS/Resources/bin/arm64_32-apple-watchos-cpp -@@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang -target arm64_32-apple-watchos -E "$@" ---- /dev/null -+++ b/watchOS/Resources/bin/x86_64-apple-watchos-simulator-ar -@@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} ar "$@" ---- /dev/null -+++ b/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang -@@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target x86_64-apple-watchos-simulator "$@" ---- /dev/null -+++ b/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang++ -@@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang++ -target x86_64-apple-watchos-simulator "$@" ---- /dev/null -+++ b/watchOS/Resources/bin/x86_64-apple-watchos-simulator-cpp -@@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target x86_64-apple-watchos-simulator -E "$@" ---- /dev/null -+++ b/watchOS/Resources/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 -+ -+ ---- /dev/null -+++ b/watchOS/Resources/pyconfig.h -@@ -0,0 +1,11 @@ -+#ifdef __arm64__ -+# ifdef __LP64__ -+#include "pyconfig-arm64.h" -+# else -+#include "pyconfig-arm64_32.h" -+# endif -+#endif ++ 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*) +@@ -883,9 +1053,15 @@ + 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) +@@ -944,8 +1120,15 @@ + 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]) + -+#ifdef __x86_64__ -+#include "pyconfig-x86_64.h" -+#endif ++# XROS_DEPLOYMENT_TARGET should get exported ++AC_SUBST([EXPORT_XROS_DEPLOYMENT_TARGET]) + + # checks for alternative programs + +@@ -979,11 +1162,19 @@ + ], + ) + +-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([$ac_sys_system], + [iOS], [ + AS_VAR_APPEND([CFLAGS], [" -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"]) + AS_VAR_APPEND([LDFLAGS], [" -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"]) ++ ],[tvOS], [ ++ AS_VAR_APPEND([CFLAGS], [" -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"]) ++ AS_VAR_APPEND([LDFLAGS], [" -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"]) ++ ],[watchOS], [ ++ AS_VAR_APPEND([CFLAGS], [" -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"]) ++ AS_VAR_APPEND([LDFLAGS], [" -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"]) + ], + ) + +@@ -1172,6 +1363,9 @@ + AS_CASE([$ac_sys_system], + [Darwin*], [MULTIARCH=""], + [iOS], [MULTIARCH=""], ++ [tvOS], [MULTIARCH=""], ++ [visionOS], [MULTIARCH=""], ++ [watchOS], [MULTIARCH=""], + [FreeBSD*], [MULTIARCH=""], + [MULTIARCH=$($CC --print-multiarch 2>/dev/null)] + ) +@@ -1193,7 +1387,7 @@ + dnl use a single "fat" binary at runtime. SOABI_PLATFORM is the component of + dnl the PLATFORM_TRIPLET that will be used in binary module extensions. + AS_CASE([$ac_sys_system], +- [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] + ) + +@@ -1220,16 +1414,22 @@ + [wasm32-unknown-wasip1/clang], [PY_SUPPORT_TIER=2], dnl WebAssembly System Interface preview1, clang + [x86_64-*-linux-gnu/clang], [PY_SUPPORT_TIER=2], dnl Linux on AMD64, any vendor, glibc, clang + +- [aarch64-pc-windows-msvc/msvc], [PY_SUPPORT_TIER=3], dnl Windows ARM64, MSVC +- [armv7l-*-linux-gnueabihf/gcc], [PY_SUPPORT_TIER=3], dnl ARMv7 LE with hardware floats, any vendor, glibc, gcc +- [powerpc64le-*-linux-gnu/clang], [PY_SUPPORT_TIER=3], dnl Linux on PPC64 little endian, glibc, clang +- [s390x-*-linux-gnu/gcc], [PY_SUPPORT_TIER=3], dnl Linux on 64bit s390x (big endian), glibc, gcc +- [x86_64-*-freebsd*/clang], [PY_SUPPORT_TIER=3], dnl FreeBSD on AMD64 +- [aarch64-apple-ios*-simulator/clang], [PY_SUPPORT_TIER=3], dnl iOS Simulator on arm64 +- [aarch64-apple-ios*/clang], [PY_SUPPORT_TIER=3], dnl iOS on ARM64 +- [aarch64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on ARM64 +- [x86_64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on AMD64 +- [wasm32-*-emscripten/emcc], [PY_SUPPORT_TIER=3], dnl Emscripten ++ [aarch64-pc-windows-msvc/msvc], [PY_SUPPORT_TIER=3], dnl Windows ARM64, MSVC ++ [armv7l-*-linux-gnueabihf/gcc], [PY_SUPPORT_TIER=3], dnl ARMv7 LE with hardware floats, any vendor, glibc, gcc ++ [powerpc64le-*-linux-gnu/clang], [PY_SUPPORT_TIER=3], dnl Linux on PPC64 little endian, glibc, clang ++ [s390x-*-linux-gnu/gcc], [PY_SUPPORT_TIER=3], dnl Linux on 64bit s390x (big endian), glibc, gcc ++ [x86_64-*-freebsd*/clang], [PY_SUPPORT_TIER=3], dnl FreeBSD on AMD64 ++ [aarch64-apple-ios*-simulator/clang], [PY_SUPPORT_TIER=3], dnl iOS Simulator on arm64 ++ [aarch64-apple-ios*/clang], [PY_SUPPORT_TIER=3], dnl iOS on ARM64 ++ [aarch64-apple-tvos*-simulator/clang], [PY_SUPPORT_TIER=3], dnl tvOS Simulator on arm64 ++ [aarch64-apple-tvos*/clang], [PY_SUPPORT_TIER=3], dnl tvOS on ARM64 ++ [aarch64-apple-xros*-simulator/clang], [PY_SUPPORT_TIER=3], dnl visionOS Simulator on arm64 ++ [aarch64-apple-xros*/clang], [PY_SUPPORT_TIER=3], dnl visionOS on ARM64 ++ [aarch64-apple-watchos*-simulator/clang], [PY_SUPPORT_TIER=3], dnl watchOS Simulator on arm64 ++ [arm64_32-apple-watchos*/clang], [PY_SUPPORT_TIER=3], dnl watchOS on ARM64 ++ [aarch64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on ARM64 ++ [x86_64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on AMD64 ++ [wasm32-*-emscripten/emcc], [PY_SUPPORT_TIER=3], dnl Emscripten + + [PY_SUPPORT_TIER=0] + ) +@@ -1537,7 +1737,7 @@ + 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]);; +@@ -1602,7 +1802,7 @@ + BLDLIBRARY='-L. -lpython$(LDVERSION)' + RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} + ;; +- iOS) ++ iOS|tvOS|visionOS|watchOS) + LDLIBRARY='libpython$(LDVERSION).dylib' + ;; + AIX*) +@@ -3469,7 +3669,7 @@ + BLDSHARED="$LDSHARED" + fi + ;; +- iOS/*) ++ iOS/*|tvOS/*|visionOS/*|watchOS/*) + LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' + LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' + BLDSHARED="$LDSHARED" +@@ -3593,7 +3793,7 @@ + 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 +@@ -3617,7 +3817,7 @@ + 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 "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' + fi + ;; +@@ -4105,7 +4305,7 @@ + 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"])] +@@ -5214,9 +5414,9 @@ + # checks for library functions + AC_CHECK_FUNCS([ \ + accept4 alarm bind_textdomain_codeset chmod chown clock closefrom close_range confstr \ +- copy_file_range ctermid dladdr dup dup3 execv explicit_bzero explicit_memset \ ++ copy_file_range ctermid dladdr dup dup3 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 getegid geteuid getgid getgrent getgrgid getgrgid_r \ + getgrnam_r getgrouplist gethostname getitimer getloadavg getlogin getlogin_r \ + getpeername getpgid getpid getppid getpriority _getpty \ +@@ -5224,8 +5424,7 @@ + getspnam getuid getwd grantpt if_nameindex initgroups kill killpg lchown linkat \ + lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \ + mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \ +- pipe2 plock poll posix_fadvise posix_fallocate posix_openpt posix_spawn posix_spawnp \ +- posix_spawn_file_actions_addclosefrom_np \ ++ pipe2 plock poll 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 +@@ -5235,7 +5434,7 @@ + sched_setparam sched_setscheduler sem_clockwait sem_getvalue sem_open \ + sem_timedwait sem_unlink sendfile setegid seteuid setgid sethostname \ + setitimer setlocale setpgid setpgrp setpriority setregid setresgid \ +- 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 tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \ +@@ -5250,12 +5449,20 @@ + 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. +-if test "$ac_sys_system" != "iOS" ; then +- AC_CHECK_FUNCS([getentropy getgroups system]) ++if test "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "visionOS" -a "$ac_sys_system" != "watchOS" ; then ++ AC_CHECK_FUNCS([ getentropy getgroups system ]) ++fi ++ ++# 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], +@@ -5550,20 +5757,22 @@ + [@%:@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]) +@@ -5602,10 +5811,10 @@ + ]) + ]) + +-# 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], [ +@@ -5763,7 +5972,7 @@ + [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" +@@ -6356,8 +6565,8 @@ + LIBPYTHON="\$(BLDLIBRARY)" + fi + +-# On iOS the shared libraries must be linked with the Python framework +-if test "$ac_sys_system" = "iOS"; then ++# On iOS/tvOS/watchOS the shared libraries must be linked with the Python framework ++if test "$ac_sys_system" = "iOS" -o $ac_sys_system = "tvOS" -o $ac_sys_system = "visionOS" -o $ac_sys_system = "watchOS"; then + MODULE_DEPS_SHARED="$MODULE_DEPS_SHARED \$(PYTHONFRAMEWORKDIR)/\$(PYTHONFRAMEWORK)" + fi + +@@ -7016,7 +7225,7 @@ + dnl NOTE: Inform user how to proceed with files when cross compiling. + dnl Some cross-compile builds are predictable; they won't ever + dnl have /dev/ptmx or /dev/ptc, so we can set them explicitly. +-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 +@@ -7316,7 +7525,7 @@ + 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] + ) + ]) +@@ -7704,6 +7913,9 @@ + 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 + *) _PYTHREAD_NAME_MAXLEN=;; +@@ -7728,7 +7940,7 @@ + [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 diff --git a/patch/Python/_cross_target.py.tmpl b/patch/Python/_cross_target.py.tmpl index fbe178f..0630335 100644 --- a/patch/Python/_cross_target.py.tmpl +++ b/patch/Python/_cross_target.py.tmpl @@ -11,8 +11,8 @@ import sysconfig sys.cross_compiling = True sys.platform = "{{platform}}" sys.implementation._multiarch = "{{arch}}-{{sdk}}" -sys.base_prefix = sysconfig.get_config_var("prefix") -sys.base_exec_prefix = sysconfig.get_config_var("prefix") +sys.base_prefix = sysconfig._get_sysconfigdata()["prefix"] +sys.base_exec_prefix = sysconfig._get_sysconfigdata()["prefix"] ########################################################################### # subprocess module patches @@ -70,7 +70,7 @@ sysconfig.get_platform = cross_get_platform sysconfig._get_sysconfigdata_name = cross_get_sysconfigdata_name # Ensure module-level values cached at time of import are updated. -sysconfig._BASE_PREFIX = sys.prefix +sysconfig._BASE_PREFIX = sys.base_prefix sysconfig._BASE_EXEC_PREFIX = sys.base_exec_prefix # Force sysconfig data to be loaded (and cached). diff --git a/tests/test_cross_env.py b/tests/test_cross_env.py new file mode 100644 index 0000000..34e8c5e --- /dev/null +++ b/tests/test_cross_env.py @@ -0,0 +1,93 @@ +import os +import platform +import sys +import sysconfig +from pathlib import Path + +import pytest + +# To run these tests, the following three environment variables must be set, +# reflecting the cross-platform environment that is in effect.' +PYTHON_CROSS_PLATFORM = os.getenv("PYTHON_CROSS_PLATFORM", "unknown") +PYTHON_CROSS_SLICE = os.getenv("PYTHON_CROSS_SLICE", "unknown") +PYTHON_CROSS_MULTIARCH = os.getenv("PYTHON_CROSS_MULTIARCH", "unknown") + +# Determine some file system anchor points for the tests +# Assumes that the tests are run in a virtual environment named +# `cross-venv`, +VENV_PREFIX = Path(__file__).parent.parent / "cross-venv" +default_support_base = f"support/{sys.version_info.major}.{sys.version_info.minor}/{PYTHON_CROSS_PLATFORM}" +SUPPORT_PREFIX = ( + Path(__file__).parent.parent + / os.getenv("PYTHON_SUPPORT_BASE", default_support_base) + / "Python.xcframework" + / PYTHON_CROSS_SLICE +) + + +########################################################################### +# sys +########################################################################### + +def test_sys_platform(): + assert sys.platform == PYTHON_CROSS_PLATFORM.lower() + + +def test_sys_cross_compiling(): + assert sys.cross_compiling + + +def test_sys_multiarch(): + assert sys.implementation._multiarch == PYTHON_CROSS_MULTIARCH + + +def test_sys_base_prefix(): + assert Path(sys.base_prefix) == SUPPORT_PREFIX + + +def test_sys_base_exec_prefix(): + assert Path(sys.base_exec_prefix) == SUPPORT_PREFIX + + +########################################################################### +# platform +########################################################################### + +def test_platform_system(): + assert platform.system() == PYTHON_CROSS_PLATFORM + + +########################################################################### +# sysconfig +########################################################################### + +def test_sysconfig_get_platform(): + parts = sysconfig.get_platform().split("-", 2) + assert parts[0] == PYTHON_CROSS_PLATFORM.lower() + assert parts[2] == PYTHON_CROSS_MULTIARCH + + +def test_sysconfig_get_sysconfigdata_name(): + parts = sysconfig._get_sysconfigdata_name().split("_", 4) + assert parts[3] == PYTHON_CROSS_PLATFORM.lower() + assert parts[4] == PYTHON_CROSS_MULTIARCH + + +@pytest.mark.parametrize( + "name, prefix", + [ + # Paths that should be relative to the support folder + ("stdlib", SUPPORT_PREFIX), + ("include", SUPPORT_PREFIX), + ("platinclude", SUPPORT_PREFIX), + ("stdlib", SUPPORT_PREFIX), + # paths that should be relative to the venv + ("platstdlib", VENV_PREFIX), + ("purelib", VENV_PREFIX), + ("platlib", VENV_PREFIX), + ("scripts", VENV_PREFIX), + ("data", VENV_PREFIX), + ] +) +def test_sysconfig_get_paths(name, prefix): + assert sysconfig.get_paths()[name].startswith(str(prefix))