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..459558bb 100755 --- a/cpython-unix/build-cpython-host.sh +++ b/cpython-unix/build-cpython-host.sh @@ -38,7 +38,9 @@ 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 diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh index 87225429..c01475e7 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 + # FIXME: new patch may be required + : +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,7 +110,9 @@ 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 @@ -136,7 +143,11 @@ 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 +291,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 @@ -832,7 +843,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 +906,9 @@ 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/ +if [ -d Tools/scripts/run_tests.py ]; then + 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..e3570054 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): @@ -782,7 +783,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 +1196,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/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..f7a4ebd2 100644 --- a/cpython-windows/build.py +++ b/cpython-windows/build.py @@ -1700,10 +1700,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`. + if meets_python_minimum_version(python_version, "3.13"): + # TODO(zanieb): Write a script to invoke `python -m test --slow-ci` + # or update the metadata to not require `run_tests.py` + pathlib.Path( + out_dir / "python" / "build" / "run_tests.py", + ).touch() + 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/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 512f2d7f..052130ee 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..af94f7c6 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -287,6 +287,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 +648,6 @@ const GLOBAL_EXTENSIONS: &[&str] = &[ "_weakref", "array", "atexit", - "audioop", "binascii", "builtins", "cmath", @@ -665,13 +674,15 @@ 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"]; const GLOBAL_EXTENSIONS_PYTHON_3_9: &[&str] = &[ + "audioop", "_peg_parser", "_sha256", "_sha512", @@ -682,6 +693,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_9: &[&str] = &[ ]; const GLOBAL_EXTENSIONS_PYTHON_3_10: &[&str] = &[ + "audioop", "_sha256", "_sha512", "_uuid", @@ -690,6 +702,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_10: &[&str] = &[ ]; const GLOBAL_EXTENSIONS_PYTHON_3_11: &[&str] = &[ + "audioop", "_sha256", "_sha512", "_tokenize", @@ -700,6 +713,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_11: &[&str] = &[ ]; const GLOBAL_EXTENSIONS_PYTHON_3_12: &[&str] = &[ + "audioop", "_sha2", "_tokenize", "_typing", @@ -708,6 +722,19 @@ const GLOBAL_EXTENSIONS_PYTHON_3_12: &[&str] = &[ "_zoneinfo", ]; +const GLOBAL_EXTENSIONS_PYTHON_3_13: &[&str] = &[ + "_interpchannels", + "_interpqueues", + "_interpreters", + "_sha2", + "_suggestions", + "_sysconfig", + "_testexternalinspection", + "_tokenize", + "_typing", + "_zoneinfo", +]; + const GLOBAL_EXTENSIONS_MACOS: &[&str] = &["_scproxy"]; const GLOBAL_EXTENSIONS_POSIX: &[&str] = &[ @@ -729,7 +756,7 @@ 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", @@ -1448,6 +1475,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,6 +1485,9 @@ 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); } @@ -1470,14 +1503,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 +1530,7 @@ fn validate_extension_modules( ]); } - if (is_linux || is_macos) && python_major_minor == "3.12" { + if (is_linux || is_macos) && matches!(python_major_minor, "3.12" | "3.13") { wanted.insert("_testsinglephase"); } @@ -1500,7 +1544,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 +1667,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")); };