GitHub Trending: fmtlib/fmt — C++ Formatting Without the Friction
Author: Rasmus

GitHub Trending: fmtlib/fmt — C++ Formatting Without the Friction


Quick answer

fmtlib/fmt is an MIT-licensed C++ formatting library that offers a concise, type-safe alternative to printf and iostreams. Add it with CMake, link fmt::fmt, and start with fmt::print or fmt::format.

fmtlib/fmt was the #1 repository on GitHub’s daily trending page when checked on September 4, 2026. The page showed 963 stars gained that day, while the repository API reported 25,242 stars and 3,023 forks. Those are a point-in-time snapshot, not a quality score, but they explain why this mature C++ library is attracting attention again.

The project calls itself {fmt}. Its job is simple: turn values into readable text without the ceremony of C++ iostreams or the unchecked format strings associated with traditional printf. The result is a compact API that scales from a one-line “Hello, world!” to custom types, date formatting, ranges, colors, files and localization-friendly positional arguments.

1. What fmtlib/fmt adds to C++

The library provides fmt::print for output and fmt::format when you need a string. Both use a format string with replacement fields such as {}:

#include <fmt/base.h>

int main() {
  fmt::print("Hello, {}!\n", "C++");
}

That style keeps the format close to the output and the values separate from the punctuation. The README also documents positional arguments, so a sentence can reorder values without changing the argument list:

auto sentence = fmt::format(
    "I'd rather be {1} than {0}.", "right", "happy");

The core is broader than convenience syntax. The project’s feature list includes portable Unicode support, date and time formatting, ranges and tuples, user-defined formatters, a safe printf implementation, terminal colors, file output and an optional header-only configuration. It also documents an implementation of C++20 std::format and C++23 std::print, making the project relevant whether you want a stable library API today or a path toward standard-library facilities.

The repository says it has no external dependencies and is distributed under the permissive MIT License. It also describes compile-time format-string checking on supported C++20 toolchains. That last point needs a precise reading: the check applies when the compiler and the call site meet the library’s requirements; runtime format strings still need a deliberate path such as fmt::runtime.

2. Add it with CMake

The official Getting Started documentation lists three CMake approaches. For a project that already installs dependencies centrally, use an installed copy:

find_package(fmt REQUIRED)
target_link_libraries(my_app PRIVATE fmt::fmt)

If you want the dependency fetched during configuration, the documentation shows CMake’s FetchContent mechanism. A simplified version looks like this:

include(FetchContent)

FetchContent_Declare(
  fmt
  GIT_REPOSITORY https://github.com/fmtlib/fmt
  GIT_TAG 12.2.0
)
FetchContent_MakeAvailable(fmt)

target_link_libraries(my_app PRIVATE fmt::fmt)

The third option is to keep the source tree in your project and call add_subdirectory(fmt). Whichever route you choose, pin a release or commit for reproducible builds instead of allowing an unreviewed moving target into a production build.

The documentation exposes two CMake targets: fmt::fmt for the compiled library and fmt::fmt-header-only for header-only use. It recommends the compiled target for improved build times. Header-only mode can be convenient for a small project or a constrained integration, but it can also move more implementation work into every translation unit. Treat that choice as a build-time trade-off, not as a universal performance setting.

3. Start with the smallest useful API

Use fmt/base.h when the base API is enough and you want minimal include dependencies. Use the more specific headers when you need extra facilities:

  • fmt/format.h for the full formatting API and locale support
  • fmt/chrono.h for dates and times
  • fmt/ranges.h for containers, ranges and tuples
  • fmt/std.h for additional standard-library types
  • fmt/color.h for terminal colors and text styles
  • fmt/os.h for file output

For example, a vector can be printed with the ranges header:

#include <vector>
#include <fmt/ranges.h>

int main() {
  std::vector<int> values = {1, 2, 3};
  fmt::print("{}\n", values);
}

This incremental approach is useful in an existing codebase. Start with one output path, compile it, and add a specialized header only when the feature is needed. It gives you a small diff and makes it easier to compare generated output with the old implementation.

4. Let the compiler catch mismatches

A format field carries expectations about the value it receives. The project’s API documentation shows that a string literal format can be checked at compile time on compilers supporting C++20 consteval. For example, this is intentionally invalid:

auto text = fmt::format("{:d}", "not a number");

The d presentation is for an integer, so a supported C++20 build can reject the call rather than waiting for a test or a production log path to expose it. Older compilers can use the documented FMT_STRING macro for legacy checks.

Do not turn that into a promise that every bad input is impossible. A runtime format string is a different case, and output can still be semantically wrong even when its types are valid. Keep user-controlled format text separate from trusted format templates, test important output, and use the library’s documented runtime wrapper when a format is genuinely known only at runtime.

5. When it is a good fit

{fmt} is a strong candidate when a C++ project needs:

  • readable application and diagnostic output without stream-state manipulation;
  • consistent formatting across platforms and standard-library implementations;
  • a migration path from printf-style calls;
  • formatters for project-specific structs or enums;
  • dates, containers, colors or file output through focused headers; or
  • a small dependency with no external runtime library requirements.

It is not a reason to replace every existing output path immediately. A large application may already have logging, localization, ABI, or dependency-management constraints. The safer migration is to choose one module, keep the old output as a comparison during review, and measure compile time and binary impact in the project’s own toolchain. The performance numbers in the README are the project’s benchmark results on specified systems, not a guarantee for your workload.

6. Release and license checks

The latest release endpoint reported 12.2.0, published on June 16, 2026, when this article was checked. The repository had also received commits in early September, so the release tag and the current default branch are not interchangeable references. Pin the version you have tested, then review upstream changes before upgrading.

The repository’s LICENSE file is the MIT License. That permits broad reuse, including commercial use, provided the required notice and disclaimer remain with the distribution. Package managers, vendored copies and future repository additions can carry their own metadata, so verify the exact files you ship rather than treating a repository-level label as a substitute for a release audit.

Bottom line

fmtlib/fmt is trending because it solves an old C++ problem with an API that feels current: concise calls, type-aware arguments, useful extensions and a build-system story that works for installed, fetched or embedded dependencies. The practical starting point is small: install a pinned version, link fmt::fmt, replace one output path with fmt::print, and let your compiler and tests validate the result.

Sources

Hero image: OxyLight, CC BY 4.0, via Wikimedia Commons.

Frequently Asked Questions

What is fmtlib/fmt?

fmtlib/fmt, usually called {fmt}, is an open-source C++ formatting library. It provides print, string-formatting, date/time, range, color, file-output and printf-compatible APIs as a fast alternative to C stdio and C++ iostreams.

How do I install fmtlib/fmt with CMake?

The official documentation lists FetchContent, an installed package used with find_package(fmt), and an embedded source tree used with add_subdirectory(fmt). Link the target to fmt::fmt for the compiled library.

Should I use fmt::fmt or the header-only target?

The official CMake documentation recommends the compiled fmt::fmt target for improved build times. Use fmt::fmt-header-only when header-only integration is a deliberate fit for your project.

Can I use fmtlib/fmt in a commercial project?

The repository includes the MIT License, which permits broad use, modification, distribution and commercial use subject to the license notice and disclaimer. Check the repository and any packaged components before shipping.

Written by Rasmus

Independent writer of practical how-tos and guides. Every article is written to be genuinely useful — no filler, no recycled content. More about lejnel.com.

Next article: How to Get Rid of Bed Bugs: 10 Steps to Stop the Spread