Build and publish Zig-powered Python extensions with native cross-compilation
Project description
zig-maturin
Build and publish Zig-powered Python extensions with native cross-compilation.
zig-maturin is a tool that compiles Zig code into Python native extensions and packages them as .whl (wheel) files — ready for pip install. Think of it as Maturin for Zig.
Why Zig?
| Feature | Rust + Maturin | Zig + zig-maturin |
|---|---|---|
| Cross-compilation | Complex: needs external linkers, toolchains, or Docker | Built-in: zig build -Dtarget=aarch64-macos works out of the box |
| Toolchain size | Gigabytes (rustc + LLVM) | A few megabytes (single Zig binary) |
| C ABI | Via #[no_mangle] and extern "C" |
Native: Zig compiles directly to C-compatible shared libraries |
Zig's built-in cross-compilation lets you build wheels for all platforms from a single machine — no Docker, no extra toolchains, no linker setup.
Quick Start
# Install zig-maturin
pip install zig-maturin
# Scaffold a new project
zig-maturin scaffold my_extension
cd my_extension
# Build and install in development mode
zig-maturin develop
# Test it
python -c "import my_extension; print(my_extension.hello())"
# → Hello from Zig!
# Build a wheel for distribution
zig-maturin build
# → dist/my_extension-0.1.0-cp314-cp314-manylinux_2_28_x86_64.whl
# Cross-compile for other platforms (no extra setup needed!)
zig-maturin build --target aarch64-macos --target x86_64-windows
# → dist/my_extension-0.1.0-cp314-cp314-macosx_11_0_arm64.whl
# → dist/my_extension-0.1.0-cp314-cp314-win_amd64.whl
How it Works
- Write Zig code — use the
zig-maturinZig package to access the Python C-API zig-maturin build— compiles withzig buildand packages the.sointo a wheelzig-maturin develop— compiles and installs directly into the current Python environment- Cross-compile — pass
--target <triple>to build for any supported platform
Writing a Python Extension in Zig
The zig-maturin Zig package provides low-level Python C-API bindings. Functions are exposed via the standard Python C extension pattern:
const zm = @import("zig-maturin");
fn hello(self: ?*zm.PyObject, args: ?*zm.PyObject) callconv(.c) ?*zm.PyObject {
_ = self;
_ = args;
return zm.PyUnicode_FromString("Hello from Zig!");
}
pub export fn PyInit_my_extension() callconv(.c) ?*zm.PyObject {
const methods = [_]zm.PyMethodDef{
zm.method("hello", &hello, zm.METH_NOARGS, "Say hello"),
.{ .ml_name = null, .ml_meth = null, .ml_flags = 0, .ml_doc = null },
};
var mod = zm.PyModuleDef{
.m_base = zm.PyModuleDef_HEAD_INIT,
.m_name = "my_extension",
.m_doc = "A Python module written in Zig",
.m_size = -1,
.m_methods = @as(?[*]zm.PyMethodDef, @ptrCast(@constCast(&methods))),
.m_slots = null,
.m_traverse = null,
.m_clear = null,
.m_free = null,
};
return zm.PyModule_Create(&mod);
}
Note: The
zig-maturinpackage exposes the raw Python C-API as Zig extern functions. A higher-level "PyO3 for Zig" layer is planned for future releases.
Available C-API Bindings
The Zig package wraps a comprehensive subset of the Python C-API:
| Category | Functions |
|---|---|
| Module | PyModule_Create, PyModule_New, PyModule_AddObject, PyModule_AddIntConstant, PyModule_AddStringConstant |
| Ref counting | Py_INCREF, Py_DECREF, Py_XINCREF, Py_XDECREF, Py_NewRef, Py_IncRef, Py_DecRef |
| Strings | PyUnicode_FromString, PyUnicode_FromStringAndSize, PyUnicode_AsUTF8, PyUnicode_Check |
| Integers | PyLong_FromLong, PyLong_FromLongLong, PyLong_FromUnsignedLongLong, PyLong_AsLong, PyLong_AsLongLong, PyLong_Check |
| Floats | PyFloat_FromDouble, PyFloat_AsDouble, PyFloat_Check |
| Booleans | PyBool_FromLong, PyBool_Check |
| Exceptions | PyErr_SetString, PyErr_SetObject, PyErr_Occurred, PyErr_Clear |
| Objects | PyObject_GetAttrString, PyObject_SetAttrString, PyObject_CallObject, PyObject_Str, PyObject_IsTrue |
| Args | PyArg_ParseTuple, Py_BuildValue |
| Lists | PyList_New, PyList_Size, PyList_GetItem, PyList_SetItem, PyList_Append, PyList_Check |
| Dicts | PyDict_New, PyDict_SetItemString, PyDict_GetItemString, PyDict_Size, PyDict_Check |
| Tuples | PyTuple_New, PyTuple_Size, PyTuple_GetItem, PyTuple_SetItem |
Commands
zig-maturin scaffold <name>
Creates a new project with:
pyproject.toml— Python project configurationbuild.zig/build.zig.zon— Zig build configuration withzig-maturindependencysrc/main.zig— Template module with a hello function
zig-maturin build
Builds the extension and creates a .whl file.
--target <triple>— cross-compile target (can be specified multiple times for multi-platform builds)--release— build in release mode--out <dir>— output directory (default:dist)
zig-maturin develop
Builds the extension and installs it into the current Python environment's site-packages.
--target <triple>— cross-compilation target (default: host native)--release— build in release mode
Configuration
zig-maturin reads [tool.zig-maturin] from pyproject.toml:
[tool.zig-maturin]
module-name = "my_extension" # Python module name (default: project name)
zig-source = "src/main.zig" # Path to Zig source file
Cross-Compilation Targets
zig-maturin maps Zig targets to Python wheel platform tags:
| Zig Target | Wheel Tag |
|---|---|
x86_64-linux-gnu |
manylinux_2_28_x86_64 |
aarch64-linux-gnu |
manylinux_2_28_aarch64 |
x86_64-linux-musl |
musllinux_1_2_x86_64 |
aarch64-macos |
macosx_11_0_arm64 |
x86_64-macos |
macosx_11_0_x86_64 |
x86_64-windows |
win_amd64 |
aarch64-windows |
win_arm64 |
Project Structure
my_extension/
├── pyproject.toml # Python project config with [tool.zig-maturin]
├── build.zig # Zig build file
├── build.zig.zon # Zig package manifest
├── src/
│ └── main.zig # Your Zig extension code
└── dist/ # Built wheels (after zig-maturin build)
Requirements
- Python 3.12+
- Zig 0.14+ (tested with 0.16.0)
- Linux, macOS, or Windows
License
MIT — Ricardo Robles Fernández
Related Projects
- Maturin — Build and publish Rust-powered Python extensions
- PyO3 — Rust bindings for Python
- zig-python — Python C-API bindings for Zig
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zig_maturin-0.1.0.tar.gz.
File metadata
- Download URL: zig_maturin-0.1.0.tar.gz
- Upload date:
- Size: 11.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c14161c690925946dd694310749fbeda4aac5de9a300c82a2467746d5afdb427
|
|
| MD5 |
294777f6b2fc30f7ecab434b11dada03
|
|
| BLAKE2b-256 |
791438b53907dfa43368af24afdf27d04bb640ecb9192fc4100b39b803ef007b
|
Provenance
The following attestation bundles were made for zig_maturin-0.1.0.tar.gz:
Publisher:
release.yml on rroblf01/zig-maturin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zig_maturin-0.1.0.tar.gz -
Subject digest:
c14161c690925946dd694310749fbeda4aac5de9a300c82a2467746d5afdb427 - Sigstore transparency entry: 1778071408
- Sigstore integration time:
-
Permalink:
rroblf01/zig-maturin@5bf01c3fa043caaa66c4c95b7af5dd7834792822 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/rroblf01
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5bf01c3fa043caaa66c4c95b7af5dd7834792822 -
Trigger Event:
push
-
Statement type:
File details
Details for the file zig_maturin-0.1.0-py3-none-any.whl.
File metadata
- Download URL: zig_maturin-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
410d982a73c7f9ef47bee3ae879dbbb2912aa83e5a37675fd87c3b051aeddf31
|
|
| MD5 |
a0e11de83799b180154e99be8bfc0d55
|
|
| BLAKE2b-256 |
c5c5a3d12a260d7403bb1fa73ef14628591a091a2866f354bf8bfb150f300b69
|
Provenance
The following attestation bundles were made for zig_maturin-0.1.0-py3-none-any.whl:
Publisher:
release.yml on rroblf01/zig-maturin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zig_maturin-0.1.0-py3-none-any.whl -
Subject digest:
410d982a73c7f9ef47bee3ae879dbbb2912aa83e5a37675fd87c3b051aeddf31 - Sigstore transparency entry: 1778071508
- Sigstore integration time:
-
Permalink:
rroblf01/zig-maturin@5bf01c3fa043caaa66c4c95b7af5dd7834792822 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/rroblf01
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5bf01c3fa043caaa66c4c95b7af5dd7834792822 -
Trigger Event:
push
-
Statement type: