zigcc-build-backend
A PEP 517 build backend that uses zig cc (via the ziglang Python package) to compile C/C++ extensions for Python.
This backend allows you to easily compile native Python extensions without needing a pre-installed C compiler on the system, as it leverages the portable Zig compiler toolchain distributed via PyPI.
How it works
When you build your project (e.g., using pip or build), this backend:
- Reads your
pyproject.tomlconfiguration. - Identifies the source files specified in
[tool.zigcc-build]. - Invokes
zig cc(provided by theziglangpackage) to compile these sources into a native extension module (.pydon Windows,.soon Linux/macOS). - Packages the result into a standard Python Wheel.
Usage
1. Configure [build-system]
In your pyproject.toml, specify zigcc-build as the build backend.
Option A: Using from PyPI (if published)
[build-system]
requires = ["zigcc-build"]
build-backend = "zigcc_build"
Option B: Using directly from GitHub
[build-system]
requires = ["zigcc-build @ git+https://github.com/jrialland/zigcc-build.git"]
build-backend = "zigcc_build"
2. Configure [tool.zigcc-build]
Define your extension module settings in the [tool.zigcc-build] table.
[tool.zigcc-build]
# The name of the compiled extension module (optional).
# Defaults to the project name (with dashes replaced by underscores).
module-name = "my_extension"
# List of source files to compile (C or C++).
sources = ["src/main.c", "src/utils.c"]
# List of additional include directories (optional).
include-dirs = ["include"]
# List of compiler macros/defines (optional).
# Translates to -Dname or -Dname=value
defines = ["MY_MACRO=1", "DEBUG"]
# List of library directories (optional).
# Translates to -Lpath
library-dirs = ["libs"]
# List of libraries to link against (optional).
# Translates to -lname
libraries = ["m", "user32"]
# Optional python script to configure the build dynamically
configurer-script = "configure.py"
# List of python packages to include (optional).
# If omitted, the backend will try to auto-discover packages in 'src/' or the root directory.
packages = ["mypackage"]
Including Pure Python Code
The backend automatically detects and includes pure Python packages.
- If a
srcdirectory exists, it looks for packages insidesrc. - Otherwise, it looks for packages in the project root.
You can also explicitly specify packages to include using the packages option in [tool.zigcc-build].
Dynamic Configuration
If you specify a configurer-script, the backend will load this Python script and call a configure(config) function. This allows you to modify the build configuration dynamically (e.g., based on the platform or environment).
Example configure.py:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from zigcc_build.config import ZigCcConfig
def configure(config: "ZigCcConfig"):
# config is a dictionary with keys: 'sources', 'include_dirs', 'defines', 'module_name'
print("Running custom configuration...")
# Add a define dynamically
config["defines"].append("DYNAMIC_MACRO=1")
# Add sources based on platform
import sys
if sys.platform == "win32":
config["sources"].append("src/windows_utils.c")
Configuration Schema
The configuration object passed to configure() follows this TypedDict schema:
class ZigCcConfig(TypedDict):
sources: List[str] # List of source files to compile
include_dirs: List[str] # List of include directories
defines: List[str] # List of compiler macros
library_dirs: List[str] # List of library directories
libraries: List[str] # List of libraries to link against
module_name: str # The name of the extension module
packages: List[str] # List of python packages to include
3. Build
You can build your project using standard Python tooling:
# Install the package in editable mode
pip install -e .
# Build a wheel and sdist
python -m build
PEP 621 Metadata Support
The zigcc-build backend fully supports PEP 621 metadata fields defined in your pyproject.toml. All metadata is automatically included in the generated wheel's METADATA file and the source distribution's PKG-INFO file.
Supported Metadata Fields
- name - Package name
- version - Package version
- description - Short one-line summary
- readme - Long description from README file (supports
.md,.rst,.txt) - requires-python - Python version requirements
- license - License information (text or file)
- authors - List of authors with name and email
- maintainers - List of maintainers with name and email
- keywords - List of keywords for PyPI
- classifiers - List of PyPI classifiers
- urls - Project URLs (Homepage, Repository, Issues, etc.)
- dependencies - Runtime dependencies
- optional-dependencies - Optional dependency groups
Example with Full Metadata
[build-system]
requires = ["zigcc-build"]
build-backend = "zigcc_build"
[project]
name = "my-package"
version = "1.0.0"
description = "A package with C extensions"
readme = "README.md"
requires-python = ">=3.12"
license = {text = "MIT"}
authors = [
{name = "Your Name", email = "you@example.com"}
]
keywords = ["c-extension", "zig", "compiler"]
classifiers = [
"Development Status :: 4 - Beta",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.12",
]
dependencies = [
"numpy>=1.20",
]
[project.urls]
Homepage = "https://github.com/user/my-package"
Repository = "https://github.com/user/my-package"
Issues = "https://github.com/user/my-package/issues"
[tool.zigcc-build]
module-name = "my_extension"
sources = ["src/extension.c"]
The backend will automatically generate complete METADATA and PKG-INFO files with all this information, ensuring your packages are fully compliant with PyPI requirements.
Example pyproject.toml
Here is a complete example for a project named demo-package:
[build-system]
requires = ["zigcc-build"]
build-backend = "zigcc_build"
[project]
name = "demo-package"
version = "1.0.0"
description = "A demo package built with zigcc"
readme = "README.md"
requires-python = ">=3.7"
[tool.zigcc-build]
module-name = "demo"
sources = ["src/hello.c"]
Requirements
- Python >= 3.7
- The
ziglangpackage (automatically handled by the build system requirements).
Tutorial: Building the Demo Project
This repository includes a demo-project to illustrate how to use zigcc-build.
1. Install the backend locally
Since zigcc-build is not yet on PyPI, you need to install it in your environment first.
# From the root of the repository
pip install -e .
2. Build the demo project
Navigate to the demo-project directory and build it. We use --no-build-isolation because the backend is installed locally, not from PyPI.
cd demo-project
python -m build --no-isolation
3. Install and Test
Install the generated wheel and run the tests.
# Install the generated wheel (replace * with the actual version/platform)
pip install dist/demo_package-*.whl --force-reinstall
# Run the tests
python -m pytest tests
4. Recompiling
To recompile after changing the C source code, simply run the build command again:
python -m build --no-isolation
Metadata
Release files for zigcc-build 0.2.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| zigcc_build-0.2.5.tar.gz | 11.6 kB | Without provenance | Details for zigcc_build-0.2.5.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| zigcc_build-0.2.5-py3-none-any.whl | Python 3 | none | any | Details for zigcc_build-0.2.5-py3-none-any.whl |
Total release size: 21.8 kB
Release files / zigcc_build-0.2.5.tar.gz
| Download URL | zigcc_build-0.2.5.tar.gz |
|---|---|
| Size | 11.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fcd132ea42e44063064e56202aca754bb28dbd5761c6727e2bbeff1f39e2aaaf
|
|
BLAKE2b-256 checksum How to use checksums |
d9f1a696fa5d96e2125c924fed1bd40d1be3162bf53f9420254874d5f4dd7dcd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / zigcc_build-0.2.5-py3-none-any.whl
| Download URL | zigcc_build-0.2.5-py3-none-any.whl |
|---|---|
| Size | 10.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
64b431eabf11a9b32420f96d67983126f663142ad517c3b463b9f66a6b8fa5a7
|
|
BLAKE2b-256 checksum How to use checksums |
bda4b42b5e9c6a2e56f0be4d990b46e9071a42697389f50d776b4769c071be2d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Security for zigcc-build 0.2.5
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.