Skip to content

Commit e40c8cd

Browse files
committed
Merge branch 'main' into 3.9
Includes updates to: * Python 3.9.18 * XZ 5.4.4 * OpenSSL 3.1.2 * LibFFI 3.4.4
2 parents bf154ef + 5f0c652 commit e40c8cd

File tree

6 files changed

+365
-103
lines changed

6 files changed

+365
-103
lines changed

Makefile

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,23 @@ BUILD_NUMBER=custom
3939
# PYTHON_VERSION is the full version number (e.g., 3.10.0b3)
4040
# PYTHON_MICRO_VERSION is the full version number, without any alpha/beta/rc suffix. (e.g., 3.10.0)
4141
# PYTHON_VER is the major/minor version (e.g., 3.10)
42-
PYTHON_VERSION=3.9.14
42+
PYTHON_VERSION=3.9.18
4343
PYTHON_MICRO_VERSION=$(shell echo $(PYTHON_VERSION) | grep -Eo "\d+\.\d+\.\d+")
4444
PYTHON_VER=$(basename $(PYTHON_VERSION))
4545

4646
BZIP2_VERSION=1.0.8
4747

48-
XZ_VERSION=5.2.6
48+
XZ_VERSION=5.4.4
4949

5050
# Preference is to use OpenSSL 3; however, Cryptography 3.4.8 (and
5151
# probably some other packages as well) only works with 1.1.1, so
5252
# we need to preserve the ability to build the older OpenSSL (for now...)
53-
OPENSSL_VERSION=3.0.5
53+
OPENSSL_VERSION=3.1.2
5454
# OPENSSL_VERSION_NUMBER=1.1.1
55-
# OPENSSL_REVISION=q
55+
# OPENSSL_REVISION=v
5656
# OPENSSL_VERSION=$(OPENSSL_VERSION_NUMBER)$(OPENSSL_REVISION)
5757

58-
LIBFFI_VERSION=3.4.2
58+
LIBFFI_VERSION=3.4.4
5959

6060
# Supported OS and dependencies
6161
DEPENDENCIES=BZip2 XZ OpenSSL libFFI
@@ -107,7 +107,7 @@ all: $(OS_LIST)
107107

108108
# Clean all builds
109109
clean:
110-
rm -rf build install merge dist support
110+
rm -rf build install merge dist support wheels
111111

112112
# Full clean - includes all downloaded products
113113
distclean: clean
@@ -314,6 +314,7 @@ $$(XZ_SRCDIR-$(target))/Makefile: downloads/xz-$(XZ_VERSION).tar.gz
314314
--disable-shared \
315315
--enable-static \
316316
--host=$$(TARGET_TRIPLE-$(target)) \
317+
--build=$(HOST_ARCH)-apple-darwin \
317318
--prefix="$$(XZ_INSTALL-$(target))" \
318319
2>&1 | tee -a ../xz-$(XZ_VERSION).config.log
319320

@@ -910,8 +911,8 @@ os=$1
910911
SDKS-$(os)=$$(sort $$(basename $$(TARGETS-$(os))))
911912

912913
# Predeclare the Python XCFramework files so they can be referenced in SDK targets
913-
PYTHON_XCFRAMEWORK-$(os)=support/$(os)/Python.xcframework
914-
PYTHON_STDLIB-$(os)=support/$(os)/python-stdlib
914+
PYTHON_XCFRAMEWORK-$(os)=support/$(PYTHON_VER)/$(os)/Python.xcframework
915+
PYTHON_STDLIB-$(os)=support/$(PYTHON_VER)/$(os)/python-stdlib
915916

916917
# Expand the build-sdk macro for all the sdks on this OS (e.g., iphoneos, iphonesimulator)
917918
$$(foreach sdk,$$(SDKS-$(os)),$$(eval $$(call build-sdk,$$(sdk),$(os))))
@@ -1033,7 +1034,7 @@ $$(PYTHON_XCFRAMEWORK-$(os)): \
10331034
mkdir -p $$(dir $$(PYTHON_XCFRAMEWORK-$(os)))
10341035
xcodebuild -create-xcframework \
10351036
-output $$@ $$(foreach sdk,$$(SDKS-$(os)),-library $$(PYTHON_FATLIB-$$(sdk)) -headers $$(PYTHON_FATINCLUDE-$$(sdk))) \
1036-
2>&1 | tee -a support/python-$(os).xcframework.log
1037+
2>&1 | tee -a support/$(PYTHON_VER)/python-$(os).xcframework.log
10371038

10381039
$$(PYTHON_STDLIB-$(os)): \
10391040
$$(PYTHON_XCFRAMEWORK-$(os)) \
@@ -1059,34 +1060,34 @@ $$(PYTHON_STDLIB-$(os)): \
10591060

10601061
dist/Python-$(PYTHON_VER)-$(os)-support.$(BUILD_NUMBER).tar.gz: $$(PYTHON_XCFRAMEWORK-$(os)) $$(PYTHON_STDLIB-$(os))
10611062
@echo ">>> Create VERSIONS file for $(os)"
1062-
echo "Python version: $(PYTHON_VERSION) " > support/$(os)/VERSIONS
1063-
echo "Build: $(BUILD_NUMBER)" >> support/$(os)/VERSIONS
1064-
echo "Min $(os) version: $$(VERSION_MIN-$(os))" >> support/$(os)/VERSIONS
1065-
echo "---------------------" >> support/$(os)/VERSIONS
1063+
echo "Python version: $(PYTHON_VERSION) " > support/$(PYTHON_VER)/$(os)/VERSIONS
1064+
echo "Build: $(BUILD_NUMBER)" >> support/$(PYTHON_VER)/$(os)/VERSIONS
1065+
echo "Min $(os) version: $$(VERSION_MIN-$(os))" >> support/$(PYTHON_VER)/$(os)/VERSIONS
1066+
echo "---------------------" >> support/$(PYTHON_VER)/$(os)/VERSIONS
10661067
ifeq ($(os),macOS)
1067-
echo "libFFI: macOS native" >> support/$(os)/VERSIONS
1068+
echo "libFFI: macOS native" >> support/$(PYTHON_VER)/$(os)/VERSIONS
10681069
else
1069-
echo "libFFI: $(LIBFFI_VERSION)" >> support/$(os)/VERSIONS
1070+
echo "libFFI: $(LIBFFI_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS
10701071
endif
1071-
echo "BZip2: $(BZIP2_VERSION)" >> support/$(os)/VERSIONS
1072-
echo "OpenSSL: $(OPENSSL_VERSION)" >> support/$(os)/VERSIONS
1073-
echo "XZ: $(XZ_VERSION)" >> support/$(os)/VERSIONS
1072+
echo "BZip2: $(BZIP2_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS
1073+
echo "OpenSSL: $(OPENSSL_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS
1074+
echo "XZ: $(XZ_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS
10741075

10751076
ifneq ($(os),macOS)
10761077
@echo ">>> Create cross-platform site sitecustomize.py for $(os)"
1077-
mkdir -p support/$(os)/platform-site
1078+
mkdir -p support/$(PYTHON_VER)/$(os)/platform-site
10781079
cat $(PROJECT_DIR)/patch/Python/sitecustomize.py \
10791080
| sed -e "s/{{os}}/$(os)/g" \
10801081
| sed -e "s/{{tag}}/$$(shell echo $(os) | tr '[:upper:]' '[:lower:]')_$$(shell echo $$(VERSION_MIN-$(os)) | sed "s/\./_/g")/g" \
1081-
> support/$(os)/platform-site/sitecustomize.py
1082+
> support/$(PYTHON_VER)/$(os)/platform-site/sitecustomize.py
10821083
endif
10831084

10841085
@echo ">>> Create final distribution artefact for $(os)"
10851086
mkdir -p dist
10861087
# Build a "full" tarball with all content for test purposes
1087-
tar zcvf dist/Python-$(PYTHON_VER)-$(os)-support.test-$(BUILD_NUMBER).tar.gz -X patch/Python/test.exclude -C support/$(os) `ls -A support/$(os)`
1088+
tar zcvf dist/Python-$(PYTHON_VER)-$(os)-support.test-$(BUILD_NUMBER).tar.gz -X patch/Python/test.exclude -C support/$(PYTHON_VER)/$(os) `ls -A support/$(PYTHON_VER)/$(os)/`
10881089
# Build a distributable tarball
1089-
tar zcvf $$@ -X patch/Python/release.common.exclude -X patch/Python/release.$(os).exclude -C support/$(os) `ls -A support/$(os)`
1090+
tar zcvf $$@ -X patch/Python/release.common.exclude -X patch/Python/release.$(os).exclude -C support/$(PYTHON_VER)/$(os) `ls -A support/$(PYTHON_VER)/$(os)/`
10901091

10911092
Python-$(os): dist/Python-$(PYTHON_VER)-$(os)-support.$(BUILD_NUMBER).tar.gz
10921093

@@ -1099,8 +1100,7 @@ clean-Python-$(os):
10991100
install/$(os)/*/python-$(PYTHON_VER)*.*.log \
11001101
merge/$(os)/*/python-$(PYTHON_VER)* \
11011102
merge/$(os)/*/python-$(PYTHON_VER)*.*.log \
1102-
support/$(os) \
1103-
support/*-$(os).*.log \
1103+
support/$(PYTHON_VER)/$(os) \
11041104
dist/Python-$(PYTHON_VER)-$(os)-*
11051105

11061106
dev-clean-Python-$(os):
@@ -1112,17 +1112,15 @@ dev-clean-Python-$(os):
11121112
install/$(os)/*/python-$(PYTHON_VERSION).*.log \
11131113
merge/$(os)/*/python-$(PYTHON_VERSION) \
11141114
merge/$(os)/*/python-$(PYTHON_VERSION).*.log \
1115-
support/$(os) \
1116-
support/*-$(os).*.log \
1115+
support/$(PYTHON_VER)/$(os) \
11171116
dist/Python-$(PYTHON_VER)-$(os)-*
11181117

11191118
merge-clean-Python-$(os):
11201119
@echo ">>> Partially clean Python build products on $(os) so that merge modifications can be made"
11211120
rm -rf \
11221121
merge/$(os)/*/python-$(PYTHON_VERSION) \
11231122
merge/$(os)/*/python-$(PYTHON_VERSION).*.log \
1124-
support/$(os) \
1125-
support/*-$(os).*.log \
1123+
support/$(PYTHON_VER)/$(os) \
11261124
dist/Python-$(PYTHON_VER)-$(os)-*
11271125

11281126
###########################################################################

README.rst

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Python Apple Support
44
This is a meta-package for building a version of Python that can be embedded
55
into a macOS, iOS, tvOS or watchOS project.
66

7-
**This branch builds a packaged version of Python 3.9.14**.
7+
**This branch builds a packaged version of Python 3.9.18**.
88
Other Python versions are available by cloning other branches of the main
99
repository:
1010

@@ -106,43 +106,17 @@ install return ``platform`` and ``sysconfig`` responses consistent with
106106
on-device behavior, which will cause ``pip`` to install platform-appropriate
107107
packages.
108108

109-
To add a support package to your own Xcode project:
110-
111-
1. Drag ``Python.xcframework`` and ``python-stdlib`` into your Xcode project
112-
tree.
113-
2. Ensure that these two objects are added to any targets that need to use
114-
them;
115-
3. Add a custom build phase to purge any binary modules for the platform you are
116-
*not* targetting; and
117-
4. Add a custom build phase to sign any of the binary modules in your app.
118-
5. Add CPython API code to your app to create an instance of the Python
119-
interpreter.
120-
121-
For examples of the scripts needed for steps 3 and 4, and the code needed for
122-
step 5, compare with a project generated with Briefcase.
123-
124-
On macOS, you must also either:
125-
1. Enable the "Disable Library Validation" entitlement (found on the "Signing
126-
& Capabilities" tab in XCode); or
127-
2. Sign your app with a Development or Distribution certificate. This will
128-
require a paid Apple Developer subscription.
129-
130-
It is not possible to use an ad-hoc signing certificate with the "Disable
131-
Library Validation" entitlement disabled.
132-
133-
On iOS/tvOS/watchOS, you can use the default developer certificate for deploying
134-
to a device simulator. However, to deploy to a physical device (including your
135-
own), you will require a Development or Distribution certificate, which requires
136-
a paid Apple Developer subscription.
109+
For a detailed instructions on using the support package in your own project,
110+
see the `usage guide <./USAGE.md>`__
137111

138112
Building binary wheels
139113
----------------------
140114

141115
When building binary wheels, you may need to use the libraries built by this
142116
project as inputs (e.g., the `cffi` module uses `libffi`). To support this, this
143117
project is able to package these dependencies as "wheels" that can be added to
144-
the `server/pypi/dist` directory of the [binary dependency builder
145-
project](https://github.com/freakboy3742/chaquopy).
118+
the `server/pypi/dist` directory of the `binary dependency builder
119+
project <https://github.com/freakboy3742/chaquopy>`__.
146120

147121
To build these wheels, run:
148122

USAGE.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Usage Guide
2+
3+
## The easy way
4+
5+
The easist way to use these packages is by creating a project with `Briefcase
6+
<https://github.com/beeware/briefcase>`__. Briefcase will download pre-compiled
7+
versions of these support packages, and add them to an Xcode project (or
8+
pre-build stub application, in the case of macOS).
9+
10+
## The manual way
11+
12+
The Python support package *can* be manually added to any Xcode project;
13+
however, you'll need to perform some steps manually (essentially reproducing what
14+
Briefcase is doing)
15+
16+
**NOTE** Briefcase usage is the officially supported approach for using this
17+
support package. If you are experiencing diffculties, one approach for debugging
18+
is to generate a "Hello World" project with Briefcase, and compare the project that
19+
Briefcase has generated with your own project.
20+
21+
To add this support package to your own project:
22+
23+
1. [Download a release tarball for your desired Python version and Apple platform](https://github.com/beeware/Python-Apple-support/releases)
24+
25+
2. Add the `python-stdlib` and `Python.xcframework` to your Xcode project. Both
26+
the `python-stdlib` folder and the `Python.xcframework` should be members of
27+
any target that needs to use Python.
28+
29+
3. In Xcode, select the root node of the project tree, and select the target you
30+
want to build.
31+
32+
4. Select "General" -> "Frameworks, Libraries and Embedded Content", and ensure
33+
that `Python.xcframework` is on the list of frameworks. It should be marked
34+
"Do not embed".
35+
36+
5. Select "General" -> "Build Phases", and ensure that the `python-stdlib` folder
37+
is listed in the "Copy Bundle Resources" step.
38+
39+
6. Add a new "Run script" build phase named "Sign Python Binary Modules", with the following content:
40+
41+
```bash
42+
set -e
43+
echo "Signing as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)"
44+
find "$CODESIGNING_FOLDER_PATH/Contents/Resources/python-stdlib/lib-dynload" -name "*.so" -exec /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \;
45+
```
46+
47+
You will now be able to access the Python runtime in your Python code.
48+
49+
If you are on iOS, you will be able to deploy to an iOS simulator without specifying
50+
development team; however, you will need to specify a valid development team to sign
51+
the binaries for deployment onto a physical device (or for submission to the App Store).
52+
53+
If you are on macOS, you will need to specify a valid development team to run
54+
the app. If you don't want to specify a development team in your project, you
55+
will also need to enable the "Disable Library Validation" entitlement under
56+
"Signing & Capabilities" -> "Hardened Runtime" for your project.
57+
58+
## Accessing the Python runtime
59+
60+
There are 2 ways to access the Python runtime in your project code.
61+
62+
### Embedded C API.
63+
64+
You can use the [Python Embedded C
65+
API](https://docs.python.org/3/extending/embedding.html) to instantiate a Python
66+
interpreter. This is the approach taken by Briefcase; you may find the bootstrap
67+
mainline code generated by Briefcase a helpful guide to what is needed to start
68+
an interpreter and run Python code.
69+
70+
### PythonKit
71+
72+
An alternate approach is to use
73+
[PythonKit](https://github.com/pvieito/PythonKit). PythonKit is a package that
74+
provides a Swift API to running Python code.
75+
76+
To use PythonKit in your project:
77+
78+
1. Add PythonKit to your project using the Swift Package manager. See the
79+
PythonKit documentation for details.
80+
81+
2. Create a file called `module.modulemap` inside
82+
`Python.xcframework/macos-arm64_x86_64/Headers/`, containing the following
83+
code:
84+
```
85+
module Python {
86+
umbrella header "Python.h"
87+
export *
88+
link "Python"
89+
}
90+
```
91+
92+
3. In your Swift code, initialize the Python runtime. This should generally be
93+
done as early as possible in the application's lifecycle, but definitely
94+
needs to be done before you invoke Python code:
95+
```swift
96+
import Python
97+
98+
guard let stdLibPath = Bundle.main.path(forResource: "python-stdlib", ofType: nil) else { return }
99+
guard let libDynloadPath = Bundle.main.path(forResource: "python-stdlib/lib-dynload", ofType: nil) else { return }
100+
setenv("PYTHONHOME", stdLibPath, 1)
101+
setenv("PYTHONPATH", "\(stdLibPath):\(libDynloadPath)", 1)
102+
Py_Initialize()
103+
// we now have a Python interpreter ready to be used
104+
```
105+
106+
5. Invoke Python code in your app. For example:
107+
```swift
108+
import PythonKit
109+
110+
let sys = Python.import("sys")
111+
print("Python Version: \(sys.version_info.major).\(sys.version_info.minor)")
112+
print("Python Encoding: \(sys.getdefaultencoding().upper())")
113+
print("Python Path: \(sys.path)")
114+
115+
_ = Python.import("math") // verifies `lib-dynload` is found and signed successfully
116+
```
117+
118+
To integrate 3rd party python code and dependencies, you will need to make sure
119+
`PYTHONPATH` contains their paths; once this has been done, you can run
120+
`Python.import("<lib name>")`. to import that module from inside swift.

0 commit comments

Comments
 (0)