Skip to content

Commit

Permalink
Merge pull request #410 from davidhewitt/abi3-cleanup
Browse files Browse the repository at this point in the history
deprecate `RustExtension.py_limited_api`
  • Loading branch information
davidhewitt authored Feb 2, 2024
2 parents ad2bc07 + ebc9e82 commit 5dd65e2
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 28 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased
### Changed
- Deprecate `py_limited_api` option to `RustExtension` in favour of always using `"auto"` to configure this from `bdist_wheel`. [#410](https://github.com/PyO3/setuptools-rust/pull/410)

## 1.8.1 (2023-10-30)
### Fixed
- Fix regression in `install_extension` crashing since 1.8.0. [#380](https://github.com/PyO3/setuptools-rust/pull/380)
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ target = "hello_world._lib" # The last part of the name (e.g. "_lib") has to ma
# but you can add a prefix to nest it inside of a Python package.
path = "Cargo.toml" # Default value, can be omitted
binding = "PyO3" # Default value, can be omitted
py-limited-api = "auto" # Default value, can be omitted
```

Each extension module should map directly into the corresponding `[lib]` table on the
Expand Down
33 changes: 25 additions & 8 deletions docs/building_wheels.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,36 @@ Because `setuptools-rust` is an extension to `setuptools`, the standard [`python
(or [`pip wheel --no-deps . --wheel-dir dist`](https://pip.pypa.io/en/stable/cli/pip_wheel/)) can be used to build distributable wheels.
These wheels can be uploaded to PyPI using standard tools such as [twine](https://github.com/pypa/twine).

`setuptools-rust` supports building for the [PEP 384](https://www.python.org/dev/peps/pep-0384/) "stable" (aka "limited") API when the `py_limited_api` option is set on the `[bdist_wheel]` section of `setup.cfg`.
If using PyO3 bindings for `RustExtension`, then the correct [`pyo3/abi3`](https://pyo3.rs/v0.14.5/features.html#abi3) sub-feature is automatically enabled.
In this way, abi3 wheels can be uploaded to make package distributors' roles easier, and package users installing from source with `pip install .` can use optimizations specific to their Python version.
A key choice to make is whether to upload [PEP 384](https://www.python.org/dev/peps/pep-0384/) "stable" (aka "limited") API wheels which support multiple Python versions in a single binary, or to build individual artifacts for each Python version. There is a longer discussion of this [in the PyO3 docs](https://pyo3.rs/latest/building_and_distribution#py_limited_apiabi3).

This chapter of the documentation explains two possible ways to build wheels for multiple Python versions below.
This chapter covers each of these options below.

## Using `cibuildwheel`
## Building for ABI3

`setuptools-rust` will automatically configure for the limited API when this is set in the `[bdist_wheel]` configuration section of [`setup.cfg`](https://setuptools.pypa.io/en/latest/deprecated/distutils/configfile.html#writing-the-setup-configuration-file):

```ini
[bdist_wheel]
py_limited_api=cp37 # replace with desired minimum Python version
```

If using a `pyproject.toml`-based build, then save the above in a file and use the `DIST_EXTRA_CONFIG` environment variable to instruct `setuptools` to pick up this extra configuration. (`DIST_EXTRA_CONFIG` is documented [on this page](https://setuptools.pypa.io/en/latest/deprecated/distutils/configfile.html#writing-the-setup-configuration-file) of the `setuptools` docs.)

It is also possible to pass this setting via the command line, e.g.

```
python -m build --config-settings=--build-option=--py-limited-api=cp37
```

## Building for multiple Python versions

### Using `cibuildwheel`

[`cibuildwheel`][cibuildwheel] is a tool to build wheels for multiple platforms using Github Actions.

The [`rtoml` package does this, for example](https://github.com/samuelcolvin/rtoml/blob/143ee0907bba616cbcd5cc58eefe9000fcc2b5f2/.github/workflows/ci.yml#L99-L195).

## Building manually
### Building manually

Place a script called `build-wheels.sh` with the following contents in your project root (next to the `setup.py` file):

Expand All @@ -27,7 +44,7 @@ Place a script called `build-wheels.sh` with the following contents in your proj

This script can be used to produce wheels for multiple Python versions.

### Binary wheels on linux
#### Binary wheels on linux

To build binary wheels on linux, you need to use the [manylinux docker container](https://github.com/pypa/manylinux). You will run the `build-wheels.sh` from above inside that container.

Expand All @@ -54,7 +71,7 @@ hello_rust-0.1.0-cp39-cp39-linux_x86_64.whl hello_rust-0.1.0-cp39-cp39

It is possible to use any of the `manylinux` docker images: `manylinux1`, `manylinux2010` or `manylinux2014`. (Just replace `manylinux2014` in the above instructions with the alternative version you wish to use.)

### Binary wheels on macOS
#### Binary wheels on macOS

For building wheels on macOS it is sufficient to use one of the default `python -m build` or `pip wheel --no-deps . --wheel-dir dist` commands.

Expand Down
1 change: 0 additions & 1 deletion examples/hello-world-setuppy/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
# in Cargo.toml and the function name in the `.rs` file,
# but you can add a prefix to nest it inside of a Python package.
path="Cargo.toml", # Default value, can be omitted
py_limited_api="auto", # Default value, can be omitted
binding=Binding.PyO3, # Default value, can be omitted
)
],
Expand Down
1 change: 0 additions & 1 deletion examples/hello-world/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ find = { where = ["python"] }
# Private Rust extension module to be nested into Python package
target = "hello_world._lib" # The last part of the name (e.g. "_lib") has to match lib.name in Cargo.toml,
# but you can add a prefix to nest it inside of a Python package.
py-limited-api = "auto" # Default value, can be omitted
binding = "PyO3" # Default value, can be omitted
# See reference for RustExtension in https://setuptools-rust.readthedocs.io/en/latest/reference.html

Expand Down
2 changes: 1 addition & 1 deletion examples/rust_with_cffi/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
packages=find_packages(where="python"),
package_dir={"": "python"},
rust_extensions=[
RustExtension("rust_with_cffi.rust", py_limited_api="auto"),
RustExtension("rust_with_cffi.rust"),
],
cffi_modules=["cffi_module.py:ffi"],
install_requires=["cffi"],
Expand Down
24 changes: 8 additions & 16 deletions setuptools_rust/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,22 +107,7 @@ class RustExtension:
optional: If it is true, a build failure in the extension will not
abort the build process, and instead simply not install the failing
extension.
py_limited_api: Similar to ``py_limited_api`` on
``setuptools.Extension``, this controls whether the built extension
should be considered compatible with the PEP 384 "limited API".
- ``'auto'``: the ``py_limited_api`` option of
``bdist_wheel`` will control whether the extension is
built as a limited api extension. The corresponding
``pyo3/abi3-pyXY`` feature will be set accordingly.
This is the recommended setting, as it allows
to build a version-specific extension for best performance.
- ``True``: the extension is assumed to be compatible with the
limited abi. You must ensure this is the case (e.g. by setting
the ``pyo3/abi3`` feature).
- ``False``: the extension is version-specific.
py_limited_api: Deprecated.
"""

def __init__(
Expand Down Expand Up @@ -180,6 +165,13 @@ def __init__(
DeprecationWarning,
)

if self.py_limited_api != "auto":
warnings.warn(
"`RustExtension.py_limited_api` is deprecated, use [bdist_wheel] configuration "
"in `setup.cfg` or `DIST_EXTRA_CONFIG` to build abi3 wheels.",
DeprecationWarning,
)

def get_lib_name(self, *, quiet: bool) -> str:
"""Parse Cargo.toml to get the name of the shared library."""
metadata = self.metadata(quiet=quiet)
Expand Down

0 comments on commit 5dd65e2

Please sign in to comment.