# pypa/setuptools: the build backend behind most Python packages

> Setuptools is the official build backend for Python packaging, still shipping releases through 2026. Here is what it does, how to install and use it, where it falls short, and how it compares to hatchling.

**pypa/setuptools** — Official project repository for the Setuptools build system

- Repository: https://github.com/pypa/setuptools
- Website: https://pypi.org/project/setuptools/
- Stars: 2,862 · Forks: 1,432
- Language: Python
- License: MIT
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/pypa-setuptools

## What Setuptools solves, and who actually needs it

Setuptools is the build system that turns a Python source tree into a distributable package. It reads project metadata, resolves dependencies, compiles extension modules, and produces wheels or source distributions that pip can install. The project's own pyproject.toml describes it as the "most extensible Python build backend with support for C/C++ extension modules," and that description is accurate: extension support is the differentiator that keeps it in place for projects that ship compiled code.

The audience is package maintainers, not application developers who only install packages. If you write a library that others will pip install, or a project with C extensions, Setuptools is the layer between your source and PyPI. The repository has been in production/stable status for years, and the latest release listed is v84.0.0, published on 2026-08-08. The last push to the default branch was on 2026-09-10, so the project is still being worked on.

A second audience is anyone maintaining older code. Setuptools carries pkg_resources and the distutils shim, which many existing packages import. That backwards compatibility is the reason the project remains in so many dependency trees even when newer backends exist.

## How the build backend and the distutils shim fit together

The mechanism is declared in pyproject.toml. Setuptools registers itself as the build backend with build-backend = "setuptools.build_meta", and pip calls into that backend when it builds a wheel or sdist. The repository's own pyproject.toml also sets backend-path = ["."], which tells the build frontend to look for the backend in the project directory rather than only in the installed environment. That is how the project bootstraps itself.

Metadata lives in the [project] table: name, version, authors, description, requires-python, license, dependencies, and classifiers. In the repository's own file, requires-python is ">=3.10" and license is "MIT". For projects that have not migrated, the same metadata can live in setup.py or setup.cfg, and Setuptools reads all three.

The distutils shim is the part that surprises people. The repository's setup.py defines an install_with_pth command that installs a .pth file named distutils-precedence. The file's contents check the environment variable SETUPTOOLS_USE_DISTUTILS; when it is unset or set to "local", the shim imports _distutils_hack and calls add_shim(). The comment in setup.py calls this a hack and says "Please do not replicate this behavior." The purpose is to give the local distutils precedence over the standard library version. If you have ever wondered why SETUPTOOLS_USE_DISTUTILS appears in build logs, this is where it comes from.

## Installing Setuptools and running a first build

Setuptools is published on PyPI, and the README points readers to the Quickstart and User's Guide at setuptools.pypa.io for usage instructions. The standard installation route is pip:

```bash
pip install setuptools
```

pip resolves the latest release from PyPI. To check what is installed, the package exposes its version string through the setuptools module, and the project's pyproject.toml sets requires-python to ">=3.10", so on an older interpreter pip will either refuse the install or resolve an older release.

For a first real use, declare the backend in your own pyproject.toml and let pip build the project:

```toml
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "example-package"
version = "0.1.0"
requires-python = ">=3.10"
```

With that file in place, running the build frontend produces a wheel and an sdist. If your project still uses setup.py, the file at the repository root shows the pattern: a setup_params dictionary and a cmdclass entry, with the actual call guarded by if __name__ == '__main__'. That guard is what lets setup.py run from another directory.

## Where Setuptools is the wrong tool

The distutils shim is a genuine liability. The setup.py comment describes it as a hack that abuses the extra_path behavior, and the file explicitly asks readers not to replicate it. Installing a .pth file means code runs at interpreter startup, which makes import behavior depend on environment variables. If SETUPTOOLS_USE_DISTUTILS is set to anything other than "local", the shim is disabled. That is a global switch, and it can change how unrelated packages resolve distutils on the same machine.

For pure-Python projects with no extension modules, the extensibility that justifies Setuptools is unused weight. A declarative backend that only reads pyproject.toml has less machinery to configure and fewer legacy code paths to carry. Setuptools will still work, but you are paying for compatibility you do not need.

The project also does not document a rollback path in the README. The README is short: it links to the Quickstart and User's Guide and directs questions to GitHub Discussions and bugs to the issue tracker. If you need to know how to revert a bad release or downgrade a broken build, that information is not in the README itself, and you will have to look in the docs or the changelog.

## Setuptools vs hatchling: two different build philosophies

Hatchling is the comparison that comes up most often, and the difference is architectural. Setuptools is an extensible build system: setup.py can contain arbitrary Python, cmdclass lets you override commands, and the distutils shim exists to keep legacy imports working. Hatchling is a declarative backend. It reads metadata from pyproject.toml and builds, with far less room for custom build logic.

The practical consequence is where each one fits. If your project compiles C or C++ extensions, Setuptools is the backend the project's own description advertises for that job. If your project is pure Python and its metadata fits cleanly in pyproject.toml, Hatchling gives you a shorter path with fewer moving parts.

The trade-off is not about which one is better. It is about how much build customization you actually need. Setuptools wins when you need it; Hatchling wins when you do not. The cost of choosing Setuptools unnecessarily is the shim, the legacy configuration surface, and a longer list of things that can behave differently across environments.

## Maintenance, releases, and the MIT licence

The repository is not archived, and the last push to the default branch was on 2026-09-10. The release cadence visible in the project's release history is roughly monthly to quarterly: v82.0.1 on 2026-03-09, v83.0.0 on 2026-07-04, and v84.0.0 on 2026-08-08. Major version numbers move, which means upgrades can carry breaking changes even though the project is classified as production/stable.

Upgrade cost is real because Setuptools sits underneath the build process. A new release can change how metadata is normalized or how the backend resolves requirements. The repository's own test extras pin wheel>=0.44.0 with the comment "Consistent requirement normalisation in METADATA (see #4547)," which is a concrete example of a build behavior that shifted and required a coordinated pin. If you build wheels in CI, pinning the Setuptools version in your build requirements is a reasonable precaution.

The licence is MIT, declared in pyproject.toml as license = "MIT". MIT is permissive: it allows commercial use, modification, and redistribution with the licence text included. That is a statement about the licence, not legal advice, and if your organization has specific compliance requirements you should have them reviewed. The README also notes that Setuptools is available as part of the Tidelift Subscription, which is a commercial support arrangement separate from the open source licence.

## Conclusion

Use setuptools if you maintain existing Python packages, need C/C++ extension support, or rely on pkg_resources and entry points that are already wired into your build. Do not reach for it if you are starting a pure-Python project and want a minimal declarative backend; hatchling is a better fit there. Before adopting, verify that your Python version is 3.10 or newer, that your project does not depend on the distutils shim being active, and that your packaging workflow works with the build_meta backend declared in pyproject.toml.

## FAQ

### What is setuptools used for?

Setuptools is the build backend that turns a Python source tree into a distributable package. Its pyproject.toml describes it as the most extensible Python build backend with support for C/C++ extension modules, and it produces the wheels and source distributions that pip installs.

### How do I install setuptools?

Install it with pip in the environment where you build packages: pip install setuptools. The README directs readers to the Quickstart and User's Guide at setuptools.pypa.io for usage instructions.

### What is the latest version of setuptools?

The latest release listed in the repository is v84.0.0, published on 2026-08-08. Earlier releases in the same series are v83.0.0 and v82.0.1.

### How do I use setuptools in Python?

Declare the backend in your pyproject.toml with build-backend = "setuptools.build_meta" and put your metadata in the [project] table, then let pip build the project. The README points to the Quickstart and User's Guide for the full instructions.

### How do I install setuptools on Linux?

The README gives no distribution-specific steps; it directs readers to the Quickstart and User's Guide at setuptools.pypa.io. The standard route is pip install setuptools in the environment where you build packages.

## Sources

- [License: MIT](https://github.com/pypa/setuptools/blob/main/LICENSE)
- [Project website](https://pypi.org/project/setuptools/)
- [pypa/setuptools on GitHub](https://github.com/pypa/setuptools)
- [README](https://github.com/pypa/setuptools/blob/main/README.md)
- [Releases](https://github.com/pypa/setuptools/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pypa-setuptools
