Expectations that projects provide ever more wheels
Most users expect
pip install project-name to work on all platforms. When
building from source is difficult, that expectation translates into requests to
projects to provide more wheels. Building many wheels can result in a lot
of maintenance work and load on CI systems.
See this summary
for the combination of operating systems, Python interpreters, CPU
libc flavors which are supported by wheel specs/tags. The
cibuildwheel matrix adds up
to 70 combinations - and that doesn't include multiple
universal2 for macOS, i686 (32-bit) Linux, or some architectures that were
added in PEP 599 (
Nor does it include tags that are likely to be added (WASM), or for which tags exist but aren't supported by PyPI
In practice, the less popular platforms are not supported by most projects and the number of wheels they upload to PyPI is in the 20-40 range. Examples:
- Kivy 2.1.0 (20 wheels),
- NumPy 1.23.5 (27 wheels),
- Numba 0.56.4 (27 wheels),
- Mypy 0.991 (29 wheels),
- asyncpg 0.27.0 (35 wheels),
- Pydantic 1.10.2 (35 wheels),
- PyGame 2.1.2 (57 wheels).
That is still a large amount of wheels, and maintaining support for them is often problematic.
A key ingredient for building wheels is availability of CI systems which
support the target platforms. Most projects use 3-4 different CI systems,
and/or make use of cross-compilation when a target platform isn't natively
supported (e.g., macOS arm64 CI runners were unavailable for 2 years, and are
still only available on Cirrus CI as of Dec 2022, and PowerPC (
IBM Z (
s390x) are only available on Travis CI).
cibuildwheel has lowered
the effort to build wheels compared to
multibuild, however the CI
system requirements haven't changed. Each CI system requires maintenance - and
self-hosted CI runners are even worse in this respect. That maintenance cost
can be shared much more easily for packaging systems with centralized builds;
for building wheels they have to be paid by every project (see Lack of a build
farm for PyPI for more details).
The primary problem is the large amount of maintenance effort on CI systems for wheel building. This is particularly painful because:
- there are usually one a couple of maintainers (perhaps even a single person) who are responsible for or have expertise in wheel building,
- issues that show up are often specific to the platform and hence cannot be debugged locally on the maintainer's development machine,
- there are a lot of "layers" to wade through: CI system, cibuildwheel, pip, build backend, backend, build system.
Another issue is that a lot of discussion needed each time there is a request to any project to support a new platform.
Links to key issues, forum discussions, PEPs, blog posts, etc.
- Supporting WASM wheels on PyPI thread on Discourse (2022)
- Reducing effort spent on wheels? thread on the NumPy mailing list (2021)
Related to platform support:
- PEP 11 - CPython platform support,
- NEP 29 - Recommend Python and NumPy version support as a community policy standard,
- SciPy Toolchain Roadmap & Official Builds.
Potential solutions or mitigations
- Reducing the number of wheels needed. HPy is probably the most promising way of achieving this.
- Defining a "supported platforms" policy that can be used across projects to make and document decisions around this topic.
- A build farm for PyPI (see this meta topic).
- Having PyPI integrate better with other packaging systems, so users can obtain pure Python packages from PyPI in combination with hard-to-build packages from a package manager with support for the platform of interest.
- Manage user expectations better, and be honest about limitations of PyPI/wheels. Users are often better served by a distribution that is built and tested in a consistent fashion than by downloading a standalone interpreter and then installing packages from PyPI. This is often not even presented on install pages as an option, let alone recommended.
Created: December 20, 2022