| examples | ||
| include | ||
| src | ||
| tests | ||
| .gitignore | ||
| AI.md | ||
| bootstrap.ps1 | ||
| bootstrap.sh | ||
| build.toml | ||
| EXAMPLES.md | ||
| GUIDE.md | ||
| LICENSE.md | ||
| README.md | ||
| SPEC.md | ||
| STYLE.md | ||
Mako
A dead-simple build tool for C/C++ that just works.
No more wrestling with gnarly build configs. Drop in a minimal build.toml, run mako build, and you're shredding. Auto-discovers your source files, headers, and system libraries so you can focus on writing code instead of debugging Makefiles.
Heads up! Mako (v0.2.10) is production-ready for most C/C++ projects. It's been battle-tested on simple to medium codebases, self-hosts (builds itself!), and rocks solid incremental builds with content-hash caching. Still shaking out the kinks on macOS/Windows, but Linux is absolutely shredding. Stoked to have you try it out!
TL;DR
mako init → mako run → 🏄 You're surfing
Why Mako?
I like Makefiles, and there are rad projects like xmake, bazel, ninja... but they're all way too complex for my taste. I wanted something declarative that auto-discovers everything, like PHP's autoloader but for C++.
The vibe:
- Zero-config defaults (literally just
nameandlanguage) - Auto-discovers everything (sources, headers, includes, system libs, tests, examples)
- Crazy-fast incremental builds with content-hash caching (survives git operations!)
- npm-style scripts for custom build workflows
- Built-in dependency graphs (ASCII + interactive HTML)
- Embedded test framework (zero external deps)
- Auto-generates
compile_commands.jsonfor sick IDE integration - Works across platforms without platform-specific BS
No dependency graphs to maintain. No build scripts to debug. Just build.
Quick Start
Option 1: Interactive setup
mako init # Set up a new project (asks for name, language, etc.)
mako build # Build it
mako run # Run it
Option 2: Quick start with defaults
mako new my-project # Creates new directory with everything ready
cd my-project
mako build
mako run
Option 3: Manual setup
# build.toml
name = "myapp"
language = "c++17"
mako build
That's it. Mako will:
- Find all
.cppfiles insrc/ - Auto-detect
include/and add it to include paths - Discover headers from your
#includedirectives - Auto-link system libraries (pthread, math, etc.)
- Compile in parallel across all your cores
- Cache everything with content-hash validation (survives git checkout!)
- Generate
compile_commands.jsonfor IDE magic - Generate
.gitignoreand initialize git automatically
Output: build/bin/myapp ⚡
Installation
From Source (Bootstrap)
Mako builds itself. First-time setup:
Linux/macOS:
git clone <repository-url>
cd mako
./bootstrap.sh
Windows (PowerShell):
git clone <repository-url>
cd mako
powershell -ExecutionPolicy Bypass -File bootstrap.ps1
After bootstrap, rebuild with itself:
./build/mako build # Now at: build/bin/mako
Commands
Project setup:
mako init # Initialize project in current directory (interactive)
mako i # Short form
mako new <name> # Create new project directory (uses defaults)
mako n <name> # Short form
Building:
mako build # Build (incremental)
mako b # Short form
mako b -c # Clean build (rebuild everything)
mako b -q # Quiet mode
mako b -v # Verbose (show compiler commands)
Running:
mako run # Build and run main executable
mako r # Short form
mako run --test foo # Build and run tests/foo.cpp
mako run -t foo # Short form
mako run --example bar # Build and run examples/bar.cpp
mako run -e bar # Short form
Development:
mako clean # Remove build artifacts
mako clean --dry-run # Preview what would be deleted
mako watch # Watch files and auto-rebuild on changes
mako w # Short form
mako list [category] # List project components (sources, headers, libs, etc.)
mako graph [format] # Visualize dependencies (ascii or html)
mako script <name> # Run custom scripts from build.toml
Project Initialization Features
mako init - Interactive setup in current directory:
- Prompts for project name, language, and build mode
- Creates
build.toml,.gitignore,src/, andmain.cpp - Smart-merges
.gitignoreif it already exists - Skips creating files/directories that already exist
- Automatically runs
git initif git is available
mako new <name> - Quick project creation:
- Creates new directory with the project name
- Uses sensible defaults (c++17, executable mode)
- Generates complete project structure
- Perfect for starting new projects quickly
Both commands generate a comprehensive .gitignore that includes build artifacts, editor files, and OS-specific files.
Auto-Discovery Magic
Mako handles the boring stuff automatically:
🔍 Auto-Detected Directories
Common directories are automatically added to include paths:
include/,inc/,headers/(standard header locations)src/(headers alongside source)lib/,libs/(library headers)
This means clean includes:
#include "core/app.hpp" // ← No ugly ../../ paths!
#include "utils/logger.hpp" // ← Just works
📦 Auto-Discovered Libraries
Mako detects system libraries from your includes:
#include <pthread.h> // → Auto-links -lpthread
#include <cmath> // → Auto-links -lm (Unix/Linux)
Build output shows what it found:
Auto-discovered 2 system libraries: m, pthread
Supports: pthread, math, dl, rt, uring, OpenSSL, zlib, and more...
📁 Source Discovery
Recursively finds all source files in src/:
- C++:
.cpp,.cc,.cxx - C:
.c - Headers:
.h,.hpp(for dependency tracking)
⚡ Incremental Builds
Tracks source files, headers, object files, and config changes. Only rebuilds what changed. Typical incremental build: < 100ms.
🧪 Auto-Discovered Tests & Examples
Drop .cpp files in tests/ or examples/ and they're automatically available:
# Project structure:
# tests/test_parser.cpp
# tests/test_lexer.cpp
# examples/hello.cpp
mako run --test test_parser # Builds and runs tests/test_parser.cpp
mako run --example hello # Builds and runs examples/hello.cpp
The magic:
- Tests and examples automatically link against your main project sources
- No need to configure each one in
build.toml - Main's
main()function is excluded from linking (no conflicts) - Build outputs go to
build/tests/bin/andbuild/examples/bin/
Zero config required. Just drop files in tests/ or examples/ and run them.
Basic Config
Minimal (required):
name = "myapp"
language = "c++17" # c++20, c++17, c11, c99, etc.
Common settings:
source_dir = "src" # Default: "src"
build_dir = "build" # Default: "build"
threads = 8 # Default: all cores
optimization = "release" # 0, 1, 2, 3, debug, release, size, fast
warnings = "all" # all, basic, none, error
External libraries:
pkg_config = ["openssl", "zlib"] # System libs via pkg-config
link_libs = ["pthread", "m"] # Direct link (optional - auto-detected!)
lib_dirs = ["vendor", "third_party"] # Vendored libraries
Note: include/ is auto-detected! Only add include_dirs for non-standard directories:
include_dirs = ["third_party/custom"] # Additional only
See EXAMPLES.md for detailed configs and advanced usage.
Multiple Executables
Auto-discovered (easiest):
Files in tests/ and examples/ are automatically built and linked:
# Just drop files in tests/ or examples/
tests/test_parser.cpp
examples/demo.cpp
mako run --test test_parser # Automatically builds and runs
mako run --example demo # Automatically builds and runs
Manual config (for custom executables):
For executables outside tests/ and examples/, or with special needs:
name = "mylib"
language = "c++17"
[executables.benchmark]
source_dir = "benchmarks"
entry_point = "bench.cpp"
ldflags = ["-lpthread"]
Build all with one command:
mako build
# Outputs:
# build/bin/mylib
# build/tests/bin/test_parser (auto-discovered)
# build/examples/bin/demo (auto-discovered)
# build/benchmarks/bin/benchmark (manual config)
Automatic linking: All additional executables automatically link against your main project sources (excluding main.cpp to avoid conflicts).
More details: EXAMPLES.md
Library Mode
For header-only or library projects (no main executable):
mode = "library" # Skips building main executable
[executables.demo]
source_dir = "examples"
entry_point = "demo.cpp"
Compiles library sources, skips main executable, links them into your examples.
Details: EXAMPLES.md
Platform-Specific Config
Override settings per platform:
[linux]
compiler = "gcc"
link_libs = ["pthread", "dl"]
[darwin]
compiler = "clang"
[windows]
link_libs = ["ws2_32"]
Supported: linux, darwin, bsd, windows
IDE Integration
Mako automatically generates compile_commands.json on every build for seamless IDE/editor integration.
What you get:
- ✅ Autocomplete that actually works
- ✅ Go-to-definition across your codebase
- ✅ Real-time error checking
- ✅ Find references and refactoring tools
How to use:
Just build your project:
mako build
This creates compile_commands.json at your project root. Most editors detect it automatically.
Editor setup examples:
VS Code (with clangd extension):
// .vscode/settings.json
{
"clangd.arguments": ["--background-index"]
}
Neovim (with nvim-lspconfig):
require('lspconfig').clangd.setup{}
CLion/IntelliJ: Automatically detects compile_commands.json - no config needed!
The database includes ALL source files (even cached ones), so your IDE has complete project information from the first build. Incremental builds preserve and update entries automatically.
Development Workflow
Clean Command
Remove all build artifacts to start fresh:
mako clean
What gets removed:
- Build directory (respects your
build.tomlconfig) compile_commands.json
Use --dry-run to preview:
mako clean --dry-run
# Shows what would be deleted without removing anything
When to use:
- Before a clean rebuild
- To free up disk space
- When troubleshooting cache issues
- Before committing to version control
Watch Mode
Automatically rebuild on file changes. Perfect for development:
mako watch
What it does:
- Performs initial build
- Watches source directory recursively
- Detects changes to
.cpp,.c,.h,.hppfiles - Automatically triggers incremental rebuilds
- Continues even if build fails (shows errors and keeps watching)
- Stops gracefully with Ctrl+C
Example output:
Watch Mode =============================
Watching: src
Running initial build...
✓ Initial build complete!
Watching for changes... (Press Ctrl+C to stop)
src/main.cpp (modified)
Change detected, rebuilding...
✓ Build complete!
Smart features:
- Debouncing: Waits 200ms after last change to avoid excessive rebuilds
- Recursive: Automatically watches new subdirectories as they're created
- Filtered: Only watches relevant C/C++ source and header files
- Efficient: Uses platform-specific file watching APIs (inotify on Linux)
Platform support:
- ✅ Linux (inotify)
- ⚠️ macOS/BSD (planned - kqueue)
- ⚠️ Windows (planned - ReadDirectoryChangesW)
Features That Rock
✅ Content-hash caching - Rebuild only what actually changed (survives git operations!)
✅ Incremental builds - Rebuild in milliseconds, not minutes
✅ Parallel compilation - Uses all CPU cores by default
✅ Auto-discovery - Source files, headers, include paths, system libraries, tests, examples
✅ Automatic linking - Tests and examples auto-link to your project sources
✅ List command - Inspect project components (sources, headers, libs, executables)
✅ Dependency graphs - Visualize your codebase (ASCII terminal or interactive HTML)
✅ Custom scripts - npm-style script system for build workflows
✅ Run command - Build and execute with mako run --test or --example
✅ Watch mode - Auto-rebuild on file changes with smart debouncing
✅ Clean command - Remove build artifacts with dry-run preview
✅ IDE integration - Auto-generates compile_commands.json for LSP servers (clangd, ccls)
✅ Embedded test framework - Echo testing built-in (zero external dependencies)
✅ Cross-platform - Linux (battle-tested), macOS/BSD/Windows (code complete, needs testing)
✅ Zero dependencies - Self-contained, no external tools needed (even xxHash64 is embedded!)
✅ Self-hosting - Mako builds itself successfully
✅ Fast - Minimal TOML parser, optimized build pipeline
Platform Support
| Platform | Status | Compilers |
|---|---|---|
| Linux | ✅ Tested | gcc, clang |
| macOS | ⚠️ Needs testing | clang, gcc |
| FreeBSD | ⚠️ Needs testing | clang, gcc |
| Windows | ⚠️ Needs testing | gcc (MinGW), msvc |
Documentation
- EXAMPLES.md - Detailed configs, advanced features, complete examples
- build.toml - Annotated config with all options
Known Limitations
Mako is intentionally simple:
- ❌ No package manager (yet - vendor your deps or use pkg-config)
- ❌ No Windows/macOS/BSD testing yet (code complete, should work, needs validation)
- ⚠️ Simplified TOML parser (supports what we need, not full spec)
These might be features, depending on your perspective. Mako is for projects that just need compilation without ceremony. Need complex build logic? Use CMake. Just want to compile code? Mako's got you.
Contributing
Mako needs testing! If you:
- Try it on macOS, BSD, or Windows
- Find bugs or rough edges
- Have ideas for staying simple while adding value
Open an issue or PR! The goal is maximum simplicity with maximum utility.
FAQ
Q: Why another build system? A: Sometimes you just want to compile code without reading 200 pages of docs.
Q: Is it production ready? A: For Linux? Absolutely! Mako v0.2.10 is battle-tested, self-hosts, and rocks solid content-hash caching. For macOS/Windows? Code's there but needs testing. Use it for real projects on Linux, be the guinea pig for other platforms.
Q: Will it support [complex feature X]? A: Probably not. Simplicity is the goal. CMake exists for complex needs.
Q: Can I use it for [language X]? A: Only C/C++ for now. Might support others if it stays simple.