CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-cibuildwheel

Build Python wheels on CI with minimal configuration.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

build-selection.mddocs/

Build Selection

Cibuildwheel provides a powerful pattern-based build selection system for controlling which Python versions, platforms, and architectures to build for.

Capabilities

Build Selector

Main interface for controlling which builds are executed.

@dataclasses.dataclass(frozen=True, kw_only=True)
class BuildSelector:
    build_config: str
    skip_config: str
    requires_python: SpecifierSet | None = None
    enable: frozenset[EnableGroup] = frozenset()
    
    def __call__(self, build_id: str) -> bool:
        """
        Test if a build identifier should be built.
        
        Args:
            build_id: Build identifier string (e.g., 'cp311-linux_x86_64')
            
        Returns:
            True if the build should be executed, False otherwise
        """

Test Selector

Controls which builds should have tests executed.

@dataclasses.dataclass(frozen=True, kw_only=True)
class TestSelector:
    skip_config: str
    
    def __call__(self, build_id: str) -> bool:
        """
        Test if a build should be tested.
        
        Args:
            build_id: Build identifier string
            
        Returns:
            True if tests should be run for this build, False otherwise
        """

Pattern Matching

Low-level pattern matching function for build selectors.

def selector_matches(patterns: str, string: str) -> bool:
    """
    Test if any pattern in a space-separated list matches a string.
    
    Args:
        patterns: Space-separated list of glob patterns
        string: String to test against patterns
        
    Returns:
        True if any pattern matches, False otherwise
    """

Enable Groups

Categories of builds that can be optionally enabled.

class EnableGroup(StrEnum):
    CPythonExperimentalRiscV64 = "cpython-experimental-riscv64"
    CPythonFreeThreading = "cpython-freethreading"
    CPythonPrerelease = "cpython-prerelease"
    GraalPy = "graalpy"
    PyPy = "pypy"
    PyPyEoL = "pypy-eol"
    PyodidePrerelease = "pyodide-prerelease"

Build Identifier Format

Build identifiers follow the pattern: {python_tag}-{platform_tag}

Python Tags

  • CPython: cp38, cp39, cp310, cp311, cp312, cp313, cp314
  • PyPy: pp38, pp39, pp310, pp311
  • GraalPy: graalpy311

Platform Tags

  • Linux: linux_x86_64, linux_i686, linux_aarch64, linux_ppc64le, linux_s390x, linux_armv7l, linux_riscv64
  • macOS: macosx_x86_64, macosx_arm64, macosx_universal2
  • Windows: win_amd64, win32, win_arm64
  • Pyodide: pyodide_wasm32
  • Android: android_arm64_v8a
  • iOS: ios_arm64_iphoneos, ios_arm64_iphonesimulator, ios_x86_64_iphonesimulator

Configuration Patterns

Build Selection Patterns

# Build specific Python versions
CIBW_BUILD = "cp39-* cp310-* cp311-*"

# Build for specific platforms
CIBW_BUILD = "*-linux_x86_64 *-macosx_x86_64"

# Build specific combinations
CIBW_BUILD = "cp311-linux_x86_64 cp311-macosx_arm64"

Skip Patterns

# Skip 32-bit builds
CIBW_SKIP = "*-win32 *-linux_i686"

# Skip PyPy builds
CIBW_SKIP = "pp*"

# Skip specific Python versions
CIBW_SKIP = "cp38-* cp39-*"

# Skip experimental architectures
CIBW_SKIP = "*-linux_riscv64 *-linux_armv7l"

Test Skip Patterns

# Skip tests for slow architectures
CIBW_TEST_SKIP = "*-linux_ppc64le *-linux_s390x"

# Skip tests for emulated builds
CIBW_TEST_SKIP = "*-linux_aarch64"

# Skip tests for specific Python versions
CIBW_TEST_SKIP = "cp38-*"

Enable Groups

CPython Prerelease

Enable building with prerelease CPython versions:

CIBW_ENABLE = "cpython-prerelease"
# Or in pyproject.toml:
# enable = ["cpython-prerelease"]

PyPy Support

Enable PyPy builds (disabled by default):

CIBW_ENABLE = "pypy"
# Enables: pp38, pp39, pp310, pp311

GraalPy Support

Enable GraalPy builds:

CIBW_ENABLE = "graalpy"
# Enables: graalpy311

Free-threaded CPython

Enable CPython builds with free-threading (Python 3.13+):

CIBW_ENABLE = "cpython-freethreading"
# Enables: cp313t (free-threaded variant)

Experimental RISC-V

Enable experimental RISC-V 64-bit builds:

CIBW_ENABLE = "cpython-experimental-riscv64"
# Note: This enable group is deprecated

Multiple Enable Groups

CIBW_ENABLE = "pypy graalpy cpython-prerelease"

Advanced Selection Examples

Platform-Specific Selection

[tool.cibuildwheel]
# Global build configuration
build = "cp39-* cp310-* cp311-*"

[tool.cibuildwheel.linux]
# Linux-specific overrides
build = "cp39-* cp310-* cp311-* cp312-*"
skip = "*-linux_i686"  # Skip 32-bit Linux

[tool.cibuildwheel.windows]
# Windows-specific overrides  
skip = "*-win32"  # Skip 32-bit Windows

[tool.cibuildwheel.macos]
# macOS-specific overrides
build = "cp310-* cp311-*"  # Only newer Python versions

Architecture-Specific Selection

# Build matrix excluding slow combinations
CIBW_BUILD = "cp311-linux_x86_64 cp311-linux_aarch64 cp311-macosx_* cp311-win_amd64"

# Skip tests on emulated architectures to save time
CIBW_TEST_SKIP = "*-linux_aarch64 *-linux_ppc64le *-linux_s390x"

Conditional Selection

# Use environment variables for conditional selection
import os

if os.environ.get("CIBW_QUICK_BUILD"):
    # Quick build: only test current Python version
    CIBW_BUILD = f"cp{sys.version_info.major}{sys.version_info.minor}-*"
else:
    # Full build: all supported versions
    CIBW_BUILD = "cp39-* cp310-* cp311-* cp312-*"

Requirements-based Selection

# Select builds based on project's requires-python
from packaging.specifiers import SpecifierSet

# Automatically skip unsupported Python versions
requires_python = SpecifierSet(">=3.10")

Build Selection Validation

Cibuildwheel validates build selectors and provides warnings for common issues:

Invalid Selectors

# This would generate a warning
CIBW_BUILD = "cp37-*"  # Python 3.7 not supported in cibuildwheel 3.x

# This would generate an error  
CIBW_SKIP = "invalid-selector"  # Invalid pattern

Empty Selection

# If no builds match, cibuildwheel will error unless:
CIBW_ALLOW_EMPTY = "1"  # Allow empty build selection

Enable Group Validation

# Using enable groups without enabling them generates warnings
CIBW_BUILD = "pp39-*"  # Warning: PyPy not enabled
CIBW_ENABLE = "pypy"   # Required to actually build PyPy

Usage Examples

Minimal Configuration

# Build for Python 3.11+ only, skip 32-bit
CIBW_BUILD = "cp311-* cp312-*"
CIBW_SKIP = "*-win32 *-linux_i686"

Full Matrix Build

# Build everything possible
CIBW_ENABLE = "pypy graalpy cpython-prerelease"
CIBW_BUILD = "*"
CIBW_SKIP = ""  # Don't skip anything

Targeted Build

# Build only for specific deployment targets
CIBW_BUILD = "cp311-linux_x86_64 cp311-macosx_universal2 cp311-win_amd64"
CIBW_TEST_COMMAND = "pytest"

Development Build

# Quick build for development/testing
CIBW_BUILD = "cp311-*"  # Current Python version only
CIBW_ARCHS = "native"   # Native architecture only
CIBW_TEST_SKIP = "*"    # Skip all tests

Install with Tessl CLI

npx tessl i tessl/pypi-cibuildwheel

docs

architecture.md

build-selection.md

ci-integration.md

cli.md

configuration.md

environment.md

errors.md

index.md

platforms.md

utilities.md

tile.json