# Build configurations

All build configurations are stored under `tool.pdm.build` table.

## Specify the package directory

You can tell the backend to find python packages in another directory by setting the `package-dir` option:

```toml
[tool.pdm.build]
package-dir = "src"
```

**Default value**: `.`(project root) or `src` if `src` is detected.

## Include and exclude files

You can tell the backend to include additional files or exclude some files from the build result with `includes` and `excludes` settings.
Each setting is an array of glob patterns, if the pattern is a directory name, it will be included or excluded recursively. All relative paths
are calculated from the project root.

```toml
[tool.pdm.build]
includes = ["src", "data/*.json"]
excludes = ["*.o"]
```

### Include files in sdist only

File patterns in `source-includes` will be included by sdist only and excluded by `wheel` and `editable` builds.

```toml
source-includes = ["tests"]
```

### Priority of includes and excludes

If a file is covered by both `includes` and `excludes`, the one with the more path parts and less wildcards in the pattern wins,
otherwise `excludes` takes precedence if the length is the same.

For example, given the following configuration:

```toml
includes = ["src"]
excludes = ["**/*.json"]
```

`src/foo/data.json` will be **excluded** since the pattern in `excludes` has more path parts, however, if we change the configuration to:

```toml
includes = ["src", "src/foo/data.json"]
excludes = ["**/*.json"]
```

the same file will be **included** since it is covered by `includes` with a more specific path.

### Default behavior

If neither `includes` and `excludes` is specified, the backend can determine them following the rules as below:

- If top-level packages are found under `package-dir`, they will be included, together with any data files inside.
- Otherwise, all top-level `*.py` files under `package-dir` will be included.
- Test files under `tests`, if found, are included by sdist and excluded by other formats.

!!! note
    Specifying `includes` and `excludes` will **override** the default values, so you need to include the package directories manually.
    `*.pyc`, `__pycache__/` and `build/` are always excluded.


## Local build hooks

You can specify a custom script to be executed before the build process, which can be used to generate files or modify the metadata.
A file named `pdm_build.py` under the project root will be detected as custom hook script automatically, or you can specifiy the name
via `custom-hook` setting:

```toml
[tool.pdm.build]
custom-hook = "build.py"
```

**Default value**: `pdm_build.py`

### Run setuptools

Due the lack of ability to build C extensions, `pdm-backend` allow users to call `setuptools` in an auto-generated `setup.py` from the
project. This is enabled by setting `run-setuptools` to `true`:

```toml
[tool.pdm.build]
run-setuptools = true
```

**Default value**: `false`

The hook function `pdm_build_update_setup_kwargs` will be called to modify the arguments passed to `setup()` function as you desire.

Read the [hooks document](./hooks.md) about the details of the hook functions.

## `is-purelib`

By default, `pdm-backend` produces non platform-specific wheels, with tag `py3-none-any`. But if `run-setuptools` is `true`, the built wheel
will be platform-specific. You can override this behavior by setting `is-purelib` to `true` or `false` explicitly:

```toml
[tool.pdm.build]
is-purelib = true
```

## Choose the editable build format

`pdm-backend` supports two ways to build an [editable wheel][PEP 660], `path` and `editables`, with the former being the default. It can be changed with `editable-backend` setting:

[PEP 660]: https://www.python.org/dev/peps/pep-0660/

```toml
[tool.pdm.build]
editable-backend = "editables"
```

**Default value**: `path`

### `path`

In this approach, the editable build will be very similar to the legacy format generated by `setuptools`. A `.pth` file containing the parent path of the packages will be installed into the site-packages directory.

### `editables`

If you choose this approach, the backend will install a proxy module which redirects the import statements to the real location of the package, which is powered by the [editables] package.

[editables]: https://pypi.org/project/editables

## Command-line build options

Some build frontends such as [build] and [pdm] supports passing options from command-line to the backend. `pdm-backend` supports the following options:

- `--python-tag=<tag>` Override the python implementation compatibility tag(e.g. `cp37`, `py3`, `pp3`)
- `--py-limited-api=<abi>` Python tag (`cp32`|`cp33`|`cpNN`) for abi3 wheel tag
- `--plat-name=<plat>` Override the platform name(e.g. `win_amd64`, `manylinux2010_x86_64`)
- `no-clean-build` Don't clean the build directory before the build starts, this can also work by setting env var `PDM_BUILD_NO_CLEAN` to `1`.

For example, you can supply these options with [build]:

```bash
python -m build --sdist --wheel --outdir dist/ --config-setting="--python-tag=cp37" --config-setting="--plat-name=win_amd64"
```

## Environment variables

- `SOURCE_DATE_EPOCH`: Set the timestamp(seconds) of the zipinfo in the wheel for reproducible builds. The default date is 2016/01/01.

[build]: https://pypi.org/project/build
[pdm]: https://pypi.org/project/pdm
