Skip to main content

Pcons

A modern open-source cross-platform zero-install Python-based build system. Builds anything that requires a repeatable workflow, using a dependency graph. Easy to use, reliable and quick. Uses Ninja (or Makefile, XCode, or MSVS) to do the builds. Optimized for C/C++, Fortran, CUDA, wasm etc. but should work for anything that needs building.

CI codecov PyPI PyPI Downloads Python Doc Status

Overview

Pcons is inspired by SCons and CMake, taking a few of the best ideas from each:

  • From SCons: Environments, Tools, dependency tracking, Python as the configuration language
  • From CMake: Generator architecture (configure once, build fast), usage requirements that propagate through dependencies

Key design principles:

  • Configuration, not execution: Pcons generates Ninja files; Ninja executes the build
  • Python is the language: No custom DSL—build scripts are real Python with full IDE support
  • Language-agnostic: Build C++, Rust, LaTeX, protobuf, or anything else
  • Explicit over implicit: Dependencies are discoverable and traceable
  • Extensible: Add-on modules for domain-specific tasks (plugin bundles, SDK configuration, etc.)

Language and OS Support

Pcons currently supports C and C++, ObjC and C++, Swift, Fortran, CUDA, assembly, WASM (Emscripten/WASI), LaTeX, Python native extensions, and Rust (via integration). The list is always growing, and it's easy to create your own tools. All built-in tools work on Mac, Windows and Linux. It has cross-compile presets for Android NDK and iOS.

Pcons can build not just executables, but also tar/zip archives, python packages, Windows installers, and MacOS installer packages.

What's in the box

  • Qt 6: find_qt(), automoc/autouic/autorcc, QML modules, translations, and ninja deploy
  • C++20 modules: named modules, partitions, and import std on GCC, Clang and MSVC, with automatic dependency scanning
  • Tests and fuzzing: project.Test(), pcons test, gtest/doctest/Catch2 case discovery, JUnit XML, libFuzzer/AFL++
  • Compiler caching: env.use_compiler_cache(), or run any command behind a launcher
  • pcons --watch: rebuilds on every save, including edits to the build script itself
  • Configure checks: check_header(), check_flag(), try_compile(), configure_file(), all cached
  • Generated sources: code generators and multi-phase builds; if a generated file didn't change, its consumers don't rebuild
  • Installers: signed and notarized .pkg and .dmg, MSIX packages, WinSxS assemblies
  • Cross-compilation: presets for Android NDK, iOS, and WebAssembly (WASI and Emscripten)
  • compile_commands.json: for clangd and friends; it always reports the real compiler
  • env.explain(): where did this flag come from? Every flag, traced back to the preset that set it

Why another software build tool?

I was one of the original developers of SCons, and helped maintain it for many years. I love that python is the config language; that makes build descriptions incredibly flexible and powerful. Recently I've been using CMake for more projects, and despite the deeply painful configuration language, I've come to appreciate its power: conan integration, the separation between describing the build andrunning it, and dependency propagation, among other things. I feel that SCons hasn't kept up with modern python; like any very widely used mature project, it has a lot of accumulated wisdom but also a bit ossified ways of doing things.

I've been thinking for years now about rearchitecting SCons onto a modern python stack with Path and decorators and all the other wonderful stuff python has been doing, and fixing some of the pain points at the same time (substitution/quoting, extensibility, tracing, separation between description and building, and more), but I've never had the time to dig into it. But recently as I've been using a lot more of Claude Code as a programming assistant, and it has gotten significantly better, it seemed like the right time to try this as a collaborative project. So, meet pcons!

Here's a comparison between pcons and other common modern build tools. I think pcons fills a real need, for a general-purpose broadly applicable extensible software build tool using a modern well-known language to describe builds and tools.

Status

✅ Ready for small-scale production use - and still under active development, so feedback is very welcome. It's working in several medium-sized projects.

Core functionality is working and well tested across Linux, macOS and Windows, on every commit: C/C++/ObjC/Fortran/Swift/CUDA compilation, C++20 modules, Qt 6, static and shared libraries, install targets, installers, cross-compilation, and mixed-language builds. There are 66 self-contained examples, and every one is built and verified in CI. See ARCHITECTURE.md for design details.

Rust / Go interop

pcons links Rust crates into C/C++ projects: project.CargoBuild() drives cargo build and links the resulting library, with optional cbindgen header generation. See examples/43_rust_cxx_hybrid (hand-written FFI header) and examples/44_rust_cxx_cbindgen (cbindgen-generated header). Go support is straightforward to add on the same pattern — open an issue if you'd like it.

Quick Start

Already have C or C++ sources? pcons init reads them and writes the build script for you:

cd myproject
uvx pcons init    # writes pcons-build.py from the sources it finds
uvx pcons         # generate build.ninja and build

Quick Example

Or write it yourself; it's ordinary Python:

# pcons-build.py
from pcons import Project

project = Project("myapp")
env = project.Environment(toolchain="c")
env.cc.flags.extend(["-Wall"])

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

# Build a program that links the library
app = project.Program("myapp", env, sources=["src/main.c"])
app.private.link_libs.append(lib)
uvx pcons # generate build.ninja and run it, producing build/myapp (or build/myapp.exe)

Installation

No installation needed, if you have uv; just use uvx pcons to configure and build. uvx pcons --help for more info. If you want to install it, though:

# Install as a CLI tool (recommended)
uv tool install pcons
pcons ...

# Or add to a project's dependencies
uv add pcons

# Or with pip
pip install pcons

Once installed, pcons completion install sets up tab completion for bash, zsh or fish. See the command-line reference.

Using the development version

To try the latest development version straight from GitHub:

# Run without installing
uvx --from git+https://github.com/DarkStarSystems/pcons pcons

# Install as a CLI tool
uv tool install git+https://github.com/DarkStarSystems/pcons

# Or with pip
pip install git+https://github.com/DarkStarSystems/pcons

Verifying Release Signatures

Release artifacts on the GitHub Releases page are signed with Sigstore using short-lived certificates issued via GitHub Actions OIDC; transparency-log records are stored at rekor.sigstore.dev. Each .tar.gz and .whl has a matching .sigstore.json bundle. To verify with cosign:

cosign verify-blob \
  pcons-x.y.z.tar.gz \
  --bundle pcons-x.y.z.tar.gz.sigstore.json \
  --new-bundle-format \
  --certificate-identity-regexp='https://github.com/DarkStarSystems/pcons/.*' \
  --certificate-oidc-issuer='https://token.actions.githubusercontent.com'

Documentation

Development

# Run tests
uv run pytest

# Run linter
make lint

# Format code
make fmt

# Or use uv directly
uv run ruff check pcons/
uvx ty check pcons/ examples/

# Use your local checkout to build a project (uv run inside the repo,
# or point uvx/uv tool at the checkout from anywhere)
uv run pcons                                # inside this repo
uvx --from ~/src/pcons pcons                # one-off, from any project dir
uvx --refresh --from ~/src/pcons pcons      # ...rebuilding uv's cached wheel
uv tool install -e ~/src/pcons             # install the checkout, editable

This Project is AI-Assisted

PCons is my long-term vision for a modern build tool. I've used Claude Code extensively to assist in creating this project, mostly Claude Opus 4.6. It has been a huge help in realizing the vision I've had for a long time. If you reflexively or morally reject all AI-generated or AI-assisted code, pcons is not for you. That said, I've reviewed every decision and nearly every line, and this code reflects my vision, my architecture, my goals and my priorities. I take full responsibility for it, and as a professional software engineer with 40+ years of C/C++/python experience I stand behind it. I also intend to support it long-term.

One of my sub-goals has been to make sure the documentation and source organization is clear; not just for humans but for browsing by AI agents. I want to make it easy for a human or an AI agent to create a best-practices pcons-build.py for your project quickly and easily. Using AI to auto-generate doc and making sure APIs are clean and consistent helps with that goal.

License

MIT License - see LICENSE

Metadata

Release files for pcons 0.30.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pcons 0.30.0
File Size Uploaded
pcons-0.30.0.tar.gz 4.1 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for pcons 0.30.0
File Interpreter ABI Platform
pcons-0.30.0-py3-none-any.whl Python 3 none any Details

Total release size: 4.8 MB

Release files / pcons-0.30.0.tar.gz

Download URL pcons-0.30.0.tar.gz
Size 4.1 MB
Tags Source
SHA-256 checksum
How to use checksums
41963896c38fb1bfef79f16aad7cb997f9a994467a38785572076a659907d045
BLAKE2b-256 checksum
How to use checksums
6286568fef5bd7320673b91f20e1a918f18d36fc159e59acfe0b56af925cb5fe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / pcons-0.30.0-py3-none-any.whl

Download URL pcons-0.30.0-py3-none-any.whl
Size 749.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f34c8c3a16f77d677b732fedbd3f72b76833a7df3d0cdb9a35c06627cae2ab0e
BLAKE2b-256 checksum
How to use checksums
ca96c1d60498b3a5a77fc6eb0840a19037cbd15e2bd18e5dbaa51b77190b7005
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release history Release notifications | RSS feed

This release

0.30.0 This release

2 release files

0.29.1

2 release files

0.29.0

2 release files

0.28.0

2 release files

0.27.0

2 release files

0.24.0

2 release files

0.23.1

2 release files

0.23.0

2 release files

0.22.0

2 release files

0.20.1

2 release files

0.20.0

2 release files

0.18.0

2 release files

0.17.0

2 release files

0.14.1

2 release files

0.14.0

2 release files

0.9.0

2 release files

0.8.4

2 release files

0.8.3

2 release files

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.0

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

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