diff --git a/README.md b/README.md
index d9f258e38..21049c093 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,7 @@ While cibuildwheel itself requires a recent Python version to run (we support th
| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A | N/A |
| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A | ✅⁴ |
| CPython 3.13³ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | ✅ | N/A |
+| CPython 3.14³ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | ✅ | N/A |
| PyPy 3.8 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A | N/A | N/A |
| PyPy 3.9 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A | N/A | N/A |
| PyPy 3.10 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A | N/A | N/A |
diff --git a/cibuildwheel/platforms/macos.py b/cibuildwheel/platforms/macos.py
index 420e16139..e2f5b9115 100644
--- a/cibuildwheel/platforms/macos.py
+++ b/cibuildwheel/platforms/macos.py
@@ -158,6 +158,8 @@ def install_cpython(_tmp: Path, version: str, url: str, free_threading: bool) ->
if version.startswith("3.13"):
# Python 3.13 is the first version to have a free-threading option
args += ["-applyChoiceChangesXML", str(resources.FREE_THREAD_ENABLE_313.resolve())]
+ elif version.startswith("3.14"):
+ args += ["-applyChoiceChangesXML", str(resources.FREE_THREAD_ENABLE_314.resolve())]
call("sudo", "installer", "-pkg", pkg_path, *args, "-target", "/")
pkg_path.unlink()
env = os.environ.copy()
diff --git a/cibuildwheel/resources/build-platforms.toml b/cibuildwheel/resources/build-platforms.toml
index 15f534022..973154586 100644
--- a/cibuildwheel/resources/build-platforms.toml
+++ b/cibuildwheel/resources/build-platforms.toml
@@ -7,6 +7,8 @@ python_configurations = [
{ identifier = "cp312-manylinux_x86_64", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-manylinux_x86_64", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-manylinux_x86_64", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-manylinux_x86_64", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-manylinux_x86_64", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "cp38-manylinux_i686", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-manylinux_i686", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-manylinux_i686", version = "3.10", path_str = "/opt/python/cp310-cp310" },
@@ -14,6 +16,8 @@ python_configurations = [
{ identifier = "cp312-manylinux_i686", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-manylinux_i686", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-manylinux_i686", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-manylinux_i686", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-manylinux_i686", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "pp38-manylinux_x86_64", version = "3.8", path_str = "/opt/python/pp38-pypy38_pp73" },
{ identifier = "pp39-manylinux_x86_64", version = "3.9", path_str = "/opt/python/pp39-pypy39_pp73" },
{ identifier = "pp310-manylinux_x86_64", version = "3.10", path_str = "/opt/python/pp310-pypy310_pp73" },
@@ -26,6 +30,8 @@ python_configurations = [
{ identifier = "cp312-manylinux_aarch64", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-manylinux_aarch64", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-manylinux_aarch64", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-manylinux_aarch64", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-manylinux_aarch64", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "cp38-manylinux_ppc64le", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-manylinux_ppc64le", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-manylinux_ppc64le", version = "3.10", path_str = "/opt/python/cp310-cp310" },
@@ -33,6 +39,8 @@ python_configurations = [
{ identifier = "cp312-manylinux_ppc64le", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-manylinux_ppc64le", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-manylinux_ppc64le", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-manylinux_ppc64le", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-manylinux_ppc64le", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "cp38-manylinux_s390x", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-manylinux_s390x", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-manylinux_s390x", version = "3.10", path_str = "/opt/python/cp310-cp310" },
@@ -40,6 +48,8 @@ python_configurations = [
{ identifier = "cp312-manylinux_s390x", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-manylinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-manylinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-manylinux_s390x", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-manylinux_s390x", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "cp38-manylinux_armv7l", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-manylinux_armv7l", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-manylinux_armv7l", version = "3.10", path_str = "/opt/python/cp310-cp310" },
@@ -47,6 +57,8 @@ python_configurations = [
{ identifier = "cp312-manylinux_armv7l", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-manylinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-manylinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-manylinux_armv7l", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-manylinux_armv7l", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "cp38-manylinux_riscv64", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-manylinux_riscv64", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-manylinux_riscv64", version = "3.10", path_str = "/opt/python/cp310-cp310" },
@@ -54,6 +66,8 @@ python_configurations = [
{ identifier = "cp312-manylinux_riscv64", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-manylinux_riscv64", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-manylinux_riscv64", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-manylinux_riscv64", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-manylinux_riscv64", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "pp38-manylinux_aarch64", version = "3.8", path_str = "/opt/python/pp38-pypy38_pp73" },
{ identifier = "pp39-manylinux_aarch64", version = "3.9", path_str = "/opt/python/pp39-pypy39_pp73" },
{ identifier = "pp310-manylinux_aarch64", version = "3.10", path_str = "/opt/python/pp310-pypy310_pp73" },
@@ -70,6 +84,8 @@ python_configurations = [
{ identifier = "cp312-musllinux_x86_64", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-musllinux_x86_64", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-musllinux_x86_64", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-musllinux_x86_64", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-musllinux_x86_64", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "cp38-musllinux_i686", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-musllinux_i686", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-musllinux_i686", version = "3.10", path_str = "/opt/python/cp310-cp310" },
@@ -77,6 +93,8 @@ python_configurations = [
{ identifier = "cp312-musllinux_i686", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-musllinux_i686", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-musllinux_i686", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-musllinux_i686", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-musllinux_i686", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "cp38-musllinux_aarch64", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-musllinux_aarch64", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-musllinux_aarch64", version = "3.10", path_str = "/opt/python/cp310-cp310" },
@@ -84,6 +102,8 @@ python_configurations = [
{ identifier = "cp312-musllinux_aarch64", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-musllinux_aarch64", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-musllinux_aarch64", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-musllinux_aarch64", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-musllinux_aarch64", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "cp38-musllinux_ppc64le", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-musllinux_ppc64le", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-musllinux_ppc64le", version = "3.10", path_str = "/opt/python/cp310-cp310" },
@@ -91,6 +111,8 @@ python_configurations = [
{ identifier = "cp312-musllinux_ppc64le", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-musllinux_ppc64le", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-musllinux_ppc64le", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-musllinux_ppc64le", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-musllinux_ppc64le", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "cp38-musllinux_s390x", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-musllinux_s390x", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-musllinux_s390x", version = "3.10", path_str = "/opt/python/cp310-cp310" },
@@ -98,6 +120,8 @@ python_configurations = [
{ identifier = "cp312-musllinux_s390x", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-musllinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-musllinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-musllinux_s390x", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-musllinux_s390x", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "cp38-musllinux_armv7l", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-musllinux_armv7l", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-musllinux_armv7l", version = "3.10", path_str = "/opt/python/cp310-cp310" },
@@ -105,6 +129,8 @@ python_configurations = [
{ identifier = "cp312-musllinux_armv7l", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-musllinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-musllinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-musllinux_armv7l", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-musllinux_armv7l", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
{ identifier = "cp38-musllinux_riscv64", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-musllinux_ricv64", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-musllinux_riscv64", version = "3.10", path_str = "/opt/python/cp310-cp310" },
@@ -112,6 +138,8 @@ python_configurations = [
{ identifier = "cp312-musllinux_riscv64", version = "3.12", path_str = "/opt/python/cp312-cp312" },
{ identifier = "cp313-musllinux_riscv64", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ identifier = "cp313t-musllinux_riscv64", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
+ { identifier = "cp314-musllinux_riscv64", version = "3.14", path_str = "/opt/python/cp314-cp314" },
+ { identifier = "cp314t-musllinux_riscv64", version = "3.14", path_str = "/opt/python/cp314-cp314t" },
]
[macos]
@@ -137,6 +165,12 @@ python_configurations = [
{ identifier = "cp313t-macosx_x86_64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.3/python-3.13.3-macos11.pkg" },
{ identifier = "cp313t-macosx_arm64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.3/python-3.13.3-macos11.pkg" },
{ identifier = "cp313t-macosx_universal2", version = "3.13", url = "https://www.python.org/ftp/python/3.13.3/python-3.13.3-macos11.pkg" },
+ { identifier = "cp314-macosx_x86_64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0b1-macos11.pkg" },
+ { identifier = "cp314-macosx_arm64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0b1-macos11.pkg" },
+ { identifier = "cp314-macosx_universal2", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0b1-macos11.pkg" },
+ { identifier = "cp314t-macosx_x86_64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0b1-macos11.pkg" },
+ { identifier = "cp314t-macosx_arm64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0b1-macos11.pkg" },
+ { identifier = "cp314t-macosx_universal2", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0b1-macos11.pkg" },
{ identifier = "pp38-macosx_x86_64", version = "3.8", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.11-macos_x86_64.tar.bz2" },
{ identifier = "pp38-macosx_arm64", version = "3.8", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.11-macos_arm64.tar.bz2" },
{ identifier = "pp39-macosx_x86_64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.16-macos_x86_64.tar.bz2" },
@@ -165,12 +199,18 @@ python_configurations = [
{ identifier = "cp313t-win32", version = "3.13.3", arch = "32" },
{ identifier = "cp313-win_amd64", version = "3.13.3", arch = "64" },
{ identifier = "cp313t-win_amd64", version = "3.13.3", arch = "64" },
+ { identifier = "cp314-win32", version = "3.14.0-b1", arch = "32" },
+ { identifier = "cp314t-win32", version = "3.14.0-b1", arch = "32" },
+ { identifier = "cp314-win_amd64", version = "3.14.0-b1", arch = "64" },
+ { identifier = "cp314t-win_amd64", version = "3.14.0-b1", arch = "64" },
{ identifier = "cp39-win_arm64", version = "3.9.10", arch = "ARM64" },
{ identifier = "cp310-win_arm64", version = "3.10.11", arch = "ARM64" },
{ identifier = "cp311-win_arm64", version = "3.11.9", arch = "ARM64" },
{ identifier = "cp312-win_arm64", version = "3.12.10", arch = "ARM64" },
{ identifier = "cp313-win_arm64", version = "3.13.3", arch = "ARM64" },
{ identifier = "cp313t-win_arm64", version = "3.13.3", arch = "ARM64" },
+ { identifier = "cp314-win_arm64", version = "3.14.0-b1", arch = "ARM64" },
+ { identifier = "cp314t-win_arm64", version = "3.14.0-b1", arch = "ARM64" },
{ identifier = "pp38-win_amd64", version = "3.8", arch = "64", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.11-win64.zip" },
{ identifier = "pp39-win_amd64", version = "3.9", arch = "64", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.16-win64.zip" },
{ identifier = "pp310-win_amd64", version = "3.10", arch = "64", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.19-win64.zip" },
diff --git a/cibuildwheel/resources/constraints-pyodide312.txt b/cibuildwheel/resources/constraints-pyodide312.txt
index 2580c967b..bfe80a4ac 100644
--- a/cibuildwheel/resources/constraints-pyodide312.txt
+++ b/cibuildwheel/resources/constraints-pyodide312.txt
@@ -19,7 +19,7 @@ charset-normalizer==3.4.2
# via requests
click==8.1.8
# via typer
-cmake==4.0.0
+cmake==4.0.2
# via pyodide-build
distlib==0.3.9
# via virtualenv
@@ -50,7 +50,7 @@ packaging==25.0
# unearth
pip==25.1.1
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
-platformdirs==4.3.7
+platformdirs==4.3.8
# via virtualenv
pydantic==2.11.4
# via
@@ -105,7 +105,7 @@ unearth==0.17.5
# via pyodide-build
urllib3==2.4.0
# via requests
-virtualenv==20.30.0
+virtualenv==20.31.2
# via
# build
# pyodide-build
diff --git a/cibuildwheel/resources/constraints-python310.txt b/cibuildwheel/resources/constraints-python310.txt
index 3f3ca6dca..5883ddfe0 100644
--- a/cibuildwheel/resources/constraints-python310.txt
+++ b/cibuildwheel/resources/constraints-python310.txt
@@ -20,7 +20,7 @@ packaging==25.0
# delocate
pip==25.1.1
# via -r cibuildwheel/resources/constraints.in
-platformdirs==4.3.7
+platformdirs==4.3.8
# via virtualenv
pyproject-hooks==1.2.0
# via build
@@ -28,7 +28,7 @@ tomli==2.2.1
# via build
typing-extensions==4.13.2
# via delocate
-virtualenv==20.30.0
+virtualenv==20.31.2
# via -r cibuildwheel/resources/constraints.in
zipp==3.21.0
# via importlib-metadata
diff --git a/cibuildwheel/resources/constraints-python311.txt b/cibuildwheel/resources/constraints-python311.txt
index b3f0cf64c..0cff478d6 100644
--- a/cibuildwheel/resources/constraints-python311.txt
+++ b/cibuildwheel/resources/constraints-python311.txt
@@ -18,11 +18,11 @@ packaging==25.0
# delocate
pip==25.1.1
# via -r cibuildwheel/resources/constraints.in
-platformdirs==4.3.7
+platformdirs==4.3.8
# via virtualenv
pyproject-hooks==1.2.0
# via build
typing-extensions==4.13.2
# via delocate
-virtualenv==20.30.0
+virtualenv==20.31.2
# via -r cibuildwheel/resources/constraints.in
diff --git a/cibuildwheel/resources/constraints-python312.txt b/cibuildwheel/resources/constraints-python312.txt
index b3f0cf64c..0cff478d6 100644
--- a/cibuildwheel/resources/constraints-python312.txt
+++ b/cibuildwheel/resources/constraints-python312.txt
@@ -18,11 +18,11 @@ packaging==25.0
# delocate
pip==25.1.1
# via -r cibuildwheel/resources/constraints.in
-platformdirs==4.3.7
+platformdirs==4.3.8
# via virtualenv
pyproject-hooks==1.2.0
# via build
typing-extensions==4.13.2
# via delocate
-virtualenv==20.30.0
+virtualenv==20.31.2
# via -r cibuildwheel/resources/constraints.in
diff --git a/cibuildwheel/resources/constraints-python313.txt b/cibuildwheel/resources/constraints-python313.txt
index b3f0cf64c..0cff478d6 100644
--- a/cibuildwheel/resources/constraints-python313.txt
+++ b/cibuildwheel/resources/constraints-python313.txt
@@ -18,11 +18,11 @@ packaging==25.0
# delocate
pip==25.1.1
# via -r cibuildwheel/resources/constraints.in
-platformdirs==4.3.7
+platformdirs==4.3.8
# via virtualenv
pyproject-hooks==1.2.0
# via build
typing-extensions==4.13.2
# via delocate
-virtualenv==20.30.0
+virtualenv==20.31.2
# via -r cibuildwheel/resources/constraints.in
diff --git a/cibuildwheel/resources/constraints-python314.txt b/cibuildwheel/resources/constraints-python314.txt
new file mode 100644
index 000000000..0cff478d6
--- /dev/null
+++ b/cibuildwheel/resources/constraints-python314.txt
@@ -0,0 +1,28 @@
+# This file was autogenerated by uv via the following command:
+# nox -s update_constraints
+altgraph==0.17.4
+ # via macholib
+build==1.2.2.post1
+ # via -r cibuildwheel/resources/constraints.in
+delocate==0.13.0
+ # via -r cibuildwheel/resources/constraints.in
+distlib==0.3.9
+ # via virtualenv
+filelock==3.18.0
+ # via virtualenv
+macholib==1.16.3
+ # via delocate
+packaging==25.0
+ # via
+ # build
+ # delocate
+pip==25.1.1
+ # via -r cibuildwheel/resources/constraints.in
+platformdirs==4.3.8
+ # via virtualenv
+pyproject-hooks==1.2.0
+ # via build
+typing-extensions==4.13.2
+ # via delocate
+virtualenv==20.31.2
+ # via -r cibuildwheel/resources/constraints.in
diff --git a/cibuildwheel/resources/constraints-python38.txt b/cibuildwheel/resources/constraints-python38.txt
index 490e373a9..2c40131f4 100644
--- a/cibuildwheel/resources/constraints-python38.txt
+++ b/cibuildwheel/resources/constraints-python38.txt
@@ -28,7 +28,7 @@ tomli==2.2.1
# via build
typing-extensions==4.13.2
# via delocate
-virtualenv==20.30.0
+virtualenv==20.31.2
# via -r cibuildwheel/resources/constraints.in
zipp==3.20.2
# via importlib-metadata
diff --git a/cibuildwheel/resources/constraints-python39.txt b/cibuildwheel/resources/constraints-python39.txt
index 3f3ca6dca..5883ddfe0 100644
--- a/cibuildwheel/resources/constraints-python39.txt
+++ b/cibuildwheel/resources/constraints-python39.txt
@@ -20,7 +20,7 @@ packaging==25.0
# delocate
pip==25.1.1
# via -r cibuildwheel/resources/constraints.in
-platformdirs==4.3.7
+platformdirs==4.3.8
# via virtualenv
pyproject-hooks==1.2.0
# via build
@@ -28,7 +28,7 @@ tomli==2.2.1
# via build
typing-extensions==4.13.2
# via delocate
-virtualenv==20.30.0
+virtualenv==20.31.2
# via -r cibuildwheel/resources/constraints.in
zipp==3.21.0
# via importlib-metadata
diff --git a/cibuildwheel/resources/constraints.txt b/cibuildwheel/resources/constraints.txt
index b3f0cf64c..0cff478d6 100644
--- a/cibuildwheel/resources/constraints.txt
+++ b/cibuildwheel/resources/constraints.txt
@@ -18,11 +18,11 @@ packaging==25.0
# delocate
pip==25.1.1
# via -r cibuildwheel/resources/constraints.in
-platformdirs==4.3.7
+platformdirs==4.3.8
# via virtualenv
pyproject-hooks==1.2.0
# via build
typing-extensions==4.13.2
# via delocate
-virtualenv==20.30.0
+virtualenv==20.31.2
# via -r cibuildwheel/resources/constraints.in
diff --git a/cibuildwheel/resources/free-threaded-enable-314.xml b/cibuildwheel/resources/free-threaded-enable-314.xml
new file mode 100644
index 000000000..88fa8dd98
--- /dev/null
+++ b/cibuildwheel/resources/free-threaded-enable-314.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ attributeSetting
+ 1
+ choiceAttribute
+ selected
+ choiceIdentifier
+ org.python.Python.PythonTFramework-3.14
+
+
+
diff --git a/cibuildwheel/resources/pinned_docker_images.cfg b/cibuildwheel/resources/pinned_docker_images.cfg
index 3d1b3283c..1ff2bef8d 100644
--- a/cibuildwheel/resources/pinned_docker_images.cfg
+++ b/cibuildwheel/resources/pinned_docker_images.cfg
@@ -1,47 +1,47 @@
[x86_64]
-manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2025.05.03-1
-manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2025.05.03-1
-manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2025.04.26-0
-musllinux_1_2 = quay.io/pypa/musllinux_1_2_x86_64:2025.05.03-1
+manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2025.05.10-2
+manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2025.05.10-2
+manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2025.05.10-2
+musllinux_1_2 = quay.io/pypa/musllinux_1_2_x86_64:2025.05.10-2
[i686]
-manylinux2014 = quay.io/pypa/manylinux2014_i686:2025.05.03-1
-musllinux_1_2 = quay.io/pypa/musllinux_1_2_i686:2025.05.03-1
+manylinux2014 = quay.io/pypa/manylinux2014_i686:2025.05.10-2
+musllinux_1_2 = quay.io/pypa/musllinux_1_2_i686:2025.05.10-2
[aarch64]
-manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2025.05.03-1
-manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2025.05.03-1
-manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2025.04.26-0
-musllinux_1_2 = quay.io/pypa/musllinux_1_2_aarch64:2025.05.03-1
+manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2025.05.10-2
+manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2025.05.10-2
+manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2025.05.10-2
+musllinux_1_2 = quay.io/pypa/musllinux_1_2_aarch64:2025.05.10-2
[ppc64le]
-manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2025.05.03-1
-manylinux_2_28 = quay.io/pypa/manylinux_2_28_ppc64le:2025.05.03-1
-manylinux_2_34 = quay.io/pypa/manylinux_2_34_ppc64le:2025.04.26-0
-musllinux_1_2 = quay.io/pypa/musllinux_1_2_ppc64le:2025.05.03-1
+manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2025.05.10-2
+manylinux_2_28 = quay.io/pypa/manylinux_2_28_ppc64le:2025.05.10-2
+manylinux_2_34 = quay.io/pypa/manylinux_2_34_ppc64le:2025.05.10-2
+musllinux_1_2 = quay.io/pypa/musllinux_1_2_ppc64le:2025.05.10-2
[s390x]
-manylinux2014 = quay.io/pypa/manylinux2014_s390x:2025.05.03-1
-manylinux_2_28 = quay.io/pypa/manylinux_2_28_s390x:2025.05.03-1
-manylinux_2_34 = quay.io/pypa/manylinux_2_34_s390x:2025.04.26-0
-musllinux_1_2 = quay.io/pypa/musllinux_1_2_s390x:2025.05.03-1
+manylinux2014 = quay.io/pypa/manylinux2014_s390x:2025.05.10-2
+manylinux_2_28 = quay.io/pypa/manylinux_2_28_s390x:2025.05.10-2
+manylinux_2_34 = quay.io/pypa/manylinux_2_34_s390x:2025.05.10-2
+musllinux_1_2 = quay.io/pypa/musllinux_1_2_s390x:2025.05.10-2
[pypy_x86_64]
-manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2025.05.03-1
-manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2025.05.03-1
-manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2025.04.26-0
+manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2025.05.10-2
+manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2025.05.10-2
+manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2025.05.10-2
[pypy_i686]
-manylinux2014 = quay.io/pypa/manylinux2014_i686:2025.05.03-1
+manylinux2014 = quay.io/pypa/manylinux2014_i686:2025.05.10-2
[pypy_aarch64]
-manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2025.05.03-1
-manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2025.05.03-1
-manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2025.04.26-0
+manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2025.05.10-2
+manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2025.05.10-2
+manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2025.05.10-2
[armv7l]
-manylinux_2_31 = quay.io/pypa/manylinux_2_31_armv7l:2025.05.03-1
-musllinux_1_2 = quay.io/pypa/musllinux_1_2_armv7l:2025.05.03-1
+manylinux_2_31 = quay.io/pypa/manylinux_2_31_armv7l:2025.05.10-2
+musllinux_1_2 = quay.io/pypa/musllinux_1_2_armv7l:2025.05.10-2
[riscv64]
diff --git a/cibuildwheel/resources/virtualenv.toml b/cibuildwheel/resources/virtualenv.toml
index e9b284617..9e5d08c24 100644
--- a/cibuildwheel/resources/virtualenv.toml
+++ b/cibuildwheel/resources/virtualenv.toml
@@ -1 +1 @@
-default = { version = "20.30.0", url = "https://github.com/pypa/get-virtualenv/blob/20.30.0/public/virtualenv.pyz?raw=true" }
+default = { version = "20.31.2", url = "https://github.com/pypa/get-virtualenv/blob/20.31.2/public/virtualenv.pyz?raw=true" }
diff --git a/cibuildwheel/util/resources.py b/cibuildwheel/util/resources.py
index e27f1f892..40e085d68 100644
--- a/cibuildwheel/util/resources.py
+++ b/cibuildwheel/util/resources.py
@@ -8,6 +8,7 @@
PATH: Final[Path] = Path(__file__).parent.parent / "resources"
INSTALL_CERTIFI_SCRIPT: Final[Path] = PATH / "install_certifi.py"
FREE_THREAD_ENABLE_313: Final[Path] = PATH / "free-threaded-enable-313.xml"
+FREE_THREAD_ENABLE_314: Final[Path] = PATH / "free-threaded-enable-314.xml"
NODEJS: Final[Path] = PATH / "nodejs.toml"
DEFAULTS: Final[Path] = PATH / "defaults.toml"
PINNED_DOCKER_IMAGES: Final[Path] = PATH / "pinned_docker_images.cfg"
diff --git a/docs/options.md b/docs/options.md
index c36c423ab..1a79d3750 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -58,6 +58,7 @@ When setting the options, you can use shell-style globbing syntax, as per [fnmat
| Python 3.11 | cp311-macosx_x86_64
cp311-macosx_universal2
cp311-macosx_arm64 | cp311-win_amd64
cp311-win32
cp311-win_arm64 | cp311-manylinux_x86_64
cp311-manylinux_i686
cp311-musllinux_x86_64
cp311-musllinux_i686 | cp311-manylinux_aarch64
cp311-manylinux_ppc64le
cp311-manylinux_s390x
cp311-manylinux_armv7l
cp311-manylinux_riscv64
cp311-musllinux_aarch64
cp311-musllinux_ppc64le
cp311-musllinux_s390x
cp311-musllinux_armv7l
cp311-musllinux_riscv64 | |
| Python 3.12 | cp312-macosx_x86_64
cp312-macosx_universal2
cp312-macosx_arm64 | cp312-win_amd64
cp312-win32
cp312-win_arm64 | cp312-manylinux_x86_64
cp312-manylinux_i686
cp312-musllinux_x86_64
cp312-musllinux_i686 | cp312-manylinux_aarch64
cp312-manylinux_ppc64le
cp312-manylinux_s390x
cp312-manylinux_armv7l
cp312-manylinux_riscv64
cp312-musllinux_aarch64
cp312-musllinux_ppc64le
cp312-musllinux_s390x
cp312-musllinux_armv7l
cp312-musllinux_riscv64 | |
| Python 3.13 | cp313-macosx_x86_64
cp313-macosx_universal2
cp313-macosx_arm64 | cp313-win_amd64
cp313-win32
cp313-win_arm64 | cp313-manylinux_x86_64
cp313-manylinux_i686
cp313-musllinux_x86_64
cp313-musllinux_i686 | cp313-manylinux_aarch64
cp313-manylinux_ppc64le
cp313-manylinux_s390x
cp313-manylinux_armv7l
cp313-manylinux_riscv64
cp313-musllinux_aarch64
cp313-musllinux_ppc64le
cp313-musllinux_s390x
cp313-musllinux_armv7l
cp313-musllinux_riscv64 | cp313-ios_arm64_iphoneos
cp313-ios_arm64_iphonesimulator
cp313-ios_x86_64_iphonesimulator |
+| Python 3.14 | cp314-macosx_x86_64
cp314-macosx_universal2
cp314-macosx_arm64 | cp314-win_amd64
cp314-win32
cp314-win_arm64 | cp314-manylinux_x86_64
cp314-manylinux_i686
cp314-musllinux_x86_64
cp314-musllinux_i686 | cp314-manylinux_aarch64
cp314-manylinux_ppc64le
cp314-manylinux_s390x
cp314-manylinux_armv7l
cp314-manylinux_riscv64
cp314-musllinux_aarch64
cp314-musllinux_ppc64le
cp314-musllinux_s390x
cp314-musllinux_armv7l
cp314-musllinux_riscv64 | |
| PyPy3.8 v7.3 | pp38-macosx_x86_64
pp38-macosx_arm64 | pp38-win_amd64 | pp38-manylinux_x86_64
pp38-manylinux_i686 | pp38-manylinux_aarch64 | |
| PyPy3.9 v7.3 | pp39-macosx_x86_64
pp39-macosx_arm64 | pp39-win_amd64 | pp39-manylinux_x86_64
pp39-manylinux_i686 | pp39-manylinux_aarch64 | |
| PyPy3.10 v7.3 | pp310-macosx_x86_64
pp310-macosx_arm64 | pp310-win_amd64 | pp310-manylinux_x86_64
pp310-manylinux_i686 | pp310-manylinux_aarch64 | |
diff --git a/noxfile.py b/noxfile.py
index 356bb8946..b018a952d 100755
--- a/noxfile.py
+++ b/noxfile.py
@@ -73,7 +73,7 @@ def update_constraints(session: nox.Session) -> None:
if session.venv_backend != "uv":
session.install("uv>=0.1.23")
- for minor_version in range(8, 14):
+ for minor_version in range(8, 15):
python_version = f"3.{minor_version}"
env = os.environ.copy()
# CUSTOM_COMPILE_COMMAND is a pip-compile option that tells users how to
@@ -92,7 +92,7 @@ def update_constraints(session: nox.Session) -> None:
)
shutil.copyfile(
- resources / "constraints-python312.txt",
+ resources / "constraints-python314.txt",
resources / "constraints.txt",
)
diff --git a/test/test_emulation.py b/test/test_emulation.py
index 0d218b000..9ffdc6de8 100644
--- a/test/test_emulation.py
+++ b/test/test_emulation.py
@@ -35,7 +35,7 @@ def test(tmp_path, request):
"CIBW_TEST_COMMAND": "pytest ./test",
"CIBW_ARCHS": archs,
# TODO remove me once proper support is added
- "CIBW_MANYLINUX_RISCV64_IMAGE": "ghcr.io/mayeut/manylinux_2_31:2025.03.02-1",
+ "CIBW_MANYLINUX_RISCV64_IMAGE": "ghcr.io/mayeut/manylinux_2_35:2025.05.11-1",
"CIBW_SKIP": "*-musllinux_riscv64",
},
)
diff --git a/test/utils.py b/test/utils.py
index 452d002fb..7e566f503 100644
--- a/test/utils.py
+++ b/test/utils.py
@@ -228,7 +228,7 @@ def _expected_wheels(
"armv7l": ["manylinux_2_17", "manylinux2014", "manylinux_2_31"],
"i686": ["manylinux_2_5", "manylinux1", "manylinux_2_17", "manylinux2014"],
"x86_64": ["manylinux_2_5", "manylinux1", "manylinux_2_28"],
- "riscv64": ["manylinux_2_31"],
+ "riscv64": ["manylinux_2_31", "manylinux_2_35"],
}.get(machine_arch, ["manylinux_2_17", "manylinux2014", "manylinux_2_28"])
if musllinux_versions is None:
@@ -247,9 +247,12 @@ def _expected_wheels(
]
if EnableGroup.CPythonFreeThreading in enable_groups:
- python_abi_tags += [
- "cp313-cp313t",
- ]
+ python_abi_tags.append("cp313-cp313t")
+
+ if EnableGroup.CPythonPrerelease in enable_groups:
+ python_abi_tags.append("cp314-cp314")
+ if EnableGroup.CPythonFreeThreading in enable_groups:
+ python_abi_tags.append("cp314-cp314t")
if EnableGroup.PyPy in enable_groups:
python_abi_tags += [
diff --git a/unit_test/option_prepare_test.py b/unit_test/option_prepare_test.py
index 3356c523a..09ff57525 100644
--- a/unit_test/option_prepare_test.py
+++ b/unit_test/option_prepare_test.py
@@ -120,6 +120,7 @@ def test_build_with_override_launches(monkeypatch, tmp_path):
monkeypatch.chdir(pkg_dir)
monkeypatch.setattr(sys, "argv", ["cibuildwheel", "--platform=linux"])
+ monkeypatch.delenv("CIBW_ENABLE", raising=False)
main()