diff --git a/.github/workflows/apple.yml b/.github/workflows/apple.yml
index 8e46ec30..b36a6064 100644
--- a/.github/workflows/apple.yml
+++ b/.github/workflows/apple.yml
@@ -114,6 +114,19 @@ jobs:
py: 'cpython-3.12'
optimizations: 'pgo+lto'
+ - target_triple: 'aarch64-apple-darwin'
+ runner: macos-14
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ - target_triple: 'aarch64-apple-darwin'
+ runner: macos-14
+ py: 'cpython-3.13'
+ optimizations: 'pgo'
+ - target_triple: 'aarch64-apple-darwin'
+ runner: macos-14
+ py: 'cpython-3.13'
+ optimizations: 'pgo+lto'
+
# macOS on Intel hardware. This is pretty straightforward. We exclude
# noopt because it doesn't provide any compelling advantages over PGO
# or LTO builds.
@@ -181,6 +194,19 @@ jobs:
runner: macos-13
py: 'cpython-3.12'
optimizations: 'pgo+lto'
+
+ - target_triple: 'x86_64-apple-darwin'
+ runner: macos-13
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ - target_triple: 'x86_64-apple-darwin'
+ runner: macos-13
+ py: 'cpython-3.13'
+ optimizations: 'pgo'
+ - target_triple: 'x86_64-apple-darwin'
+ runner: macos-13
+ py: 'cpython-3.13'
+ optimizations: 'pgo+lto'
needs:
- pythonbuild
runs-on: ${{ matrix.build.runner }}
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 364d982e..4c354cc2 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -175,6 +175,16 @@ jobs:
py: 'cpython-3.12'
optimizations: 'lto'
+ - target_triple: 'aarch64-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ - target_triple: 'aarch64-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'noopt'
+ - target_triple: 'aarch64-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'lto'
+
# Cross-compiles can't do PGO and require Python 3.9.
- target_triple: 'armv7-unknown-linux-gnueabi'
py: 'cpython-3.9'
@@ -216,6 +226,16 @@ jobs:
py: 'cpython-3.12'
optimizations: 'lto'
+ - target_triple: 'armv7-unknown-linux-gnueabi'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ - target_triple: 'armv7-unknown-linux-gnueabi'
+ py: 'cpython-3.13'
+ optimizations: 'noopt'
+ - target_triple: 'armv7-unknown-linux-gnueabi'
+ py: 'cpython-3.13'
+ optimizations: 'lto'
+
# Cross-compiles can't do PGO and require Python 3.9.
- target_triple: 'armv7-unknown-linux-gnueabihf'
py: 'cpython-3.9'
@@ -257,6 +277,16 @@ jobs:
py: 'cpython-3.12'
optimizations: 'lto'
+ - target_triple: 'armv7-unknown-linux-gnueabihf'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ - target_triple: 'armv7-unknown-linux-gnueabihf'
+ py: 'cpython-3.13'
+ optimizations: 'noopt'
+ - target_triple: 'armv7-unknown-linux-gnueabihf'
+ py: 'cpython-3.13'
+ optimizations: 'lto'
+
# Cross-compiles can't do PGO and require Python 3.9.
- target_triple: 'mips-unknown-linux-gnu'
py: 'cpython-3.9'
@@ -298,6 +328,16 @@ jobs:
py: 'cpython-3.12'
optimizations: 'lto'
+ - target_triple: 'mips-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ - target_triple: 'mips-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'noopt'
+ - target_triple: 'mips-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'lto'
+
# Cross-compiles can't do PGO and require Python 3.9.
- target_triple: 'mipsel-unknown-linux-gnu'
py: 'cpython-3.9'
@@ -339,6 +379,16 @@ jobs:
py: 'cpython-3.12'
optimizations: 'lto'
+ - target_triple: 'mipsel-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ - target_triple: 'mipsel-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'noopt'
+ - target_triple: 'mipsel-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'lto'
+
# Cross-compiles can't do PGO and require Python 3.9.
- target_triple: 's390x-unknown-linux-gnu'
py: 'cpython-3.9'
@@ -380,6 +430,16 @@ jobs:
py: 'cpython-3.12'
optimizations: 'lto'
+ - target_triple: 's390x-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ - target_triple: 's390x-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'noopt'
+ - target_triple: 's390x-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'lto'
+
# Cross-compiles can't do PGO and require Python 3.9.
- target_triple: 'ppc64le-unknown-linux-gnu'
py: 'cpython-3.9'
@@ -421,6 +481,16 @@ jobs:
py: 'cpython-3.12'
optimizations: 'lto'
+ - target_triple: 'ppc64le-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ - target_triple: 'ppc64le-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'noopt'
+ - target_triple: 'ppc64le-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'lto'
+
# We don't publish noopt builds when PGO is available.
- target_triple: 'x86_64-unknown-linux-gnu'
py: 'cpython-3.8'
@@ -487,6 +557,19 @@ jobs:
optimizations: 'pgo+lto'
run: true
+ - target_triple: 'x86_64-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ run: true
+ - target_triple: 'x86_64-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'pgo'
+ run: true
+ - target_triple: 'x86_64-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'pgo+lto'
+ run: true
+
- target_triple: 'x86_64_v2-unknown-linux-gnu'
py: 'cpython-3.9'
optimizations: 'debug'
@@ -539,6 +622,19 @@ jobs:
optimizations: 'pgo+lto'
run: true
+ - target_triple: 'x86_64_v2-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ run: true
+ - target_triple: 'x86_64_v2-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'pgo'
+ run: true
+ - target_triple: 'x86_64_v2-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'pgo+lto'
+ run: true
+
- target_triple: 'x86_64_v3-unknown-linux-gnu'
py: 'cpython-3.9'
optimizations: 'debug'
@@ -591,6 +687,19 @@ jobs:
optimizations: 'pgo+lto'
run: true
+ - target_triple: 'x86_64_v3-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ run: true
+ - target_triple: 'x86_64_v3-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'pgo'
+ run: true
+ - target_triple: 'x86_64_v3-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'pgo+lto'
+ run: true
+
# GitHub Actions runners don't support x86-64-v4 so we can't PGO.
- target_triple: 'x86_64_v4-unknown-linux-gnu'
py: 'cpython-3.9'
@@ -633,6 +742,16 @@ jobs:
py: 'cpython-3.12'
optimizations: 'lto'
+ - target_triple: 'x86_64_v4-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ - target_triple: 'x86_64_v4-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'noopt'
+ - target_triple: 'x86_64_v4-unknown-linux-gnu'
+ py: 'cpython-3.13'
+ optimizations: 'lto'
+
# musl doesn't support PGO.
- target_triple: 'x86_64-unknown-linux-musl'
py: 'cpython-3.8'
@@ -699,6 +818,19 @@ jobs:
optimizations: 'lto'
run: true
+ - target_triple: 'x86_64-unknown-linux-musl'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ run: true
+ - target_triple: 'x86_64-unknown-linux-musl'
+ py: 'cpython-3.13'
+ optimizations: 'noopt'
+ run: true
+ - target_triple: 'x86_64-unknown-linux-musl'
+ py: 'cpython-3.13'
+ optimizations: 'lto'
+ run: true
+
- target_triple: 'x86_64_v2-unknown-linux-musl'
py: 'cpython-3.9'
optimizations: 'debug'
@@ -751,6 +883,19 @@ jobs:
optimizations: 'lto'
run: true
+ - target_triple: 'x86_64_v2-unknown-linux-musl'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ run: true
+ - target_triple: 'x86_64_v2-unknown-linux-musl'
+ py: 'cpython-3.13'
+ optimizations: 'noopt'
+ run: true
+ - target_triple: 'x86_64_v2-unknown-linux-musl'
+ py: 'cpython-3.13'
+ optimizations: 'lto'
+ run: true
+
- target_triple: 'x86_64_v3-unknown-linux-musl'
py: 'cpython-3.9'
optimizations: 'debug'
@@ -803,6 +948,19 @@ jobs:
optimizations: 'lto'
run: true
+ - target_triple: 'x86_64_v3-unknown-linux-musl'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ run: true
+ - target_triple: 'x86_64_v3-unknown-linux-musl'
+ py: 'cpython-3.13'
+ optimizations: 'noopt'
+ run: true
+ - target_triple: 'x86_64_v3-unknown-linux-musl'
+ py: 'cpython-3.13'
+ optimizations: 'lto'
+ run: true
+
- target_triple: 'x86_64_v4-unknown-linux-musl'
py: 'cpython-3.9'
optimizations: 'debug'
@@ -843,6 +1001,16 @@ jobs:
py: 'cpython-3.12'
optimizations: 'lto'
+ - target_triple: 'x86_64_v4-unknown-linux-musl'
+ py: 'cpython-3.13'
+ optimizations: 'debug'
+ - target_triple: 'x86_64_v4-unknown-linux-musl'
+ py: 'cpython-3.13'
+ optimizations: 'noopt'
+ - target_triple: 'x86_64_v4-unknown-linux-musl'
+ py: 'cpython-3.13'
+ optimizations: 'lto'
+
needs:
- pythonbuild
- image
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 2f2b5f3c..413cdd3f 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -54,6 +54,7 @@ jobs:
- 'cpython-3.10'
- 'cpython-3.11'
- 'cpython-3.12'
+ - 'cpython-3.13'
vcvars:
- 'vcvars32.bat'
- 'vcvars64.bat'
diff --git a/cpython-unix/Makefile b/cpython-unix/Makefile
index 08488956..d3225451 100644
--- a/cpython-unix/Makefile
+++ b/cpython-unix/Makefile
@@ -270,6 +270,8 @@ $(OUTDIR)/cpython-3.11-$(CPYTHON_3.11_VERSION)-$(HOST_PLATFORM).tar: $(PYTHON_HO
$(OUTDIR)/cpython-3.12-$(CPYTHON_3.12_VERSION)-$(HOST_PLATFORM).tar: $(PYTHON_HOST_DEPENDS)
$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) cpython-3.12-host
+$(OUTDIR)/cpython-3.13-$(CPYTHON_3.13_VERSION)-$(HOST_PLATFORM).tar: $(PYTHON_HOST_DEPENDS)
+ $(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) cpython-3.13-host
PYTHON_DEPENDS := \
$(PYTHON_SUPPORT_FILES) \
@@ -318,3 +320,6 @@ $(OUTDIR)/cpython-$(CPYTHON_3.11_VERSION)-$(PACKAGE_SUFFIX).tar: $(ALL_PYTHON_DE
$(OUTDIR)/cpython-$(CPYTHON_3.12_VERSION)-$(PACKAGE_SUFFIX).tar: $(ALL_PYTHON_DEPENDS)
$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) cpython-3.12
+
+$(OUTDIR)/cpython-$(CPYTHON_3.13_VERSION)-$(PACKAGE_SUFFIX).tar: $(ALL_PYTHON_DEPENDS)
+ $(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) cpython-3.13
diff --git a/cpython-unix/build-cpython-host.sh b/cpython-unix/build-cpython-host.sh
index cfc1e8a7..338219ad 100755
--- a/cpython-unix/build-cpython-host.sh
+++ b/cpython-unix/build-cpython-host.sh
@@ -38,11 +38,18 @@ pushd "Python-${PYTHON_VERSION}"
# configure. This is reported as https://bugs.python.org/issue45405. We nerf the
# check since we know what we're doing.
if [ "${CC}" = "clang" ]; then
- if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_9}" ]; then
+ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
+ patch -p1 -i ${ROOT}/patch-disable-multiarch-13.patch
+ elif [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_9}" ]; then
patch -p1 -i ${ROOT}/patch-disable-multiarch.patch
else
patch -p1 -i ${ROOT}/patch-disable-multiarch-legacy.patch
fi
+elif [ "${CC}" = "musl-clang" ]; then
+ # Similarly, this is a problem for musl Clang on Python 3.13+
+ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
+ patch -p1 -i ${ROOT}/patch-disable-multiarch-13.patch
+ fi
fi
autoconf
diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 87225429..1b37da8f 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -72,7 +72,10 @@ cat Makefile.extra
pushd Python-${PYTHON_VERSION}
# configure doesn't support cross-compiling on Apple. Teach it.
-if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
+if [ "${PYTHON_MAJMIN_VERSION}" = "3.13" ]; then
+ # TODO: Add support for cross-compiling on 3.13
+ :
+elif [ "${PYTHON_MAJMIN_VERSION}" = "3.12" ]; then
patch -p1 -i ${ROOT}/patch-apple-cross-3.12.patch
else
patch -p1 -i ${ROOT}/patch-apple-cross.patch
@@ -94,7 +97,9 @@ fi
# Configure nerfs RUNSHARED when cross-compiling, which prevents PGO from running when
# we can in fact run the target binaries (e.g. x86_64 host and i686 target). Undo that.
if [ -n "${CROSS_COMPILING}" ]; then
- if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_11}" ]; then
+ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
+ patch -p1 -i ${ROOT}/patch-dont-clear-runshared-13.patch
+ elif [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_11}" ]; then
patch -p1 -i ${ROOT}/patch-dont-clear-runshared.patch
else
patch -p1 -i ${ROOT}/patch-dont-clear-runshared-legacy.patch
@@ -105,11 +110,18 @@ fi
# configure. This is reported as https://bugs.python.org/issue45405. We nerf the
# check since we know what we're doing.
if [ "${CC}" = "clang" ]; then
- if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_9}" ]; then
+ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
+ patch -p1 -i ${ROOT}/patch-disable-multiarch-13.patch
+ elif [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_9}" ]; then
patch -p1 -i ${ROOT}/patch-disable-multiarch.patch
else
patch -p1 -i ${ROOT}/patch-disable-multiarch-legacy.patch
fi
+elif [ "${CC}" = "musl-clang" ]; then
+ # Similarly, this is a problem for musl Clang on Python 3.13+
+ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
+ patch -p1 -i ${ROOT}/patch-disable-multiarch-13.patch
+ fi
fi
# Python 3.11 supports using a provided Python to use during bootstrapping
@@ -134,9 +146,19 @@ if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_10}" ]; then
patch -p1 -i ${ROOT}/patch-makesetup-deduplicate-objs.patch
fi
+# testembed links against Tcl/Tk and libpython which already includes Tcl/Tk leading duplicate
+# symbols and warnings from objc (which then causes failures in `test_embed` during PGO).
+if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" ]; then
+ patch -p1 -i ${ROOT}/patch-make-testembed-nolink-tcltk.patch
+fi
+
# The default build rule for the macOS dylib doesn't pick up libraries
# from modules / makesetup. So patch it accordingly.
-patch -p1 -i ${ROOT}/patch-macos-link-extension-modules.patch
+if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
+ patch -p1 -i ${ROOT}/patch-macos-link-extension-modules-13.patch
+else
+ patch -p1 -i ${ROOT}/patch-macos-link-extension-modules.patch
+fi
# Also on macOS, the `python` executable is linked against libraries defined by statically
# linked modules. But those libraries should only get linked into libpython, not the
@@ -280,7 +302,7 @@ if [ "${PYBUILD_PLATFORM}" != "macos" ]; then
fi
fi
-# On Python 3.12 we need to link the special hacl library provided some SHA-256
+# On Python 3.12+ we need to link the special hacl library provided some SHA-256
# implementations. Since we hack up the regular extension building mechanism, we
# need to reinvent this wheel.
if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
@@ -336,7 +358,12 @@ fi
if [ -n "${CPYTHON_OPTIMIZED}" ]; then
CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-optimizations"
- if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" && -n "${BOLT_CAPABLE}" ]]; then
+ if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" && -n "${BOLT_CAPABLE}" ]]; then
+ # Due to a SEGFAULT when running `test_embed` with BOLT instrumented binaries, we can't use
+ # BOLT on Python 3.13+.
+ # TODO: Find a fix for this or consider skipping these tests specifically
+ echo "BOLT is disabled on Python 3.13+"
+ elif [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" && -n "${BOLT_CAPABLE}" ]]; then
CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-bolt"
fi
fi
@@ -426,6 +453,11 @@ if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
export MACOSX_DEPLOYMENT_TARGET="${APPLE_MIN_DEPLOYMENT_TARGET}"
fi
+# ptsrname_r is only available in SDK 13.4+, but we target a lower version for compatibility.
+if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+ CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_func_ptsname_r=no"
+fi
+
# We use ndbm on macOS and BerkeleyDB elsewhere.
if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --with-dbmliborder=ndbm"
@@ -742,7 +774,13 @@ s390x-unknown-linux-gnu)
PYTHON_ARCH="s390x-linux-gnu"
;;
x86_64-unknown-linux-*)
- PYTHON_ARCH="x86_64-linux-gnu"
+ # In Python 3.13+, the musl target is identified in cross compiles and the output directory
+ # is named accordingly.
+ if [ "${CC}" = "musl-clang" ] && [ "${PYTHON_MAJMIN_VERSION}" = "3.13" ]; then
+ PYTHON_ARCH="x86_64-linux-musl"
+ else
+ PYTHON_ARCH="x86_64-linux-gnu"
+ fi
;;
*)
echo "unhandled target triple: ${TARGET_TRIPLE}"
@@ -832,7 +870,7 @@ ${BUILD_PYTHON} ${ROOT}/fix_shebangs.py ${ROOT}/out/python/install
# downstream consumers.
OBJECT_DIRS="Objects Parser Parser/pegen Programs Python"
OBJECT_DIRS="${OBJECT_DIRS} Modules"
-for ext in _blake2 cjkcodecs _ctypes _ctypes/darwin _decimal _expat _hacl _io _multiprocessing _sha3 _sqlite _sre _xxtestfuzz ; do
+for ext in _blake2 cjkcodecs _ctypes _ctypes/darwin _decimal _expat _hacl _io _multiprocessing _sha3 _sqlite _sre _testinternalcapi _xxtestfuzz ; do
OBJECT_DIRS="${OBJECT_DIRS} Modules/${ext}"
done
@@ -895,7 +933,12 @@ cp -av Python/frozen.c ${ROOT}/out/python/build/Python/
cp -av Modules/Setup* ${ROOT}/out/python/build/Modules/
# Copy the test hardness runner for convenience.
-cp -av Tools/scripts/run_tests.py ${ROOT}/out/python/build/
+# As of Python 3.13, the test harness runner has been removed so we provide a compatibility script
+if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
+ cp -av ${ROOT}/run_tests-13.py ${ROOT}/out/python/build/run_tests.py
+else
+ cp -av Tools/scripts/run_tests.py ${ROOT}/out/python/build/
+fi
mkdir ${ROOT}/out/python/licenses
cp ${ROOT}/LICENSE.*.txt ${ROOT}/out/python/licenses/
diff --git a/cpython-unix/build-main.py b/cpython-unix/build-main.py
index b9b3c5dc..34a90d19 100755
--- a/cpython-unix/build-main.py
+++ b/cpython-unix/build-main.py
@@ -67,6 +67,7 @@ def main():
"cpython-3.10",
"cpython-3.11",
"cpython-3.12",
+ "cpython-3.13",
},
default="cpython-3.11",
help="Python distribution to build",
diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index ccea702c..5c32586b 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -435,6 +435,7 @@ def build_cpython_host(
support = {
"build-cpython-host.sh",
"patch-disable-multiarch.patch",
+ "patch-disable-multiarch-13.patch",
"patch-disable-multiarch-legacy.patch",
}
for s in sorted(support):
@@ -455,7 +456,7 @@ def build_cpython_host(
# Set environment variables allowing convenient testing for Python
# version ranges.
- for v in ("3.8", "3.9", "3.10", "3.11", "3.12"):
+ for v in ("3.8", "3.9", "3.10", "3.11", "3.12", "3.13"):
normal_version = v.replace(".", "_")
if meets_python_minimum_version(python_version, v):
@@ -745,6 +746,7 @@ def build_cpython(
setuptools_archive,
pip_archive,
SUPPORT / "build-cpython.sh",
+ SUPPORT / "run_tests-13.py",
):
build_env.copy_file(p)
@@ -782,7 +784,7 @@ def build_cpython(
# Set environment variables allowing convenient testing for Python
# version ranges.
- for v in ("3.8", "3.9", "3.10", "3.11", "3.12"):
+ for v in ("3.8", "3.9", "3.10", "3.11", "3.12", "3.13"):
normal_version = v.replace(".", "_")
if meets_python_minimum_version(python_version, v):
@@ -1195,6 +1197,7 @@ def main():
"cpython-3.10",
"cpython-3.11",
"cpython-3.12",
+ "cpython-3.13",
):
build_cpython(
settings,
diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml
index 37f78101..52150b59 100644
--- a/cpython-unix/extension-modules.yml
+++ b/cpython-unix/extension-modules.yml
@@ -67,6 +67,7 @@ _contextvars:
- _contextvarsmodule.c
_crypt:
+ maximum-python-version: "3.12"
build-mode: shared
sources:
- _cryptmodule.c
@@ -286,6 +287,21 @@ _heapq:
_imp:
config-c-only: true
+_interpchannels:
+ minimum-python-version: "3.13"
+ sources:
+ - _interpchannelsmodule.c
+
+_interpqueues:
+ minimum-python-version: "3.13"
+ sources:
+ - _interpqueuesmodule.c
+
+_interpreters:
+ minimum-python-version: "3.13"
+ sources:
+ - _interpretersmodule.c
+
_io:
setup-enabled: true
required-targets:
@@ -528,9 +544,21 @@ _struct:
sources:
- _struct.c
+_suggestions:
+ setup-enabled: true
+ minimum-python-version: '3.13'
+ sources:
+ - _suggestions.c
+
_symtable:
setup-enabled: true
+_sysconfig:
+ setup-enabled: true
+ minimum-python-version: '3.13'
+ sources:
+ - _sysconfig.c
+
_testbuffer:
minimum-python-version: '3.9'
sources:
@@ -545,6 +573,11 @@ _testcapi:
sources:
- _testcapimodule.c
+_testexternalinspection:
+ minimum-python-version: '3.13'
+ sources:
+ - _testexternalinspection.c
+
_testimportmultiple:
minimum-python-version: '3.9'
sources:
@@ -558,6 +591,18 @@ _testinternalcapi:
- Include/internal
sources:
- _testinternalcapi.c
+ includes-conditional:
+ - path: _testinternalcapi/parts.h
+ minimum-python-version: "3.13"
+ sources-conditional:
+ - source: _testinternalcapi/pytime.c
+ minimum-python-version: "3.13"
+ - source: _testinternalcapi/set.c
+ minimum-python-version: "3.13"
+ - source: _testinternalcapi/test_critical_sections.c
+ minimum-python-version: "3.13"
+ - source: _testinternalcapi/test_lock.c
+ minimum-python-version: "3.13"
_testmultiphase:
minimum-python-version: '3.9'
@@ -659,11 +704,13 @@ _weakref:
_xxinterpchannels:
minimum-python-version: '3.12'
+ maximum-python-version: '3.12'
sources:
- _xxinterpchannelsmodule.c
_xxsubinterpreters:
minimum-python-version: '3.9'
+ maximum-python-version: '3.12'
sources:
- _xxsubinterpretersmodule.c
@@ -687,6 +734,7 @@ atexit:
# Modules/Setup comment is ambiguous as to whether this module actually works.
audioop:
+ maximum-python-version: '3.12'
sources:
- audioop.c
@@ -745,6 +793,7 @@ mmap:
- mmapmodule.c
nis:
+ maximum-python-version: "3.12"
disabled-targets:
# NIS is not available on Apple OS.
- aarch64-apple-.*
@@ -767,6 +816,7 @@ nis:
- nsl
ossaudiodev:
+ maximum-python-version: "3.12"
disabled-targets:
# ossaudiodev not available on Apple OS.
- aarch64-apple-.*
@@ -806,6 +856,7 @@ readline:
- readline.c
defines:
- USE_LIBEDIT=1
+ - Py_RL_STARTUP_HOOK_TAKES_ARGS
includes-deps:
- libedit/include
- libedit/include/ncursesw
@@ -828,6 +879,7 @@ select:
- selectmodule.c
spwd:
+ maximum-python-version: "3.12"
sources:
- spwdmodule.c
diff --git a/cpython-unix/patch-disable-multiarch-13.patch b/cpython-unix/patch-disable-multiarch-13.patch
new file mode 100644
index 00000000..3ff33246
--- /dev/null
+++ b/cpython-unix/patch-disable-multiarch-13.patch
@@ -0,0 +1,17 @@
+diff -u 13-a/configure.ac 13-b/configure.ac
+--- 13-a/configure.ac 2024-05-08 05:21:00.000000000 -0400
++++ 13-b/configure.ac 2024-05-19 07:42:23.294762624 -0400
+@@ -1090,12 +1090,7 @@
+ dnl architecture. PLATFORM_TRIPLET will be a pair or single value for these
+ dnl platforms.
+ AC_MSG_CHECKING([for multiarch])
+-AS_CASE([$ac_sys_system],
+- [Darwin*], [MULTIARCH=""],
+- [iOS], [MULTIARCH=""],
+- [FreeBSD*], [MULTIARCH=""],
+- [MULTIARCH=$($CC --print-multiarch 2>/dev/null)]
+-)
++MULTIARCH=
+ AC_SUBST([MULTIARCH])
+
+ if test x$PLATFORM_TRIPLET != x && test x$MULTIARCH != x; then
diff --git a/cpython-unix/patch-dont-clear-runshared-13.patch b/cpython-unix/patch-dont-clear-runshared-13.patch
new file mode 100644
index 00000000..7dcba084
--- /dev/null
+++ b/cpython-unix/patch-dont-clear-runshared-13.patch
@@ -0,0 +1,14 @@
+diff -u 13-a/configure.ac 13-b/configure.ac
+--- 13-a/configure.ac 2024-05-08 05:21:00.000000000 -0400
++++ 13-b/configure.ac 2024-05-19 12:44:04.530770938 -0400
+@@ -1564,10 +1564,6 @@
+ fi
+ AC_MSG_RESULT([$LDLIBRARY])
+
+-if test "$cross_compiling" = yes; then
+- RUNSHARED=
+-fi
+-
+ AC_MSG_CHECKING([HOSTRUNNER])
+ AC_ARG_VAR([HOSTRUNNER], [Program to run CPython for the host platform])
+ if test -z "$HOSTRUNNER"
diff --git a/cpython-unix/patch-macos-link-extension-modules-13.patch b/cpython-unix/patch-macos-link-extension-modules-13.patch
new file mode 100644
index 00000000..75b0d781
--- /dev/null
+++ b/cpython-unix/patch-macos-link-extension-modules-13.patch
@@ -0,0 +1,12 @@
+diff -u 13-a/Makefile.pre.in 13-b/Makefile.pre.in
+--- 13-a/Makefile.pre.in 2024-05-08 05:21:00.000000000 -0400
++++ 13-b/Makefile.pre.in 2024-05-19 07:55:45.091521909 -0400
+@@ -903,7 +903,7 @@
+ $(BLDSHARED) $(NO_AS_NEEDED) -o $@ -Wl,-h$@ $^
+
+ libpython$(LDVERSION).dylib: $(LIBRARY_OBJS)
+- $(CC) -dynamiclib $(PY_CORE_LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(LDVERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(DTRACE_OBJS) $(SHLIBS) $(LIBC) $(LIBM); \
++ $(CC) -dynamiclib $(PY_CORE_LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(LDVERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(DTRACE_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM); \
+
+
+ libpython$(VERSION).sl: $(LIBRARY_OBJS)
diff --git a/cpython-unix/patch-make-testembed-nolink-tcltk.patch b/cpython-unix/patch-make-testembed-nolink-tcltk.patch
new file mode 100644
index 00000000..65c1989f
--- /dev/null
+++ b/cpython-unix/patch-make-testembed-nolink-tcltk.patch
@@ -0,0 +1,10 @@
+diff --git a/Makefile.pre.in b/Makefile.pre.in
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -1432,6 +1432,8 @@
+ $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/build/generate_re_casefix.py $(srcdir)/Lib/re/_casefix.py
+
+ Programs/_testembed: Programs/_testembed.o $(LINK_PYTHON_DEPS)
++ $(eval MODLIBS := $(subst -Xlinker -hidden-ltcl8.6, , $(MODLIBS)))
++ $(eval MODLIBS := $(subst -Xlinker -hidden-ltk8.6, , $(MODLIBS)))
+ $(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/_testembed.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS)
diff --git a/cpython-unix/run_tests-13.py b/cpython-unix/run_tests-13.py
new file mode 100644
index 00000000..a78210cc
--- /dev/null
+++ b/cpython-unix/run_tests-13.py
@@ -0,0 +1,30 @@
+"""
+Run Python's test suite.
+
+As of Python 3.13, this script is no longer included in Python itself.
+Instead, use:
+
+ $ python -m test --slow-ci
+
+"""
+
+import os
+import sys
+
+
+def main(regrtest_args):
+ args = [
+ sys.executable,
+ "-m",
+ "test",
+ "--slow-ci",
+ ]
+
+ args.extend(regrtest_args)
+ print(" ".join(args))
+
+ os.execv(sys.executable, args)
+
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/cpython-unix/targets.yml b/cpython-unix/targets.yml
index fd81e286..02e41311 100644
--- a/cpython-unix/targets.yml
+++ b/cpython-unix/targets.yml
@@ -64,6 +64,7 @@ aarch64-apple-darwin:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
needs_toolchain: true
host_cc: clang
host_cxx: clang++
@@ -153,6 +154,7 @@ aarch64-unknown-linux-gnu:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
docker_image_suffix: .cross
host_cc: /usr/bin/x86_64-linux-gnu-gcc
host_cxx: /usr/bin/x86_64-linux-gnu-g++
@@ -231,6 +233,7 @@ armv7-unknown-linux-gnueabi:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
docker_image_suffix: .cross
host_cc: /usr/bin/x86_64-linux-gnu-gcc
host_cxx: /usr/bin/x86_64-linux-gnu-g++
@@ -269,6 +272,7 @@ armv7-unknown-linux-gnueabihf:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
docker_image_suffix: .cross
host_cc: /usr/bin/x86_64-linux-gnu-gcc
host_cxx: /usr/bin/x86_64-linux-gnu-g++
@@ -308,6 +312,7 @@ i686-unknown-linux-gnu:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
needs_toolchain: true
host_cc: clang
host_cxx: clang++
@@ -351,6 +356,7 @@ mips-unknown-linux-gnu:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
docker_image_suffix: .cross
host_cc: /usr/bin/x86_64-linux-gnu-gcc
host_cxx: /usr/bin/x86_64-linux-gnu-g++
@@ -389,6 +395,7 @@ mipsel-unknown-linux-gnu:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
docker_image_suffix: .cross
host_cc: /usr/bin/x86_64-linux-gnu-gcc
host_cxx: /usr/bin/x86_64-linux-gnu-g++
@@ -427,6 +434,7 @@ ppc64le-unknown-linux-gnu:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
docker_image_suffix: .cross
host_cc: /usr/bin/x86_64-linux-gnu-gcc
host_cxx: /usr/bin/x86_64-linux-gnu-g++
@@ -465,6 +473,7 @@ s390x-unknown-linux-gnu:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
docker_image_suffix: .cross
host_cc: /usr/bin/x86_64-linux-gnu-gcc
host_cxx: /usr/bin/x86_64-linux-gnu-g++
@@ -548,6 +557,7 @@ x86_64-apple-darwin:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
needs_toolchain: true
apple_sdk_platform: macosx
host_cc: clang
@@ -717,6 +727,7 @@ x86_64-unknown-linux-gnu:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
needs_toolchain: true
host_cc: clang
host_cxx: clang++
@@ -761,6 +772,7 @@ x86_64_v2-unknown-linux-gnu:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
needs_toolchain: true
host_cc: clang
host_cxx: clang++
@@ -806,6 +818,7 @@ x86_64_v3-unknown-linux-gnu:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
needs_toolchain: true
host_cc: clang
host_cxx: clang++
@@ -851,6 +864,7 @@ x86_64_v4-unknown-linux-gnu:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
needs_toolchain: true
host_cc: clang
host_cxx: clang++
@@ -896,6 +910,7 @@ x86_64-unknown-linux-musl:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
needs_toolchain: true
host_cc: clang
host_cxx: clang++
@@ -938,6 +953,7 @@ x86_64_v2-unknown-linux-musl:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
needs_toolchain: true
host_cc: clang
host_cxx: clang++
@@ -981,6 +997,7 @@ x86_64_v3-unknown-linux-musl:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
needs_toolchain: true
host_cc: clang
host_cxx: clang++
@@ -1024,6 +1041,7 @@ x86_64_v4-unknown-linux-musl:
- '3.10'
- '3.11'
- '3.12'
+ - '3.13'
needs_toolchain: true
host_cc: clang
host_cxx: clang++
diff --git a/cpython-windows/build.py b/cpython-windows/build.py
index bc97cd57..88bcf6e0 100644
--- a/cpython-windows/build.py
+++ b/cpython-windows/build.py
@@ -65,7 +65,10 @@
"_lzma": {
"ignore_additional_depends": {"$(OutDir)liblzma$(PyDebugExt).lib"},
},
- "_msi": {},
+ "_msi": {
+ # Removed in 3.13.
+ "ignore_missing": True,
+ },
"_overlapped": {},
"_multiprocessing": {},
"_socket": {},
@@ -352,6 +355,7 @@ def hack_props(
xz_version = DOWNLOADS["xz"]["version"]
zlib_version = DOWNLOADS["zlib"]["version"]
tcltk_commit = DOWNLOADS["tk-windows-bin"]["git_commit"]
+ mpdecimal_version = DOWNLOADS["mpdecimal"]["version"]
sqlite_path = td / ("sqlite-autoconf-%s" % sqlite_version)
bzip2_path = td / ("bzip2-%s" % bzip2_version)
@@ -359,6 +363,7 @@ def hack_props(
tcltk_path = td / ("cpython-bin-deps-%s" % tcltk_commit)
xz_path = td / ("xz-%s" % xz_version)
zlib_path = td / ("zlib-%s" % zlib_version)
+ mpdecimal_path = td / ("mpdecimal-%s" % mpdecimal_version)
openssl_root = td / "openssl" / arch
openssl_libs_path = openssl_root / "lib"
@@ -398,6 +403,9 @@ def hack_props(
elif b"%s\\" % zlib_path
+ elif b"%s\\" % mpdecimal_path
+
lines.append(line)
with python_props_path.open("wb") as fh:
@@ -1155,15 +1163,17 @@ def collect_python_build_artifacts(
"_ctypes_test",
"_testbuffer",
"_testcapi",
+ "_testclinic_limited",
"_testclinic",
"_testconsole",
"_testembed",
"_testimportmultiple",
"_testinternalcapi",
- "_testsinglephase",
+ "_testlimitedcapi",
"_testmultiphase",
- "xxlimited",
+ "_testsinglephase",
"xxlimited_35",
+ "xxlimited",
}
other_projects = {"pythoncore"}
@@ -1409,6 +1419,14 @@ def build_cpython(
setuptools_wheel = download_entry("setuptools", BUILD)
pip_wheel = download_entry("pip", BUILD)
+ # CPython 3.13+ no longer uses a bundled `mpdecimal` version so we build it
+ if meets_python_minimum_version(python_version, "3.13"):
+ mpdecimal_archive = download_entry("mpdecimal", BUILD)
+ else:
+ # TODO: Consider using the built mpdecimal for earlier versions as well,
+ # as we do for Unix builds.
+ mpdecimal_archive = None
+
if arch == "amd64":
build_platform = "x64"
build_directory = "amd64"
@@ -1426,12 +1444,16 @@ def build_cpython(
for a in (
python_archive,
bzip2_archive,
+ mpdecimal_archive,
openssl_archive,
sqlite_archive,
tk_bin_archive,
xz_archive,
zlib_archive,
):
+ if a is None:
+ continue
+
log("extracting %s to %s" % (a, td))
fs.append(e.submit(extract_tar_to_directory, a, td))
@@ -1700,10 +1722,18 @@ def build_cpython(
log("copying %s to %s" % (source, dest))
shutil.copyfile(source, dest)
- shutil.copyfile(
- cpython_source_path / "Tools" / "scripts" / "run_tests.py",
- out_dir / "python" / "build" / "run_tests.py",
- )
+ # CPython 3.13 removed `run_tests.py`, we provide a compatibility script
+ # for now.
+ if meets_python_minimum_version(python_version, "3.13"):
+ shutil.copyfile(
+ SUPPORT / "run_tests-13.py",
+ out_dir / "python" / "build" / "run_tests.py",
+ )
+ else:
+ shutil.copyfile(
+ cpython_source_path / "Tools" / "scripts" / "run_tests.py",
+ out_dir / "python" / "build" / "run_tests.py",
+ )
licenses_dir = out_dir / "python" / "licenses"
licenses_dir.mkdir()
diff --git a/cpython-windows/run_tests-13.py b/cpython-windows/run_tests-13.py
new file mode 100644
index 00000000..f3c165fb
--- /dev/null
+++ b/cpython-windows/run_tests-13.py
@@ -0,0 +1,30 @@
+"""
+Run Python's test suite.
+
+As of Python 3.13, this script is no longer included in Python itself.
+Instead, use:
+
+ $ python -m test --slow-ci
+
+"""
+
+import sys
+from subprocess import call
+
+
+def main(regrtest_args):
+ args = [
+ sys.executable,
+ "-m",
+ "test",
+ "--slow-ci",
+ ]
+
+ args.extend(regrtest_args)
+ print(" ".join(args))
+
+ sys.exit(call(args))
+
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/pythonbuild/cpython.py b/pythonbuild/cpython.py
index 97a715d5..c499cc0f 100644
--- a/pythonbuild/cpython.py
+++ b/pythonbuild/cpython.py
@@ -41,6 +41,8 @@
"properties": {
"path": {"type": "string"},
"targets": {"type": "array", "items": {"type": "string"}},
+ "minimum-python-version": {"type": "string"},
+ "maximum-python-version": {"type": "string"},
},
"additionalProperties": False,
},
@@ -534,7 +536,19 @@ def derive_setup_local(
line += f" -I{path}"
for entry in info.get("includes-conditional", []):
- if any(re.match(p, target_triple) for p in entry["targets"]):
+ if targets := entry.get("targets", []):
+ target_match = any(re.match(p, target_triple) for p in targets)
+ else:
+ target_match = True
+
+ python_min_match = meets_python_minimum_version(
+ python_version, entry.get("minimum-python-version", "1.0")
+ )
+ python_max_match = meets_python_maximum_version(
+ python_version, entry.get("maximum-python-version", "100.0")
+ )
+
+ if target_match and (python_min_match and python_max_match):
line += f" -I{entry['path']}"
for path in info.get("includes-deps", []):
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 16835ac7..c526b3eb 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -79,6 +79,15 @@
"license_file": "LICENSE.cpython.txt",
"python_tag": "cp312",
},
+ "cpython-3.13": {
+ "url": "https://www.python.org/ftp/python/3.13.0/Python-3.13.0rc1.tar.xz",
+ "size": 20881016,
+ "sha256": "678b884775eec0224d5159fa900879020baca2a36ce942fd95febfa1adb4a6bd",
+ "version": "3.13.0rc1",
+ "licenses": ["Python-2.0", "CNRI-Python"],
+ "license_file": "LICENSE.cpython.txt",
+ "python_tag": "cp313",
+ },
"expat": {
"url": "https://github.com/libexpat/libexpat/releases/download/R_2_5_0/expat-2.5.0.tar.xz",
"size": 460560,
diff --git a/src/validation.rs b/src/validation.rs
index 12155132..f77c44cd 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -125,6 +125,7 @@ const PE_ALLOWED_LIBRARIES: &[&str] = &[
"python310.dll",
"python311.dll",
"python312.dll",
+ "python313.dll",
"sqlite3.dll",
"tcl86t.dll",
"tk86t.dll",
@@ -287,6 +288,16 @@ static DARWIN_ALLOWED_DYLIBS: Lazy> = Lazy::new(|| {
max_compatibility_version: "3.12.0".try_into().unwrap(),
required: false,
},
+ MachOAllowedDylib {
+ name: "@executable_path/../lib/libpython3.13.dylib".to_string(),
+ max_compatibility_version: "3.13.0".try_into().unwrap(),
+ required: false,
+ },
+ MachOAllowedDylib {
+ name: "@executable_path/../lib/libpython3.13d.dylib".to_string(),
+ max_compatibility_version: "3.13.0".try_into().unwrap(),
+ required: false,
+ },
MachOAllowedDylib {
name: "/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit".to_string(),
max_compatibility_version: "45.0.0".try_into().unwrap(),
@@ -638,7 +649,6 @@ const GLOBAL_EXTENSIONS: &[&str] = &[
"_weakref",
"array",
"atexit",
- "audioop",
"binascii",
"builtins",
"cmath",
@@ -665,13 +675,21 @@ const GLOBAL_EXTENSIONS: &[&str] = &[
// _testsinglephase added in 3.12.
// _sha256 and _sha512 merged into _sha2 in 3.12.
// _xxinterpchannels added in 3.12.
+// audioop removed in 3.13.
// We didn't build ctypes_test until 3.9.
// We didn't build some test extensions until 3.9.
-const GLOBAL_EXTENSIONS_PYTHON_3_8: &[&str] = &["_sha256", "_sha512", "parser"];
+const GLOBAL_EXTENSIONS_PYTHON_3_8: &[&str] = &[
+ "audioop",
+ "_sha256",
+ "_sha512",
+ "parser",
+ "_xxsubinterpreters",
+];
const GLOBAL_EXTENSIONS_PYTHON_3_9: &[&str] = &[
+ "audioop",
"_peg_parser",
"_sha256",
"_sha512",
@@ -682,6 +700,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_9: &[&str] = &[
];
const GLOBAL_EXTENSIONS_PYTHON_3_10: &[&str] = &[
+ "audioop",
"_sha256",
"_sha512",
"_uuid",
@@ -690,6 +709,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_10: &[&str] = &[
];
const GLOBAL_EXTENSIONS_PYTHON_3_11: &[&str] = &[
+ "audioop",
"_sha256",
"_sha512",
"_tokenize",
@@ -700,6 +720,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_11: &[&str] = &[
];
const GLOBAL_EXTENSIONS_PYTHON_3_12: &[&str] = &[
+ "audioop",
"_sha2",
"_tokenize",
"_typing",
@@ -708,6 +729,17 @@ const GLOBAL_EXTENSIONS_PYTHON_3_12: &[&str] = &[
"_zoneinfo",
];
+const GLOBAL_EXTENSIONS_PYTHON_3_13: &[&str] = &[
+ "_interpchannels",
+ "_interpqueues",
+ "_interpreters",
+ "_sha2",
+ "_sysconfig",
+ "_tokenize",
+ "_typing",
+ "_zoneinfo",
+];
+
const GLOBAL_EXTENSIONS_MACOS: &[&str] = &["_scproxy"];
const GLOBAL_EXTENSIONS_POSIX: &[&str] = &[
@@ -729,19 +761,19 @@ const GLOBAL_EXTENSIONS_POSIX: &[&str] = &[
"termios",
];
-const GLOBAL_EXTENSIONS_LINUX: &[&str] = &["spwd"];
+const GLOBAL_EXTENSIONS_LINUX_PRE_3_13: &[&str] = &["spwd"];
const GLOBAL_EXTENSIONS_WINDOWS: &[&str] = &[
- "_msi",
"_overlapped",
"_winapi",
- "_xxsubinterpreters",
"msvcrt",
"nt",
"winreg",
"winsound",
];
+const GLOBAL_EXTENSIONS_WINDOWS_PRE_3_13: &[&str] = &["_msi"];
+
/// Extension modules not present in Windows static builds.
const GLOBAL_EXTENSIONS_WINDOWS_NO_STATIC: &[&str] = &["_testinternalcapi", "_tkinter"];
@@ -1448,6 +1480,9 @@ fn validate_extension_modules(
"3.12" => {
wanted.extend(GLOBAL_EXTENSIONS_PYTHON_3_12);
}
+ "3.13" => {
+ wanted.extend(GLOBAL_EXTENSIONS_PYTHON_3_13);
+ }
_ => {
panic!("unhandled Python version: {}", python_major_minor);
}
@@ -1455,12 +1490,19 @@ fn validate_extension_modules(
if is_macos {
wanted.extend(GLOBAL_EXTENSIONS_POSIX);
+ if python_major_minor == "3.13" {
+ wanted.remove("_crypt");
+ }
wanted.extend(GLOBAL_EXTENSIONS_MACOS);
}
if is_windows {
wanted.extend(GLOBAL_EXTENSIONS_WINDOWS);
+ if matches!(python_major_minor, "3.8" | "3.9" | "3.10" | "3.11" | "3.12") {
+ wanted.extend(GLOBAL_EXTENSIONS_WINDOWS_PRE_3_13);
+ }
+
if static_crt {
for x in GLOBAL_EXTENSIONS_WINDOWS_NO_STATIC {
wanted.remove(*x);
@@ -1470,14 +1512,25 @@ fn validate_extension_modules(
if is_linux {
wanted.extend(GLOBAL_EXTENSIONS_POSIX);
- wanted.extend(GLOBAL_EXTENSIONS_LINUX);
+ if python_major_minor == "3.13" {
+ wanted.remove("_crypt");
+ }
+ if matches!(python_major_minor, "3.8" | "3.9" | "3.10" | "3.11" | "3.12") {
+ wanted.extend(GLOBAL_EXTENSIONS_LINUX_PRE_3_13);
+ }
- if !is_linux_musl {
+ if !is_linux_musl && matches!(python_major_minor, "3.8" | "3.9" | "3.10" | "3.11" | "3.12")
+ {
wanted.insert("ossaudiodev");
}
}
- if (is_linux || is_macos) && matches!(python_major_minor, "3.9" | "3.10" | "3.11" | "3.12") {
+ if (is_linux || is_macos)
+ && matches!(
+ python_major_minor,
+ "3.9" | "3.10" | "3.11" | "3.12" | "3.13"
+ )
+ {
wanted.extend([
"_testbuffer",
"_testimportmultiple",
@@ -1486,7 +1539,11 @@ fn validate_extension_modules(
]);
}
- if (is_linux || is_macos) && python_major_minor == "3.12" {
+ if (is_linux || is_macos) && python_major_minor == "3.13" {
+ wanted.extend(["_suggestions", "_testexternalinspection"]);
+ }
+
+ if (is_linux || is_macos) && matches!(python_major_minor, "3.12" | "3.13") {
wanted.insert("_testsinglephase");
}
@@ -1500,7 +1557,7 @@ fn validate_extension_modules(
}
// _wmi is Windows only on 3.12+.
- if python_major_minor == "3.12" && is_windows {
+ if matches!(python_major_minor, "3.12" | "3.13") && is_windows {
wanted.insert("_wmi");
}
@@ -1623,6 +1680,8 @@ fn validate_distribution(
"3.11"
} else if dist_filename.starts_with("cpython-3.12.") {
"3.12"
+ } else if dist_filename.starts_with("cpython-3.13.") {
+ "3.13"
} else {
return Err(anyhow!("could not parse Python version from filename"));
};
@@ -1903,9 +1962,14 @@ fn validate_distribution(
// Static distributions never export symbols.
let wanted = if is_static {
false
- // For some strange reason _PyWarnings_Init is exported as part of the ABI.
+ // For some strange reason _PyWarnings_Init is exported as part of the ABI
} else if name == "_warnings" {
- true
+ // But not on Python 3.13 on Windows
+ if triple.contains("-windows-") {
+ matches!(python_major_minor, "3.8" | "3.9" | "3.10" | "3.11" | "3.12")
+ } else {
+ true
+ }
// Windows dynamic doesn't export extension module init functions.
} else if triple.contains("-windows-") {
false