Build Backends
Build backends turn your source tree into distributable wheels and sdists. Hatchling is the modern default; setuptools remains common for legacy projects.
Search across all documentation pages
Build backends turn your source tree into distributable wheels and sdists. Hatchling is the modern default; setuptools remains common for legacy projects.
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"uv buildWhen to reach for this:
setup.py to pyproject.toml[project]
name = "invoice-sdk"
version = "0.2.0"
requires-python = ">=3.14"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/invoice_sdk"]
[tool.hatch.build.targets.sdist]
include = ["src/", "tests/", "README.md"]uv build
tar -tzf dist/invoice-sdk-0.2.0-py3-none-any.whl | head
# invoice_sdk/__init__.py
# invoice_sdk/client.pyWhat this demonstrates:
hatchling.build backend specified in [build-system]packages tells hatchling where source livesuv build produces wheel and sdist| Backend | Best for | Config |
|---|---|---|
| hatchling | New projects | [tool.hatch.*] |
| setuptools | Legacy, extensions | [tool.setuptools.*] |
| poetry-core | Poetry projects | [tool.poetry] |
| maturin | Rust extensions | [tool.maturin] |
| cffi/setuptools | C extensions | setup.py + pyproject |
packages config - empty wheel. Fix: configure package discovery in [tool.hatch.build].setup.py alongside pyproject - conflicting metadata. Fix: migrate fully; delete setup.py.pip install dist/*.whl before upload.| Alternative | Use When | Don't Use When |
|---|---|---|
| setuptools | Existing setuptools config | Greenfield project |
| flit | Simple single-package | Complex monorepos |
| PDM backend | PDM-managed project | uv/hatchling shop |
hatchling. Minimal config, fast, PEP 621 native.
No with hatchling or setuptools pyproject.toml config.
uv build --sdist or python -m build --sdist.
hatchling force-include, exclude, and artifacts options.
pip install -e . or uv pip install -e . - not a wheel build.
Standard for specifying build backends in pyproject.toml.
[build-system] requires = ["hatchling", "cython"].
Separate pyproject.toml per package or uv workspace with per-member builds.
tar -tzf dist/*.whl or unzip -l dist/*.whl.
Move metadata to [project], configure [tool.setuptools.packages.find].
Stack versions: This page was written for Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026