# `pyproject.toml`

```{versionadded} 10.0

```

Modern Python packages can contain a `pyproject.toml` file, first introduced in
{pep}`518` and later expanded in {pep}`517`, {pep}`621` and {pep}`660`.
This file contains build system requirements and information, which are used by
pip to build the package.

## Build process

The overall process for building a package is:

- Create an isolated build environment.
- Populate the build environment with build dependencies.
- Generate the package's metadata, if necessary and possible.
- Generate a wheel for the package.

The wheel can then be used to perform an installation, if necessary.

### Build Isolation

For building packages using this interface, pip uses an _isolated environment_.
That is, pip will install build-time Python dependencies in a temporary
directory which will be added to `sys.path` for the build commands. This ensures
that build requirements are handled independently of the user's runtime
environment.

For example, a project that needs an older version of setuptools to build can
still be installed, even if the user has an newer version installed (and
without silently replacing that version).

### Build-time dependencies

Introduced in {pep}`518`, the `build-system.requires` key in the
`pyproject.toml` file is a list of requirement specifiers for build-time
dependencies of a package.

```toml
[build-system]
requires = ["setuptools ~= 58.0", "cython ~= 0.29.0"]
```

It is also possible for a build backend to provide dynamically calculated
build dependencies, using {pep}`517`'s `get_requires_for_build_wheel` hook. This
hook will be called by pip, and dependencies it describes will also be installed
in the build environment. For example, newer versions of setuptools expose the
contents of `setup_requires` to pip via this hook.

Build-time requirement specifiers follow {pep}`508`, so it's possible to
reference packages with URLs. For example:

```toml
[build-system]
requires = ["setuptools @ git+https://github.com/pypa/setuptools.git@main"]
```

### Metadata Generation

```{versionadded} 19.0

```

Once the build environment has been created and populated with build-time
dependencies, `pip` will usually need metadata about a package (name, version,
dependencies, and more).

If {pep}`517`'s `prepare_metadata_for_build_wheel` hook is provided by the
build backend, that will be used to generate the packages' metadata. Otherwise,
a wheel will be generated (as described below) and the metadata contained
within such a wheel will be used.

### Wheel Generation

```{versionadded} 19.0

```

For generating a wheel, pip uses the {pep}`517` `build_wheel` hook that has
to be provided by the build backend. The build backend will generate a wheel,
which may involve compiling extension code written in C/C++ (or other
languages).

Wheels generated using this mechanism can be [cached](wheel-caching) for reuse,
to speed up future installations.

### Editable Installation

```{versionadded} 21.3

```

For performing editable installs, pip will use {pep}`660`
`build_wheel_for_editable` hook that has to be provided by the build backend.
The wheels generated using this mechanism are not cached.

```{admonition} Compatibility fallback
If this hook is missing on the build backend _and_ there's a `setup.py` file
in the project, pip will fallback to the legacy setup.py-based editable
installation.

This is considered a stopgap solution until setuptools adds support for
{pep}`660`, at which point this functionality will be removed; following pip's
regular {ref}`deprecation policy <Deprecation Policy>`.
```

### Backend Configuration

Build backends have the ability to accept configuration settings, which can
change the way the build is handled. These settings take the form of a
series of `key=value` pairs. The user can supply configuration settings
using the `--config-settings` command line option (which can be supplied
multiple times, in order to specify multiple settings).

The supplied configuration settings are passed to every backend hook call.

## Build output

It is the responsibility of the build backend to ensure that the output is
in the correct encoding, as described in {pep}`517`. This likely involves
dealing with [the same challenges as pip has for legacy builds](build-output).

## Fallback Behaviour

If a project does not have a `pyproject.toml` file containing a `build-system`
section, it will be assumed to have the following backend settings:

```toml
[build-system]
requires = ["setuptools>=40.8.0", "wheel"]
build-backend = "setuptools.build_meta:__legacy__"
```

If a project has a `build-system` section but no `build-backend`, then:

- It is expected to include `setuptools` and `wheel` as build requirements. An
  error is reported if the available version of `setuptools` is not recent
  enough.

- The `setuptools.build_meta:__legacy__` build backend will be used.

## Disabling build isolation

This can be disabled using the `--no-build-isolation` flag -- users supplying
this flag are responsible for ensuring the build environment is managed
appropriately, including ensuring that all required build-time dependencies are
installed, since pip does not manage build-time dependencies when this flag is
passed.

## Historical notes

As this feature was incrementally rolled out, there have been various notable
changes and improvements in it.

- setuptools 40.8.0 is the first version of setuptools that offers a
  {pep}`517` backend that closely mimics directly executing `setup.py`.
- Prior to pip 18.0, pip only supports installing build requirements from
  wheels, and does not support the use of environment markers and extras (only
  version specifiers are respected).
- Prior to pip 18.1, build dependencies using `.pth` files are not properly
  supported; as a result namespace packages do not work under Python 3.2 and
  earlier.
