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") {