Skip to content

Commit 73613ab

Browse files
Bump Pythons to 3.12.15/3.13.16/3.14.8; iOS 15.0 / macOS 12.0 minimums; dart_bridge 1.11.0 (#46)
* Bump Pythons to 3.12.15/3.13.16/3.14.8; iOS 15.0 / macOS 12.0 minimums; dart_bridge 1.11.0 * 3.12 iOS patch: use ASN1_STRING accessors in _ssl.c so the build-python compiles against OpenSSL 4
1 parent 34448b9 commit 73613ab

8 files changed

Lines changed: 124 additions & 26 deletions

File tree

‎.github/workflows/build-python-version.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ on:
1414
required: true
1515
type: choice
1616
options:
17-
- 3.12.14
18-
- 3.13.15
19-
- 3.14.7
17+
- 3.12.15
18+
- 3.13.16
19+
- 3.14.8
2020

2121
env:
2222
PYTHON_VERSION: ${{ inputs.python_version || github.event.inputs.python_version }}

‎darwin/build_ios.py‎

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@
3838

3939
_LOG = None # open file handle; set via set_log()
4040

41+
# Minimum iOS version for every slice. Xcode 27 rejects deployment targets below 15.0,
42+
# and Flutter 3.47 / Flet 1.1.0 use the same floor. CPython's configure hardcodes
43+
# 13.0 as its default (see build()), so it's rewritten to this value.
44+
IOS_DEPLOYMENT_TARGET = "15.0"
45+
4146

4247
def set_log(path: Path) -> None:
4348
"""Tee all subsequent run()/_emit output to a build log file."""
@@ -139,14 +144,29 @@ def build(
139144
# and upstream's iOS PY_STDLIB_MOD_SET_NA (3.14+); a no-op if the string isn't
140145
# present.
141146
configure = src / "configure"
142-
configure.write_text(
147+
configure_text = (
143148
configure.read_text()
144149
.replace(
145150
"py_cv_module__multiprocessing=n/a", "py_cv_module__multiprocessing=yes"
146151
)
147152
.replace("py_cv_module__posixshmem=n/a", "py_cv_module__posixshmem=yes")
148153
)
149154

155+
# Raise the iOS deployment target. The Apple tool configures an unversioned
156+
# --host=arm64-apple-ios, so configure falls back to its hardcoded 13.0 default
157+
# (and overwrites IPHONEOS_DEPLOYMENT_TARGET from the environment), then derives
158+
# -mios[-simulator]-version-min, the framework's MinimumOSVersion and the
159+
# sysconfig platform tag from it. The same line exists in 3.14+ upstream, 3.13
160+
# upstream and the 3.12 back-port patch; fail loudly if upstream ever changes it.
161+
default_target = "IPHONEOS_DEPLOYMENT_TARGET:=13.0}"
162+
if configure_text.count(default_target) != 1:
163+
raise SystemExit(f"Expected exactly one {default_target!r} in {configure}")
164+
configure.write_text(
165+
configure_text.replace(
166+
default_target, f"IPHONEOS_DEPLOYMENT_TARGET:={IOS_DEPLOYMENT_TARGET}}}"
167+
)
168+
)
169+
150170
# iOS's SDK declares pipe2/dup3 in headers but doesn't provide them, and on recent
151171
# SDKs configure mis-detects them (esp. the simulator), then the build fails with
152172
# "call to undeclared function 'pipe2'". The Apple tool doesn't expose configure
@@ -182,8 +202,8 @@ def _strip(paths: list) -> None:
182202

183203
def _embed_ios_version_in_host_triple(sysconfig_path: Path) -> None:
184204
"""Rewrite HOST_GNU_TYPE in a _sysconfigdata file to embed IPHONEOS_DEPLOYMENT_TARGET
185-
(e.g. ``aarch64-apple-ios`` -> ``aarch64-apple-ios13.0``,
186-
``...-ios-simulator`` -> ``...-ios13.0-simulator``)."""
205+
(e.g. ``aarch64-apple-ios`` -> ``aarch64-apple-ios15.0``,
206+
``...-ios-simulator`` -> ``...-ios15.0-simulator``)."""
187207
text = sysconfig_path.read_text()
188208
m = re.search(r"'IPHONEOS_DEPLOYMENT_TARGET':\s*'([^']+)'", text)
189209
if not m:
@@ -235,11 +255,24 @@ def reshape(version: str, short: str, src: Path, root: Path) -> None:
235255
# the _sysconfigdata lacks the iOS deployment version. mobile-forge's crossenv recovers
236256
# the iOS release by splitting HOST_GNU_TYPE (when _PYTHON_HOST_PLATFORM isn't set), so a
237257
# version-less triple yields an empty release and pip's iOS-tag code crashes. Embed the
238-
# version (e.g. aarch64-apple-ios -> aarch64-apple-ios13.0), matching beeware. Fixing the
258+
# version (e.g. aarch64-apple-ios -> aarch64-apple-ios15.0), matching beeware. Fixing the
239259
# xcframework copies here means the dart-install + platform-config copies inherit it.
240260
for sc in dst_xcf.glob(f"*/lib-*/{pyver}/_sysconfigdata__ios_*.py"):
241261
_embed_ios_version_in_host_triple(sc)
242262

263+
# The Apple tool also ships its testbed's dylib Info.plist template inside the
264+
# xcframework (build/iOS-dylib-Info-template.plist), with MinimumOSVersion
265+
# hardcoded to 13.0. Keep it consistent with the slices.
266+
dylib_plist_template = dst_xcf / "build" / "iOS-dylib-Info-template.plist"
267+
if dylib_plist_template.is_file():
268+
dylib_plist_template.write_text(
269+
re.sub(
270+
r"(<key>MinimumOSVersion</key>\s*<string>)[^<]*(</string>)",
271+
rf"\g<1>{IOS_DEPLOYMENT_TARGET}\g<2>",
272+
dylib_plist_template.read_text(),
273+
)
274+
)
275+
243276
shared_stdlib = dst_xcf / "lib" / pyver
244277
if not (shared_stdlib / "os.py").exists():
245278
raise SystemExit(f"Expected shared stdlib at {shared_stdlib}")
@@ -277,7 +310,11 @@ def reshape(version: str, short: str, src: Path, root: Path) -> None:
277310

278311
support = root / "support" / short / "iOS"
279312
support.mkdir(parents=True, exist_ok=True)
280-
lines = [f"Python version: {version}", "Build: custom", "Min iOS version: 13.0"]
313+
lines = [
314+
f"Python version: {version}",
315+
"Build: custom",
316+
f"Min iOS version: {IOS_DEPLOYMENT_TARGET}",
317+
]
281318
if deps:
282319
lines.append("---------------------")
283320
lines += [f"{name}: {ver}" for name, ver in sorted(deps.items())]

‎darwin/build_macos.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
DEFAULT_XZ_VERSION = "5.8.3"
3838
# zstd backs the _zstd module added in CPython 3.14 (PEP 784); built only for 3.14+.
3939
DEFAULT_ZSTD_VERSION = "1.5.7"
40-
DEFAULT_DEPLOYMENT_TARGET = "11.0"
40+
DEFAULT_DEPLOYMENT_TARGET = "12.0"
4141
ARCHES = ("x86_64", "arm64")
4242

4343
# A minimal PATH keeps Homebrew / user Python installs from leaking into the build.

‎darwin/ios_patches/3.12/Python.patch‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9282,6 +9282,53 @@ index 7ca3dc62c01..a1e28beff42 100644
92829282
-rm -f python-config.py python-config
92839283

92849284
# Make things extra clean, before making a distribution:
9285+
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
9286+
index 91ca136..364cf9e 100644
9287+
--- a/Modules/_ssl.c
9288+
+++ b/Modules/_ssl.c
9289+
@@ -1339,14 +1339,14 @@ _get_peer_alt_names (_sslmodulestate *state, X509 *certificate) {
9290+
}
9291+
PyTuple_SET_ITEM(t, 0, v);
9292+
9293+
- if (name->d.ip->length == 4) {
9294+
- unsigned char *p = name->d.ip->data;
9295+
+ if (ASN1_STRING_length(name->d.ip) == 4) {
9296+
+ const unsigned char *p = ASN1_STRING_get0_data(name->d.ip);
9297+
v = PyUnicode_FromFormat(
9298+
"%d.%d.%d.%d",
9299+
p[0], p[1], p[2], p[3]
9300+
);
9301+
- } else if (name->d.ip->length == 16) {
9302+
- unsigned char *p = name->d.ip->data;
9303+
+ } else if (ASN1_STRING_length(name->d.ip) == 16) {
9304+
+ const unsigned char *p = ASN1_STRING_get0_data(name->d.ip);
9305+
v = PyUnicode_FromFormat(
9306+
"%X:%X:%X:%X:%X:%X:%X:%X",
9307+
p[0] << 8 | p[1],
9308+
@@ -1477,8 +1477,9 @@ _get_aia_uri(X509 *certificate, int nid) {
9309+
continue;
9310+
}
9311+
uri = ad->location->d.uniformResourceIdentifier;
9312+
- ostr = PyUnicode_FromStringAndSize((char *)uri->data,
9313+
- uri->length);
9314+
+ ostr = PyUnicode_FromStringAndSize(
9315+
+ (const char *)ASN1_STRING_get0_data(uri),
9316+
+ ASN1_STRING_length(uri));
9317+
if (ostr == NULL) {
9318+
goto fail;
9319+
}
9320+
@@ -1544,8 +1545,9 @@ _get_crl_dp(X509 *certificate) {
9321+
continue;
9322+
}
9323+
uri = gn->d.uniformResourceIdentifier;
9324+
- ouri = PyUnicode_FromStringAndSize((char *)uri->data,
9325+
- uri->length);
9326+
+ ouri = PyUnicode_FromStringAndSize(
9327+
+ (const char *)ASN1_STRING_get0_data(uri),
9328+
+ ASN1_STRING_length(uri));
9329+
if (ouri == NULL)
9330+
goto done;
9331+
92859332
diff --git a/Modules/getpath.c b/Modules/getpath.c
92869333
index 0a310000751..83a2bc469ae 100644
92879334
--- a/Modules/getpath.c

‎darwin/ios_patches/3.13/Python.patch‎

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7102,16 +7102,16 @@ index 0df4751..cf32adf 100755
71027102

71037103

71047104
# checks for alternative programs
7105-
@@ -4709,6 +4907,16 @@ case $ac_sys_system in #(
7105+
@@ -4714,6 +4912,16 @@ case $host in #(
71067106
as_fn_append CFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"
71077107
as_fn_append LDFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"
71087108
;; #(
7109-
+ tvOS) :
7109+
+ *-apple-tvos*) :
71107110
+
71117111
+ as_fn_append CFLAGS " -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"
71127112
+ as_fn_append LDFLAGS " -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"
71137113
+ ;; #(
7114-
+ watchOS) :
7114+
+ *-apple-watchos*) :
71157115
+
71167116
+ as_fn_append CFLAGS " -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"
71177117
+ as_fn_append LDFLAGS " -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"
@@ -7785,25 +7785,31 @@ index a016a43..698553b 100644
77857785

77867786
# checks for alternative programs
77877787

7788-
@@ -944,11 +1127,19 @@ AS_CASE([$host],
7788+
@@ -944,15 +1127,25 @@ AS_CASE([$host],
77897789
],
77907790
)
77917791

77927792
-dnl Add the compiler flag for the iOS minimum supported OS version.
77937793
+dnl Add the compiler flag for the iOS/tvOS/watchOS minimum supported OS
77947794
+dnl version. visionOS doesn't use an explicit -mxros-version-min option -
77957795
+dnl it encodes the min version into the target triple.
7796-
AS_CASE([$ac_sys_system],
7797-
[iOS], [
7796+
AS_CASE([$host],
7797+
[*-apple-ios*-simulator], [
7798+
AS_VAR_APPEND([CFLAGS], [" -mios-simulator-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"])
7799+
AS_VAR_APPEND([LDFLAGS], [" -mios-simulator-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"])
7800+
],
7801+
[*-apple-ios*], [
77987802
AS_VAR_APPEND([CFLAGS], [" -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"])
77997803
AS_VAR_APPEND([LDFLAGS], [" -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"])
7800-
+ ],[tvOS], [
7804+
],
7805+
+ [*-apple-tvos*], [
78017806
+ AS_VAR_APPEND([CFLAGS], [" -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"])
78027807
+ AS_VAR_APPEND([LDFLAGS], [" -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"])
7803-
+ ],[watchOS], [
7808+
+ ],
7809+
+ [*-apple-watchos*], [
78047810
+ AS_VAR_APPEND([CFLAGS], [" -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"])
78057811
+ AS_VAR_APPEND([LDFLAGS], [" -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"])
7806-
],
7812+
+ ],
78077813
)
78087814

78097815
@@ -1136,6 +1327,9 @@ AC_MSG_CHECKING([for multiarch])

‎darwin/ios_patches/README.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,13 @@ When that happens:
3535
built nor shipped — that is exactly why the 3.12 patch here has had its
3636
`Lib/test/test_genericpath.py` hunk removed for 3.12.13).
3737

38+
The 3.12 patch also carries one fix that isn't about iOS: `Modules/_ssl.c` reads
39+
`ASN1_STRING` fields through `ASN1_STRING_length()` / `ASN1_STRING_get0_data()` instead of
40+
the struct members, as 3.13+ does upstream. OpenSSL 4 made `ASN1_STRING` opaque, and the
41+
native build-python that the Apple tool compiles first picks up whatever OpenSSL Homebrew
42+
links (`openssl@4` on current GitHub macOS runners), so without it the 3.12 build fails in
43+
`_ssl.c`. The accessors exist since OpenSSL 1.1.0, so the iOS slices (OpenSSL 3.x) are
44+
unaffected.
45+
3846
A minor-version bump (e.g. adding 3.15) means refreshing from the corresponding upstream
3947
back-port branch.

‎darwin/xcframework_utils.sh‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ create_plist() {
9393
<key>DTXcodeBuild</key>
9494
<string>$xcode_build</string>
9595
<key>MinimumOSVersion</key>
96-
<string>13.0</string>
96+
<string>15.0</string>
9797
<key>UIDeviceFamily</key>
9898
<array>
9999
<integer>1</integer>

‎manifest.json‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
{
22
"default_python_version": "3.14",
3-
"dart_bridge_version": "1.10.0",
3+
"dart_bridge_version": "1.11.0",
44
"pythons": {
55
"3.12": {
6-
"full_version": "3.12.14",
7-
"standalone_release_date": "20260901",
6+
"full_version": "3.12.15",
7+
"standalone_release_date": "20261001",
88
"pyodide_version": "0.27.8",
99
"pyodide_platform_tag": "pyodide-2024.0-wasm32",
1010
"android_abis": ["arm64-v8a", "x86_64", "armeabi-v7a"],
1111
"prerelease": false
1212
},
1313
"3.13": {
14-
"full_version": "3.13.15",
15-
"standalone_release_date": "20260901",
14+
"full_version": "3.13.16",
15+
"standalone_release_date": "20261001",
1616
"pyodide_version": "0.29.5",
1717
"pyodide_platform_tag": "pyemscripten-2025.0-wasm32",
1818
"android_abis": ["arm64-v8a", "x86_64", "armeabi-v7a"],
1919
"prerelease": false
2020
},
2121
"3.14": {
22-
"full_version": "3.14.7",
23-
"standalone_release_date": "20260901",
22+
"full_version": "3.14.8",
23+
"standalone_release_date": "20261001",
2424
"pyodide_version": "314.0.7",
2525
"pyodide_platform_tag": "pyemscripten-2026.0-wasm32",
2626
"android_abis": ["arm64-v8a", "x86_64", "armeabi-v7a"],

0 commit comments

Comments
 (0)