# How to Use fmtlib as a Header-Only Library: Complete Setup Guide

> Learn to use fmtlib as a header-only library. Follow our setup guide to link against the fmt::fmt-header-only CMake target or define the FMT_HEADER_ONLY macro for easy integration.

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

---

**To use {fmt} as a header-only library, link against the `fmt::fmt-header-only` CMake target or manually define the `FMT_HEADER_ONLY` macro before including the headers.**

{fmt} is a modern C++ formatting library that provides fast, safe text formatting. While it traditionally builds as a compiled library, the fmtlib/fmt repository supports a header-only mode that eliminates the need to link against a separate binary, simplifying dependency management in projects where adding a compiled library is impractical.

## Understanding Header-Only Mode

When you use fmtlib as a header-only library, all implementation code is provided inline through public headers rather than in a separate compiled archive. The source code uses conditional compilation to toggle between linked and inline implementations.

In [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) at line 1351 and [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h) at line 2957, the library checks for the `FMT_HEADER_ONLY` macro:

```cpp
#ifndef FMT_HEADER_ONLY
// … implementation that requires linking against the compiled library …
#endif  // FMT_HEADER_ONLY

```

When the macro is defined, these guards expose the inline implementation; otherwise, the code expects to link against the compiled `libfmt`.

## Method 1: CMake Interface Target (Recommended)

The recommended way to enable header-only mode is through the `fmt::fmt-header-only` CMake target. This target is defined in the top-level [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt) (lines 454-458) as an **INTERFACE** library:

```cmake
add_library(fmt-header-only INTERFACE)
target_compile_definitions(fmt-header-only INTERFACE FMT_HEADER_ONLY=1)
target_compile_features(fmt-header-only INTERFACE cxx_std_11)
setup_target(fmt-header-only INTERFACE)

```

When you link against this target, CMake automatically propagates the `FMT_HEADER_ONLY=1` definition and C++11 feature requirements to consuming targets. You do **not** need to define the macro manually in your source code.

Example CMake configuration:

```cmake
cmake_minimum_required(VERSION 3.14)
project(myapp)

find_package(fmt REQUIRED)
add_executable(myapp main.cpp)

target_link_libraries(myapp PRIVATE fmt::fmt-header-only)

```

## Method 2: Direct Macro Definition

If you are not using CMake, define the `FMT_HEADER_ONLY` macro manually before including any {fmt} headers. You can pass it as a compiler flag:

```bash
g++ -std=c++11 -DFMT_HEADER_ONLY -I/path/to/fmt/include main.cpp -o myapp

```

Alternatively, define it at the top of your source file:

```cpp
#define FMT_HEADER_ONLY
#include <fmt/format.h>

int main() {
    fmt::print("The answer is {}.\n", 42);
    return 0;
}

```

## Complete Usage Examples

### CMake Project with Header-Only fmtlib

Create a [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt) that finds the package and links to the header-only target:

```cmake
cmake_minimum_required(VERSION 3.14)
project(myapp)

find_package(fmt REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE fmt::fmt-header-only)

```

Your [`main.cpp`](https://github.com/fmtlib/fmt/blob/main/main.cpp) requires no special configuration:

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

int main() {
    fmt::print("Hello, {}!\n", "world");
    return 0;
}

```

### Manual Compilation Without Build Systems

For simple projects or single-file builds, compile directly with the macro defined:

```bash
g++ -std=c++11 -DFMT_HEADER_ONLY -I/path/to/fmt/include main.cpp -o myapp

```

The source code remains identical to standard usage:

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

int main() {
    fmt::print("The answer is {}.\n", 42);
    return 0;
}

```

## Key Implementation Details

The header-only mode is validated by the test suite in `test/header-only-test.cc`, which ensures the library functions correctly when `FMT_HEADER_ONLY` is defined.

According to the source in [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt), the header-only target requires **C++11** as the minimum standard. The macro guards in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) (line 1351) and [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h) (line 2957) control whether the implementation is pulled from the compiled library or expanded inline.

## Summary

- **Define `FMT_HEADER_ONLY`** to activate inline implementations in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) and [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h).
- **Use `fmt::fmt-header-only`** in CMake projects to automatically propagate the required compile definitions from [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt).
- **No linking required** in header-only mode; the compiler processes all implementation code directly from headers.
- **C++11 minimum** is required regardless of which integration method you choose.

## Frequently Asked Questions

### Does header-only mode affect compile times?

Yes. Using fmtlib as a header-only library typically increases compile times compared to the compiled version because the compiler must process the full implementation for every translation unit that includes the headers. The trade-off is simplified deployment without worrying about library paths or ABI compatibility.

### Can I mix header-only and compiled modes in the same project?

No. You must choose one mode for your entire project. Defining `FMT_HEADER_ONLY` in some files but not others will cause **One Definition Rule (ODR)** violations and link-time errors, as the compiled library and inline implementations define the same symbols.

### How do I know if my version supports header-only mode?

Header-only mode has been supported for multiple versions. The current implementation in [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt) (lines 454-458) uses modern CMake **INTERFACE** target features. You can verify support by checking [`doc/get-started.md`](https://github.com/fmtlib/fmt/blob/main/doc/get-started.md) in your specific {fmt} release, which documents substituting `fmt::fmt` with `fmt::fmt-header-only`.

### Do I need to link additional libraries in header-only mode?

No. When using the header-only configuration, you do not need to link against `libfmt` or any additional libraries. The `FMT_HEADER_ONLY` macro ensures all necessary code is included inline from [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h) and related headers, making the library truly self-contained.