Skip to main content

Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages

Project description

Maturin

formerly pyo3-pack

Actions Status FreeBSD Crates.io PyPI Maturin User Guide Chat on Gitter

Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages.

This project is meant as a zero configuration replacement for setuptools-rust and milksnake. It supports building wheels for python 3.5+ on windows, linux, mac and freebsd, can upload them to pypi and has basic pypy support.

Check out the User Guide!

Usage

You can either download binaries from the latest release or install it with pip:

pip install maturin

There are four main commands:

  • maturin new creates a new cargo project with maturin configured.
  • maturin publish builds the crate into python packages and publishes them to pypi.
  • maturin build builds the wheels and stores them in a folder (target/wheels by default), but doesn't upload them. It's possible to upload those with twine or maturin upload.
  • maturin develop builds the crate and installs it as a python module directly in the current virtualenv. Note that while maturin develop is faster, it doesn't support all the feature that running pip install after maturin build supports.

pyo3 and rust-cpython bindings are automatically detected, for cffi or binaries you need to pass -b cffi or -b bin. maturin doesn't need extra configuration files and doesn't clash with an existing setuptools-rust or milksnake configuration. You can even integrate it with testing tools such as tox. There are examples for the different bindings in the test-crates folder.

The name of the package will be the name of the cargo project, i.e. the name field in the [package] section of Cargo.toml. The name of the module, which you are using when importing, will be the name value in the [lib] section (which defaults to the name of the package). For binaries, it's simply the name of the binary generated by cargo.

Python packaging basics

Python packages come in two formats: A built form called wheel and source distributions (sdist), both of which are archives. A wheel can be compatible with any python version, interpreter (cpython and pypy, mainly), operating system and hardware architecture (for pure python wheels), can be limited to a specific platform and architecture (e.g. when using ctypes or cffi) or to a specific python interpreter and version on a specific architecture and operating system (e.g. with pyo3 and rust-cpython).

When using pip install on a package, pip tries to find a matching wheel and install that. If it doesn't find one, it downloads the source distribution and builds a wheel for the current platform, which requires the right compilers to be installed. Installing a wheel is much faster than installing a source distribution as building wheels is generally slow.

When you publish a package to be installable with pip install, you upload it to pypi, the official package repository. For testing, you can use test pypi instead, which you can use with pip install --index-url https://test.pypi.org/simple/. Note that for publishing for linux, you need to use the manylinux docker container, while for publishing from your repository you can use the messense/maturin-action github action.

pyo3 and rust-cpython

For pyo3 and rust-cpython, maturin can only build packages for installed python versions. On linux and mac, all python versions in PATH are used. If you don't set your own interpreters with -i, a heuristic is used to search for python installations. On windows all versions from the python launcher (which is installed by default by the python.org installer) and all conda environments except base are used. You can check which versions are picked up with the list-python subcommand.

pyo3 will set the used python interpreter in the environment variable PYTHON_SYS_EXECUTABLE, which can be used from custom build scripts. Maturin can build and upload wheels for pypy with pyo3, even though only pypy3.7-7.3 on linux is tested.

Cffi

Cffi wheels are compatible with all python versions including pypy. If cffi isn't installed and python is running inside a virtualenv, maturin will install it, otherwise you have to install it yourself (pip install cffi).

maturin uses cbindgen to generate a header file, which can be customized by configuring cbindgen through a cbindgen.toml file inside your project root. Alternatively you can use a build script that writes a header file to $PROJECT_ROOT/target/header.h.

Based on the header file maturin generates a module which exports an ffi and a lib object.

Example of a custom build script
use cbindgen;
use std::env;
use std::path::Path;

fn main() {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

    let bindings = cbindgen::Builder::new()
        .with_no_includes()
        .with_language(cbindgen::Language::C)
        .with_crate(crate_dir)
        .generate()
        .unwrap();
    bindings.write_to_file(Path::new("target").join("header.h"));
}

Mixed rust/python projects

To create a mixed rust/python project, create a folder with your module name (i.e. lib.name in Cargo.toml) next to your Cargo.toml and add your python sources there:

my-project
├── Cargo.toml
├── my_project
│   ├── __init__.py
│   └── bar.py
├── pyproject.toml
├── Readme.md
└── src
    └── lib.rs

You can specify a different python source directory in Cargo.toml by setting package.metadata.maturin.python-source, for example

[package.metadata.maturin]
python-source = "python"

then the project structure would look like this:

my-project
├── Cargo.toml
├── python
│   └── my_project
│       ├── __init__.py
│       └── bar.py
├── pyproject.toml
├── Readme.md
└── src
    └── lib.rs

maturin will add the native extension as a module in your python folder. When using develop, maturin will copy the native library and for cffi also the glue code to your python folder. You should add those files to your gitignore.

With cffi you can do from .my_project import lib and then use lib.my_native_function, with pyo3/rust-cpython you can directly from .my_project import my_native_function.

Example layout with pyo3 after maturin develop:

my-project
├── Cargo.toml
├── my_project
│   ├── __init__.py
│   ├── bar.py
│   └── my_project.cpython-36m-x86_64-linux-gnu.so
├── Readme.md
└── src
    └── lib.rs

Python metadata

maturin supports PEP 621, you can specify python package metadata in pyproject.toml. maturin merges metadata from Cargo.toml and pyproject.toml, pyproject.toml take precedence over Cargo.toml.

To specify python dependencies, add a list dependencies in a [project] section in the pyproject.toml. This list is equivalent to install_requires in setuptools:

[project]
name = "my-project"
dependencies = ["flask~=1.1.0", "toml==0.10.0"]

Pip allows adding so called console scripts, which are shell commands that execute some function in you program. You can add console scripts in a section [project.scripts]. The keys are the script names while the values are the path to the function in the format some.module.path:class.function, where the class part is optional. The function is called with no arguments. Example:

[project.scripts]
get_42 = "my_project:DummyClass.get_42"

You can also specify trove classifiers in your Cargo.toml under project.classifiers:

[project]
name = "my-project"
classifiers = ["Programming Language :: Python"]

Source distribution

maturin supports building through pyproject.toml. To use it, create a pyproject.toml next to your Cargo.toml with the following content:

[build-system]
requires = ["maturin>=0.12,<0.13"]
build-backend = "maturin"

If a pyproject.toml with a [build-system] entry is present, maturin will build a source distribution of your package, unless --no-sdist is specified. The source distribution will contain the same files as cargo package. To only build a source distribution, pass --interpreter without any values.

You can then e.g. install your package with pip install .. With pip install . -v you can see the output of cargo and maturin.

You can use the options compatibility, skip-auditwheel, bindings, strip, cargo-extra-args and rustc-extra-args under [tool.maturin] the same way you would when running maturin directly. The bindings key is required for cffi and bin projects as those can't be automatically detected. Currently, all builds are in release mode (see this thread for details).

For a non-manylinux build with cffi bindings you could use the following:

[build-system]
requires = ["maturin>=0.12,<0.13"]
build-backend = "maturin"

[tool.maturin]
bindings = "cffi"
compatibility = "linux"

manylinux option is also accepted as an alias of compatibility for backward compatibility with old version of maturin.

To include arbitrary files in the sdist for use during compilation specify sdist-include as an array of globs:

[tool.maturin]
sdist-include = ["path/**/*"]

There's a maturin sdist command for only building a source distribution as workaround for pypa/pip#6041.

Manylinux and auditwheel

For portability reasons, native python modules on linux must only dynamically link a set of very few libraries which are installed basically everywhere, hence the name manylinux. The pypa offers special docker images and a tool called auditwheel to ensure compliance with the manylinux rules. If you want to publish widely usable wheels for linux pypi, you need to use a manylinux docker image.

The Rust compiler since version 1.47 requires at least glibc 2.11, so you need to use at least manylinux2010. For publishing, we recommend enforcing the same manylinux version as the image with the manylinux flag, e.g. use --manylinux 2014 if you are building in quay.io/pypa/manylinux2014_x86_64. The messense/maturin-action github action already takes care of this if you set e.g. manylinux: 2014.

maturin contains a reimplementation of auditwheel automatically checks the generated library and gives the wheel the proper. If your system's glibc is too new or you link other shared libraries, it will assign the linux tag. You can also manually disable those checks and directly use native linux target with --manylinux off.

For full manylinux compliance you need to compile in a CentOS docker container. The pyo3/maturin image is based on the manylinux2010 image, and passes arguments to the maturin binary. You can use it like this:

docker run --rm -v $(pwd):/io ghcr.io/pyo3/maturin build --release  # or other maturin arguments

Note that this image is very basic and only contains python, maturin and stable rust. If you need additional tools, you can run commands inside the manylinux container. See konstin/complex-manylinux-maturin-docker for a small educational example or nanoporetech/fast-ctc-decode for a real world setup.

maturin itself is manylinux compliant when compiled for the musl target.

Code

The main part is the maturin library, which is completely documented and should be well integrable. The accompanying main.rs takes care username and password for the pypi upload and otherwise calls into the library.

The sysconfig folder contains the output of python -m sysconfig for different python versions and platform, which is helpful during development.

You need to install cffi and virtualenv (pip install cffi virtualenv) to run the tests.

There are some optional hacks that can speed up the tests (over 80s to 17s on my machine).

  1. By running cargo build --release --manifest-path test-crates/cargo-mock/Cargo.toml you can activate a cargo cache avoiding to rebuild the pyo3 test crates with every python version.
  2. Delete target/test-cache to clear the cache (e.g. after changing a test crate) or remove test-crates/cargo-mock/target/release/cargo to deactivate it.
  3. By running the tests with the faster-tests feature, binaries are stripped and wheels are only stored and not compressed.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

maturin-0.12.17.tar.gz (153.6 kB view details)

Uploaded Source

Built Distributions

maturin-0.12.17-py3-none-win_arm64.whl (5.1 MB view details)

Uploaded Python 3 Windows ARM64

maturin-0.12.17-py3-none-win_amd64.whl (5.8 MB view details)

Uploaded Python 3 Windows x86-64

maturin-0.12.17-py3-none-win32.whl (5.3 MB view details)

Uploaded Python 3 Windows x86

maturin-0.12.17-py3-none-musllinux_1_1_x86_64.whl (9.2 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ x86-64

maturin-0.12.17-py3-none-musllinux_1_1_ppc64le.whl (8.3 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ ppc64le

maturin-0.12.17-py3-none-musllinux_1_1_i686.whl (9.3 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ i686

maturin-0.12.17-py3-none-musllinux_1_1_armv7l.whl (9.0 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ ARMv7l

maturin-0.12.17-py3-none-musllinux_1_1_aarch64.whl (8.8 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ ARM64

maturin-0.12.17-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl (9.5 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ s390x

maturin-0.12.17-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (8.3 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ppc64le

maturin-0.12.17-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (9.0 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ARMv7l

maturin-0.12.17-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (8.8 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ARM64

maturin-0.12.17-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl (9.3 MB view details)

Uploaded Python 3 manylinux: glibc 2.12+ i686

maturin-0.12.17-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl (9.2 MB view details)

Uploaded Python 3 manylinux: glibc 2.5+ x86-64

maturin-0.12.17-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl (12.5 MB view details)

Uploaded Python 3 macOS 10.9+ universal2 (ARM64, x86-64) macOS 10.9+ x86-64 macOS 11.0+ ARM64

maturin-0.12.17-py3-none-macosx_10_7_x86_64.whl (6.5 MB view details)

Uploaded Python 3 macOS 10.7+ x86-64

File details

Details for the file maturin-0.12.17.tar.gz.

File metadata

  • Download URL: maturin-0.12.17.tar.gz
  • Upload date:
  • Size: 153.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/0.12.16

File hashes

Hashes for maturin-0.12.17.tar.gz
Algorithm Hash digest
SHA256 70bd19f5698db05417dd5e206d9f2893e149ae5d5e9d3e2b3cef31dd26fe3a67
MD5 8025c3f90f15f0acb491eaa13ca26c4e
BLAKE2b-256 cd750705ea01f62429c283e070ea842a2543490b61720a45fda32a7410b8b320

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-win_arm64.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 fafa013a4f20d53740773781f6469fc284d7b8fab6c099b42ecb275e52b25641
MD5 3196d8d640015a36ea5572ffc7177d38
BLAKE2b-256 7d85da958b20a5fef6b08176b9cf0f45e0b89300e86672201cbc30e7d7f530ef

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 8da58ff0df1e326da7a547479f37637fec6718ec4d19f5501119b67b1cc56e0c
MD5 4f4ff7e0ebcf03486f932deaca9860e3
BLAKE2b-256 37ac08661c6f2356c5b31f0318cfefc6172fc3b433d160d60021b05c9f84fd6a

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-win32.whl.

File metadata

  • Download URL: maturin-0.12.17-py3-none-win32.whl
  • Upload date:
  • Size: 5.3 MB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/0.12.16

File hashes

Hashes for maturin-0.12.17-py3-none-win32.whl
Algorithm Hash digest
SHA256 1228eecdadaba35b5b82d532705dec1b24beacfb62f0ec0ddf90fa37e4d41198
MD5 600b46655f75e0bca7b7ab6dbbbeefce
BLAKE2b-256 1a901b7c87198f4e453168d9b562933ef27d818e51989e38fdd22202816b53f8

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 54a17b089339959a24488faf686df31e70daf46a830cf193e0183f8bf7079663
MD5 fb458b012572e6a2766321bb39808398
BLAKE2b-256 89cbb9066be49e5fb332cdb61c7c41f053c59d1f44ea1258b672190159c3587f

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-musllinux_1_1_ppc64le.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-musllinux_1_1_ppc64le.whl
Algorithm Hash digest
SHA256 3ccfee81053538ff25b6debd3c47674fa0a6dc48d2a107a9d36688b0296d6b84
MD5 3b4ca31c74271b5d14e3e292e31b6684
BLAKE2b-256 063f2232b749a7189bba0e7e8dfc08657640d1a8aa0f47c9b6c5ae1406416312

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-musllinux_1_1_i686.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 bfe24007766bf2e91f94e5007ede536e702e65121225eeeeb393ecbe4d41b2f8
MD5 b522b5182302fd211a875175ea89655c
BLAKE2b-256 732e078dac0b533f76c2684184a30fe5c13a14093389f56a6c195efc2d4656bf

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 16047902a0262fa2126a4c86ff5d616b93f09dfeb6d3536b53791b0a8ec3c10b
MD5 b219d2962b2f335d3fedd6e8ddecf748
BLAKE2b-256 fdb2f4997a30b1804aa076cf12ffecd9044bd5da9d95b1c6d9efe282361a3d29

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 fb0607ae2a3b8a9eabc4447099090c5d82188b101f3d68d10cbe15e77dd8a7ce
MD5 cca2e3c39390c2c092d32d9f9f78ebb4
BLAKE2b-256 99253497d365ec3c5ae8e7a91a3a912ab77474b04b382b7d3da9575fece3d14d

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 74d6858193776888e2f232e21d6cc13391ad3e47357006ab5b70c19ec0d1948a
MD5 7391982bbd6ccaeb9949370c259b22d4
BLAKE2b-256 882fc12ba30ee3fd6400913c8a82f4332d5467da234f4b8fa9bde16b9b1abe5c

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 a714868f40696a7cbe9a51c9d201e509e490fe63ab2d47f57e24bd8ff85f22e8
MD5 7e499aedd3938d933e09f78f0ba08f05
BLAKE2b-256 3a524a2e7cc3fa04e2e215ab8ca3dfb8f081e39088de7f7161c448dcd647db1c

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 4a5cf66297967f495e3cd05a58e40c03f69c2d3f6fad7e938a71d1d54f82d148
MD5 00b935bd6900a15d15b37f5de46d7536
BLAKE2b-256 925ab0a336b8fd4d14fae3f2d34b035ede3b68cf0cb6ac57452a718a752be629

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 28256bfe4312c14e05f500694ae537ddbaaecdad1c4fd5d3bff02047e2034202
MD5 60c18c3e41516997deb87da619eb17a2
BLAKE2b-256 c5d7977e44045bdd53dcaef32b94c5a4ef72ee589f948f6a969335fcee001344

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 aebe27ef8f81cad054b78953869e50648760f946c4561539feb5d24ede9e16a4
MD5 4da8bcbf1bffab000d73ce28fdbf9c6c
BLAKE2b-256 c88d60406c8341ea2458f8b2a4079603c69cf773b06b425d2a407ebacc7520c2

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 48509abf2072cae4a41ba1be49b3e054f69dbaa2ff5c2b3ffb93276e5ecfe664
MD5 c645b85b0bac9b6243e4daa0ec08f13d
BLAKE2b-256 debeb66abedcedd638d051434b612ece0ee3b1a8c09ca2e8a8be83c8616ba0a0

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 1a515722df69064c14aa3852382374288ca960d0408f92fbffa98fc5cd6932be
MD5 2a438694050d53e885449d5b6c8ef38f
BLAKE2b-256 4e80be0ca640670286e906cf7d698a53311937dd16e699487d4b177efd88f551

See more details on using hashes here.

File details

Details for the file maturin-0.12.17-py3-none-macosx_10_7_x86_64.whl.

File metadata

File hashes

Hashes for maturin-0.12.17-py3-none-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 547b0511025e8fe712e23219f42d31c8f3605d23f2ebedaffae9daab2c9c9c78
MD5 f4cdd73c89c54bb7da4997c8669a278c
BLAKE2b-256 af4a1bebfda98ac3cb23bb0b14cb368cde857e17018eb122433e1b0e8bc71dc9

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page