diff --git a/README.md b/README.md
index e6f6b4aa..b841e9ac 100644
--- a/README.md
+++ b/README.md
@@ -24,19 +24,18 @@ While cibuildwheel itself requires a recent Python version to run (we support th
| | macOS Intel | macOS Apple Silicon | Windows 64bit | Windows 32bit | Windows Arm64 | manylinux
musllinux x86_64 | manylinux
musllinux i686 | manylinux
musllinux aarch64 | manylinux
musllinux ppc64le | manylinux
musllinux s390x | manylinux
musllinux armv7l | Android | iOS | Pyodide |
| ------------------ | ----------- | ------------------- | ------------- | ------------- | -------------- | ------------------------------ | ---------------------------- | ------------------------------- | ------------------------------- | ----------------------------- | ------------------------------ | ------- | --- | -------------- |
-| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | N/A |
-| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | N/A |
-| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | N/A |
-| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | N/A |
-| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | ✅3 |
-| CPython 3.13 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | ✅ | ✅ | ✅3 |
-| CPython 3.14 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | ✅ | ✅ | N/A |
-| PyPy 3.8 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | ✅1 | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A |
-| PyPy 3.9 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | ✅1 | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A |
-| PyPy 3.10 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | ✅1 | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A |
-| PyPy 3.11 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | ✅1 | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A |
-| GraalPy 3.11 v24.2 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | N/A | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A |
-| GraalPy 3.12 v25.0 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | N/A | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A |
+| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | N/A |
+| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | N/A |
+| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | N/A |
+| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | ✅3 |
+| CPython 3.13 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | ✅ | ✅ | ✅3 |
+| CPython 3.14 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | ✅ | ✅ | N/A |
+| PyPy 3.8 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | ✅1 | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A |
+| PyPy 3.9 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | ✅1 | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A |
+| PyPy 3.10 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | ✅1 | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A |
+| PyPy 3.11 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | ✅1 | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A |
+| GraalPy 3.11 v24.2 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | N/A | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A |
+| GraalPy 3.12 v25.0 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | N/A | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A |
**1** PyPy & GraalPy are only supported for manylinux wheels.
**2** Windows arm64 support is experimental.
diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py
index 0584e77a..02fb4663 100644
--- a/cibuildwheel/__main__.py
+++ b/cibuildwheel/__main__.py
@@ -533,10 +533,13 @@ def check_for_invalid_selectors(
msg += "This selector matches a group that wasn't enabled. Enable it using the `enable` option or remove this selector. "
if "p2" in selector_ or "p35" in selector_:
- msg += f"cibuildwheel 3.x no longer supports Python < 3.8. Please use the 1.x series or update `{selector_name}`. "
+ msg += f"cibuildwheel 4.x no longer supports Python < 3.9. Please use the 1.x series or update `{selector_name}`. "
error_type = errors.DeprecationError
if "p36" in selector_ or "p37" in selector_:
- msg += f"cibuildwheel 3.x no longer supports Python < 3.8. Please use the 2.x series or update `{selector_name}`. "
+ msg += f"cibuildwheel 4.x no longer supports Python < 3.9. Please use the 2.x series or update `{selector_name}`. "
+ error_type = errors.DeprecationError
+ if "p38" in selector_:
+ msg += f"cibuildwheel 4.x no longer supports Python < 3.9. Please use the 3.x series or update `{selector_name}`. "
error_type = errors.DeprecationError
if "cp313t" in selector_:
msg += f"cibuildwheel 4.x no longer supports Python 3.13 free-threading. Please use the 3.x series or update `{selector_name}`. "
diff --git a/cibuildwheel/frontend.py b/cibuildwheel/frontend.py
index e6808c0f..11c3e93d 100644
--- a/cibuildwheel/frontend.py
+++ b/cibuildwheel/frontend.py
@@ -4,7 +4,6 @@ import typing
from collections.abc import Sequence
from typing import Literal, Self, get_args
-from cibuildwheel.logger import log
from cibuildwheel.typing import PathOrStr
from cibuildwheel.util.helpers import parse_key_value_string, prepare_command
@@ -37,12 +36,8 @@ class BuildFrontendConfig:
return {"name": self.name, "args": repr(self.args)}
-def _get_verbosity_flags(level: int, frontend: BuildFrontendName, *, py38: bool) -> list[str]:
+def _get_verbosity_flags(level: int, frontend: BuildFrontendName) -> list[str]:
if level < 0:
- if frontend.startswith("build") and py38:
- msg = f"build_verbosity {level} is not supported for {frontend} frontend. Ignoring."
- log.warning(msg)
- return []
return ["-" + -level * "q"]
if level > 0:
@@ -80,10 +75,10 @@ def parse_config_settings(config_settings_str: str) -> dict[str, str | list[str]
def get_build_frontend_extra_flags(
- build_frontend: BuildFrontendConfig, verbosity_level: int, config_settings: str, *, py38: bool
+ build_frontend: BuildFrontendConfig, verbosity_level: int, config_settings: str
) -> list[str]:
return [
*_split_config_settings(config_settings),
*build_frontend.args,
- *_get_verbosity_flags(verbosity_level, build_frontend.name, py38=py38),
+ *_get_verbosity_flags(verbosity_level, build_frontend.name),
]
diff --git a/cibuildwheel/platforms/android.py b/cibuildwheel/platforms/android.py
index b7be5a6f..94a5de1c 100644
--- a/cibuildwheel/platforms/android.py
+++ b/cibuildwheel/platforms/android.py
@@ -475,7 +475,6 @@ def build_wheel(state: BuildState) -> Path:
project=".",
package=state.options.package_dir,
),
- py38=False,
),
env=state.android_env,
)
@@ -497,7 +496,6 @@ def build_wheel(state: BuildState) -> Path:
project=".",
package=state.options.package_dir,
),
- py38=False,
),
env=state.android_env,
)
diff --git a/cibuildwheel/platforms/ios.py b/cibuildwheel/platforms/ios.py
index 8b4e3d98..217b4ddf 100644
--- a/cibuildwheel/platforms/ios.py
+++ b/cibuildwheel/platforms/ios.py
@@ -486,7 +486,6 @@ def build(options: Options, tmp_path: Path) -> None:
project=".",
package=build_options.package_dir,
),
- py38=False,
)
match build_frontend.name:
diff --git a/cibuildwheel/platforms/linux.py b/cibuildwheel/platforms/linux.py
index a5bbabab..437e4dc7 100644
--- a/cibuildwheel/platforms/linux.py
+++ b/cibuildwheel/platforms/linux.py
@@ -291,7 +291,6 @@ def build_in_container(
project=container_project_path,
package=container_package_dir,
),
- py38=config.identifier[1:].startswith("p38"),
)
match build_frontend.name:
diff --git a/cibuildwheel/platforms/macos.py b/cibuildwheel/platforms/macos.py
index 4688263d..4fe894cf 100644
--- a/cibuildwheel/platforms/macos.py
+++ b/cibuildwheel/platforms/macos.py
@@ -483,7 +483,6 @@ def build(options: Options, tmp_path: Path) -> None:
project=".",
package=build_options.package_dir,
),
- py38=config.identifier[1:].startswith("p38"),
)
build_env = env.copy()
@@ -576,13 +575,6 @@ def build(options: Options, tmp_path: Path) -> None:
if build_options.test_command and build_options.test_selector(config.identifier):
machine_arch = platform.machine()
- python_arch = call(
- "python",
- "-sSc",
- "import platform; print(platform.machine())",
- env=env,
- capture_stdout=True,
- ).strip()
testing_archs: list[Literal["x86_64", "arm64"]]
if config_is_arm64:
@@ -630,24 +622,6 @@ def build(options: Options, tmp_path: Path) -> None:
# skip this test
continue
- is_cp38 = config.identifier.startswith("cp38-")
- if testing_arch == "arm64" and is_cp38 and python_arch != "arm64":
- log.warning(
- unwrap(
- """
- While cibuildwheel can build CPython 3.8 universal2/arm64 wheels, we
- cannot test the arm64 part of them, even when running on an Apple
- Silicon machine. This is because we use the x86_64 installer of
- CPython 3.8. See the discussion in
- https://github.com/pypa/cibuildwheel/pull/1169 for the details. To
- silence this warning, set `CIBW_TEST_SKIP: "cp38-macosx_*:arm64"`.
- """
- )
- )
-
- # skip this test
- continue
-
log.step(
"Testing wheel..."
if testing_arch == machine_arch
@@ -704,33 +678,16 @@ def build(options: Options, tmp_path: Path) -> None:
shell_with_arch(before_test_prepared, env=virtualenv_env)
# install the wheel
- if is_cp38 and python_arch == "x86_64":
- virtualenv_env_install_wheel = virtualenv_env.copy()
- virtualenv_env_install_wheel["SYSTEM_VERSION_COMPAT"] = "0"
- log.notice(
- unwrap(
- """
- Setting SYSTEM_VERSION_COMPAT=0 to ensure CPython 3.8 can get
- correct macOS version and allow installation of wheels with
- MACOSX_DEPLOYMENT_TARGET >= 11.0.
- See https://github.com/pypa/cibuildwheel/issues/1767 for the
- details.
- """
- )
- )
- else:
- virtualenv_env_install_wheel = virtualenv_env
-
pip_install(
f"{repaired_wheel}{build_options.test_extras}",
- env=virtualenv_env_install_wheel,
+ env=virtualenv_env,
)
# test the wheel
if build_options.test_requires:
pip_install(
*build_options.test_requires,
- env=virtualenv_env_install_wheel,
+ env=virtualenv_env,
)
# run the tests from a temp dir, with an absolute path in the command
diff --git a/cibuildwheel/platforms/pyodide.py b/cibuildwheel/platforms/pyodide.py
index 60f4a656..2c2e9082 100644
--- a/cibuildwheel/platforms/pyodide.py
+++ b/cibuildwheel/platforms/pyodide.py
@@ -428,7 +428,6 @@ def build(options: Options, tmp_path: Path) -> None:
project=".",
package=build_options.package_dir,
),
- py38=False,
)
call(
diff --git a/cibuildwheel/platforms/windows.py b/cibuildwheel/platforms/windows.py
index 0eced5c9..3f2c74fc 100644
--- a/cibuildwheel/platforms/windows.py
+++ b/cibuildwheel/platforms/windows.py
@@ -242,11 +242,6 @@ def setup_rust_cross_compile(
)
-def can_use_uv(python_configuration: PythonConfiguration) -> bool:
- conditions = (not python_configuration.identifier.startswith("pp38-"),)
- return all(conditions)
-
-
def setup_python(
tmp: Path,
python_configuration: PythonConfiguration,
@@ -278,9 +273,6 @@ def setup_python(
raise ValueError(msg)
assert base_python.exists()
- if build_frontend == "build[uv]" and not can_use_uv(python_configuration):
- build_frontend = "build"
-
use_uv = build_frontend in {"build[uv]", "uv"}
uv_path = find_uv()
@@ -419,7 +411,7 @@ def build(options: Options, tmp_path: Path) -> None:
for config in python_configurations:
build_options = options.build_options(config.identifier)
build_frontend = build_options.build_frontend
- use_uv = build_frontend.name in {"build[uv]", "uv"} and can_use_uv(config)
+ use_uv = build_frontend.name in {"build[uv]", "uv"}
log.build_start(config.identifier)
identifier_tmp_dir = tmp_path / config.identifier
@@ -471,7 +463,6 @@ def build(options: Options, tmp_path: Path) -> None:
project=".",
package=options.globals.package_dir,
),
- py38=config.identifier[1:].startswith("p38"),
)
if (
diff --git a/cibuildwheel/resources/build-platforms.toml b/cibuildwheel/resources/build-platforms.toml
index 60e440d1..03abceff 100644
--- a/cibuildwheel/resources/build-platforms.toml
+++ b/cibuildwheel/resources/build-platforms.toml
@@ -1,6 +1,5 @@
[linux]
python_configurations = [
- { identifier = "cp38-manylinux_x86_64", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-manylinux_x86_64", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-manylinux_x86_64", version = "3.10", path_str = "/opt/python/cp310-cp310" },
{ identifier = "cp311-manylinux_x86_64", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -8,7 +7,6 @@ python_configurations = [
{ identifier = "cp313-manylinux_x86_64", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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" },
{ identifier = "cp311-manylinux_i686", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -16,13 +14,11 @@ python_configurations = [
{ identifier = "cp313-manylinux_i686", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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" },
{ identifier = "pp311-manylinux_x86_64", version = "3.11", path_str = "/opt/python/pp311-pypy311_pp73" },
{ identifier = "gp311_242-manylinux_x86_64", version = "3.11", path_str = "/opt/python/graalpy311-graalpy242_311_native" },
{ identifier = "gp312_250-manylinux_x86_64", version = "3.12", path_str = "/opt/python/graalpy312-graalpy250_312_native" },
- { identifier = "cp38-manylinux_aarch64", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-manylinux_aarch64", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-manylinux_aarch64", version = "3.10", path_str = "/opt/python/cp310-cp310" },
{ identifier = "cp311-manylinux_aarch64", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -30,7 +26,6 @@ python_configurations = [
{ identifier = "cp313-manylinux_aarch64", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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" },
{ identifier = "cp311-manylinux_ppc64le", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -38,7 +33,6 @@ python_configurations = [
{ identifier = "cp313-manylinux_ppc64le", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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" },
{ identifier = "cp311-manylinux_s390x", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -46,7 +40,6 @@ python_configurations = [
{ identifier = "cp313-manylinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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" },
{ identifier = "cp311-manylinux_armv7l", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -54,7 +47,6 @@ python_configurations = [
{ identifier = "cp313-manylinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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" },
{ identifier = "cp311-manylinux_riscv64", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -62,17 +54,14 @@ python_configurations = [
{ identifier = "cp313-manylinux_riscv64", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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" },
{ identifier = "pp311-manylinux_aarch64", version = "3.11", path_str = "/opt/python/pp311-pypy311_pp73" },
{ identifier = "gp311_242-manylinux_aarch64", version = "3.11", path_str = "/opt/python/graalpy311-graalpy242_311_native" },
{ identifier = "gp312_250-manylinux_aarch64", version = "3.12", path_str = "/opt/python/graalpy312-graalpy250_312_native" },
- { identifier = "pp38-manylinux_i686", version = "3.8", path_str = "/opt/python/pp38-pypy38_pp73" },
{ identifier = "pp39-manylinux_i686", version = "3.9", path_str = "/opt/python/pp39-pypy39_pp73" },
{ identifier = "pp310-manylinux_i686", version = "3.10", path_str = "/opt/python/pp310-pypy310_pp73" },
{ identifier = "pp311-manylinux_i686", version = "3.11", path_str = "/opt/python/pp311-pypy311_pp73" },
- { identifier = "cp38-musllinux_x86_64", version = "3.8", path_str = "/opt/python/cp38-cp38" },
{ identifier = "cp39-musllinux_x86_64", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-musllinux_x86_64", version = "3.10", path_str = "/opt/python/cp310-cp310" },
{ identifier = "cp311-musllinux_x86_64", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -80,7 +69,6 @@ python_configurations = [
{ identifier = "cp313-musllinux_x86_64", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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" },
{ identifier = "cp311-musllinux_i686", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -88,7 +76,6 @@ python_configurations = [
{ identifier = "cp313-musllinux_i686", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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" },
{ identifier = "cp311-musllinux_aarch64", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -96,7 +83,6 @@ python_configurations = [
{ identifier = "cp313-musllinux_aarch64", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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" },
{ identifier = "cp311-musllinux_ppc64le", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -104,7 +90,6 @@ python_configurations = [
{ identifier = "cp313-musllinux_ppc64le", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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" },
{ identifier = "cp311-musllinux_s390x", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -112,7 +97,6 @@ python_configurations = [
{ identifier = "cp313-musllinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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" },
{ identifier = "cp311-musllinux_armv7l", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -120,7 +104,6 @@ python_configurations = [
{ identifier = "cp313-musllinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313" },
{ 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_riscv64", version = "3.9", path_str = "/opt/python/cp39-cp39" },
{ identifier = "cp310-musllinux_riscv64", version = "3.10", path_str = "/opt/python/cp310-cp310" },
{ identifier = "cp311-musllinux_riscv64", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -132,9 +115,6 @@ python_configurations = [
[macos]
python_configurations = [
- { identifier = "cp38-macosx_x86_64", version = "3.8", url = "https://www.python.org/ftp/python/3.8.10/python-3.8.10-macosx10.9.pkg" },
- { identifier = "cp38-macosx_arm64", version = "3.8", url = "https://www.python.org/ftp/python/3.8.10/python-3.8.10-macosx10.9.pkg" },
- { identifier = "cp38-macosx_universal2", version = "3.8", url = "https://www.python.org/ftp/python/3.8.10/python-3.8.10-macosx10.9.pkg" },
{ identifier = "cp39-macosx_x86_64", version = "3.9", url = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-macos11.pkg" },
{ identifier = "cp39-macosx_arm64", version = "3.9", url = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-macos11.pkg" },
{ identifier = "cp39-macosx_universal2", version = "3.9", url = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-macos11.pkg" },
@@ -156,8 +136,6 @@ python_configurations = [
{ identifier = "cp314t-macosx_x86_64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.4/python-3.14.4-macos11.pkg" },
{ identifier = "cp314t-macosx_arm64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.4/python-3.14.4-macos11.pkg" },
{ identifier = "cp314t-macosx_universal2", version = "3.14", url = "https://www.python.org/ftp/python/3.14.4/python-3.14.4-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" },
{ identifier = "pp39-macosx_arm64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.16-macos_arm64.tar.bz2" },
{ identifier = "pp310-macosx_x86_64", version = "3.10", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.19-macos_x86_64.tar.bz2" },
@@ -172,8 +150,6 @@ python_configurations = [
[windows]
python_configurations = [
- { identifier = "cp38-win32", version = "3.8.10" },
- { identifier = "cp38-win_amd64", version = "3.8.10" },
{ identifier = "cp39-win32", version = "3.9.13" },
{ identifier = "cp39-win_amd64", version = "3.9.13" },
{ identifier = "cp310-win32", version = "3.10.11" },
@@ -195,7 +171,6 @@ python_configurations = [
{ identifier = "cp313-win_arm64", version = "3.13.13" },
{ identifier = "cp314-win_arm64", version = "3.14.4" },
{ identifier = "cp314t-win_arm64", version = "3.14.4" },
- { identifier = "pp38-win_amd64", version = "3.8", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.11-win64.zip" },
{ identifier = "pp39-win_amd64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.16-win64.zip" },
{ identifier = "pp310-win_amd64", version = "3.10", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.19-win64.zip" },
{ identifier = "pp311-win_amd64", version = "3.11", url = "https://downloads.python.org/pypy/pypy3.11-v7.3.22-win64.zip" },
diff --git a/cibuildwheel/resources/constraints-python38.txt b/cibuildwheel/resources/constraints-python38.txt
deleted file mode 100644
index e53d1481..00000000
--- a/cibuildwheel/resources/constraints-python38.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-# This file was autogenerated by uv via the following command:
-# nox -s update_constraints
-altgraph==0.17.5
- # via macholib
-build==1.2.2.post1
- # via -r cibuildwheel/resources/constraints.in
-delocate==0.12.0
- # via -r cibuildwheel/resources/constraints.in
-distlib==0.4.0
- # via virtualenv
-filelock==3.16.1
- # via
- # python-discovery
- # virtualenv
-importlib-metadata==8.5.0
- # via build
-macholib==1.16.4
- # via delocate
-packaging==26.2
- # via
- # build
- # delocate
-pip==25.0.1
- # via -r cibuildwheel/resources/constraints.in
-platformdirs==4.3.6
- # via
- # python-discovery
- # virtualenv
-pyproject-hooks==1.2.0
- # via build
-python-discovery==1.2.2
- # via virtualenv
-tomli==2.4.1
- # via build
-typing-extensions==4.13.2
- # via
- # delocate
- # virtualenv
-virtualenv==21.2.1
- # via -r cibuildwheel/resources/constraints.in
-zipp==3.20.2
- # via importlib-metadata
diff --git a/docs/configuration.md b/docs/configuration.md
index c35c697f..62bef786 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -132,17 +132,17 @@ which means it can be given multiple times.
manylinux-x86_64-image = "manylinux_2_34"
[[tool.cibuildwheel.overrides]]
-select = "cp38-*"
+select = "cp39-*"
manylinux-x86_64-image = "manylinux2014"
[[tool.cibuildwheel.overrides]]
-select = "cp3{9,10}-*"
+select = "cp3{10,11}-*"
manylinux-x86_64-image = "manylinux_2_28"
```
-This example will build CPython 3.8 wheels on manylinux2014, CPython 3.9-3.10
+This example will build CPython 3.9 wheels on manylinux2014, CPython 3.10-3.11
wheels on manylinux_2_28, and manylinux_2_34 wheels for any newer Python
-(like 3.10).
+(like 3.14).
```toml
[tool.cibuildwheel]
diff --git a/docs/contributing.md b/docs/contributing.md
index 36abbf8f..f5693cf2 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -161,32 +161,6 @@ bin/run_example_ci_configs.py examples/github-with-qemu.yml
The script then outputs a Markdown table that can be copy/pasted into a PR to monitor and record the test.
-### Preparing environments
-
-This has been moved to using docker, so you only need the following instructions if you add `--no-docker` to avoid using docker.
-
-The dependency update script in the next section requires multiple python versions installed. One way to do this is to use `pyenv`:
-
-```bash
-pyenv install 3.7.8
-# Optionally add 3.8 and make it the local version;
-# otherwise assuming 3.8+ already is your current python version
-```
-
-Then, you need to make the required virtual environments:
-
-```bash
-$(pyenv prefix 3.7.8)/bin/python -m venv env37
-```
-
-
-
-And, you need to install the requirements into each environment:
-
-```bash
-for f in env*/bin/pip; do $f install pip-tools; done
-```
-
### Making a release
Before making a release, ensure pinned dependencies are up-to-date. Autoupdates are run weekly, with a PR being raised with any changes as required, so just make sure the latest one is merged before continuing.
diff --git a/docs/faq.md b/docs/faq.md
index db574127..db3d7cc6 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -344,34 +344,6 @@ To work around this, use a different environment variable such as `REPAIR_LIBRAR
See [#816](https://github.com/pypa/cibuildwheel/issues/816), thanks to @phoerious for reporting.
-### macOS: Building CPython 3.8 wheels on arm64
-
-If you're building on an arm64 runner, you might notice something strange about CPython 3.8 - unlike Python 3.9+, it's cross-compiled to arm64 from an x86_64 version of Python running under Rosetta emulation. This is because (despite the prevalence of arm64 versions of Python 3.8 from Apple and Homebrew) there is no officially supported Python.org installer of Python 3.8 for arm64.
-
-This is fine for simple C extensions, but for more complicated builds on arm64 it becomes an issue.
-
-So, if you want to build macOS arm64 wheels on an arm64 runner (e.g., `macos-14`) on Python 3.8, before invoking cibuildwheel, you should install a native arm64 Python 3.8 interpreter on the runner:
-
-
-!!! tab "GitHub Actions"
-
- ```yaml
- - uses: actions/setup-python@v5
- with:
- python-version: 3.8
- if: runner.os == 'macOS' && runner.arch == 'ARM64'
- ```
-
-!!! tab "Generic"
-
- ```bash
- curl -o /tmp/Python38.pkg https://www.python.org/ftp/python/3.8.10/python-3.8.10-macos11.pkg
- sudo installer -pkg /tmp/Python38.pkg -target /
- sh "/Applications/Python 3.8/Install Certificates.command"
- ```
-
-Then cibuildwheel will detect that it's installed and use it instead. However, you probably don't want to build x86_64 wheels on this Python, unless you're happy with them only supporting macOS 11+.
-
### macOS: Library dependencies do not satisfy target MacOS
Since delocate 0.11.0 there is added verification that the library binary dependencies match the target macOS version. This is to prevent the situation where a wheel platform tag is lower than the actual minimum macOS version required by the library. To resolve this error you need to build the library to the same macOS version as the target wheel (for example using `MACOSX_DEPLOYMENT_TARGET` environment variable).
diff --git a/docs/options.md b/docs/options.md
index 917d1c5c..9ffc706b 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -45,7 +45,7 @@ This option can also be set using the [command-line option](#command-line) `--pl
> Choose the Python versions to build
-List of builds to build and skip. Each build has an identifier like `cp38-manylinux_x86_64` or `cp37-macosx_x86_64` - you can list specific ones to build and cibuildwheel will only build those, and/or list ones to skip and cibuildwheel won't try to build them.
+List of builds to build and skip. Each build has an identifier like `cp314-manylinux_x86_64` or `cp313-macosx_x86_64` - you can list specific ones to build and cibuildwheel will only build those, and/or list ones to skip and cibuildwheel won't try to build them.
When both options are specified, both conditions are applied and only builds with a tag that matches `build` and does not match `skip` will be built.
@@ -54,14 +54,12 @@ When setting the options, you can use shell-style globbing syntax, as per [fnmat