# mcpp
> A modern C++ module-first build tool — written in pure C++23 modules, fully self-hosted
**English** | [简体中文](README.zh-CN.md)
[](https://github.com/mcpp-community/mcpp/releases)
[](https://en.cppreference.com/w/cpp/23)
[](https://en.cppreference.com/w/cpp/language/modules)
[](LICENSE)
[](https://github.com/mcpp-community/mcpp/actions/workflows/ci.yml)
| [Documentation](docs/) · [Getting Started](docs/01-getting-started.md) · [mcpp.toml Guide](docs/04-mcpp-toml.md) · [Examples](docs/03-examples.md) · [Toolchains](docs/20-toolchains.md) |
|:---:|
| [Package index mcpp-index](https://mcpplibs.github.io/mcpp-index/) · [Module libraries mcpplibs](https://github.com/mcpplibs) · [Community Forum](https://forum.d2learn.org/category/20) · [Issues](https://github.com/mcpp-community/mcpp/issues) · [Releases](https://github.com/mcpp-community/mcpp/releases) |
| Plugins · [mcpp-language-server (mcppls)](https://github.com/Sunrisepeak/mcpp-language-server) — a C++20/23 modules language server |
## Highlights
- **Modular build system** — C++ modules first: `import std` handled automatically, file-level incremental builds, automatic dependency analysis, nothing to configure
- **Build plugins and heterogeneous hardware** — `build.mcpp` and rule packages extend the build; CUDA, HIP, SYCL, Vulkan/SPIR-V and Ascend C are each a rule package
- **Package management and a module-library ecosystem** — SemVer constraints, lockfile, cross-project BMI cache, custom indices; a library from [mcpplibs](https://github.com/mcpplibs) is two lines away from `import`
- **Toolchain management and cross-compilation** — `family@version` installed on demand; `--target` moves the same build to Windows, macOS, Cortex-M or RISC-V bare metal, and one source tree reaches several hosted targets over openkal
- **Environment and runtime** — the user-space environment xlings provides: toolchains and dependencies stay in an isolated sandbox, and a runner puts the artifact on a board or an emulator
- **Pure modular self-hosting** — mcpp is written entirely in C++23 module interface units and builds itself
## Why mcpp
mcpp is built specifically for **C++23 module-first development**. If you want to use `import std`, module interface units (`.cppm`), module partitions, and other modern C++ features in your project, mcpp gives you a smooth, friendly experience on Linux, macOS ARM64, and Windows x86_64.
C++ normally spreads these five jobs across five tools, and mcpp is one command
for all five. The second row names what each column is usually recognised as.
| mcpp | build system | build plugins | package manager | toolchain manager | environment and runtime |
|---|---|---|---|---|---|
| **closest to** | CMake + Ninja | CMake modules, xmake rules | vcpkg, Conan | rustup, nvm | conda, Nix |
> [!NOTE]
> **Early-stage project** — mcpp is under active development; interfaces and behavior may change in future releases.
> Developers interested in modern C++ module-first build tooling are welcome to [contribute](#contributing).
> Questions / feedback / ideas — drop a note in [issues](https://github.com/mcpp-community/mcpp/issues).
## Getting Started
### Install
**Install via xlings** (recommended)
```bash
xlings install mcpp -y
```
Don't have xlings yet? Click for the install command
**Linux / macOS**
```bash
curl -fsSL https://d2learn.org/xlings-install.sh | bash
```
**Windows — PowerShell**
```powershell
irm https://d2learn.org/xlings-install.ps1.txt | iex
```
> More about xlings → [xlings.d2learn.org](https://xlings.d2learn.org)
Optional — short commands (mp, mbuild, mrun, …)
```bash
xlings install mcpp-short-cmd -y
```
Registers 30 shims, so `mcpp build` becomes `mbuild`. Naming rule: initial of
every word but the last, plus the last word in full — `mcpp self doctor` →
`msdoctor`. `mp` is bare `mcpp`. They alias the `mcpp` shim rather than a fixed
binary, so `xlings use mcpp ` switches them too.
| Short | Expands to | Short | Expands to |
| --- | --- | --- | --- |
| `mp` | `mcpp` | `mexpkg` | `mcpp emit xpkg` |
| `mnew` | `mcpp new` | `mxparse` | `mcpp xpkg parse` |
| `mbuild` | `mcpp build` | `mtinstall` | `mcpp toolchain install` |
| `mrun` | `mcpp run` | `mtlist` | `mcpp toolchain list` |
| `mtest` | `mcpp test` | `mtdefault` | `mcpp toolchain default` |
| `mclean` | `mcpp clean` | `mcdir` | `mcpp cache dir` |
| `madd` | `mcpp add` | `mclist` | `mcpp cache list` |
| `mremove` | `mcpp remove` | `mcinfo` | `mcpp cache info` |
| `mupdate` | `mcpp update` | `mcgc` | `mcpp cache gc` |
| `msearch` | `mcpp search` | `milist` | `mcpp index list` |
| `mpublish` | `mcpp publish` | `miadd` | `mcpp index add` |
| `mpack` | `mcpp pack` | `miremove` | `mcpp index remove` |
| `msdoctor` | `mcpp self doctor` | `miupdate` | `mcpp index update` |
| `msenv` | `mcpp self env` | `msconfig` | `mcpp self config` |
| `msversion` | `mcpp self version` | `msexplain` | `mcpp self explain` |
**Other options**
Option 1 — one-line installer (Linux x86_64/aarch64, macOS ARM64)
```bash
curl -fsSL https://github.com/mcpp-community/mcpp/releases/latest/download/install.sh | bash
```
This installer does not support Windows; use the PowerShell xlings route above.
It installs into `~/.mcpp/` and adds it to your shell PATH. Deleting `~/.mcpp`
uninstalls cleanly.
Option 2 — Homebrew (macOS / Linux)
```bash
brew install mcpp-community/mcpp/mcpp-m
```
One command — it taps [`mcpp-community/homebrew-mcpp`](https://github.com/mcpp-community/homebrew-mcpp)
and installs the same prebuilt release binary. macOS needs Apple silicon +
macOS 14; per-user data lives in `~/.mcpp/`.
Homebrew's `mcpp` is an unrelated C preprocessor, hence the `mcpp-m` formula
name — the command it installs is still `mcpp`.
**Homebrew 6 gates third-party taps.** The fully-qualified command above is
read as explicit intent and works as-is, but every *other* spelling — the short
`brew install mcpp-m`, the `mcpp` alias, and later upgrades — is refused with:
```
Refusing to load formula mcpp-community/mcpp/mcpp-m from untrusted tap
mcpp-community/mcpp.
```
Trust the tap once and all of them work:
```bash
brew trust mcpp-community/mcpp
```
Option 3 — Arch Linux (AUR)
```bash
yay -S mcpp-bin # prebuilt release binary
yay -S mcpp-m # or build from source (bootstrapped with mcpp-bin)
```
Installs the `mcpp` command system-wide; per-user data still lives in `~/.mcpp/`.
On Arch the name `mcpp` is an unrelated C preprocessor, so the packages are
`mcpp-bin` / `mcpp-m` (see [`tools/aur/`](tools/aur/)).
Stable-release automation reconciles `mcpp-bin` only; `mcpp-m` and `mcpp-git`
remain manually maintained and may intentionally lag.
Option 4 — pip (PyPI)
```bash
pip install mcpp-bin
```
Installs the `mcpp` command into the active Python environment; `pipx install
mcpp-bin` gives it an environment of its own. The wheels carry the same
prebuilt release binary for Linux x86_64 / aarch64, macOS 14+ on Apple silicon
and Windows x86_64. Per-user data still lives in `~/.mcpp/`, outside the Python
environment. On PyPI the name `mcpp` belongs to an unrelated project, hence
`mcpp-bin` (see [`tools/pypi/`](tools/pypi/)).
Option 5 — Nix (flake)
```bash
nix run github:mcpp-community/nix-mcpp -- --version # try it
nix profile install github:mcpp-community/nix-mcpp # install it
```
The flake in [`mcpp-community/nix-mcpp`](https://github.com/mcpp-community/nix-mcpp)
packages the same prebuilt release binary for Linux x86_64 / aarch64 and macOS
on Apple silicon, and follows each stable release. Its overlay adds
`pkgs.mcpp-bin`: nixpkgs' `mcpp` is an unrelated C preprocessor. Per-user data
still lives in `~/.mcpp/`.
Option 6 — let an AI assistant install it for you
Copy the following prompt to your AI coding assistant (Claude Code / Cursor / Copilot, etc.):
```
Read the README of https://github.com/mcpp-community/mcpp,
then install mcpp for me and create a C++23 module project, build and run it.
The repo's .agents/skills/mcpp-usage/SKILL.md has a detailed usage guide.
```
### Create, build & run a project
```bash
mcpp new hello
cd hello
mcpp build
mcpp run
```
> Note: the first build initializes the environment and fetches the toolchain, which may take a while.
### Project layout
```
hello/
├── mcpp.toml ← project manifest
├── src/
│ └── main.cpp ← import std; works directly
└── tests/
└── test_smoke.cpp ← discovered by `mcpp test`
```
```toml
# mcpp.toml
[package]
name = "hello"
version = "0.1.0"
description = "A modular C++23 package"
license = "Apache-2.0"
```
The built-in scaffold relies on convention: it does not write `[targets.hello]`.
`src/main.cpp` infers the binary target, and `mcpp test` automatically discovers
`tests/test_smoke.cpp`.
### Using module libraries
Add a two-line dependency to `mcpp.toml` to pull in a community module library from [mcpplibs](https://github.com/mcpplibs):
```toml
[dependencies]
cmdline = "0.0.2"
```
Then `import` it directly in your code:
```cpp
import mcpplibs.cmdline;
```
> For more dependency options (version constraints, namespaces, Git references, local paths, etc.), see the [mcpp.toml guide — dependency management](docs/04-mcpp-toml.md).
## Feature Overview
Build system
- Native C++20/23/26 module support (interface units, implementation units, module partitions), plus `c++latest` / `c++fly` experimental modes
- Fully automatic precompilation and caching of `import std` / `import std.compat`
- Three-layer incremental optimization: front-end dirty check + per-file P1689 dyndep + BMI copy-if-different restat
- Fingerprinted BMI cache: hashed by compiler/flags/standard library, shared across projects
- Ninja backend: auto-generated build.ninja, parallel compilation
- `compile_commands.json` generated automatically (ready for clangd / ccls); use
`mcpp build --configure-only` to refresh it before ordinary sources compile
- First-class C support: `.c` files auto-detected, mixed C/C++ projects
- User-defined cflags / cxxflags / ldflags / c_standard
Toolchain management
- Bundled GCC 16.1.0 + LLVM/Clang 20.1.7, one-command install
- Host-aware defaults: native glibc GCC on Linux x86_64, native glibc LLVM on Linux aarch64, musl GCC on other Linux architectures, LLVM on macOS and on Windows with usable MSVC, MinGW-w64 GCC on bare Windows
- Multiple versions side by side: `mcpp toolchain install gcc 16` / `mcpp toolchain install llvm 20`
- Isolated sandbox: all toolchains live in `~/.mcpp/registry/`, leaving the system untouched
- Per-platform selection: `linux = "gcc@16"`, `macos = "llvm@20"`
- GCC and Clang compile pipelines at parity (driven by the `BmiTraits` abstraction layer)
Cross-compilation, bare metal and devices
- `mcpp build --target ` — one flag; the toolchain payload for that target is resolved and installed automatically
- Targets from `x86_64-linux-gnu` to Cortex-M, Cortex-A and RISC-V bare metal; the full table is under [Platform Support](#platform-support)
- Freestanding targets carry no operating system: the C library, startup code, memory layout and emulator travel with a board-support package rather than with mcpp
- Runners reach an artifact that cannot run on the build machine — `mcpp run --runner flash`, `--list-runners`, `mcpp why runners`
- `mcpp new --template riscv-virt-rt` — a board template a package ships, instantiated by name
- Cross-compilation over openkal: a portable program builds for a target whose kernel interface and C library come from packages
Heterogeneous builds and accelerators
- `[build] accel = "cuda12.9+{sm_89}, vulkan1.2"` — a build names one or more device backends, and `cfg(accelerator = "cuda")` is true in that build
- Five programming models have rule packages today: CUDA, HIP, SYCL, Vulkan/SPIR-V and Ascend C
- Device translation units are compiled by their own compiler and join the ordinary link; the host/device boundary is generated rather than written twice
- A constrained glob selects device sources: `{ glob = "src/kernels/**/*.cu", accel = "cuda12.9+{sm_89}" }`
- Nothing in the engine holds a vendor name, so a sixth backend is a package rather than an engine change
Package & dependency management
- SemVer constraint resolution: `^`, `~`, ranges, exact versions
- Three-stage resolution: constraint merging → multi-version mangling fallback → exact match
- Lockfile mcpp.lock (v2 format: index snapshot + namespaces)
- Namespace system: `[dependencies.myteam] foo = "1.0"`
- Custom package indices: `[indices] acme = "git@..."` / `{ path = "..." }`
- Project-level index isolation (`.mcpp/` directory, no global pollution)
- Dependency sources: index / Git / local path
Workspaces
- `[workspace] members = ["libs/*", "apps/*"]`
- Unified lockfile + unified target directory
- Centralized version management: `[workspace.dependencies]` + `.workspace = true`
- Selective builds: `mcpp build -p member-name`
- Config inheritance: toolchains, build flags, and indices cascade from root to members
Packaging & publishing
- `mcpp pack`: four Linux release modes — system / vendored (default) / self-contained / static; `bundle-project` and `bundle-all` remain compatibility aliases
- Fully static musl binaries: single-file distribution, no glibc dependency (matching Linux x86_64 or aarch64 target)
- `mcpp publish`: generates xpkg.lua + publishes to a package index
- Automatic RPATH fix-up via patchelf (Linux)
Extending the build
- `build.mcpp` — a build program for a step mcpp has no rule for, speaking a directive protocol that is versioned rather than guessed
- `mcpp::action` declares work with explicit inputs and outputs, so a generated file takes part in the incremental graph instead of sitting outside it
- A rule package carries that step to other projects: it declares a rule module, and a consumer selects it as a feature
- Payloads, runtime adapters and board-support packages are ordinary packages — a tool, a driver or a board is installed by the resolver that installs a library
Developer experience
- `mcpp new` — create a modular project; `--template [ns.]name[@version][:tname]` uses a **package-provided template** with the same exact identity style as `mcpp add`. A sole template is the default even without `default = true`; `--list-templates [ns.]name[@version]` lists ambiguous sets
- `mcpp run [-- args]` — build and run
- `mcpp test [pattern] [-- args]` — auto-discover and run tests (filter by name; `--list`, `--timeout `, `--message-format json`)
- `mcpp search` — search package indices
- `mcpp add / remove / update` — dependency management
- Profiles and features on the command line: `--release` / `--profile ` on `build` and `run`, `--features ` on `build`, `run` and `test`
- `mcpp why [toolchain|runtime|deps|runners]` — explain resolved build decisions; `--format json` for a machine reader
- `mcpp emit sbom` — a CycloneDX bill of materials for the resolution just recorded
- `mcpp --offline` / `MCPP_OFFLINE=1` — use only already available local state
- `mcpp explain E0001` — detailed error-code explanations
- `mcpp self doctor` — environment self-diagnosis
## Benchmark
Building **mcpp itself** — 137 module interface units and 57k lines at the
pinned workload, every one of them `import std;` — with four engines handed the
**same compiler binary**. Each cell is the median of **3 samples** and how many
times faster it is than cmake. Every column comes from **one run**.
| scenario | `mcpp` | `mcpp +opt` | `mcpp (old)` | `cmake` | `xmake` |
|---|---|---|---|---|---|
| `cold` | 86.69s · 1.1x | **35.73s · 2.6x** | 86.75s · 1.1x | 91.74s · 1.0x | 90.54s · 1.0x |
| `noop` | **0.16s · 2.0x** | 0.18s · 1.8x | 0.24s · 1.3x | 0.32s · 1.0x | 0.38s · 0.8x |
| `touch-hub` | **0.42s · 197.7x** | 0.42s · 197.2x | 81.72s · 1.0x | 83.21s · 1.0x | 82.48s · 1.0x |
| `edit-body` | 80.87s · 1.1x | **29.83s · 2.9x** | 81.19s · 1.1x | 85.30s · 1.0x | 84.33s · 1.0x |
| `edit-comment` | **0.40s · 207.0x** | **0.40s · 207.0x** | 79.11s · 1.1x | 83.21s · 1.0x | 82.15s · 1.0x |
`cold` nothing built yet · `noop` nothing at all · `touch-hub` mtime only, content unchanged · `edit-body` a real edit inside a function body · `edit-comment` a comment added to a hub interface.
`mcpp` = mcpp@2026.8.13.1, the build under test · `mcpp +opt` = the SAME binary as `mcpp`, with the opt-in key `[build] bmi_schedule = "on"` (off by default) · `mcpp (old)` = mcpp@2026.8.11.3, the previously published release.
Linux x86_64 · i9-13900K · gcc 16.1.0 · n=3 · pinned workload `a749e9f` ·
cmake 4.4.2 / xmake 3.1.0 · min/max sit within 4% of every median above 1s ·
data: [`standard-20260814-linux-x86_64`](bench/results/standard-20260814-linux-x86_64/).
* **Cascade suppression accounts for the `touch-hub` and `edit-comment` rows.**
cmake and xmake decide by timestamp and rebuild every downstream unit; mcpp
compares the BMI the compiler has just produced against the previous one and
skips the cascade when the interface is unchanged. This is default behaviour
and requires no configuration. `mcpp (old)` measures the previous release at
81.72s, level with cmake, so the effect is new in this revision.
* **`edit-body` is the control, and mcpp is deliberately not fast on it.** The
perturbation inserts a statement into an interface unit, which moves the
source positions GCC records, so the BMI changes and every importer is owed a
rebuild — an engine that were fast on that row would be skipping work it owes.
Whether an edit owes a cascade depends on where the body lives: an in-place
edit of the same length, or a body in a separate `.cpp`, owes none and lands
near the 200x rows. Measured in
[`.agents/docs/2026-08-15-module-edit-granularity.md`](.agents/docs/2026-08-15-module-edit-granularity.md).
* **`bmi_schedule` is opt-in and disabled by default** (`auto` resolves to off).
It moves code generation off the critical path, so it pays only where a
cascade is owed — `cold` 86.69s → 35.73s, `edit-body` 80.87s → 29.83s, and
nothing on the two rows mcpp already skips. An incorrect scheduling change
fails silently rather than loudly, so the default is not changed on the
evidence of a single machine.
**[Methodology, pinned versions, and the full data →
`bench/README.md`](bench/README.md)** · [简体中文](bench/README.zh-CN.md)
## Platform Support
mcpp's identity model has two orthogonal axes: a **toolchain** is
`family@version` (family ∈ gcc | llvm | msvc), a **target** is a triple
`arch-os[-env]`. Cross-compiling is just `mcpp build --target ` —
the right toolchain payload is resolved and installed automatically.
`mcpp toolchain list` shows live status on your machine.
**Hosts** (where mcpp itself runs): Linux x86_64 / aarch64, macOS arm64, Windows x86_64.
**Targets** (what `--target` accepts; the rows and their tiers are the ones in
`modules/toolchain-model/src/triple.cppm`, which is also what `mcpp toolchain
list` reports for this machine):
| Target | Convention toolchain | Tier |
|---|---|:---:|
| `x86_64-linux-gnu` | gcc *(Linux default)* or llvm | verified |
| `x86_64-linux-musl` | gcc 16, fully static | verified |
| `aarch64-linux-musl` | gcc 16, fully static — cross from x86_64 (qemu) or native | verified |
| `x86_64-windows-gnu` | gcc 16 MinGW-w64 — native on Windows, cross from Linux (wine) *(Windows default without Visual Studio)* | verified |
| `x86_64-windows-msvc` | `msvc@system` (detected VS/BuildTools) or llvm ¹ *(Windows default with Visual Studio)* | verified |
| `x86_64-windows-musl` | llvm 23 — a PE with a musl C library, which no gcc emits; the system comes from the dependency graph | preview |
| `aarch64-macos` | llvm *(macOS default)* | verified |
| `riscv64-none-elf` · `riscv32-none-elf` | llvm 23 — bare metal, `xim:picolibc-riscv` ² | verified |
| `thumbv6m-none-eabi` · `thumbv7m-none-eabi` | llvm 23 — Cortex-M0/M0+/M1, Cortex-M3 ² | verified |
| `thumbv7em-none-eabihf` · `thumbv8m.main-none-eabi` | llvm 23 — Cortex-M4F/M7F hard float, Cortex-M33/M55 soft float ² | verified |
| `armv7a-none-eabi` · `armv7a-none-eabihf` | llvm 23 — Cortex-A 32-bit, the first row with an MMU ² | verified |
| `aarch64-none-elf` · `x86_64-none-elf` | llvm 23 — bare metal, no C library by default ² | preview |
| `thumbv7em-none-eabi` · `thumbv8m.base-none-eabi` · `thumbv8m.main-none-eabihf` | llvm 23 — Cortex-M4/M7 soft float, M23, M33F/M55F ² | preview |
| `aarch64-linux-gnu` | `llvm@23.1.3` | preview |
| `riscv64-linux-musl` · `x86_64-macos` | — | planned |
| `wasm32-emscripten` | `emsdk@6.0.9` — Emscripten ships its own sysroot and its own libc++ module surface; `mcpp run` executes the module with the `node` the payload declares (`xim:node`), not one found on PATH | verified |
| `x86_64-linux-android` | `android-ndk@30.0.16248370` — bionic from the NDK, one payload for both ABIs; ran on an API 24 x86_64 emulator image | verified |
| `aarch64-linux-android` | the same payload and the same build; ran under qemu-user over the system image's own bionic, which the platform emulator cannot do from an x86_64 host | verified |
| `aarch64-ios-sim` | llvm 23 plus the machine's iPhoneSimulator SDK, which mcpp locates rather than installs; ran on a simulator through `simctl-run` ³ | verified |
| `aarch64-ios` | the same split for the device; the artefact names the iOS platform, and running it off a device needs a signature the developer owns ³ | preview |
| `x86_64-ios-sim` | the same build; nothing ran it, because a simulator runs the host's architecture and the machine measured was Apple silicon ³ | preview |
`verified` an image has been built **and run** for the row, qemu and wine
included · `preview` it builds and links, and no emulator run has been recorded
· `planned` registered in the vocabulary and nothing wired yet — a build for
such a target is refused rather than attempted.
> Linux release binaries are fully static musl builds for x86_64 and aarch64
> (`x86_64-linux-musl` and `aarch64-linux-musl`).
> Legacy spellings — `x86_64-w64-mingw32`, `gcc@16.1.0-musl`, `mingw-cross@…`,
> `musl-gcc@…` — stay permanently accepted as aliases and normalize to the
> canonical forms above.
>
> ¹ On Windows, llvm targets the MSVC ABI and therefore requires an existing
> **MSVC BuildTools or Visual Studio** (UCRT, Windows SDK, MSVC STL). You do
> not have to arrange this: on first run mcpp checks for a usable MSVC and,
> finding none, defaults to `x86_64-windows-gnu` (winlibs MinGW-w64) — fully
> self-contained, no Visual Studio, `import std` included. Nothing to install
> or configure; `mcpp new && mcpp build` just works on a stock Windows box.
> An explicit `[toolchain]` in `mcpp.toml` is always respected as written —
> mcpp revises its own default, never yours.
>
> ² The bare-metal rows carry no operating system: clang and lld are
> cross-compilers by construction, so any host that can install the LLVM
> payload produces these targets. The C library, startup code, memory layout
> and emulator travel with a board-support package rather than with mcpp — see
> [40 — Bare-Metal and Freestanding Targets](docs/40-baremetal.md).
>
> ³ The three iOS rows need a macOS host, and the compiler is still the
> ecosystem's: `xim:llvm` emits arm64 Mach-O for an iOS deployment target. What
> the machine supplies is the SDK, which ships inside Xcode and is not
> redistributable, so mcpp locates it through `xcrun` exactly as it has always
> located the macOS SDK — and refuses, naming the SDK, when it cannot. The
> simulator session belongs to `xim:apple-simulator-tools`. See
> [20 — Toolchain Management](docs/20-toolchains.md).
## Documentation
[`docs/`](docs/README.md) is the manual. A chapter's first digit says which part
it belongs to, and the index carries the reverse lookup — from a manifest key or
a command in front of a reader, to the chapter that owns it.
| Part | Start at |
|---|---|
| `0x` fundamentals | [01 Getting Started](docs/01-getting-started.md) · [04 The mcpp.toml Manifest](docs/04-mcpp-toml.md) · [09 Commands by Scenario](docs/09-commands-by-scenario.md) |
| `1x` publishing | [10 Packaging an Application for Release](docs/10-pack-and-release.md) · [11 Publishing a Library to mcpp-index](docs/11-publishing-a-library.md) · [12 Distributing a Prebuilt Library](docs/12-binary-distribution.md) |
| `2x` toolchains and targets | [20 Toolchain Management](docs/20-toolchains.md) · [21 The Target Triple](docs/21-the-target-triple.md) · [24 Cross-Compilation Over openkal](docs/24-openkal-cross.md) |
| `3x` extending mcpp | [30 Build Programs: `build.mcpp`](docs/30-build-mcpp.md) · [31 Authoring a Rule Package](docs/31-authoring-a-rule-package.md) · [34 Authoring a Board-Support Package](docs/34-authoring-a-bsp.md) |
| `4x` devices and accelerators | [40 Bare-Metal and Freestanding Targets](docs/40-baremetal.md) · [41 Reaching a Device](docs/41-devices.md) · [42 Heterogeneous Builds](docs/42-heterogeneous-builds.md) |
| `5x` contracts for programs | [50 Machine-Readable Output](docs/50-machine-output.md) · [51 Supported Versions and Compatibility](docs/51-supported-versions.md) · [the specifications](docs/specs/README.md) |
| `9x` mcpp itself | [90 Building from Source and Contributing](docs/90-build-from-source.md) · [92 Releasing mcpp](docs/92-release.md) |
Every directory under [`examples/`](examples/) is a project that builds, and
[03 — Examples](docs/03-examples.md) says which one teaches what. Full options
for any command are available via `mcpp --help`.
**AI-assisted learning**: send the following prompt to an AI coding assistant to get up to speed with mcpp quickly:
```
Read .agents/skills/mcpp-usage/SKILL.md and the docs/ directory of the
https://github.com/mcpp-community/mcpp repository,
then tell me how to create a C++23 module project with dependencies using mcpp.
```
## Who's Using mcpp
Real projects built with mcpp — `import`-able C++23 modules and the toolchain it builds on:
| Project | Description |
| --- | --- |
| [mcpp](https://github.com/mcpp-community/mcpp) | mcpp itself — written in C++23 modules, fully self-hosted |
| [xlings](https://github.com/openxlings/xlings) | Toolchain and package-management foundation mcpp builds on |
| [tinyhttps](https://github.com/mcpplibs/tinyhttps) | Minimal C++23 HTTP/HTTPS client with SSE streaming |
| [llmapi](https://github.com/mcpplibs/llmapi) | Modern C++ LLM API client (OpenAI-compatible) |
| [imgui-m](https://github.com/mcpplibs/imgui-m) | Dear ImGui as a C++23 module package |
| [cmdline](https://github.com/mcpplibs/cmdline) | Command-line parsing library / framework (mcpp uses it) |
More modular libraries → [mcpplibs](https://github.com/mcpplibs) · package index → [mcpp-index](https://mcpplibs.github.io/mcpp-index/)
## Contributing
Contributions via issues and PRs are welcome. The project accepts contributions developed with AI agents.
**Basic workflow**
1. Open an issue — for bug fixes, new features, or improvements, start a discussion in [issues](https://github.com/mcpp-community/mcpp/issues) first
2. Implement the change — fork the repo, create a branch, and verify according to scope (`mcpp build` plus relevant tests for behavior changes; examples and links for documentation-only changes)
3. Submit a PR — use `gh pr create` and make sure CI passes
4. CI must pass — PRs with failing CI will not be merged
**Commit message convention**: `feat:` / `fix:` / `test:` / `docs:` / `refactor:` prefixes
**AI agent contributions**: the repo's [`.agents/skills/mcpp-contributing/SKILL.md`](.agents/skills/mcpp-contributing/SKILL.md) provides a complete agent contribution workflow and project structure guide. Just send this prompt to your AI assistant:
```
Read .agents/skills/mcpp-contributing/SKILL.md of the
https://github.com/mcpp-community/mcpp repository,
then follow the guide to help me submit a contribution to mcpp.
```
## Community & Ecosystem
- [Community Forum](https://forum.d2learn.org/category/20) — chat group (QQ: 1067245099)
- [mcpp-index](https://mcpplibs.github.io/mcpp-index/) — default package index
- [mcpplibs](https://github.com/mcpplibs) — collection of modular C++ libraries
### Acknowledgements
Dependencies and sources of inspiration:
- [xlings](https://github.com/openxlings/xlings) — toolchain / package-management foundation
- [mcpplibs.cmdline](https://github.com/mcpplibs/cmdline) — CLI framework
- [ninja](https://github.com/ninja-build/ninja) — underlying build engine
- [xmake](https://github.com/xmake-io/xmake) — cross-platform build tool
- [cargo](https://github.com/rust-lang/cargo) — Rust package manager