Skip to main content

zigcc-build-backend

Test 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:

  1. Reads your pyproject.toml configuration.
  2. Identifies the source files specified in [tool.zigcc-build].
  3. Invokes zig cc (provided by the ziglang package) to compile these sources into a native extension module (.pyd on Windows, .so on Linux/macOS).
  4. 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 src directory exists, it looks for packages inside src.
  • 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 ziglang package (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)

Source distribution for zigcc-build 0.2.5
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)

Table of built distributions (wheels) for zigcc-build 0.2.5
File Interpreter ABI Platform Actions
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page