TopGit
GitHub Repo Review

cibuildwheel Python Wheels: Built for Every CI

pypa/cibuildwheel
CTopGit review image for pypa/cibuildwheel
Review by Topgit.dev for pypa/cibuildwheel, with GitHub repository stats and README context.
Quick verdict

cibuildwheel is a PyPA command-line tool that builds and tests Python wheels for macOS, Windows, and Linux inside your CI pipeline. It hands the repair step to auditwheel, delocate, or delvewheel per platform, replacing hand-written build scripts per OS. Reach for it once your package has a C extension and needs wheels for more than one platform; skip it for pure-Python projects, where a plain sdist already does the job.

Stars
โ˜… 2.3k
Forks
โ‘‚ 320
Contributors
๐Ÿ‘ฅ 169
Language
Python
License
BSD-2-Clause
Topic
Automation
Updated
Aug 2026

The Challenge of Cross-Platform Python Wheels

Python package maintainers who ship a C extension can't just run `pip install` and call it done โ€” every combination of OS, architecture, and CPython/PyPy/GraalPy version needs its own compiled wheel, built inside a container with the right compiler toolchain, then repaired so it doesn't silently depend on a shared library that only exists on the build machine. Before cibuildwheel, that meant hand-writing separate build scripts per CI provider and manually wiring up manylinux containers, delocate, and delvewheel yourself. cibuildwheel's README frames its own reason for existing around exactly that: one command that drives the platform-specific repair tool and target Python matrix for you.

What cibuildwheel Automates

cibuildwheel automates building and testing Python wheels across every platform your package needs to ship for, driven from inside a CI job rather than your laptop. It runs `python -m cibuildwheel --output-dir wheelhouse`, builds against the CPython, PyPy, or GraalPy versions you select, repairs each wheel with auditwheel, delocate, or delvewheel depending on platform, then reinstalls it and runs your test command against it.

Comprehensive Platform and Python Support

  • โœ“Targets CPython 3.9 through 3.15, PyPy 3.9-3.11 v7.3, and GraalPy 3.12 v25.0, per the version support table in the README โ€” PyPy and GraalPy builds are restricted to manylinux wheels.
  • โœ“Builds manylinux and musllinux wheels for x86_64, i686, aarch64, ppc64le, and s390x, plus an armv7l target the README marks experimental (it runs on an Ubuntu-based image since no RHEL-based image exists for that architecture).
  • โœ“Covers macOS Intel and Apple Silicon, plus Windows 64-bit, 32-bit, and an experimental Windows ARM64 target built via cross-compilation โ€” the README notes arm64 can't be tested on Windows CI runners.
  • โœ“Also builds Pyodide (WebAssembly) wheels, and โ€” starting with CPython 3.13 โ€” Android and iOS wheels, per the support table.
  • โœ“Repairs shared library dependencies per platform: auditwheel on Linux, delocate on macOS, delvewheel on Windows, bundling what each wheel needs so it runs without extra install steps.
  • โœ“Reinstalls the just-built wheel and runs the project's own test command against it, rather than just checking that the build didn't error.
  • โœ“Runs on GitHub Actions, Azure Pipelines, CircleCI, and GitLab CI, with configuration set either in pyproject.toml or as environment variables โ€” the same config works across providers.
  • โœ“Options cover build selection (platform, archs, enable), build customization (before-build, repair-wheel-command, container-engine), and test control (test-command, test-requires, test-skip), per the options table in the README.
How this repository's GitHub stars have grown over time. Source: star-history.com.View the star history โ†—

Integrating with Your CI Workflow

The README's example workflow installs a pinned version with `python -m pip install cibuildwheel==4.2.0`, then runs `python -m cibuildwheel --output-dir wheelhouse` as a CI step โ€” no local install is expected, since cibuildwheel is meant to run inside the CI job itself. The sample `.github/workflows/wheels.yml` in the README builds across a matrix of `ubuntu-latest`, `ubuntu-24.04-arm`, `windows-latest`, `windows-11-arm`, `macos-15-intel`, and `macos-latest` runners, using `actions/setup-python` to host cibuildwheel and `actions/upload-artifact` to collect the built `.whl` files from the `wheelhouse` directory. The README also points to a dedicated GitHub Action and to per-provider setup for Azure Pipelines, CircleCI, and GitLab CI in the full documentation, though it doesn't spell those out inline.

Customizing Your Wheel Builds

Every option can be set in `pyproject.toml` or as an environment variable, which is what the `CIBW_`-prefixed variables in most examples map to. Build selection options like `platform`, `archs`, and `build`/`skip` narrow which wheels actually get built; `enable` turns on extra selector categories such as CPython prereleases. Build customization runs shell commands at defined points โ€” `before-all` runs once per platform before any wheel builds, `before-build` runs before each individual wheel, and `repair-wheel-command` overrides the default auditwheel/delocate/delvewheel step entirely if you need a custom repair tool. Testing options are separate: `test-command` runs against the installed wheel, `test-requires` and `test-extras` pull in test dependencies, and `test-skip` excludes specific build identifiers from testing, all documented in the options table in the README.

Projects Using cibuildwheel

  • โ€ขBuilding wheels with Cython and C++ extensions at scale โ€” the README names scikit-learn's own cibuildwheel config as 'a complex but clean' example of this.
  • โ€ขShipping compiled Python packages for data tooling: the README lists DuckDB, an analytical in-process SQL database, and NumPy as projects using cibuildwheel.
  • โ€ขCompiling with mypyc instead of plain Python โ€” the README names MyPy's own mypyc-compiled wheel builds as an example.
  • โ€ขRunning wheel builds on self-hosted runners: the README lists Triton as doing exactly that with cibuildwheel.
  • โ€ขBuilding C-extension-heavy libraries like Facebook AI Research's fairseq toolkit and the Prophet forecasting library, both named in the README's working-examples table.

Strengths

  • โœ“One config drives four CI providers โ€” GitHub Actions, Azure Pipelines, CircleCI, and GitLab CI โ€” set through the same pyproject.toml options or environment variables, per the README.
  • โœ“Covers an unusually wide platform matrix for a single tool: manylinux/musllinux across five architectures, macOS Intel and Apple Silicon, Windows including ARM64, Pyodide, Android, and iOS.
  • โœ“Handles the repair step itself โ€” auditwheel, delocate, or delvewheel โ€” instead of leaving you to wire each one up by hand per platform.
  • โœ“Tests the actual built-and-installed wheel, not just a source checkout, catching packaging bugs that unit tests run against the repo wouldn't.
  • โœ“Backed by real-world adopters named in the README โ€” scikit-learn, NumPy, DuckDB, Matplotlib, and MyPy among them โ€” across a range of build complexities.
  • โœ“BSD-2-Clause license, and configuration lives in pyproject.toml alongside the rest of your packaging metadata rather than a separate proprietary format.

Important Considerations and Warnings

  • โ–ณWhen wheels are built and tested, arbitrary code originating in your project and its dependencies is executed; the README itself warns that OCI containers and Pyodide offer no security assurances, therefore suggesting that the build job be kept separate from the job uploading to PyPI, and that credentials be handled with care.
  • โ–ณThe repaired wheel can bundle dynamically linked libraries from the build machine โ€” the README's legal note compares this to static linking and says it 'might have some license implications,' so you need to check the licenses of what you're pulling in.
  • โ–ณWindows ARM64 support is marked experimental and built via cross-compilation; the README states arm64 can't actually be tested on that CI platform.
  • โ–ณmanylinux armv7l support is also experimental โ€” the README notes there's no RHEL-based container image for that architecture, so it runs on an Ubuntu-based image instead.
  • โ–ณGitLab CI's Linux ARM support requires emulation distributed separately from cibuildwheel, and several CI-provider combinations for Android, iOS, and Pyodide builds are flagged in the README's own support table as untested in cibuildwheel's CI even though they may work.

Other Python Wheel Building Tools

auditwheel โ€” the Linux wheel-repair tool cibuildwheel itself calls for manylinux builds; useful stand-alone if you already have a Linux build pipeline and just need the repair step, not full CI orchestration.delocate โ€” the macOS equivalent, again a tool cibuildwheel wraps rather than replaces; pick it directly if you're scripting a macOS-only build outside CI.delvewheel โ€” the Windows shared-library bundler cibuildwheel calls under the hood; same trade-off, useful alone if you don't need cross-platform CI orchestration.build โ€” PyPA's own front-end for building a single sdist/wheel locally; simpler than cibuildwheel but it won't cross-compile or target multiple platforms for you.maturin โ€” geared specifically at Rust-backed Python extensions with its own wheel-building and publishing workflow, a narrower alternative if your compiled code is Rust rather than C/C++.

Frequently Asked Questions

What CI services does cibuildwheel support?

cibuildwheel runs on GitHub Actions, Azure Pipelines, CircleCI, and GitLab CI, per its README, with the same pyproject.toml or environment-variable configuration working across all four.

Which Python versions can cibuildwheel build wheels for?

cibuildwheel builds wheels for CPython 3.9 through 3.15, PyPy 3.9 through 3.11 (v7.3), and GraalPy 3.12 (v25.0), though PyPy and GraalPy builds are limited to manylinux wheels.

What platforms does cibuildwheel support for building wheels?

cibuildwheel targets macOS (Intel and Apple Silicon), Windows (64-bit, 32-bit, and experimental ARM64), manylinux/musllinux Linux across five architectures plus experimental armv7l, Pyodide, Android, and iOS.

Are there any licensing considerations when using cibuildwheel?

cibuildwheel's README flags one: since repair tools like delocate, auditwheel, and delvewheel can bundle dynamically linked libraries from the build machine, similar to static linking, you should check the license of any code you're pulling in.

How does cibuildwheel handle shared library dependencies?

cibuildwheel repairs each wheel with a platform-specific tool โ€” auditwheel on Linux, delocate on macOS, delvewheel on Windows โ€” bundling shared library dependencies so the wheel runs without extra install steps.

Can cibuildwheel run tests against built wheels?

cibuildwheel installs each built wheel and runs your project's own test command against it, configurable through the test-command, test-requires, and test-skip options in its README.

Who should try it โ€” and who should skip

Try cibuildwheel if you maintain a Python package with a C, C++, Cython, or Rust extension and need wheels for more than one OS or architecture โ€” the CI-driven matrix and automatic repair step replace what would otherwise be hand-written build scripts per platform. Skip it if your package is pure Python with no compiled code, since a plain sdist or a single `pip wheel` covers that without any of cibuildwheel's platform matrix or container overhead; it's also not the tool for building a single local wheel on your own machine outside CI.

Related repositories

Source & attribution

Facts and details sourced from the pypa/cibuildwheel GitHub repository and its README.

GitHub data ยท last synced Aug 12, 2026Reviewed by Henry
โ† Back to TopGit

Curious whether cibuildwheel is right for you?

Let ChatGPT, Claude, or Perplexity look into it โ€” click below and see what AI actually says about cibuildwheel.

GitHub