Python Maturin Build Tool — Core Concepts

Maturin is a build tool designed specifically for creating Python packages from Rust code. It replaces the multi-step, error-prone process of manually configuring setuptools, compiler flags, and platform-specific packaging.

The Problem Maturin Solves

Building a Python extension from Rust involves:

  • Compiling Rust to a shared library (.so, .dylib, .pyd)
  • Naming the file to match Python’s import conventions
  • Creating a wheel with the correct platform tags (manylinux, macosx, win_amd64)
  • Writing metadata (METADATA, RECORD, WHEEL files)

Doing this manually is tedious and fragile. Maturin automates the entire chain.

Supported Binding Types

Maturin supports three binding strategies:

BindingUse CaseHow It Works
PyO3Full-featured Rust extensionsRust code uses PyO3 macros to define Python classes and functions
cffiC-compatible interfacesRust exposes a C ABI; Python calls it via CFFI
uniffiMulti-language bindingsMozilla’s uniffi generates Python, Kotlin, and Swift bindings from a single interface definition

PyO3 is the most common choice for Python-specific extensions.

Developer Workflow

Setup

A minimal Maturin project has:

my-package/
├── Cargo.toml        # Rust dependencies and crate config
├── pyproject.toml    # Python build config
├── src/
│   └── lib.rs        # Rust source with PyO3 annotations
└── python/
    └── my_package/   # Optional pure-Python code alongside Rust
        └── __init__.py

The pyproject.toml declares Maturin as the build backend:

[build-system]
requires = ["maturin>=1.0,<2.0"]
build-backend = "maturin"

[project]
name = "my-package"
requires-python = ">=3.9"

Key Commands

  • maturin develop: Compiles and installs into the active virtualenv. Fast iteration during development.
  • maturin build: Creates wheel files in target/wheels/.
  • maturin build --release: Optimized build for distribution.
  • maturin publish: Builds and uploads to PyPI in one step.

Mixed Rust + Python Packages

Maturin supports placing pure Python code alongside compiled Rust. The python/ directory contains .py files that ship alongside the native module. This is useful for high-level wrappers, type stubs, and convenience functions.

Cross-Compilation

Maturin can build wheels for platforms other than the host:

# Build Linux wheels on macOS using Docker
maturin build --release --target x86_64-unknown-linux-gnu

# Build for multiple Python versions
maturin build --release --interpreter python3.10 python3.11 python3.12

For CI pipelines, the maturin-action GitHub Action or the ghcr.io/pyo3/maturin Docker image handle manylinux compliance automatically.

Common Misconception

“Maturin is only for PyO3 projects.” While PyO3 is the most popular binding, Maturin also supports cffi and uniffi. You can even use it for pure Rust binaries distributed via pip (bin mode), which is how some CLI tools are packaged.

One Thing to Remember

Maturin is the standard build tool for Rust-Python packages. It turns cargo build output into PEP-compliant wheels that work with pip, conda, and every Python packaging tool — across every major platform.

pythonmaturinrustbuild-toolspackaging

See Also

  • Python Boost Python Bindings Boost.Python lets C++ code talk to Python using clever C++ tricks, like teaching two people to understand each other through a shared phrasebook.
  • Python Buffer Protocol The buffer protocol lets Python objects share raw memory without copying, like passing a notebook around the table instead of photocopying every page.
  • Python Capsule Api Python Capsules let C extensions secretly pass pointers to each other through Python, like friends passing a sealed envelope through a mailbox.
  • Python Cffi Bindings CFFI lets Python talk to fast C libraries, like giving your app a translator that speaks both languages at the same table.
  • Python Extension Modules Api The C Extension API is how Python lets you plug in hand-built C code, like adding a turbo engine under your Python program's hood.