# How to Contribute to the fmtlib Project: A Complete Guide for C++ Developers

> Learn how to contribute to the fmtlib C++ project. Fork the repo, build with CMake, follow GitHub Flow, and pass style checks and CTest for successful contributions.

- Repository: [Hello World Foundation/fmt](https://github.com/fmtlib/fmt)
- Tags: how-to-guide
- Published: 2026-09-06

---

**Contributing to the fmtlib project requires forking the repository on GitHub, building the library with CMake, following the standard GitHub Flow workflow, and ensuring all changes pass the clang-format and clang-tidy style checks along with the comprehensive CTest suite.**

The fmtlib/fmt repository hosts {fmt}, a modern C++ formatting library that provides type-safe, fast alternatives to printf and iostreams. If you want to contribute to the fmtlib project, understanding its header-only core architecture and the location of key files like [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) is essential for submitting effective pull requests. This guide covers the exact development workflow, coding standards, and common contribution patterns used in the codebase.

## Understanding the fmtlib Architecture

The fmt library separates compile-time parsing from runtime formatting to maximize performance while maintaining extensibility. Familiarize yourself with these core components before modifying code:

- **Core Formatting Engine**: Located in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h), this implements the compile-time parser (`fmt::detail::compile_string`) and the `fmt::formatter<T>` template specialization system that validates format strings against argument types.

- **Implementation Details**: Heavy template logic resides in [`include/fmt/format-inl.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format-inl.h), containing the actual implementations for `fmt::format`, `fmt::printf`, `fmt::vformat`, and `fmt::vprint` to keep the main header clean.

- **Public API Layer**: [`include/fmt/printf.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/printf.h) exposes legacy printf-style interfaces, while [`include/fmt/ostream.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/ostream.h) provides integration with standard streams via `operator<<`.

- **Build System**: [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt) configures both header-only and compiled library modes, manages test discovery, and enforces code style through automated tooling.

## Setting Up the Development Environment

### Clone and Build

Start by forking the repository on GitHub, then clone your fork locally:

```bash
git clone https://github.com/<your-username>/fmt.git
cd fmt

```

Configure the build with CMake and compile:

```bash
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release
cmake --build build

```

The project requires a recent C++ compiler (C++11 or later) and supports multiple platforms including Linux, macOS, and Windows.

### Running Tests

Verify your build works by executing the test suite:

```bash
ctest --test-dir build

```

This command runs all unit tests in the `test/` directory and reports failures.

## The Contribution Workflow

The fmtlib project follows the standard GitHub Flow process documented in [`CONTRIBUTING.md`](https://github.com/fmtlib/fmt/blob/main/CONTRIBUTING.md):

1. **Create a feature branch** with a descriptive name (e.g., `fix-double-formatting` or `add-chrono-support`).

2. **Make atomic commits** with clear messages describing the technical change.

3. **Follow code style guidelines** enforced by clang-format and clang-tidy configurations in the repository root.

4. **Add test coverage** for new functionality in the `test/` directory using the project's lightweight test harness.

5. **Update documentation** in `doc/` if your change modifies public APIs like `fmt::format` or `fmt::print`.

6. **Push your branch** to your fork and open a Pull Request against `fmtlib/fmt:main`.

## Common Contribution Patterns

### Adding Custom Type Formatters

The preferred way to extend the library is specializing `fmt::formatter<T>` for user-defined types. The specialization must implement two methods: `parse()` for handling format specifications and `format()` for output generation.

Here is a complete example for a custom `Point` struct:

```cpp
#include <fmt/core.h>

struct Point {
  int x, y;
};

template <> struct fmt::formatter<Point> {
  constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
    // No custom format specs; consume the whole range
    return ctx.begin();
  }

  template <typename FormatContext>
  auto format(const Point& p, FormatContext& ctx) const -> decltype(ctx.out()) {
    return fmt::format_to(ctx.out(), "({},{})", p.x, p.y);
  }
};

int main() {
  Point p{3, 4};
  fmt::print("Point: {}\n", p);  // Output: Point: (3,4)
}

```

The `fmt::format_to` function writes directly to the output iterator provided by the format context, ensuring zero-copy performance where possible.

### Extending the Test Suite

Add new test files to the `test/` directory. The project uses an internal test harness included via [`test.h`](https://github.com/fmtlib/fmt/blob/main/test.h):

```cpp
#include <fmt/core.h>
#include "test.h"

TEST_CASE("custom point formatter") {
  Point p{1, 2};
  CHECK(fmt::format("{}", p) == "(1,2)");
  CHECK(fmt::format("{:}", p) == "(1,2)");
}

```

Run `ctest --test-dir build` after adding tests to verify your formatter works correctly and does not regress existing functionality in `fmt::vprint` or other formatting functions.

### Updating Documentation

Public API changes require updates to markdown files in `doc/`. For example, if adding a feature that affects `fmt::printf`, add a usage example to [`doc/api.md`](https://github.com/fmtlib/fmt/blob/main/doc/api.md) or [`doc/get-started.md`](https://github.com/fmtlib/fmt/blob/main/doc/get-started.md):

```markdown

```cpp
struct Point { int x, y; };
fmt::print("{}", Point{5,7}); // prints "(5,7)"

```

```

## Summary

- Fork `fmtlib/fmt` and create descriptive feature branches before starting work.
- The core formatting logic lives in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) and [`include/fmt/format-inl.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format-inl.h), with public APIs declared in headers like [`include/fmt/printf.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/printf.h).
- All contributions must pass automated style checks (clang-format/clang-tidy) and the full CTest suite.
- Extend the library by specializing `fmt::formatter<T>` in your own headers or the relevant `include/fmt/` files for built-in type support.
- Add corresponding unit tests in the `test/` directory and documentation updates in `doc/` for any public API changes.

## Frequently Asked Questions

### What is the fmt library used for?

The fmt library provides fast, type-safe string formatting as a modern replacement for printf and iostreams. According to the fmtlib source code, it is used by major projects like SPDLOG and offers compile-time format string checking through mechanisms like `fmt::detail::compile_string` in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h).

### Do I need to be a template metaprogramming expert to contribute?

No. While [`include/fmt/format-inl.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format-inl.h) contains advanced template code for the core engine, many contributions involve simple `fmt::formatter<T>` specializations, documentation improvements, or test additions. The [`CONTRIBUTING.md`](https://github.com/fmtlib/fmt/blob/main/CONTRIBUTING.md) file outlines tasks suitable for various skill levels.

### How do I run only specific tests during development?

Use `ctest` with the `-R` flag to filter test names: `ctest --test-dir build -R formatter_test`. This executes only tests matching the regular expression, significantly speeding up the development cycle when iterating on specific components like custom formatters or `fmt::printf` functionality.

### Where is the main formatting logic implemented?

The primary formatting algorithms are implemented in [`include/fmt/format-inl.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format-inl.h), which contains the template-heavy implementations of `fmt::format`, `fmt::vformat`, and related functions. Public interfaces are exposed through [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h), which provides the `fmt::formatter` base template and parse context definitions.