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.12.tar.gz (142.8 kB view details)

Uploaded Source

Built Distributions

maturin-0.12.12-py3-none-win_arm64.whl (4.3 MB view details)

Uploaded Python 3 Windows ARM64

maturin-0.12.12-py3-none-win_amd64.whl (5.0 MB view details)

Uploaded Python 3 Windows x86-64

maturin-0.12.12-py3-none-win32.whl (4.6 MB view details)

Uploaded Python 3 Windows x86

maturin-0.12.12-py3-none-musllinux_1_1_x86_64.whl (8.1 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ x86-64

maturin-0.12.12-py3-none-musllinux_1_1_ppc64le.whl (7.0 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ ppc64le

maturin-0.12.12-py3-none-musllinux_1_1_i686.whl (8.3 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ i686

maturin-0.12.12-py3-none-musllinux_1_1_armv7l.whl (8.0 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ ARMv7l

maturin-0.12.12-py3-none-musllinux_1_1_aarch64.whl (7.7 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ ARM64

maturin-0.12.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl (9.0 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ s390x

maturin-0.12.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (7.0 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ppc64le

maturin-0.12.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (8.0 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ARMv7l

maturin-0.12.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (7.7 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ARM64

maturin-0.12.12-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl (8.3 MB view details)

Uploaded Python 3 manylinux: glibc 2.12+ i686

maturin-0.12.12-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl (8.1 MB view details)

Uploaded Python 3 manylinux: glibc 2.5+ x86-64

maturin-0.12.12-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl (10.7 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.12-py3-none-macosx_10_7_x86_64.whl (5.5 MB view details)

Uploaded Python 3 macOS 10.7+ x86-64

File details

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

File metadata

  • Download URL: maturin-0.12.12.tar.gz
  • Upload date:
  • Size: 142.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/0.12.11

File hashes

Hashes for maturin-0.12.12.tar.gz
Algorithm Hash digest
SHA256 c7ace888bedc106ae37d86a1639aae8f034498c96940bf52dc2451b6fffac851
MD5 2935ee92b88f86d3b50db13ef4c618e7
BLAKE2b-256 a84400f2e625c413b46f4dafc19b79d0a798babd0683a4caeb4dd7cb99605882

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 886fa90e9e28ae716fd226108bb0bcb9305e21a13de714e2a84ff04e170d1eee
MD5 86f8640f94c472033628730018e3f23a
BLAKE2b-256 f00dd99692680c265b59052228a0ab40fb926edb7155c5fe64f81920de60ebc4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 10f4442e3229ecb23045b72f82b6a635adf864d8bd39375020157625eee38b1b
MD5 6331c4497be90337358746e6de18e513
BLAKE2b-256 a82271f991cda993457bf1768bfa5d0e34145463b6aec555f2dd3d684e624599

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for maturin-0.12.12-py3-none-win32.whl
Algorithm Hash digest
SHA256 b5d6b2f38ac8df769ad8dce888187fd9132adf3d661c34faf84763841e560eb1
MD5 b1f6df56aff0f9864fe0bdd2af4619b5
BLAKE2b-256 f37ba79c9d1e3223e2c99f9a63f2bc553911173c46f12cec797eb7fde3efba28

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 5e66caa86c24579d010323c4ebf57f649a98601c037e637229bdb932e0b7b6df
MD5 1dbe25207c68bc2b24f836910609fcd0
BLAKE2b-256 0d2e9afc1a624a7540c3ee667a6606640b0ba35c2c5bd6d4527076656a01aa89

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-musllinux_1_1_ppc64le.whl
Algorithm Hash digest
SHA256 c80fa740a68f0d65aca2169adbdb12be5b91f880b002914bb7e7ba5b7f819ddd
MD5 74e7bc9bd920bd78b437a4ba3a5b8f34
BLAKE2b-256 5ff8c07174232af2cdb01a2a077198e58a89dbb8d428092664e88a5174b7b718

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 3e9dc8d2ad56a163c341c89d3c51cd23a91d6b9392be7d779662bffbf49b5886
MD5 6824b86662b01d1f9a4ff1f9be801fe6
BLAKE2b-256 695bcc5f45bf718b621602870ec467312c806b446fb9de1ff093d4b9304dc773

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 3eb5898316057be9c6ce913d0f48e47586bbcc9135fd88d89579e98681dab506
MD5 61236fd134a4d582ebc72831e36122e3
BLAKE2b-256 e855cc77f1537c832717b1d8ba33797656e373e892efff42ca08ed383ab43b1d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 e5b5458515b97651a1ab657b05a6ad47d36fc6a3284cc6a8e1843ec4fef32bc4
MD5 9c6a69a4f7d0f5aa46cc3ae378954ac6
BLAKE2b-256 759740add165e1e28d2a7f584424eb55824442d0c1b0940fa26793bdb73303ea

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 d0cd671238c3cf4c8040e3fa8e70ab806ea174b0468c3d112180c48ab638f67f
MD5 81f411a22b78e7a87f71d7fc72f6ef66
BLAKE2b-256 b389d7857612aab9b2792d2345c505aee2cf66d17fa175230170ac5370b19c3b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 c66afd1a77ddd2b82005bc2885da64b517af58590220e379f603c538497197a1
MD5 b1c990657b19d67af0b1c02d35cc2e88
BLAKE2b-256 ba53591799c480883090d56ddbd34306c1d149de3a0b98865f8e66d1d07e719b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 023a3610fe244136762de2cb9beef432addec2b9278f0132aaf9c9ae6d9d1089
MD5 299215e59fc223b48d05e49d84ec3ac5
BLAKE2b-256 3f2c7e24bf0705baa9c9c6a196a1ba4008710742f6f40ef8a9c339ce7d0ccb22

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ef915d8631317845d219b739fa6055b2f2fd14aeb8d004d8b9de67fd3a8761bb
MD5 5a262b7b33d2cf7a45db636b8c3572fb
BLAKE2b-256 c439cb9987ffefb8401e85263a41260201ba7c0580ed53bd8d86d999924c4c08

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 873f04c991fa114f66229e837edbda7ec8567b2b98ef54c64dca77463c4757c9
MD5 e11eeffbbb3c1e4cbff1999b36d5b71b
BLAKE2b-256 eded63b87d639cf3c2bec592aa8bc526c7273f500d1600de6f56d10cfd7172a4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 165540233392c099458e7e1fdcdaecab83ac9d61a24b707a0904f7fb7765ffcc
MD5 f6e86dd0ee285634efedb57bb62a96c3
BLAKE2b-256 a0a3258afca0af467d6f4fdc1f3cfe74167a76aa5bbcfa751ef15f96ba3f825d

See more details on using hashes here.

File details

Details for the file maturin-0.12.12-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.12-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 4df0fb9bec6ce1cd88e5132660c0b9ed718e91b7dcbb8b15fe414b5a29ab1319
MD5 ea2d9c7ff87516c73194082906dc59cd
BLAKE2b-256 20760926fa6561adedaf7ac19c7cb6f87fad05e00d7d7fbd5957253ad6e8c90d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for maturin-0.12.12-py3-none-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 402a65f0c93d4ffa12183e001bdd83074fa4f2be9603c770ac1ac744cd44bca3
MD5 5e93a6928add3884eaaf450b7724975d
BLAKE2b-256 8d6d07e292e487badab2931c46540479b919896856ed1c4c967fc349c824046d

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