diff --git a/.cirrus.yml b/.cirrus.yml
index f8e84294f..2fe3559c2 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -73,19 +73,3 @@ macos_arm64_task:
- brew install python@3.12
- python3.12 -m venv ${VENV_ROOT}
<<: *RUN_TESTS
-
-macos_arm64_cp38_task:
- macos_instance:
- image: ghcr.io/cirruslabs/macos-runner:sequoia
- env:
- VENV_ROOT: ${HOME}/venv-cibuildwheel
- PATH: ${VENV_ROOT}/bin:${PATH}
- PYTEST_ADDOPTS: --run-cp38-universal2 -k 'test_cp38_arm64_testing_universal2_installer or test_arch_auto or test_dummy_serial'
- install_pre_requirements_script:
- - brew install python@3.12
- - python3.12 -m venv ${VENV_ROOT}
- - curl -fsSLO https://www.python.org/ftp/python/3.8.10/python-3.8.10-macos11.pkg
- - sudo installer -pkg python-3.8.10-macos11.pkg -target /
- - rm python-3.8.10-macos11.pkg
- - sh "/Applications/Python 3.8/Install Certificates.command"
- <<: *RUN_TESTS
diff --git a/README.md b/README.md
index 84466c199..8fd195bbb 100644
--- a/README.md
+++ b/README.md
@@ -24,14 +24,12 @@ 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 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A | N/A | N/A |
| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A | N/A | N/A |
| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A | N/A | N/A |
| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A | N/A | N/A |
| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A | N/A | ✅⁴ |
| CPython 3.13³ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | ✅ | ✅ | ✅⁴ |
| CPython 3.14 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | ✅ | ✅ | N/A |
-| PyPy 3.8 v7.3 | ✅ | ✅ | ✅ | N/A | 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 | N/A |
| PyPy 3.10 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A | N/A | N/A | N/A |
| PyPy 3.11 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A | N/A | N/A | N/A |
diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py
index 72e2434bc..b7e547b8d 100644
--- a/cibuildwheel/__main__.py
+++ b/cibuildwheel/__main__.py
@@ -534,10 +534,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 selector_name == "build":
diff --git a/cibuildwheel/frontend.py b/cibuildwheel/frontend.py
index 6f54de550..ba38bb610 100644
--- a/cibuildwheel/frontend.py
+++ b/cibuildwheel/frontend.py
@@ -4,7 +4,6 @@
from collections.abc import Sequence
from typing import Literal, Self, get_args
-from .logger import log
from .util.helpers import parse_key_value_string
BuildFrontendName = Literal["pip", "build", "build[uv]", "uv"]
@@ -36,12 +35,8 @@ def options_summary(self) -> str | dict[str, str]:
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:
@@ -75,10 +70,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 5f4839e58..3d23deb16 100644
--- a/cibuildwheel/platforms/android.py
+++ b/cibuildwheel/platforms/android.py
@@ -457,7 +457,6 @@ def build_wheel(state: BuildState) -> Path:
state.options.build_frontend,
state.options.build_verbosity,
state.options.config_settings,
- py38=False,
),
env=state.android_env,
)
@@ -475,7 +474,6 @@ def build_wheel(state: BuildState) -> Path:
state.options.build_frontend,
state.options.build_verbosity,
state.options.config_settings,
- py38=False,
),
env=state.android_env,
)
diff --git a/cibuildwheel/platforms/ios.py b/cibuildwheel/platforms/ios.py
index a4229e994..72320e165 100644
--- a/cibuildwheel/platforms/ios.py
+++ b/cibuildwheel/platforms/ios.py
@@ -490,7 +490,6 @@ def build(options: Options, tmp_path: Path) -> None:
build_frontend,
build_options.build_verbosity,
build_options.config_settings,
- py38=False,
)
match build_frontend.name:
diff --git a/cibuildwheel/platforms/linux.py b/cibuildwheel/platforms/linux.py
index 818ad8f08..f9119376b 100644
--- a/cibuildwheel/platforms/linux.py
+++ b/cibuildwheel/platforms/linux.py
@@ -277,7 +277,6 @@ def build_in_container(
build_frontend,
build_options.build_verbosity,
build_options.config_settings,
- py38=config.identifier[1:].startswith("p38"),
)
match build_frontend.name:
diff --git a/cibuildwheel/platforms/macos.py b/cibuildwheel/platforms/macos.py
index 137c68964..e2cc175fd 100644
--- a/cibuildwheel/platforms/macos.py
+++ b/cibuildwheel/platforms/macos.py
@@ -475,7 +475,6 @@ def build(options: Options, tmp_path: Path) -> None:
build_frontend,
build_options.build_verbosity,
build_options.config_settings,
- py38=config.identifier[1:].startswith("p38"),
)
build_env = env.copy()
@@ -568,13 +567,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:
@@ -622,24 +614,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
@@ -696,33 +670,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 996f0484d..c68cc6bb0 100644
--- a/cibuildwheel/platforms/pyodide.py
+++ b/cibuildwheel/platforms/pyodide.py
@@ -419,7 +419,6 @@ def build(options: Options, tmp_path: Path) -> None:
build_frontend,
build_options.build_verbosity,
build_options.config_settings,
- py38=False,
)
call(
diff --git a/cibuildwheel/platforms/windows.py b/cibuildwheel/platforms/windows.py
index d13d925bf..8d1be7e21 100644
--- a/cibuildwheel/platforms/windows.py
+++ b/cibuildwheel/platforms/windows.py
@@ -232,11 +232,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,
@@ -268,9 +263,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()
@@ -405,7 +397,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
@@ -453,7 +445,6 @@ def build(options: Options, tmp_path: Path) -> None:
build_frontend,
build_options.build_verbosity,
build_options.config_settings,
- py38=config.identifier[1:].startswith("p38"),
)
if (
diff --git a/cibuildwheel/resources/build-platforms.toml b/cibuildwheel/resources/build-platforms.toml
index 15c5afecc..f62392302 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" },
@@ -9,7 +8,6 @@ python_configurations = [
{ 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" },
{ identifier = "cp311-manylinux_i686", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -18,13 +16,11 @@ python_configurations = [
{ 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" },
{ 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" },
@@ -33,7 +29,6 @@ python_configurations = [
{ 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" },
{ identifier = "cp311-manylinux_ppc64le", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -42,7 +37,6 @@ python_configurations = [
{ 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" },
{ identifier = "cp311-manylinux_s390x", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -51,7 +45,6 @@ python_configurations = [
{ 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" },
{ identifier = "cp311-manylinux_armv7l", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -60,7 +53,6 @@ python_configurations = [
{ 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" },
{ identifier = "cp311-manylinux_riscv64", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -69,17 +61,14 @@ python_configurations = [
{ 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" },
{ 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" },
@@ -88,7 +77,6 @@ python_configurations = [
{ 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" },
{ identifier = "cp311-musllinux_i686", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -97,7 +85,6 @@ python_configurations = [
{ 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" },
{ identifier = "cp311-musllinux_aarch64", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -106,7 +93,6 @@ python_configurations = [
{ 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" },
{ identifier = "cp311-musllinux_ppc64le", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -115,7 +101,6 @@ python_configurations = [
{ 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" },
{ identifier = "cp311-musllinux_s390x", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -124,7 +109,6 @@ python_configurations = [
{ 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" },
{ identifier = "cp311-musllinux_armv7l", version = "3.11", path_str = "/opt/python/cp311-cp311" },
@@ -133,7 +117,6 @@ python_configurations = [
{ 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_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" },
@@ -146,9 +129,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" },
@@ -173,8 +153,6 @@ python_configurations = [
{ identifier = "cp314t-macosx_x86_64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.3/python-3.14.3-macos11.pkg" },
{ identifier = "cp314t-macosx_arm64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.3/python-3.14.3-macos11.pkg" },
{ identifier = "cp314t-macosx_universal2", version = "3.14", url = "https://www.python.org/ftp/python/3.14.3/python-3.14.3-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" },
@@ -189,8 +167,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" },
@@ -215,7 +191,6 @@ python_configurations = [
{ identifier = "cp313t-win_arm64", version = "3.13.12" },
{ identifier = "cp314-win_arm64", version = "3.14.3" },
{ identifier = "cp314t-win_arm64", version = "3.14.3" },
- { 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.20-win64.zip" },
diff --git a/cibuildwheel/resources/constraints-python38.txt b/cibuildwheel/resources/constraints-python38.txt
deleted file mode 100644
index bbbf70d46..000000000
--- 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.0
- # 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.1.0
- # via virtualenv
-tomli==2.4.0
- # via build
-typing-extensions==4.13.2
- # via
- # delocate
- # virtualenv
-virtualenv==21.1.0
- # via -r cibuildwheel/resources/constraints.in
-zipp==3.20.2
- # via importlib-metadata
diff --git a/docs/configuration.md b/docs/configuration.md
index 0bdfd01b4..0e5146505 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -142,17 +142,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 31c879a79..14e255512 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 25198231d..043cf410f 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -341,34 +341,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 fd84d83c0..bd7d363ec 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