Skip to main content

Build system generator - Makefile, CMake, and more.

Project description

buildgen

A zero-dependency[^1] build system generator package supporting Makefile, CMake, and cross-generator project definitions.

Originally inspired by prior work on shedskin.makefile in the shedskin project.

[^1]: uses an embedded lite version of Mako Templates

Installation

pip install buildgen

Quick Start

# Create a C++ project
buildgen new myapp

# Create a Python extension with pybind11
buildgen new myext -r py/pybind11

# List available recipes
buildgen list

Features

  • Makefile Generation: Programmatic Makefile creation with variables, pattern rules, conditionals
  • CMake Generation: Full CMakeLists.txt generation with find_package, FetchContent, install rules
  • Cross-Generator: Define project once in JSON/YAML, generate both build systems
  • CMake Frontend: Use CMake as build system with convenient Makefile frontend
  • Project Templates: Quick-start templates for common project types
  • scikit-build-core Templates: Python extension project scaffolding (pybind11, cython, nanobind, C)
  • Template Customization: Override templates per-project, per-user, or via environment variable (Mako syntax)

Usage

CLI

# Create projects from recipes
buildgen new myapp -r cpp/executable
buildgen new mylib -r c/static
buildgen new myext -r py/pybind11

# List available recipes
buildgen list

# Generate build files from a config file
buildgen generate --from project.json

# Test recipe generation and building
buildgen test --all

# Direct Makefile generation (advanced)
buildgen makefile generate -o Makefile --targets "all:main.o:"

# Direct CMake generation (advanced)
buildgen cmake generate -o CMakeLists.txt --project myapp --cxx-standard 17

Python API

from buildgen import ProjectConfig, TargetConfig, DependencyConfig

# Load from config file
config = ProjectConfig.load("project.json")
config.generate_all()  # Creates Makefile and CMakeLists.txt

# Or build programmatically
config = ProjectConfig(
    name="myproject",
    version="1.0.0",
    cxx_standard=17,
    compile_options=["-Wall", "-Wextra"],
    dependencies=[
        DependencyConfig(name="Threads"),
        DependencyConfig(
            name="fmt",
            git_repository="https://github.com/fmtlib/fmt.git",
            git_tag="10.1.1",
        ),
    ],
    targets=[
        TargetConfig(
            name="mylib",
            target_type="static",
            sources=["src/lib.cpp"],
            include_dirs=["include"],
        ),
        TargetConfig(
            name="myapp",
            target_type="executable",
            sources=["src/main.cpp"],
            link_libraries=["mylib", "fmt::fmt"],
            install=True,
        ),
    ],
)
config.generate_all()

CMake with Makefile Frontend

Generate CMake as the build system with a Makefile that wraps cmake commands:

config.generate_cmake_with_frontend(
    build_dir="build",
    build_type="Release",
)

This creates:

  • CMakeLists.txt - The actual build logic
  • Makefile - Convenience wrapper with targets:
make              # Configure and build
make build        # Same as above
make configure    # Run cmake configure only
make clean        # Remove build directory
make rebuild      # Clean and rebuild
make install      # Install the project
make test         # Run tests with ctest
make myapp        # Build specific target
make help         # Show available targets

# Override defaults
make BUILD_TYPE=Debug
make BUILD_DIR=cmake-build
make CMAKE_FLAGS="-DFOO=bar"

Project Configuration

JSON Format

{
    "name": "myproject",
    "version": "1.0.0",
    "cxx_standard": 17,
    "compile_options": ["-Wall", "-Wextra"],
    "dependencies": [
        "Threads",
        {"name": "OpenSSL", "required": true},
        {
            "name": "fmt",
            "git_repository": "https://github.com/fmtlib/fmt.git",
            "git_tag": "10.1.1"
        }
    ],
    "targets": [
        {
            "name": "mylib",
            "type": "static",
            "sources": ["src/lib.cpp"],
            "include_dirs": ["include"],
            "install": true
        },
        {
            "name": "myapp",
            "type": "executable",
            "sources": ["src/main.cpp"],
            "link_libraries": ["mylib", "Threads::Threads"],
            "install": true
        }
    ]
}

Project Recipes

Recipes use a category/variant naming convention:

buildgen list

C++ Recipes (CMake + Makefile frontend):

Recipe Description
cpp/executable Single executable
cpp/static Static library
cpp/shared Shared library (-fPIC)
cpp/header-only Header-only library
cpp/library-with-tests Library + tests
cpp/app-with-lib App with internal library
cpp/full Library + app + tests

C Recipes (CMake + Makefile frontend):

Recipe Description
c/executable Single executable
c/static Static library
c/shared Shared library (-fPIC)
c/header-only Header-only library
c/library-with-tests Library + tests
c/app-with-lib App with internal library
c/full Library + app + tests

Python Extension Recipes (scikit-build-core):

Recipe Description
py/pybind11 C++ extension using pybind11
py/nanobind C++ extension using nanobind
py/cython Extension using Cython
py/cext C extension (Python.h)

Python Extension Projects

Generate complete Python extension projects with scikit-build-core:

# Create a pybind11 extension project
buildgen new myext -r py/pybind11

# Use traditional virtualenv instead of uv
buildgen new myext -r py/pybind11 --env venv

This creates a complete project structure:

myext/
  pyproject.toml      # scikit-build-core configuration
  CMakeLists.txt      # CMake build instructions
  Makefile            # Convenience wrapper
  src/myext/
    __init__.py       # Python package
    _core.cpp         # C++ extension source
  tests/
    test_myext.py     # pytest tests

The generated Makefile provides convenient commands (using uv by default):

make sync     # Initial setup (uv sync)
make build    # Rebuild extension after code changes
make test     # Run tests (uv run pytest)
make wheel    # Build wheel distribution
make clean    # Remove build artifacts

For traditional virtualenv workflows, use --env venv to generate pip/python commands instead.

Template Customization

Templates can be customized without modifying buildgen. Override files are resolved in this order (first match wins):

  1. $BUILDGEN_TEMPLATES/{recipe}/ - Environment variable (for CI/CD)
  2. .buildgen/templates/{recipe}/ - Project-local overrides
  3. ~/.buildgen/templates/{recipe}/ - User-global defaults
  4. Built-in templates

Template Commands

# List available templates and show which have overrides
buildgen templates list

# Copy templates for local customization
buildgen templates copy py/pybind11

# Copy to global location for user-wide defaults
buildgen templates copy py/pybind11 --global

# Show where each template file is resolved from
buildgen templates show py/pybind11

Customizing Templates

  1. Copy the templates you want to customize:

    buildgen templates copy py/pybind11
    
  2. Edit the .mako files in .buildgen/templates/py/pybind11/:

    # Customize pyproject.toml template
    edit .buildgen/templates/py/pybind11/pyproject.toml.mako
    
  3. Generate projects - your customizations will be used:

    buildgen new myext -r py/pybind11
    

Templates use Mako syntax with ${variable} for substitution.

Per-File Overrides

You can override individual files while keeping others from built-in templates. For example, to customize only pyproject.toml:

mkdir -p .buildgen/templates/py/pybind11
cp $(buildgen templates show py/pybind11 | grep pyproject) .buildgen/templates/py/pybind11/
# Edit your local copy

Low-Level API

For fine-grained control, use the generators directly:

from buildgen import MakefileGenerator, CMakeListsGenerator

# Makefile
gen = MakefileGenerator("Makefile")
gen.add_cxxflags("-Wall", "-std=c++17")
gen.add_target("myapp", "$(CXX) $(CXXFLAGS) -o $@ $^", deps=["main.o"])
gen.add_pattern_rule("%.o", "%.cpp", "$(CXX) $(CXXFLAGS) -c $< -o $@")
gen.add_phony("all", "clean")
gen.generate()

# CMake
gen = CMakeListsGenerator("CMakeLists.txt")
gen.set_project("myapp", version="1.0.0")
gen.set_cxx_standard(17)
gen.add_find_package("Threads", required=True)
gen.add_executable("myapp", ["src/main.cpp"], link_libraries=["Threads::Threads"])
gen.generate()

Development

make test        # Run tests
make lint        # Run ruff check
make coverage    # Coverage report

Credits

  • Template rendering powered by an embedded version of Mako Templates (MIT License)
  • Originally inspired by prior work in shedskin.makefile in the shedskin project

License

GPL-3.0-or-later

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

buildgen-0.1.5.tar.gz (101.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

buildgen-0.1.5-py3-none-any.whl (154.5 kB view details)

Uploaded Python 3

File details

Details for the file buildgen-0.1.5.tar.gz.

File metadata

  • Download URL: buildgen-0.1.5.tar.gz
  • Upload date:
  • Size: 101.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for buildgen-0.1.5.tar.gz
Algorithm Hash digest
SHA256 11d223c2abc6b73216fbd96f0b3210287cabe029c7ded49352dc29798a4b66df
MD5 5c98bb15ca65284441822de8881d010a
BLAKE2b-256 3792cc8affc101ca470987dffc8cd8c0315703fe58f15364263fce959ab56e07

See more details on using hashes here.

File details

Details for the file buildgen-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: buildgen-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 154.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for buildgen-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 15a0b895562a95e419b0dc46a888ae7315af7467f498dbcfaf0f87aac94076cb
MD5 298076ef759ee4513280d4b85b1405c0
BLAKE2b-256 0e1707e4523c831a5275055408635d0b713a8ca508eb739d3d744cea20b26106

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page