Platforms

Linux

System requirements

If you've gotDocker installed on your development machine, you can run a Linux build.

Tip

You can run the Linux build on any platform. Even Windows can runLinux containers these days, but there are a few hoops to jumpthrough. Checkthis documentfor more info.

Because the builds are happening in manylinux Docker containers, they're perfectly reproducible.

The only side effect to your system will be docker images being pulled.

Build containers

Linux wheels are built inmanylinux/musllinux containers to provide binary compatible wheels on Linux, according toPEP 600 /PEP 656. Because of this, when building withcibuildwheel on Linux, a few things should be taken into account:

  • Programs and libraries are not installed on the CI runner host, but rather should be installed inside the container - usingyum formanylinux2014,apt-get formanylinux_2_31 ormanylinux_2_35,dnf formanylinux_2_28 andapk formusllinux_1_1 ormusllinux_1_2, or manually. The same goes for environment variables that are potentially needed to customize the wheel building.

    cibuildwheel supports this by providing theenvironment andbefore-all options to setup the build environment inside the running container.

  • The project directory is copied into the container as/project, the output directory for the wheels to be copied out is/output. In general, this is handled transparently bycibuildwheel. For a more finegrained level of control however, the root of the host file system is mounted as/host, allowing for example to access shared files, caches, etc. on the host file system. Note that/host is not available on CircleCI and GitLab CI due to their Docker policies.

  • Alternative Docker images can be specified with themanylinux-*-image/musllinux-*-image options to allow for a custom, preconfigured build environment for the Linux builds. Seeoptions for more details.

macOS

System requirements

You need to have native build tools installed. Usexcode-select --install to install the Xcode command line tools.

Because the builds are happening without full isolation, there might be some differences compared to CI builds (Xcode version, OS version, local files, ...) that might prevent you from finding an issue only seen in CI.

In order to speed-up builds, cibuildwheel will cache the tools it needs to be reused for future builds. The folder used for caching is system/user dependent and is reported in the printed preamble of each run (e.g.Cache folder: /Users/Matt/Library/Caches/cibuildwheel). You can override the cache folder using theCIBW_CACHE_PATH environment variable.

Warning

cibuildwheel uses official python.org macOS installers for CPython but those can only be installed globally.

In order not to mess with your system, cibuildwheel won't install those if they are missing. Instead, it will error out with a message to let you install the missing CPython:

Error: CPython 3.9 is not installed.cibuildwheel will not perform system-wide installs when running outside of CI.To build locally, install CPython 3.9 on this machine, or, disable this version of Python using CIBW_SKIP=cp39-macosx_*Download link: https://www.python.org/ftp/python/3.9.8/python-3.9.8-macosx10.9.pkg

macOS Version Compatibility

macOS allows you to specify a "deployment target" version that will ensure backwards compatibility with older versions of macOS. For most projects, the way to do this is to set theMACOSX_DEPLOYMENT_TARGET environment variable.

macOS builds will honor theMACOSX_DEPLOYMENT_TARGET environment variable to control the minimum supported macOS version for generated wheels. The lowest value you can setMACOSX_DEPLOYMENT_TARGET is as follows:

ArchPython version rangeMinimum target
IntelCPython 3.8-3.1110.9
IntelCPython 3.12-3.1310.13
IntelCPython 3.14+10.15
ASCPython or PyPy11
IntelPyPy 3.810.13
IntelPyPy 3.9+10.15

If you set the value lower, cibuildwheel will cap it to the lowest supported value for each target as needed.

Note

For Rust-based extensions,Rustc requiresMACOSX_DEPLOYMENT_TARGET to be atleast 10.12. However,cibuildwheel defaults to 10.9 forIntel / CPython 3.8-3.11 builds. Users must manually setMACOSX_DEPLOYMENT_TARGET to 10.12 or higher when building Rust extensions.

macOS architectures

cibuildwheel supports both native builds and cross-compiling betweenarm64 (Apple Silicon) andx86_64 (Intel) architectures, including the cross-compatibleuniversal2 format. By default, macOS builds will build a single architecture wheel, using the build machine's architecture.

If you need to support bothx86_64 and Apple Silicon, you can use themacos.archs setting to specify the architectures you want to build, or the valueuniversal2 to build a multi-architecture wheel. cibuildwheelwill testx86_64 wheels (or thex86_64 slice of auniversal2 wheel) when running on Apple Silicon hardware using Rosetta 2 emulation, but it isnot possible to test Apple Silicon wheels onx86_64 hardware.

Overview of Mac architectures

x86_64

The traditional wheel for Apple, loads on Intel machines, and onApple Silicon when running Python under Rosetta 2 emulation.

Due to a change in naming, Pip 20.3+ (or an installer using packaging 20.5+)is required to install a binary wheel on macOS Big Sur.

arm64

The native wheel for macOS on Apple Silicon.

universal2

This wheel contains both architectures, causing it to be up to twice thesize (data files do not get doubled, only compiled code).

The dual-architectureuniversal2 has a few benefits, but a key benefitto a universal wheel is that a user can bundle these wheels into anapplication and ship a single binary.

However, if you have a large library, then you might prefer to shipthe two single-arch wheels instead -x86_64 andarm64. In rare cases,you might want to build all three, but in that case, pip will not downloadthe universal wheels, because it prefers the most specific wheelavailable.

What to provide?

Opinions vary on which of arch-specific oruniversal2 wheels are best - some packagers preferuniversal2 because it's one wheel for all Mac users, so simpler, and easier to build into apps for downstream users. However, because they contain code for both architectures, their file size is larger, meaning they consume more disk space and bandwidth, and are harder to build for some projects.

SeeGitHub issue 1333 for more discussion.

How?

It's easiest to buildx86_64 wheels onx86_64 runners, andarm64 wheels onarm64 runners.

On GitHub Actions,macos-14 runners arearm64, andmacos-15-intel runners arex86_64. So all you need to do is ensure both are in your build matrix.

Cross-compiling

If your CI provider doesn't offer arm64 runners yet, or you want to createuniversal2, you'll have to cross-compile. Cross-compilation can be enabled by adding extra archs to theCIBW_ARCHS_MACOS option - e.g.CIBW_ARCHS_MACOS="x86_64 universal2". Cross-compilation is provided by Xcode toolchain v12.2+.

Regarding testing,

  • On an arm64 runner, it is possible to testx86_64 wheels and both parts of auniversal2 wheel using Rosetta 2 emulation.
  • On anx86_64 runner, arm64 code can be compiled but it can't be tested.cibuildwheel will raise a warning to notify you of this - these warnings can be silenced by skipping testing on these platforms:test-skip = ["*_arm64", "*_universal2:arm64"].

Note

If your project usesPoetry as a build backend, cross-compiling on macOSdoes not currently work. In some cases arm64 wheels can be built but their tags will be incorrect, with the platform tag showingx86_64 instead ofarm64.

As a workaround, the tag can be fixed before running delocate to repair the wheel. Thewheel tags command is ideal for this. Seethis workflow for an example usage ofwheel tags.

Windows

System requirements

You must have native build tools (i.e., Visual Studio) installed.

Because the builds are happening without full isolation, there might be some differences compared to CI builds (Visual Studio version, OS version, local files, ...) that might prevent you from finding an issue only seen in CI.

In order to speed-up builds, cibuildwheel will cache the tools it needs to be reused for future builds. The folder used for caching is system/user dependent and is reported in the printed preamble of each run (e.g.Cache folder: C:\Users\Matt\AppData\Local\pypa\cibuildwheel\Cache). You can override the cache folder using theCIBW_CACHE_PATH environment variable.

Windows ARM64 builds

cibuildwheel supports cross-compilingARM64 wheels on all Windows runners, but a nativeARM64 runner is required for testing. On non-native runners, tests forARM64 wheels will be automatically skipped with a warning. Add"*-win_arm64" to yourtest-skip setting to suppress the warning.

Cross-compilation on Windows relies on a supported build backend. Supported backends use an environment variable to specify their target platform (the one they are compiling native modules for, as opposed to the one they are running on), which is set incibuildwheel's windows.py before building. Currently,setuptools>=65.4.1 andsetuptools_rust are the only supported backends.

By default,ARM64 is not enabled when running on non-ARM64 runners. UseCIBW_ARCHS to select it.

Pyodide/WebAssembly

Pyodide is offered as an experimental feature in cibuildwheel.

System requirements

Pyodide builds require a Linux or macOS machine.

Specifying a pyodide build

You must target pyodide with--platform pyodide (or use--only on the identifier).

Choosing a Pyodide version

It is also possible to target a specific Pyodide version by setting thepyodide-version option to the desired version. Users are responsible for setting an appropriate Pyodide version according to thepyodide-build version. A list is available in Pyodide'scross-build environments metadata file, which can be viewed more easily by installingpyodide-build from PyPI and usingpyodide xbuildenv search --all to see a compatibility table.

If there are pre-releases available for a newer Pyodide version, thepyodide-prereleaseenable can be used to include pre-release versions.

Running tests

Currently, it's recommended to run tests using apython -m entrypoint, rather than a command line entrypoint, or a shell script. This is because custom entrypoints have some issues in the Pyodide virtual environment. For example,pytest may not work as a command line entrypoint, but will work as apython -m pytest entrypoint.

Android

Prerequisites

cibuildwheel can build Android wheels on any POSIX platform supported by the Androiddevelopment tools, which currently means Linux x86_64, macOS ARM64 or macOS x86_64. Anyof these platforms can be used to build wheels for any Android architecture supported byPython. However,testing wheels has additional requirements: see the section below.

If you already have an Android SDK, export theANDROID_HOME environment variable topoint at its location. Otherwise, here's how to install it:

  • Download the "Command line tools" fromhttps://developer.android.com/studio.
  • Create a directoryandroid-sdk/cmdline-tools, and unzip the command line tools package into it.
  • Renameandroid-sdk/cmdline-tools/cmdline-tools toandroid-sdk/cmdline-tools/latest.
  • export ANDROID_HOME=/path/to/android-sdk

cibuildwheel will automatically use the SDK'ssdkmanager to install any packages itneeds.

It also requires the following commands to be on thePATH:

  • curl
  • java (or set theJAVA_HOME environment variable)

Android version compatibility

Android builds will honor theANDROID_API_LEVEL environment variable to set theminimum supportedAPI levelfor generated wheels. This will default to the minimum API level of the selected Pythonversion.

If therepair-wheel-command adds any libraries tothe wheel, thenANDROID_API_LEVEL must be at least 24. This is already the defaultwhen building for Python 3.14 and later, but you may need to set it when building forPython 3.13.

Build frontend support

Android builds only support thebuild frontend. In principle, support for thebuild[uv] frontend should be possible, butuvdoesn't currently have support forcross-platform builds, anddoesn't havesupport for iOS or Android wheel tags.

Tests

Tests are executed on a Gradle-managed emulator matching the architecture of the buildmachine – for example, if you're building on an ARM64 machine, then you can test anARM64 wheel. Wheels of other architectures can still be built, but testing willautomatically be skipped.

Any arguments specified usingtest-runtime will be passed as arguments to the Python script that starts thetestbed project. cibuildwheel will automatically start the testbed project with--site-packages and--cwd arguments matching your test environment, as well as enabling verbose output with-v ifbuild-verbosity is enabled. The most common additional arguments to use will be--managed minVersion or--managed maxVersion, specifying the use of a managed Android emulator with the minimum or maximum supported Android version; or--connected <serial>, specifying the use of an existing booted Android emulator or device. By default, the testbed project will run with--managed maxVersion.

Running an emulator requires the build machine to either be bare-metal or supportnested virtualization. CI platforms known to meet this requirement are:

  • GitHub Actions Linux x86_64

On Linux, the emulator needs access to the KVM virtualization interface. This mayrequire adding your user to a group, or changing your udev rules. On GitHubActions, cibuildwheel will do this automatically using the commands shownhere.

The Android test environment can't support running shell scripts, so thetest-command must be a Python command – see itsdocumentation for details.

If your package has dependencies which haven't been released on PyPI yet, you may wantto use theenvironment option to setPIP_EXTRA_INDEX_URLto one of the following URLs:

iOS

System requirements

You must be building on a macOS machine, with Xcode installed. The Xcode installation must have an iOS SDK available, with all license agreements agreed to by the user. To check if an iOS SDK is available, open the Xcode settings panel, and check the Platforms tab. This will also ensure that license agreements have been acknowledged.

Building iOS wheels also requires a working macOS Python installation. See the notes onmacOS builds for details about configuration of the macOS environment.

Specifying an iOS build

iOS is effectively 2 platforms - physical devices, and simulators. While the API for these two platforms are identical, the ABI is not compatible, even when dealing with a device and simulator with the same CPU architecture. For this reason, the architecture specification for iOS builds includesboth the CPU architectureand the ABI that is being targeted. There are three possible values for architecture on iOS; the values match those used bysys.implementation._multiarch when running on iOS (with hyphens replaced with underscores, matching wheel filename normalization):

  • arm64_iphoneos (for physical iOS devices);
  • arm64_iphonesimulator (for iOS simulators running on Apple Silicon macOS machines); and
  • x86_64_iphonesimulator (for iOS simulators running on Intel macOS machines).

By default, cibuildwheel will build all wheels for the CPU architecture of the build machine. You can build all wheels for all architectures by specifying--archs all.

If you need to specify different compilation flags or other properties on a per-ABI or per-CPU basis, you can useconfiguration overrides with aselect clause that targets the specific ABI or architecture. For example, consider the following example:

[tool.cibuildwheel.ios]test-sources = ["tests"]test-requires = ["pytest"][[tool.cibuildwheel.overrides]]select = "*_iphoneos"environment.PATH = "/path/to/special/device/details:..."[[tool.cibuildwheel.overrides]]select = "*-ios_arm64_*"inherit.test-requires = "append"test-requires = ["arm64-testing-helper"]

This configuration would:

  • Specify atest-sources andtest-requires for all iOS targets;
  • Add aPATH setting that will be used on physical iOS devices; and
  • Addarm64-testing-helper to the test environment for all ARM64 iOS devices (whether simulator or device).

iOS version compatibility

iOS builds will honor theIPHONEOS_DEPLOYMENT_TARGET environment variable to set the minimum supported API version for generated wheels. This will default to13.0 if the environment variable isn't set.

Cross platform builds

iOS builds arecross platform builds, as it not possible to run compilers and other build tools "on device". The pre-compiled iOS binaries used to support iOS builds include tooling that can convert any virtual environment into a cross platform virtual environment - that is, an environment that can run binaries on the build machine (macOS), but, if asked, will respond as if it is an iOS machine. This allowspip,build, and other build tools to perform iOS-appropriate behaviour.

Build frontend support

iOS builds support both thepip andbuild build frontends. In principle, support foruv with thebuild[uv] frontend should be possible, butuvdoesn't currently have support for cross-platform builds, anddoesn't have support for iOS (or Android) tags.

Build environment

The environment used to run builds does not inherit the full user environment - in particular,PATH is deliberately re-written. This is because UNIX C tooling doesn't do a great job differentiating between "macOS ARM64" and "iOS ARM64" binaries. If (for example) Homebrew is on the path when compilation commands are invoked, it's easy for a macOS version of a library to be linked into the iOS binary, rendering it unusable on iOS. To prevent this, iOS builds always forcePATH to a "known minimal" path, that includes only the bare system utilities, and the iOS compiler toolchain.

If your project requires additional tools to build (such ascmake,ninja, orrustc), those tools must be explicitly declared as cross-build tools usingxbuild-tools.Any tool used by the build process must be included in thexbuild-tools list, not just tools that cibuildwheel will invoke directly. For example, if your build script invokescmake, and thecmake script invokesmagick to perform some image transformations, bothcmake andmagick must be included in your cross-build tools list.

Tests

If tests have been configured, the test suite will be executed on the simulator matching the architecture of the build machine - that is, if you're building on an ARM64 macOS machine, the ARM64 wheel will be tested on an ARM64 simulator. It is not possible to use cibuildwheel to test wheels on other simulators, or on physical devices.

The iOS test environment can't support running shell scripts, so thetest-command value must be specified as if it were a command line being passed topython -m ....

The test process uses thesame testbed used by CPython itself to run the CPython test suite. It is an Xcode project that has been configured to have a single Xcode "XCUnit" test - the result of which reports the success or failure of runningpython -m <test-command>.

Any arguments specified usingtest-runtime will be passed as arguments to the Python script that starts the testbed project. The testbed project will be started with-v enabling verbose output ifbuild-verbosity is enabled; the most common additional argument to use will be--simulator, which allows the specification of a specific device or iOS version for the test simulator. By default, the testbed project will attempt to find an "SE class" simulator (i.e., an iPhone SE, iPhone 16e, or similar), running the newest iOS version available.