build vs Other Tools

The Python packaging ecosystem has several tools that work together. This guide helps you understand when to use build versus other tools.

When to use build

Use build when you want to:

  • Create distribution packages (source distributions and/or wheels) for your project

  • Build for your current Python version and platform only

  • Create packages to upload to PyPI

  • Test that your package builds correctly

  • Build as part of a development workflow

Build is a build frontend - it knows how to invoke build backends (setuptools, hatchling, flit, etc.) but doesn’t handle testing, multi-version builds, or task automation.

$ python -m build

This builds your package for the currently active Python interpreter.

When to use cibuildwheel

Use cibuildwheel when you need to build wheels for multiple Python versions and platforms:

  • Building wheels for distribution on PyPI

  • Supporting Python 3.8, 3.9, 3.10, 3.11, 3.12, 3.13, 3.14

  • Supporting multiple operating systems (Linux, macOS, Windows)

  • Building manylinux/musllinux wheels (standardized Linux wheel formats)

  • Building wheels with compiled extensions (C, C++, Rust, etc.)

cibuildwheel uses build under the hood but handles all the complexity of:

Example .github/workflows/build.yml:

name: Build

on: [push, pull_request]

jobs:
  build_wheels:
    name: Build wheels on ${{ matrix.os }}
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]

    steps:
      - uses: actions/checkout@v4
      - uses: pypa/cibuildwheel@v2.17
      - uses: actions/upload-artifact@v4
        with:
          name: wheels
          path: ./wheelhouse/*.whl

See cibuildwheel documentation for complete details.

When to use tox

Use tox when you need to:

  • Test your package across multiple Python versions (e.g., 3.9, 3.10, 3.11)

  • Run tests in isolated environments

  • Automate testing workflows

  • Run linters (code checkers), formatters, type checkers

  • Build documentation

  • Orchestrate multiple development tasks

Example tox.toml:

[env_run_base]
description = "run test suite with {basepython}"
deps = [
    "pytest",
    "pytest-cov",
]
commands = [
    ["pytest", "tests"],
]

[env.build]
description = "build the package"
deps = ["build"]
commands = [["python", "-m", "build"]]

[env.lint]
description = "run linters and type checkers"
deps = [
    "ruff",
    "mypy",
]
commands = [
    ["ruff", "check", "."],
    ["mypy", "src"],
]

Tox can call build to create distributions, but its main purpose is test automation.

See tox documentation for complete details.

When to use nox

Use nox when you want tox-like functionality but prefer Python over INI:

Example noxfile.py:

import nox


@nox.session(python=["3.8", "3.9", "3.10", "3.11", "3.12"])
def tests(session):
    session.install("pytest", "pytest-cov")
    session.run("pytest", "tests")


@nox.session
def build(session):
    session.install("build")
    session.run("python", "-m", "build")

See nox documentation for complete details.

When to use uv

Use uv when you want:

  • Fast package installation (faster than pip)

  • Workspace management (monorepos with multiple packages)

  • Combined dependency resolution and installation

  • Modern Python packaging workflows

uv can also build packages:

$ uv build

This is equivalent to python -m build --installer=uv.

See uv documentation for complete details.

When to use pip

Use pip when you need to:

  • Install packages (not build them)

  • Install from PyPI or other indexes

  • Install in editable mode for development

  • Manage dependencies in your environment

pip can build packages as a side effect of installation, but for explicit building, use build.

# Installing (use pip)
$ pip install mypackage

# Installing in editable mode (use pip)
$ pip install -e .

# Building distributions (use build)
$ python -m build

How they work together

A typical complete workflow might use all these tools:

Development workflow

# Install your package in editable mode
$ pip install -e .[dev]

# Run tests across Python versions
$ tox

# Build distributions
$ python -m build

# Upload to PyPI
$ twine upload dist/*

CI/CD workflow

name: CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python }}
      - run: pip install tox
      - run: tox -e py

  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hynek/build-and-inspect-python-package@v2

  build_wheels:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: pypa/cibuildwheel@v2.17

This workflow:

  1. Uses tox to test across Python versions

  2. Uses build (via hynek’s action) to create sdist

  3. Uses cibuildwheel to create wheels for all platforms

Decision tree

        %%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#4051b5','primaryTextColor':'#fff','primaryBorderColor':'#2c3e8f','lineColor':'#5468c4','secondaryColor':'#7c8fd6','tertiaryColor':'#e8eaf6'}}}%%
flowchart TD
    A[What do you need to do?] --> B{Build a package?}
    B -->|Yes| C{For how many platforms?}
    B -->|No, just testing| D{Multiple Python versions?}
    B -->|No, just installing| E[Use pip or uv]

    C -->|Current platform only| F[Use python -m build]
    C -->|Multiple platforms/versions| G[Use cibuildwheel]

    D -->|Yes| H[Use tox or nox]
    D -->|No| I[Use pytest or your test runner]

    style F fill:#4051b5,stroke:#2c3e8f,color:#fff
    style G fill:#4051b5,stroke:#2c3e8f,color:#fff
    style H fill:#7c8fd6,stroke:#5468c4,color:#fff
    style I fill:#7c8fd6,stroke:#5468c4,color:#fff
    style E fill:#f57c00,stroke:#e65100,color:#fff
    

Quick reference

Tool

Purpose

Use for

build

Build sdist/wheel for one Python

Creating distributions

cibuildwheel

Build wheels for all platforms

Distributing on PyPI

tox

Test across Python versions

CI/testing automation

nox

Like tox, but Python-based

CI/testing automation

uv

Fast package manager

Installing + optional building

pip

Package installer

Installing packages

twine

Upload to PyPI

Publishing

See also