zig-cc-python
zig cc as a drop-in CC= replacement for Python extension builds.
uv add --dev ziglang zig-cc-python
CC="zig-cc" uv run python setup.py build_ext --inplace
What this is
This is not magic. It's a thin wrapper that drops or rewrites a handful of flags that zig cc doesn't support but Python's build system passes by default. The real work is in figuring out which flags those are — the code itself is trivial.
The whole point is building Python C extensions with zig cc instead of gcc or clang. That's the only use case it targets.
It uses the ziglang PyPI package as the compiler — not a system zig installation. The zig version is pinned in your uv.lock, the binary lives in your venv, nothing needs to be installed system-wide.
If you've decided to use this and hit a bug, open an issue or a PR.
Not zigcc
There is a zigcc package on PyPI. It is archived and has bugs that break Python extension builds on Linux x86_64 and macOS. This is not that package.
Usage
# C extension
CC="zig-cc" uv run python setup.py build_ext --inplace
# C++ extension
CC="zig-cc" CXX="zig-cc-cxx" uv run python setup.py build_ext --inplace
# python -m build
CC="zig-cc" uv run python -m build
What it fixes
| Flag | Platform | Problem | Fix |
|---|---|---|---|
-bundle |
macOS | silently ignored by zig ld → broken output | rewrite to -shared |
-LModules/_hacl |
macOS/Linux | CPython sysconfig artifact → crashes zig | drop |
-Wl,-headerpad,N |
macOS | crashes zig 0.15.x | drop |
-Wl,-w |
macOS/Linux | unsupported linker arg | drop |
-Wl,--exclude-libs |
Linux | unsupported linker arg | drop |
-Wl,-Bsymbolic-functions |
Linux | unsupported linker arg (Ubuntu system Python) | drop |
-Wl,-Bsymbolic |
Linux | unsupported linker arg | drop |
-exported_symbols_list <file> |
macOS | unsupported Apple linker flag | drop (both tokens) |
-x wildcard |
Linux x86_64 | zigcc dropped output paths containing -x |
exact matching only |
Known limitations
OpenMP (-fopenmp) — partially supported. Linux works: install libomp-dev and pass -I/-L/-lomp flags manually. macOS does not work: zig cc 0.15.x / Clang 20 compiles Cython's outlined parallel regions without emitting the expected ___kmpc_fork_call runtime calls, so prange loops silently return wrong results. Use a system compiler for OpenMP on macOS.
Dropped flags have minor side effects. zig-cc-python silently drops several flags that zig cc does not support. Verified consequences:
-Wl,-headerpad,0x40— no effect in practice; zig cc and Apple ld produce identical header sizes.-Wl,--exclude-libs,ALL— static library symbols may leak into the extension's dynamic symbol table. This only causes conflicts if another extension is loaded withRTLD_GLOBALand exports the same symbol. Python loads extensions withRTLD_LOCALby default, so normalimportis unaffected.-exported_symbols_list— same symbol visibility note as above. Not observed in any real build during testing.
Metadata
Release files for zig-cc-python 0.1.0
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 | |
|---|---|---|---|---|
| zig_cc_python-0.1.0.tar.gz | 14.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| zig_cc_python-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.2 kB
Release files / zig_cc_python-0.1.0.tar.gz
| Download URL | zig_cc_python-0.1.0.tar.gz |
|---|---|
| Size | 14.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e87c65ac8cac4b92e0ee46ffb24655f4077e5875ad0aa9d84e5c0bb9d54edfca
|
|
BLAKE2b-256 checksum How to use checksums |
38313dd3c45c09143314be2a928ead38c1882610f284d3c149fd0b7fbcf7bff7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / zig_cc_python-0.1.0-py3-none-any.whl
| Download URL | zig_cc_python-0.1.0-py3-none-any.whl |
|---|---|
| Size | 5.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7d948d088065fc97d7a11f8dfaba62710641c5da79bcd1c4f777c743f9c4d5bd
|
|
BLAKE2b-256 checksum How to use checksums |
1611b5f694d039c46d49343f8f6178848449370426523384b6785a520855845e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for zig-cc-python 0.1.0
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.