Skip to content
Back to top

# Command-Line Interface

A simple, correct Python build frontend.

By default, a source distribution (sdist) is built from the project root and a binary distribution (wheel) is built from the sdist. If this is undesirable, you can pass `--sdist` and/or `--wheel` to build distributions independently of each other.

The positional `srcdir` argument also accepts a `.tar.gz` source distribution. Build checks the filename and the presence of `PKG-INFO`, extracts the archive into a temporary directory, and runs the wheel build against the extracted source. The default `--outdir` is the directory containing the archive. `--sdist` errors against an archive, since the archive already is an sdist.

## python -m build

        A simple, correct Python build frontend.

        By default, a source distribution (sdist) is built from the project root
        and a binary distribution (wheel) is built from the sdist.
        If this is undesirable, you can pass `--sdist` and/or `--wheel`
        to build distributions independently of each other.

    python -m build [-h] [--version] [--quiet | --verbose] [--outdir PATH]
                    [--sdist-extract-dir PATH] [--sdist] [--wheel] [--metadata]
                    [--report PATH] [--config-setting KEY=[VALUE] | --config-json JSON_STRING]
                    [--installer {pip,uv} | --no-isolation] [--env-dir PATH]
                    [--dependency-constraints-txt PATH] [--skip-dependency-check]
                    [srcdir]

### python -m build positional arguments

- `srcdir` - source directory, .tar.gz source distribution, or (with –metadata) a .whl to read metadata from (defaults to the current working directory)

### python -m build global options

- `-h`, `--help` - show this help message and exit

- `--version`, `-V` - show program’s version number and exit

- `--quiet`, `-q` - reduce verbosity (default: `0`)

- `--verbose`, `-v` - increase verbosity (default: `0`)

### python -m build build options

- `--outdir` `PATH`, `-o` `PATH` - output directory (defaults to `{srcdir}`/dist). Cannot be used together with `--metadata`

- `--sdist-extract-dir` `PATH` - extract the intermediate sdist to PATH (created if missing and kept afterwards) instead of a random temporary directory; reusing it across rebuilds gives compiler caches such as ccache/sccache a stable source path. Only affects the default (via-sdist) build and building a wheel from an sdist

- `--sdist`, `-s` - build a source distribution (disables the default behavior)

- `--wheel`, `-w` - build a wheel (disables the default behavior)

- `--metadata` - print out a wheel’s metadata in JSON format, building it first unless the source argument is already a .whl. Cannot be used in conjunction with `--sdist` or `--wheel`

- `--report` `PATH` - write a machine-readable JSON report of the built artifacts (name, path, kind, size and SHA-256 hash) to this path. Cannot be used together with `--metadata`

- `--config-setting` `KEY=[VALUE]`, `-C` `KEY=[VALUE]` - settings to pass to the backend. Multiple settings can be provided. Settings beginning with a hyphen will erroneously be interpreted as options to build if separated by a space; use `--config-setting=--my-setting -C--my-other-setting` instead. A setting passed without `=VALUE` is given an empty value, but this form is not supported by pip; write `KEY=` instead for compatibility

- `--config-json` `JSON_STRING` - settings to pass to the backend as a JSON object. This is an alternative to `--config-setting` that allows complex nested structures. Cannot be used together with `--config-setting`

### python -m build installation options

- `--installer` `INSTALLER` - Python package installer to use (defaults to pip)

- `--no-isolation`, `-n` - disable building the project in an isolated virtual environment. Build dependencies must be installed separately when this option is used

- `--env-dir` `PATH` - create the isolated build environment at this location instead of a temporary directory. The location must be empty; it is removed on success and kept on failure so it can be inspected

- `--dependency-constraints-txt` `PATH` - constrain build dependencies using a constraints.txt when installing dependencies

- `--skip-dependency-check`, `-x` - do not check that build dependencies are installed

## Isolation Behavior

By default build will build the package in an isolated environment, but this behavior can be disabled with `--no-isolation`. When using isolation, build creates a temporary virtual environment, installs the build dependencies specified in your `pyproject.toml`, runs the build, and then cleans up the environment. This ensures reproducible builds regardless of what packages are installed in your development environment.

Pass `--env-dir PATH` to put the environment at a fixed location instead of a temporary directory. The location must be empty. build removes it after a successful build and keeps it after a failure so you can inspect it. A fixed path helps compilation caches like ccache and sccache, which treat a changed build-environment path as a new file and miss the cache. You cannot combine `--env-dir` with `--no-isolation`.

When a build fails, `--env-dir` and `--sdist-extract-dir` keep the environment and the extracted sources for inspection; see Debug a failed build.

## Dependency Check

With `--no-isolation`, build does not install anything; it checks that the build dependencies are already present in the interpreter running build. When a requirement is unmet it exits with an `Unmet dependencies` error that names the interpreter checked and, for each requirement, the version specifier that was `wanted` and the version that was `found` (`not installed` when absent):

    ERROR Unmet dependencies (checked against /usr/local/bin/python3.9):
        anndata>=0.7.4
            wanted: >=0.7.4
            found: not installed
        matplotlib>=3.4 -> kiwisolver>=1.0.1
            wanted: >=1.0.1
            found: 1.0.0

Transitive requirements are shown as a `parent -> child` chain; the `wanted`/`found` lines describe the unmet leaf. Pass `--skip-dependency-check` to skip this check (see Basic Usage).

## Verbose Output

Repeating `-v` raises the verbosity level. Each level adds to the previous one:

- `-v` streams the output of the environment-creation and dependency-installation subprocesses.

- `-vv` additionally passes `-v` through to the installer.

Regardless of verbosity, after installing the build dependencies of an isolated build, build prints a summary of the resolved versions, one `name==version` per line. build reads these from the isolated environment’s installed metadata, so they reflect what was installed rather than the specifiers in `pyproject.toml`:

    $ python -m build --wheel
    * Creating isolated environment: venv+pip...
    * Installing packages in isolated environment:
      - setuptools >= 42.0.0
    * Getting build dependencies for wheel...
    * Installed build dependency versions:
      - setuptools==82.0.1
    * Building wheel...
    Successfully built mypackage-1.0.0-py3-none-any.whl

build reports this for isolated builds only; with `--no-isolation` build installs nothing, so inspect the active interpreter with your installer instead (for example `pip list`).

## Build Report

`--report PATH` writes a JSON description of the built artifacts to `PATH` after a successful build. The artifact names are dynamic (they encode version, Python, ABI and platform tags), so this gives scripts and CI a stable way to refer to the produced files instead of globbing `dist/`. Build writes the report to a file it controls, not to standard output, because the build backend may write to `stdout`/`stderr` too.

    $ python -m build --report build-report.json
    $ twine upload $(jq -r '.artifacts[].path' build-report.json)

Note

Keep the report out of the output directory: tools commonly upload `dist/*` wholesale (`twine upload dist/*`), and a stray non-distribution file there can break that. The write is atomic, so a reader never sees a partial file; builds running in parallel still need a distinct `PATH` each to avoid overwriting one another’s report.

The schema is:

    {
      "version": "1.0",
      "artifacts": [
        {
          "name": "mypackage-1.0.0.tar.gz",
          "path": "dist/mypackage-1.0.0.tar.gz",
          "kind": "sdist",
          "size": 852,
          "hashes": {
            "sha256": "dbd5486e6e893663263caf84a4b87d67cc28f6963b6650f69eaa54b78e42ece4"
          }
        },
        {
          "name": "mypackage-1.0.0-py3-none-any.whl",
          "path": "dist/mypackage-1.0.0-py3-none-any.whl",
          "kind": "wheel",
          "size": 1121,
          "hashes": {
            "sha256": "ef460897fdce998634efc3385aa4261b4280a2fe2ab0e08ddcacc8496658465d"
          }
        }
      ]
    }

`version` is the schema version. Each artifact lists its `name` (basename), `path` (relative to the current directory, mirroring `--outdir`), `kind` (`sdist` or `wheel`), `size` in bytes, and `hashes` keyed by algorithm. `--report` cannot be combined with `--metadata`.

To inspect a wheel listed in the report, pass its path straight to `--metadata`: when the source argument is a `.whl` file, build reads `METADATA` from the archive and prints it as JSON instead of building anything.

    $ python -m build --report build-report.json
    $ python -m build --metadata "$(jq -r '.artifacts[] | select(.kind=="wheel") | .path' build-report.json)"

## Alternative CLI Script

A `pyproject-build` CLI script is also available, which is functionally identical to `python -m build`. This is useful for tools like pipx that prefer direct script entry points.

    $ pyproject-build
    $ pyproject-build --help

Both commands accept the same options and behave identically.

## Common Patterns

For practical usage examples and workflows, see Basic Usage.

## See Also

- Basic Usage for common workflows

- Backend Configuration for passing options to backends

- Environment Variables for environment variables that affect build