diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh index b44bb971..49e1873c 100755 --- a/cpython-unix/build-cpython.sh +++ b/cpython-unix/build-cpython.sh @@ -466,7 +466,8 @@ if [ -n "${CPYTHON_OPTIMIZED}" ]; then # Do not enable on x86-64 macOS because the JIT requires macOS 11+ and we are currently # using 10.15 as a miniumum version. - if [ "${TARGET_TRIPLE}" != "x86_64-apple-darwin" ]; then + # Do not enable when free-threading, because they're not compatible yet. + if [[ ! ( "${TARGET_TRIPLE}" == "x86_64-apple-darwin" || -n "${CPYTHON_FREETHREADED}" ) ]]; then CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-experimental-jit=yes-off" fi @@ -588,6 +589,13 @@ if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" && -n "${CROSS_COMPILING}" && "$ export PROFILE_TASK='-m test --pgo --ignore test_strftime_y2k' fi +# ./configure tries to auto-detect whether it can build 128-bit and 256-bit SIMD helpers for HACL, +# but on x86-64 that requires v2 and v3 respectively, and on arm64 the performance is bad as noted +# in the comments, so just don't even try. (We should check if we can make this conditional) +if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]]; then + patch -p1 -i "${ROOT}/patch-python-configure-hacl-no-simd.patch" +fi + # We use ndbm on macOS and BerkeleyDB elsewhere. if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --with-dbmliborder=ndbm" diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml index 028eadde..3d69f049 100644 --- a/cpython-unix/extension-modules.yml +++ b/cpython-unix/extension-modules.yml @@ -43,7 +43,7 @@ _blake2: minimum-python-version: "3.14" - define: _DEFAULT_SOURCE minimum-python-version: "3.14" - # Disable `explicit_bzero`, it requires glib 2.25+ + # Disable `explicit_bzero`, it requires glibc 2.25+ - define: LINUX_NO_EXPLICIT_BZERO minimum-python-version: "3.14" @@ -88,6 +88,9 @@ _collections: _contextvars: sources: - _contextvarsmodule.c + config-c-only-conditional: + - config-c-only: true + minimum-python-version: "3.14" _crypt: maximum-python-version: "3.12" @@ -315,12 +318,6 @@ _hmac: includes: - Modules/_hacl/ - Modules/_hacl/include/ - links: - - :libHacl_Hash_Blake2.a - - :libHacl_Hash_SHA1.a - - :libHacl_Hash_SHA2.a - - :libHacl_Hash_SHA3.a - - :libHacl_Hash_MD5.a defines: - _BSD_SOURCE - _DEFAULT_SOURCE @@ -376,7 +373,6 @@ _md5: sources-conditional: - source: _hacl/Hacl_Hash_MD5.c minimum-python-version: "3.12" - maximum-python-version: "3.13" defines-conditional: - define: _BSD_SOURCE minimum-python-version: "3.12" @@ -435,6 +431,12 @@ _random: sources: - _randommodule.c + +_remote_debugging: + minimum-python-version: "3.14" + sources: + - _remote_debugging_module.c + _scproxy: # _scproxy is Apple OS only. # APIs required by _scproxy not available on iOS. @@ -453,7 +455,6 @@ _sha1: sources-conditional: - source: _hacl/Hacl_Hash_SHA1.c minimum-python-version: "3.12" - maximum-python-version: "3.13" includes: - Modules/_hacl/include defines-conditional: @@ -475,7 +476,6 @@ _sha2: - sha2module.c sources-conditional: - source: _hacl/Hacl_Hash_SHA2.c - maximum-python-version: "3.13" includes: - Modules/_hacl/include defines: @@ -491,7 +491,6 @@ _sha3: minimum-python-version: "3.12" - source: _hacl/Hacl_Hash_SHA3.c minimum-python-version: "3.12" - maximum-python-version: "3.13" includes: - Modules/_hacl/include defines-conditional: @@ -617,6 +616,7 @@ _testcapi: _testexternalinspection: minimum-python-version: '3.13' + maximum-python-version: '3.13' sources: - _testexternalinspection.c @@ -645,6 +645,8 @@ _testinternalcapi: minimum-python-version: "3.13" - source: _testinternalcapi/test_lock.c minimum-python-version: "3.13" + - source: _testinternalcapi/complex.c + minimum-python-version: "3.14" _testmultiphase: minimum-python-version: '3.9' @@ -769,6 +771,17 @@ _xxtestfuzz: - _xxtestfuzz/_xxtestfuzz.c - _xxtestfuzz/fuzzer.c +_zstd: + # Disable on all targets until we add a zstd library + disabled-targets: + - .* + minimum-python-version: '3.14' + sources: + - _zstd/_zstdmodule.c + - _zstd/zdict.c + - _zstd/compressor.c + - _zstd/decompressor.c + _zoneinfo: minimum-python-version: "3.9" sources: diff --git a/cpython-unix/patch-jit-cflags-314.patch b/cpython-unix/patch-jit-cflags-314.patch index 81f6fd02..3fc200ad 100644 --- a/cpython-unix/patch-jit-cflags-314.patch +++ b/cpython-unix/patch-jit-cflags-314.patch @@ -1,5 +1,5 @@ diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py -index b3b065652e0..d361f57382e 100644 +index 6ceb4404e74..94b74b5c8b0 100644 --- a/Tools/jit/_targets.py +++ b/Tools/jit/_targets.py @@ -10,6 +10,7 @@ @@ -10,7 +10,7 @@ index b3b065652e0..d361f57382e 100644 import _llvm import _schema -@@ -42,6 +43,7 @@ class _Target(typing.Generic[_S, _R]): +@@ -46,6 +47,7 @@ class _Target(typing.Generic[_S, _R]): stable: bool = False debug: bool = False verbose: bool = False @@ -18,7 +18,7 @@ index b3b065652e0..d361f57382e 100644 known_symbols: dict[str, int] = dataclasses.field(default_factory=dict) def _get_nop(self) -> bytes: -@@ -115,6 +117,7 @@ async def _compile( +@@ -119,6 +121,7 @@ async def _compile( ) -> _stencils.StencilGroup: o = tempdir / f"{opname}.o" args = [ @@ -27,10 +27,10 @@ index b3b065652e0..d361f57382e 100644 "-DPy_BUILD_CORE_MODULE", "-D_DEBUG" if self.debug else "-DNDEBUG", diff --git a/Tools/jit/build.py b/Tools/jit/build.py -index a8cb0f67c36..663874ad439 100644 +index 49b08f477db..49a1b11de47 100644 --- a/Tools/jit/build.py +++ b/Tools/jit/build.py -@@ -22,7 +22,11 @@ +@@ -26,11 +26,15 @@ parser.add_argument( "-v", "--verbose", action="store_true", help="echo commands as they are run" ) @@ -38,33 +38,37 @@ index a8cb0f67c36..663874ad439 100644 + "--with-cflags", help="additional flags to pass to the compiler", default="" + ) args = parser.parse_args() - args.target.debug = args.debug - args.target.verbose = args.verbose -+ args.target.cflags = args.with_cflags - args.target.build(pathlib.Path.cwd(), comment=comment, force=args.force) + for target in args.target: + target.debug = args.debug + target.force = args.force + target.verbose = args.verbose ++ target.cflags = args.with_cflags + target.build( + out, + comment=comment, diff --git a/configure b/configure -index 1b75ddfa26d..3c9e550b5d3 100755 +index c51192f12c8..0dcef7c2617 100755 --- a/configure +++ b/configure -@@ -8399,7 +8399,7 @@ then : +@@ -10863,7 +10863,7 @@ then : else case e in #( e) as_fn_append CFLAGS_NODIST " $jit_flags" -- REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host" -+ REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host --with-cflags=\"\$(CONFIGURE_CFLAGS)\"" +- REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host}" ++ REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --with-cflags=\"\$(CONFIGURE_CFLAGS)\"" JIT_STENCILS_H="jit_stencils.h" if test "x$Py_DEBUG" = xtrue then : diff --git a/configure.ac b/configure.ac -index c449bb5ebb3..5f9d08a4ee7 100644 +index a7b2f62579b..5998f896a4e 100644 --- a/configure.ac +++ b/configure.ac -@@ -1827,7 +1827,7 @@ AS_VAR_IF([jit_flags], +@@ -2776,7 +2776,7 @@ AS_VAR_IF([jit_flags], [], [AS_VAR_APPEND([CFLAGS_NODIST], [" $jit_flags"]) AS_VAR_SET([REGEN_JIT_COMMAND], -- ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host"]) -+ ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host --with-cflags=\"\$(CONFIGURE_CFLAGS)\""]) +- ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host}"]) ++ ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --with-cflags=\"\$(CONFIGURE_CFLAGS)\""]) AS_VAR_SET([JIT_STENCILS_H], ["jit_stencils.h"]) AS_VAR_IF([Py_DEBUG], [true], diff --git a/cpython-unix/patch-python-configure-hacl-no-simd.patch b/cpython-unix/patch-python-configure-hacl-no-simd.patch new file mode 100644 index 00000000..125aea33 --- /dev/null +++ b/cpython-unix/patch-python-configure-hacl-no-simd.patch @@ -0,0 +1,24 @@ +diff --git a/configure.ac b/configure.ac +index a7b2f62579b..06c0c0c0da0 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -7897,8 +7897,7 @@ AC_SUBST([LIBHACL_LDFLAGS]) + # The SIMD files use aligned_alloc, which is not available on older versions of + # Android. + # The *mmintrin.h headers are x86-family-specific, so can't be used on WASI. +-if test "$ac_sys_system" != "Linux-android" -a "$ac_sys_system" != "WASI" || \ +- { test -n "$ANDROID_API_LEVEL" && test "$ANDROID_API_LEVEL" -ge 28; } ++if false + then + dnl This can be extended here to detect e.g. Power8, which HACL* should also support. + AX_CHECK_COMPILE_FLAG([-msse -msse2 -msse3 -msse4.1 -msse4.2],[ +@@ -7930,8 +7929,7 @@ AC_SUBST([LIBHACL_BLAKE2_SIMD128_OBJS]) + # Although AVX support is not guaranteed on Android + # (https://developer.android.com/ndk/guides/abis#86-64), this is safe because we do a + # runtime CPUID check. +-if test "$ac_sys_system" != "Linux-android" -a "$ac_sys_system" != "WASI" || \ +- { test -n "$ANDROID_API_LEVEL" && test "$ANDROID_API_LEVEL" -ge 28; } ++if false + then + AX_CHECK_COMPILE_FLAG([-mavx2],[ + [LIBHACL_SIMD256_FLAGS="-mavx2"] diff --git a/cpython-windows/build.py b/cpython-windows/build.py index e981a8ac..15b0a44d 100644 --- a/cpython-windows/build.py +++ b/cpython-windows/build.py @@ -72,6 +72,10 @@ }, "_overlapped": {}, "_multiprocessing": {}, + "_remote_debugging": { + # Added in 3.14 + "ignore_missing": True + }, "_socket": {}, "_sqlite3": {"shared_depends": ["sqlite3"]}, # See the one-off calls to copy_link_to_lib() and elsewhere to hack up @@ -90,6 +94,10 @@ "ignore_missing": True, }, "_zoneinfo": {"ignore_missing": True}, + "_zstd": { + # Added in 3.14 + "ignore_missing": True + }, "pyexpat": {}, "select": {}, "unicodedata": {}, @@ -117,6 +125,7 @@ "_tkinter": ["tcl-8612", "tk-8612", "tix"], "_uuid": ["uuid"], "zlib": ["zlib"], + "_zstd": ["zstd"], } @@ -357,6 +366,7 @@ def hack_props( sqlite_version = DOWNLOADS["sqlite"]["version"] xz_version = DOWNLOADS["xz"]["version"] zlib_version = DOWNLOADS[zlib_entry]["version"] + zstd_version = DOWNLOADS["zstd"]["version"] mpdecimal_version = DOWNLOADS["mpdecimal"]["version"] @@ -372,6 +382,7 @@ def hack_props( xz_path = td / ("xz-%s" % xz_version) zlib_prefix = "cpython-source-deps-" if zlib_entry == "zlib-ng" else "" zlib_path = td / ("%s%s-%s" % (zlib_prefix, zlib_entry, zlib_version)) + zstd_path = td / ("cpython-source-deps-zstd-%s" % zstd_version) mpdecimal_path = td / ("mpdecimal-%s" % mpdecimal_version) openssl_root = td / "openssl" / arch @@ -416,6 +427,9 @@ def hack_props( elif b"%s\\" % zlib_path + elif b"%s\\" % zstd_path + elif b"%s\\" % mpdecimal_path @@ -1255,6 +1269,12 @@ def build_cpython( "tk-windows-bin-8612", BUILD, local_name="tk-windows-bin.tar.gz" ) + # On CPython 3.14+, zstd is included + if meets_python_minimum_version(python_version, "3.14"): + zstd_archive = download_entry("zstd", BUILD) + else: + zstd_archive = None + # 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) @@ -1297,6 +1317,7 @@ def build_cpython( tk_bin_archive, xz_archive, zlib_archive, + zstd_archive, ): if a is None: continue diff --git a/pythonbuild/cpython.py b/pythonbuild/cpython.py index e59eecd3..f339037c 100644 --- a/pythonbuild/cpython.py +++ b/pythonbuild/cpython.py @@ -16,6 +16,19 @@ "properties": { "build-mode": {"type": "string"}, "config-c-only": {"type": "boolean"}, + "config-c-only-conditional": { + "type": "array", + "items": { + "type": "object", + "properties": { + "config-c-only": {"type": "boolean"}, + "minimum-python-version": {"type": "string"}, + "maximum-python-version": {"type": "string"}, + }, + "additionalProperties": False, + "required": ["config-c-only"], + }, + }, "defines": {"type": "array", "items": {"type": "string"}}, "defines-conditional": { "type": "array", @@ -286,6 +299,18 @@ def derive_setup_local( if info.get("config-c-only"): config_c_only_wanted.add(name) + for entry in info.get("config-c-only-conditional", []): + python_min_match_setup = meets_python_minimum_version( + python_version, entry.get("minimum-python-version", "1.0") + ) + python_max_match_setup = meets_python_maximum_version( + python_version, entry.get("maximum-python-version", "100.0") + ) + if entry.get("config-c-only", False) and ( + python_min_match_setup and python_max_match_setup + ): + config_c_only_wanted.add(name) + # Parse more files in the distribution for their metadata. with tarfile.open(str(cpython_source_archive)) as tf: diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py index 12abd7ae..2fb34e89 100644 --- a/pythonbuild/downloads.py +++ b/pythonbuild/downloads.py @@ -82,10 +82,10 @@ "python_tag": "cp313", }, "cpython-3.14": { - "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0a7.tar.xz", - "size": 23015952, - "sha256": "71adbcec3ac9edf93308e55cfb4184f2eb4b16fda2bb0a5a382929ed29c8386d", - "version": "3.14.0a7", + "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0b1.tar.xz", + "size": 23358200, + "sha256": "2ddd30a77c9f62e065ce648664a254b9b0c011bcdaa8c1c2787087e644cbeb39", + "version": "3.14.0b1", "licenses": ["Python-2.0", "CNRI-Python"], "license_file": "LICENSE.cpython.txt", "python_tag": "cp314", @@ -429,4 +429,13 @@ "licenses": ["Zlib"], "license_file": "LICENSE.zlib-ng.txt", }, + "zstd": { + "url": "https://github.com/python/cpython-source-deps/archive/refs/tags/zstd-1.5.7.tar.gz", + "size": 2440298, + "sha256": "f24b52470d12f466e9fa4fcc94e6c530625ada51d7b36de7fdc6ed7e6f499c8e", + "version": "1.5.7", + "library_names": ["zstd"], + "licenses": ["BSD-3-Clause"], + "license_file": "LICENSE.zstd.txt", + }, } diff --git a/src/validation.rs b/src/validation.rs index 55139df7..19aace00 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -748,6 +748,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_13: &[&str] = &[ "_interpqueues", "_interpreters", "_sha2", + "_suggestions", "_sysconfig", "_tokenize", "_typing", @@ -758,7 +759,9 @@ const GLOBAL_EXTENSIONS_PYTHON_3_14: &[&str] = &[ "_interpchannels", "_interpqueues", "_interpreters", + "_remote_debugging", "_sha2", + "_suggestions", "_sysconfig", "_tokenize", "_typing", @@ -800,7 +803,8 @@ const GLOBAL_EXTENSIONS_WINDOWS: &[&str] = &[ "winsound", ]; -const GLOBAL_EXTENSIONS_WINDOWS_3_14: &[&str] = &["_wmi"]; +// TODO(zanieb): Move `_zstd` to non-Windows specific once we add support on Unix. +const GLOBAL_EXTENSIONS_WINDOWS_3_14: &[&str] = &["_wmi", "_zstd"]; const GLOBAL_EXTENSIONS_WINDOWS_PRE_3_13: &[&str] = &["_msi"]; @@ -1598,12 +1602,8 @@ fn validate_extension_modules( ]); } - if is_windows && matches!(python_major_minor, "3.13" | "3.14") { - wanted.extend(["_suggestions"]); - } - - if (is_linux || is_macos) && matches!(python_major_minor, "3.13" | "3.14") { - wanted.extend(["_suggestions", "_testexternalinspection"]); + if (is_linux || is_macos) && matches!(python_major_minor, "3.13") { + wanted.insert("_testexternalinspection"); } if (is_linux || is_macos) && matches!(python_major_minor, "3.12" | "3.13" | "3.14") {