Scaffold and build Python C extensions with CMake and just-buildit.
Project description
Python C extensions the easy way.
just-makeit new scaffolds a complete, working C99 extension project in one
command: core C library, thin Python binding, CMake build system, and full test
coverage — no boilerplate to write.
Installation
pip install just-makeit
Quickstart
just-makeit new my_project --component engine --state gain:double:1.0
cd my_project && make && make test
What you get:
my_project/
├── native/
│ ├── inc/
│ │ ├── clib_common.h # common C99 types
│ │ ├── pyex_common.h # Python extension includes
│ │ └── engine/
│ │ └── engine_core.h # component API
│ ├── src/
│ │ └── engine/
│ │ ├── CMakeLists.txt
│ │ ├── engine_core.c # core logic — your algorithm goes here
│ │ └── engine_ext.c # thin Python binding
│ └── tests/
│ └── test_engine_core.c # CTest
├── src/my_project/
│ ├── __init__.py
│ ├── engine.pyi # type stub
│ └── tests/
│ └── test_engine.py # pytest / unittest
├── CMakeLists.txt
├── Makefile
├── pyproject.toml
└── just-makeit.toml
Commands
| Command | Description |
|---|---|
just-makeit new <project> [--component name] [--state ...] |
Create a new project (optionally with a first component) |
just-makeit init <component> [--state ...] |
Add a component to an existing project |
just-makeit add --state name:type[:default] [...] |
Add state variables to a component |
just-makeit config [key value] |
Show or edit project configuration |
just-makeit build [dir] |
Configure + build C, then package a wheel |
just-makeit test |
Build and run CTest + pytest |
just-makeit dry-run |
Preview what would be compiled |
State types: double, float, int. Default value is 0 for each type if omitted.
Both reset and the Python __init__ use the declared default — Engine() with no args is valid.
C conventions
Generated code follows a consistent lifecycle pattern:
// Constructor — parameters match your --state declarations
engine_state_t *engine_create(double gain);
// Destructor
void engine_destroy(engine_state_t *state);
// Reset — restores every variable to its declared default
void engine_reset(engine_state_t *state);
// Single sample (inlined, pass-through stub — implement your algorithm here)
static inline float complex
engine_step(const engine_state_t *state, float complex x);
// Block processor
void engine_steps(
engine_state_t *state,
const float complex *input,
float complex *output,
size_t n);
// Getter / setter for each --state variable
double engine_get_gain(const engine_state_t *state);
void engine_set_gain(engine_state_t *state, double gain);
Python API
from my_project import Engine
import numpy as np
obj = Engine(gain=1.0) # explicit
obj = Engine() # uses declared defaults
# single sample
y: complex = obj.step(1.0 + 0.5j)
# block processing
x = np.ones(1024, dtype=np.complex64)
y = obj.steps(x) # returns complex64 ndarray
# getters / setters
obj.get_gain()
obj.set_gain(2.0)
# reset restores declared defaults
obj.reset()
# context manager
with Engine() as e:
y = e.steps(x)
Multiple state variables
just-makeit new my_project \
--component engine \
--state center_freq:double:1000.0 \
--state bandwidth:double:200.0 \
--state order:int:4
Each --state name:type:default becomes a struct field, a constructor parameter
(optional in Python, required in C), getter/setter pair, and reset target — in
both C and Python.
Integrations
- CMake —
Python3_add_librarywithWITH_SOABI;.solands insrc/for zero-install dev workflow - GNU Make — convenience wrapper with
build,test, andjust-buildtargets - NumPy buffer protocol —
steps()accepts and returnscomplex64ndarrays - pytest — tests generated covering create, step, steps, getters/setters, reset, context manager, and destroy
- CTest — C-level test for the core lifecycle
- just-buildit — PEP 517 backend;
pip install .andpip install -e .work out of the box
Packaging
The generated project uses just-buildit as its PEP 517 build backend.
# Build and install
pip install .
# Development install (no rebuild needed after editing Python files)
pip install -e .
# Build a wheel manually
just-makeit build
Examples
See examples/gain/ for a complete generated project.
Requirements
- Python 3.11+
- CMake ≥ 3.16
- A C99 compiler (GCC, Clang, MSVC/MinGW)
- NumPy (runtime, for generated projects)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
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 just_makeit-0.1.1-py3-none-any.whl.
File metadata
- Download URL: just_makeit-0.1.1-py3-none-any.whl
- Upload date:
- Size: 22.4 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 |
08d47a34a0a23fa527893a4e206fcf1cce4965102ba6fdf4a846761daa085908
|
|
| MD5 |
035c7ee85ed5b76147d15e8285e7abe4
|
|
| BLAKE2b-256 |
b3a416e857d33a1de057f4456e610d03a91810c725cfd5bed56d8dde90918da2
|
Provenance
The following attestation bundles were made for just_makeit-0.1.1-py3-none-any.whl:
Publisher:
release.yml on just-buildit/just-makeit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
just_makeit-0.1.1-py3-none-any.whl -
Subject digest:
08d47a34a0a23fa527893a4e206fcf1cce4965102ba6fdf4a846761daa085908 - Sigstore transparency entry: 1449661224
- Sigstore integration time:
-
Permalink:
just-buildit/just-makeit@1893eec3f7f10f294114d4ec077c0660914688a0 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/just-buildit
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1893eec3f7f10f294114d4ec077c0660914688a0 -
Trigger Event:
push
-
Statement type: