pcons

Build anything. Effortlessly.

A modern, cross-platform, zero-install build system. Describe your builds in real Python. Generate Ninja files. Build fast.

PyPI version Python versions CI Docs
Read the Docs View on GitHub
$ uvx pcons

Why pcons?

Inspired by SCons and CMake, taking the best ideas from each.

Python is the language

No custom DSL to learn. Your build scripts are real Python with full IDE support, debugging, type checking, and the entire ecosystem at your fingertips.

Zero install

Run with uvx pcons — no installation required beyond uv. No daemon, no workspace lock files, no registry setup.

Fast builds via Ninja

Pcons generates Ninja build files and lets Ninja handle execution. Fast, parallel builds with minimal overhead. Also supports Makefile, Xcode, and MSVS output.

Transitive dependencies

Like CMake's usage requirements: include directories, link flags, and defines propagate automatically through your dependency graph.

Cross-platform

First-class support for Linux, macOS, and Windows. GCC, Clang, MSVC, Clang-CL, plus cross-compilation for Android, iOS, and WebAssembly.

Tool-agnostic core

The core knows nothing about compilers or languages. All tool-specific logic lives in pluggable toolchains. Build C++, Fortran, CUDA, Cython, Metal shaders, or anything else.

Simple and expressive

Real build scripts from the pcons examples.

pcons-build.py — Hello World
from pcons import Project, find_c_toolchain

project = Project("hello")
env = project.Environment(toolchain=find_c_toolchain())

project.Program("hello", env, sources=["src/hello.c"])

project.generate()
pcons-build.py — Libraries + Transitive Deps
from pcons import Project, find_c_toolchain

project = Project("myapp")
env = project.Environment(toolchain=find_c_toolchain())

# Build a static library
lib = project.StaticLibrary("core", env, sources=["src/core.c"])
lib.public.include_dirs.append("include")

# Program links the library — includes propagate
app = project.Program("myapp", env, sources=["src/main.c"])
app.link(lib)

project.generate()
Terminal
$ uvx pcons
Generating build/build.ninja...
Generating build/compile_commands.json...
$ ninja -C build
[3/3] Linking myapp

Built-in support

Toolchains, generators, and packages — all pluggable and extensible.

GCC Clang / LLVM MSVC Clang-CL CUDA Cython Fortran WASI Emscripten Metal

Generators

Ninja (default), Makefile, Xcode, compile_commands.json, and Mermaid dependency diagrams.

Package management

Integrates with pkg-config, Conan, and vcpkg. The pcons-fetch tool builds dependencies from source.

Configure-time checks

check_header(), check_flag(), try_compile(), configure_file() with CMake-style template substitution. Results are cached.

How it compares

pcons sits between Meson's ergonomics and Bazel's extensibility.

Feature pcons CMake Meson Bazel
Config language Python 3.11+ CMake DSL Custom DSL Starlark
Execution model Generates Ninja/Make/Xcode Generates Ninja/Make Generates Ninja/VS/Xcode Executes directly
Transitive deps Yes Yes Limited Yes
IDE support compile_commands.json compile_commands.json compile_commands.json External tools
Windows support Excellent Excellent Excellent Fair
Setup overhead uvx pcons Install CMake + generator pip/brew + Ninja Bazel + workspace setup
Learning curve Low (it's Python) High Low-Medium High
Extensibility Plugin registry CMake modules Limited Custom Starlark rules
Debuggability Full Python debugger message() / cmake --trace Print statements bazel query

Under active development

pcons is working in several medium-sized projects. Core C/C++/Fortran compilation, static and shared libraries, programs, install targets, installers, and mixed-language builds are all tested and working across Linux, macOS, and Windows.