cibuildwheel

cibuildwheel simplifies the creation of Python Wheels for the different platforms and Python versions through Continuous Integration (CI) workflows. More precisely it builds manylinux, macOS 10.9+, and Windows wheels for CPython and PyPy with GitHub Actions, Azure Pipelines, Travis CI, AppVeyor, CircleCI, or GitLab CI/CD.

In addition, it bundles shared library dependencies on Linux and macOS through auditwheel and delocate.

Finally, the tests can also run against the wheels.

See also

To build Linux, macOS, and Windows wheels, create a .github/workflows/build_wheels.yml file in your GitHub repo:

.github/workflows/build_wheels.yml
name: Build

on:
  workflow_dispatch:
  release:
    types:
      - published
workflow_dispatch

allows you to click a button in the graphical user interface to trigger a build. This is perfect for manually testing wheels before a release, as you can easily download them from artifacts.

release

is executed when a tagged version is transferred.

See also

Now the wheels can be built with:

jobs:
  build_wheels:
    name: Build wheels on ${{ matrix.os }}
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        # macos-13 is an intel runner, macos-14 is apple silicon
        os: [ubuntu-latest, windows-latest, macos-13, macos-14]

    steps:
      - uses: actions/checkout@v4

      - name: Build wheels
        uses: pypa/cibuildwheel@v2.21.3

This runs the CI workflow with the following default settings:

  • package-dir: .

  • output-dir: wheelhouse

  • config-file: "{package}/pyproject.toml"

Now you can finally upload the artefacts of both jobs to the PyPI:

      - uses: actions/upload-artifact@v4
        with:
          name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
          path: ./wheelhouse/*.whl

To build wheels for Linux, macOS, and Windows with GitLab CI/CD, create a .gitlab-ci.yml file in your repository:

linux:
  image: python:latest
  # make a docker daemon available for cibuildwheel to use
  services:
    - name: docker:dind
      entrypoint: ["env", "-u", "DOCKER_HOST"]
      command: ["dockerd-entrypoint.sh"]
  variables:
    DOCKER_HOST: tcp://docker:2375/
    DOCKER_DRIVER: overlay2
    # See https://github.com/docker-library/docker/pull/166
    DOCKER_TLS_CERTDIR: ""
  script:
    - curl -sSL https://get.docker.com/ | sh
    - python -m pip install cibuildwheel==2.21.3
    - cibuildwheel --output-dir wheelhouse
  artifacts:
    paths:
      - wheelhouse/

windows:
  image: mcr.microsoft.com/windows/servercore:1809
  before_script:
    - choco install python -y --version 3.12.4
    - choco install git.install -y
    - py -m pip install cibuildwheel==2.21.3
  script:
    - py -m cibuildwheel --output-dir wheelhouse --platform windows
  artifacts:
    paths:
      - wheelhouse/
  tags:
    - saas-windows-medium-amd64

macos:
  image: macos-14-xcode-15
  before_script:
    - python3 -m pip install cibuildwheel==2.21.3
  script:
    - python3 -m cibuildwheel --output-dir wheelhouse
  artifacts:
    paths:
      - wheelhouse/
  tags:
    - saas-macos-medium-m1

Options

cibuildwheel can be configured either via environment variables or via a configuration file such as pyproject.toml, for example:

[tool.cibuildwheel]
test-requires = "pytest"
test-command = "pytest {project}/tests"
build-verbosity = 1

# support Universal2 for Apple Silicon:
[tool.cibuildwheel.macos]
archs = ["auto", "universal2"]
test-skip = ["*universal2:arm64"]

Examples