Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 13 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,24 @@ What does it do?

While cibuildwheel itself requires a recent Python version to run (we support the last three releases), it can target the following versions to build wheels:

| | macOS Intel | macOS Apple Silicon | Windows 64bit | Windows 32bit | Windows Arm64 | manylinux<br/>musllinux x86_64 | manylinux<br/>musllinux i686 | manylinux<br/>musllinux aarch64 | manylinux<br/>musllinux ppc64le | manylinux<br/>musllinux s390x | manylinux<br/>musllinux armv7l | Android | iOS | Pyodide |
| ------------------------ | ----------- | ------------------- | ------------- | ------------- | -------------- | ------------------------------ | ---------------------------- | ------------------------------- | ------------------------------- | ----------------------------- | ------------------------------ | ------- | --- | -------------- |
| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | ✅<sup>3</sup> |
| CPython 3.13 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | ✅ |
| CPython 3.14 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | ✅ |
| CPython 3.15<sup>5</sup> | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | ✅ |
| PyPy 3.9 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | ✅<sup>1</sup> | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| PyPy 3.10 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | ✅<sup>1</sup> | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| PyPy 3.11 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | ✅<sup>1</sup> | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| GraalPy 3.12 v25.0 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | N/A | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| | macOS Intel | macOS Apple Silicon | Windows 64bit | Windows 32bit | Windows Arm64 | manylinux<br/>musllinux x86_64 | manylinux<br/>musllinux i686 | manylinux<br/>musllinux aarch64 | manylinux<br/>musllinux ppc64le | manylinux<br/>musllinux s390x | manylinux<br/>musllinux armv7l | Android | iOS | Pyodide |
|--------------------| ----------- | ------------------- | ------------- | ------------- | -------------- | ------------------------------ | ---------------------------- | ------------------------------- | ------------------------------- | ----------------------------- | ------------------------------ | ------- | --- | -------------- |
| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | N/A |
| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | N/A | N/A | ✅<sup>3</sup> |
| CPython 3.13 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | ✅ |
| CPython 3.14 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | ✅ |
| CPython 3.15 | ✅ | ✅ | ✅ | ✅ | ✅<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅<sup>4</sup> | ✅ | ✅ | ✅ |
| PyPy 3.9 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | ✅<sup>1</sup> | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| PyPy 3.10 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | ✅<sup>1</sup> | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| PyPy 3.11 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | ✅<sup>1</sup> | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |
| GraalPy 3.12 v25.0 | ✅ | ✅ | ✅ | N/A | N/A | ✅<sup>1</sup> | N/A | ✅<sup>1</sup> | N/A | N/A | N/A | N/A | N/A | N/A |

<sup>**1** PyPy & GraalPy are only supported for manylinux wheels.</sup><br>
<sup>**2** Windows arm64 support is experimental.</sup><br>
<sup>**3** Not supported on PyPI, uses old `pyodide` tag instead of `pyemscripten`. Requires `pyodide-eol` [`enable`](https://cibuildwheel.pypa.io/en/stable/options/#enable).</sup><br>
<sup>**4** manylinux armv7l support is experimental. As there are no RHEL based image for this architecture, it's using an Ubuntu based image instead.</sup><br>
<sup>**5** Python 3.15 requires opt-in using [`enable`](https://cibuildwheel.pypa.io/en/stable/options/#enable).</sup><br>

- Builds manylinux, musllinux, macOS, Windows, pyemscripten, iOS, and Android wheels
- Supports CPython, PyPy, and GraalPy
Expand Down
2 changes: 1 addition & 1 deletion cibuildwheel/selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def __call__(self, build_id: str) -> bool:
return False

# filter out groups that are not enabled
if EnableGroup.CPythonPrerelease not in self.enable and fnmatch(build_id, "cp315*"):
if EnableGroup.CPythonPrerelease not in self.enable and fnmatch(build_id, "cp316*"):
return False
is_pypy_eol = fnmatch(build_id, "pp3?-*") or fnmatch(build_id, "pp310-*")
is_pypy = fnmatch(build_id, "pp*") and not is_pypy_eol
Expand Down
23 changes: 12 additions & 11 deletions test/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,20 +278,18 @@ def _expected_wheels(

# To be kept in sync with Python versions for Pyodide identifiers in cibuildwheel/selector.py.
if platform == "pyodide" and python_abi_tags is None:
python_abi_tags = ["cp313-cp313", "cp314-cp314"]
python_abi_tags = ["cp313-cp313", "cp314-cp314", "cp315-cp315"]
if EnableGroup.PyodideEoL in enable_groups:
python_abi_tags.insert(0, "cp312-cp312")
if EnableGroup.CPythonPrerelease in enable_groups:
python_abi_tags.append("cp315-cp315")
elif (platform == "android" and python_abi_tags is None) or (
platform == "ios" and python_abi_tags is None
):
elif platform in {"android", "ios"} and python_abi_tags is None:
python_abi_tags = [
"cp313-cp313",
"cp314-cp314",
"cp315-cp315",
]
if EnableGroup.CPythonPrerelease in enable_groups:
python_abi_tags += ["cp315-cp315"]
# python_abi_tags += ["cp316-cp316"]
... # Add cp316 here when available
elif python_abi_tags is None:
python_abi_tags = [
"cp39-cp39",
Expand All @@ -301,13 +299,16 @@ def _expected_wheels(
"cp313-cp313",
"cp314-cp314",
"cp314-cp314t",
"cp315-cp315",
"cp315-cp315t",
]

if EnableGroup.CPythonPrerelease in enable_groups:
python_abi_tags += [
"cp315-cp315",
"cp315-cp315t",
]
# python_abi_tags += [
# "cp316-cp316",
# "cp316-cp316t",
# ]
... # Add cp316 here when available

if EnableGroup.PyPyEoL in enable_groups:
python_abi_tags += [
Expand Down
6 changes: 4 additions & 2 deletions unit_test/build_selector_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def test_build() -> None:
assert build_selector("cp312-manylinux_x86_64")
assert build_selector("cp313-manylinux_x86_64")
assert build_selector("cp314-manylinux_x86_64")
assert build_selector("cp315-manylinux_x86_64")
assert build_selector("pp311-manylinux_x86_64")
assert build_selector("cp36-manylinux_i686")
assert build_selector("cp37-manylinux_i686")
Expand All @@ -37,6 +38,7 @@ def test_build() -> None:
assert build_selector("cp312-win_amd64")
assert build_selector("cp313-win_amd64")
assert build_selector("cp314-win_amd64")
assert build_selector("cp315-win_amd64")
assert not build_selector("pp310-win_amd64")
assert not build_selector("pp311-win_amd64")

Expand Down Expand Up @@ -100,7 +102,7 @@ def test_build_filter_pyodide() -> None:
assert build_selector("cp313-pyodide_wasm32")
assert build_selector("cp314-pyodide_wasm32")
assert not build_selector("cp312-pyodide_wasm32")
assert not build_selector("cp315-pyodide_wasm32")
assert build_selector("cp315-pyodide_wasm32")


def test_build_filter_pyodide_eol() -> None:
Expand All @@ -112,7 +114,7 @@ def test_build_filter_pyodide_eol() -> None:
assert build_selector("cp312-pyodide_wasm32")
assert build_selector("cp313-pyodide_wasm32")
assert build_selector("cp314-pyodide_wasm32")
assert not build_selector("cp315-pyodide_wasm32")
assert build_selector("cp315-pyodide_wasm32")


def test_skip() -> None:
Expand Down
6 changes: 4 additions & 2 deletions unit_test/linux_build_steps_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ def container_engines(
"cp313-manylinux_x86_64",
"cp314-manylinux_x86_64",
"cp314t-manylinux_x86_64",
"cp315-manylinux_x86_64",
"cp315t-manylinux_x86_64",
]
assert before_alls(build_steps[3]) == [""] * 4
assert container_engines(build_steps[3]) == [default_container_engine] * 4
assert before_alls(build_steps[3]) == [""] * 6
assert container_engines(build_steps[3]) == [default_container_engine] * 6


def test_package_dir_outside_working_directory_raises_configuration_error(
Expand Down
6 changes: 5 additions & 1 deletion unit_test/option_prepare_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from cibuildwheel.oci_container import OCIPlatform
from cibuildwheel.util import file

DEFAULT_IDS = {"cp39", "cp310", "cp311", "cp312", "cp313", "cp314", "cp314t"}
DEFAULT_IDS = {"cp39", "cp310", "cp311", "cp312", "cp313", "cp314", "cp314t", "cp315", "cp315t"}
ALL_IDS = DEFAULT_IDS | {"pp39", "pp310", "pp311", "gp312_250"}


Expand Down Expand Up @@ -155,6 +155,8 @@ def test_build_with_override_launches(monkeypatch: pytest.MonkeyPatch, tmp_path:
"cp313",
"cp314",
"cp314t",
"cp315",
"cp315t",
"pp39",
"pp310",
"pp311",
Expand All @@ -176,6 +178,8 @@ def test_build_with_override_launches(monkeypatch: pytest.MonkeyPatch, tmp_path:
"cp313",
"cp314",
"cp314t",
"cp315",
"cp315t",
"pp39",
"pp310",
"pp311",
Expand Down
Loading