Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3a7cd86
More updates to USAGE and README (#250)
freakboy3742 Feb 17, 2025
1158013
Bump ncipollo/release-action from 1.15.0 to 1.16.0 (#253)
dependabot[bot] Feb 23, 2025
832d393
Bump actions/upload-artifact from 4.6.0 to 4.6.1 (#254)
dependabot[bot] Feb 23, 2025
aa545e9
Add patch for handling empty simulator lists.
freakboy3742 Feb 25, 2025
c794b06
Bump actions/download-artifact from 4.1.8 to 4.1.9 (#255)
dependabot[bot] Mar 3, 2025
0013ca0
Update patch for Python 3.14.0a6 (#258)
freakboy3742 Mar 18, 2025
ca43143
Bump actions/download-artifact from 4.1.9 to 4.2.1 (#265)
dependabot[bot] Mar 23, 2025
cfd548d
Bump actions/upload-artifact from 4.6.1 to 4.6.2 (#266)
dependabot[bot] Mar 23, 2025
db04fbd
Bump actions/setup-python from 5.4.0 to 5.5.0 (#267)
dependabot[bot] Mar 30, 2025
81428db
Add Python.patch Note to Contributing.md (#271)
johnzhou721 Apr 17, 2025
92d8d95
Add support for visionOS (#270)
johnzhou721 Apr 23, 2025
f8fd686
Fix an iOS reference in testbed cloning. (#272)
johnzhou721 Apr 23, 2025
344aaf6
Update patch to include visionOS plist changes.
freakboy3742 Apr 25, 2025
515625c
visionOS Support and Other Fixes (#276)
johnzhou721 Apr 27, 2025
e29c0fd
Bump actions/setup-python from 5.5.0 to 5.6.0 (#277)
dependabot[bot] Apr 27, 2025
80296f0
Bump actions/download-artifact from 4.2.1 to 4.3.0 (#278)
dependabot[bot] Apr 27, 2025
b5bed64
Ensure base_prefix is set in a cross-venv. (#279)
freakboy3742 May 1, 2025
7a7aad1
Document the Patch Tree Approach. (#281)
johnzhou721 May 4, 2025
6583edf
Update CONTRIBUTING.md for Grammar + Clarity (#282)
johnzhou721 May 4, 2025
a041905
Remove some useless PATHs in Usage.md (#284)
johnzhou721 May 6, 2025
76b7f30
Bump patch to Python 3.14.0b2. (#290)
freakboy3742 Jun 3, 2025
c012e5d
Add xcprivacy and dSYM handling (#285)
freakboy3742 Jun 3, 2025
6014bf0
Merge branch 'main' into 3.13-update
freakboy3742 Jun 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ jobs:
- uses: actions/[email protected]

- name: Set up Python
uses: actions/setup-python@v5.4.0
uses: actions/setup-python@v5.6.0
with:
# Appending -dev ensures that we can always build the dev release.
# It's a no-op for versions that have been published.
Expand All @@ -120,7 +120,7 @@ jobs:
make ${{ matrix.target }} BUILD_NUMBER=${{ needs.config.outputs.BUILD_NUMBER }}

- name: Upload build artefacts
uses: actions/[email protected].1
uses: actions/[email protected].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
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
- uses: actions/checkout@v4

- name: Set up Python environment
uses: actions/setup-python@v5.4.0
uses: actions/setup-python@v5.6.0
with:
python-version: "3.X"

Expand Down Expand Up @@ -48,3 +48,6 @@ jobs:
# watchOS build
curl -o watchOS-artefact.tar.gz -L https://github.com/beeware/Python-Apple-support/releases/download/${{ steps.build-vars.outputs.TAG }}/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-watchOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz
aws s3 cp watchOS-artefact.tar.gz s3://briefcase-support/python/${{ steps.build-vars.outputs.PYTHON_VER }}/watchOS/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-watchOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz
# visionOS build
curl -o visionOS-artefact.tar.gz -L https://github.com/beeware/Python-Apple-support/releases/download/${{ steps.build-vars.outputs.TAG }}/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-visionOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz
aws s3 cp visionOS-artefact.tar.gz s3://briefcase-support/python/${{ steps.build-vars.outputs.PYTHON_VER }}/visionOS/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-visionOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
needs: [ config, ci ]
steps:
- name: Get build artifacts
uses: actions/download-artifact@v4.1.9
uses: actions/download-artifact@v4.3.0
with:
pattern: Python-*
path: dist
Expand Down
41 changes: 39 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,44 @@

BeeWare <3's contributions!

Please be aware, BeeWare operates under a Code of Conduct.
Please be aware that BeeWare operates under a [Code of
Conduct](https://beeware.org/community/behavior/code-of-conduct/).

See [CONTRIBUTING to BeeWare](https://beeware.org/contributing) for details.
See [CONTRIBUTING to BeeWare](https://beeware.org/contributing) for general
project contribution guidelines.

Unless a fix is version specific, PRs should genereally be made against the
`main` branch of this repo, targeting the current development version of Python.
Project maintainers will manage the process of backporting changes to older
Python versions.

## Changes to `Python.patch`

Additional handling is required if you need to make modifications to the patch
applied to Python sources (`patch/Python/Python.patch`).

Any iOS or macOS-specific changes should be submitted to the [upstream CPython
repository](https://github.com/python/cpython). macOS and iOS are both
officially supported Python platforms, and the code distributed by this project
for those platforms is unmodified from the official repository.

Changes to to support other platforms can be included in a PR for this repo, but
they must also be submitted as a pull request against the `MAJOR.MINOR-patched`
branch on [the `freakboy3742` fork of the CPython
repo](https://github.com/freakboy3742/cpython). This is required to ensure that
any contributed changes can be easily reproduced in future patches as more
changes are made.

Note that the `MAJOR.MINOR-patched` branch of that fork is maintained in the format
of a *patch tree*, which is a branch that consists of an entirely linear sequence of
commits applied on top of another branch (in the case of the fork, `MAJOR.MINOR`),
each of which adds a significant new feature. Therefore, a bug fix for an existing commit
in the patch tree *will* be merged when appropriate, but its changes will get combined
with that existing commit that adds the feature. A feature addition PR will be squashed
into a single, new commit, and then put on top of the patch tree.

This also means that if another contributor gets a pull request merged into
`MAJOR.MINOR-patched`, you must *rebase* your changes on top of the updated
`MAJOR.MINOR-patched` branch, as opposed to *merging* `MAJOR.MINOR-patched` into your
branch, since the "history" of a patch tree is likely to change in a way that is
incompatible with merge commits.
46 changes: 31 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,43 @@ 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.13.2
PYTHON_VERSION=3.13.3
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+")
PYTHON_VER=$(basename $(PYTHON_VERSION))

# The binary releases of dependencies, published at:
# https://github.com/beeware/cpython-apple-source-deps/releases
BZIP2_VERSION=1.0.8-1
LIBFFI_VERSION=3.4.7-1
MPDECIMAL_VERSION=4.0.0-1
OPENSSL_VERSION=3.0.16-1
XZ_VERSION=5.6.4-1
BZIP2_VERSION=1.0.8-2
LIBFFI_VERSION=3.4.7-2
MPDECIMAL_VERSION=4.0.0-2
OPENSSL_VERSION=3.0.16-2
XZ_VERSION=5.6.4-2

# Supported OS
OS_LIST=macOS iOS tvOS watchOS
OS_LIST=macOS iOS tvOS watchOS visionOS

CURL_FLAGS=--disable --fail --location --create-dirs --progress-bar

# macOS targets
TARGETS-macOS=macosx.x86_64 macosx.arm64
TRIPLE_OS-macOS=macos
VERSION_MIN-macOS=11.0

# iOS targets
TARGETS-iOS=iphonesimulator.x86_64 iphonesimulator.arm64 iphoneos.arm64
TRIPLE_OS-iOS=ios
VERSION_MIN-iOS=13.0

# tvOS targets
TARGETS-tvOS=appletvsimulator.x86_64 appletvsimulator.arm64 appletvos.arm64
TRIPLE_OS-tvOS=tvos
VERSION_MIN-tvOS=12.0

# watchOS targets
TARGETS-watchOS=watchsimulator.x86_64 watchsimulator.arm64 watchos.arm64_32
TRIPLE_OS-watchOS=watchos
VERSION_MIN-watchOS=4.0

# The architecture of the machine doing the build
Expand Down Expand Up @@ -128,10 +132,10 @@ ARCH-$(target)=$$(subst .,,$$(suffix $(target)))

ifneq ($(os),macOS)
ifeq ($$(findstring simulator,$$(SDK-$(target))),)
TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(OS_LOWER-$(target))$$(VERSION_MIN-$(os))
TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(os))
IS_SIMULATOR-$(target)=False
else
TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(OS_LOWER-$(target))$$(VERSION_MIN-$(os))-simulator
TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(os))-simulator
IS_SIMULATOR-$(target)=True
endif
endif
Expand Down Expand Up @@ -398,15 +402,13 @@ define build-sdk
sdk=$1
os=$2

OS_LOWER-$(sdk)=$(shell echo $(os) | tr '[:upper:]' '[:lower:]')

SDK_TARGETS-$(sdk)=$$(filter $(sdk).%,$$(TARGETS-$(os)))
SDK_ARCHES-$(sdk)=$$(sort $$(subst .,,$$(suffix $$(SDK_TARGETS-$(sdk)))))

ifeq ($$(findstring simulator,$(sdk)),)
SDK_SLICE-$(sdk)=$$(OS_LOWER-$(sdk))-$$(shell echo $$(SDK_ARCHES-$(sdk)) | sed "s/ /_/g")
SDK_SLICE-$(sdk)=$$(TRIPLE_OS-$(os))-$$(shell echo $$(SDK_ARCHES-$(sdk)) | sed "s/ /_/g")
else
SDK_SLICE-$(sdk)=$$(OS_LOWER-$(sdk))-$$(shell echo $$(SDK_ARCHES-$(sdk)) | sed "s/ /_/g")-simulator
SDK_SLICE-$(sdk)=$$(TRIPLE_OS-$(os))-$$(shell echo $$(SDK_ARCHES-$(sdk)) | sed "s/ /_/g")-simulator
endif

# Expand the build-target macro for target on this OS
Expand Down Expand Up @@ -450,6 +452,7 @@ $$(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
dsymutil $$@ -o $$(PYTHON_INSTALL-$(sdk))/Python.dSYM

$$(PYTHON_FRAMEWORK-$(sdk))/Info.plist: $$(PYTHON_LIB-$(sdk))
@echo ">>> Install Info.plist for the $(sdk) SDK"
Expand Down Expand Up @@ -481,11 +484,15 @@ $$(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


$$(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)))
Expand All @@ -510,6 +517,14 @@ $$(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))); )

# 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
Expand Down Expand Up @@ -647,10 +662,11 @@ $$(PYTHON_XCFRAMEWORK-$(os))/Info.plist: \
$$(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)); )
$$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/Python.dSYM $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); )

ifeq ($(os),iOS)
ifeq ($(filter $(os),iOS visionOS),$(os))
@echo ">>> Clone testbed project for $(os)"
$(HOST_PYTHON) $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/iOS/testbed clone --framework $$(PYTHON_XCFRAMEWORK-$(os)) support/$(PYTHON_VER)/$(os)/testbed
$(HOST_PYTHON) $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/$(os)/testbed clone --framework $$(PYTHON_XCFRAMEWORK-$(os)) support/$(PYTHON_VER)/$(os)/testbed
endif

@echo ">>> Create VERSIONS file for $(os)"
Expand Down
32 changes: 19 additions & 13 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Python Apple Support
====================

This is a meta-package for building a version of Python that can be embedded
into a macOS, iOS, tvOS or watchOS project.
into a macOS, iOS, tvOS, watchOS, or visionOS project.

**This branch builds a packaged version of Python 3.13**.
Other Python versions are available by cloning other branches of the main
Expand All @@ -16,21 +16,24 @@ repository:

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
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 and watchOS 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.9-3.12.
Additional patches have been applied to add tvOS and watchOS support.
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.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; and arm64_32 for watchOS devices. It also supports device simulators on
both x86_64 and M1 hardware. This should enable the code to run on:
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)
Expand All @@ -49,6 +52,8 @@ both x86_64 and M1 hardware. This should enable the code to run 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
----------
Expand All @@ -69,23 +74,24 @@ repository, and then in the root directory, and run:
* ``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 a ``.tar.gz`` file
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
* ``Python.xcframework``, a multi-architecture build of the Python runtime library.

On iOS/tvOS/watchOS, the ``Python.xcframework`` contains a
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.
Expand Down Expand Up @@ -131,8 +137,8 @@ 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 and
watchOS, although that hasn't been tested).
tooling to build build binary wheels for iOS (and potentially for tvOS, watchOS,
and visionOS, although that hasn't been tested).

Historical support
------------------
Expand Down
Loading