# FMT_VERSION Macro: How to Detect the fmtlib Version at Compile Time

> Learn how to use the FMT_VERSION macro to detect the fmtlib version at compile time. Enable conditional compilation and ensure compatibility for your C++ projects.

- Repository: [Hello World Foundation/fmt](https://github.com/fmtlib/fmt)
- Tags: internals
- Published: 2026-09-04

---

**The `FMT_VERSION` macro is a preprocessor constant defined in [`include/fmt/base.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/base.h) that encodes the fmt library version as a single integer using the formula `major×10000 + minor×100 + patch`, enabling compile-time version checks and conditional compilation paths.**

The **fmt** library provides a standardized mechanism to query its version directly from source code. This eliminates guesswork when writing portable applications that must support multiple fmt releases. This guide explains the macro's encoding scheme, demonstrates how to extract version components, and shows integration with CMake and pkg-config.

## Understanding the FMT_VERSION Macro Encoding

The `FMT_VERSION` macro packs semantic version components into a single comparable integer value defined in the fmt source headers.

### Macro Definition and Location

According to the **fmtlib/fmt** source code, the macro is defined in [`include/fmt/base.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/base.h) at line 24:

```c
#define FMT_VERSION 120201   // major·10000 + minor·100 + patch

```

This definition is the single source of truth for the library's version number. The CMake build system extracts this value using a regex in [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt) (lines 112-119) to populate the `FMT_VERSION` CMake variable, ensuring consistency between build-time and compile-time version detection.

### Version Encoding Formula

The integer follows the pattern **major × 10000 + minor × 100 + patch**. For example, the value `120201` represents version **12.2.1**:
- **Major**: 12 (`120201 / 10000`)
- **Minor**: 2 (`(120201 / 100) % 100`)
- **Patch**: 1 (`120201 % 100`)

This encoding allows for simple integer comparisons to check version requirements.

## Compile-Time Version Detection in C++

You can query the fmt version directly in your source code to enable or disable features based on the available API.

### Basic Version Checks

To conditionally compile code based on the fmt version, include [`fmt/base.h`](https://github.com/fmtlib/fmt/blob/main/fmt/base.h) and compare against the encoded integer:

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

#if FMT_VERSION >= 120200   // Require at least 12.2.0
  // Use API features introduced in fmt 12.2.0
  auto formatted = fmt::format(std::runtime_format("{}"), value);
#else
  // Fallback implementation for older versions
#endif

```

### Extracting Individual Components

For logging or validation purposes, you can extract the major, minor, and patch versions using integer arithmetic:

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

constexpr int fmt_major = FMT_VERSION / 10000;
constexpr int fmt_minor = (FMT_VERSION / 100) % 100;
constexpr int fmt_patch = FMT_VERSION % 100;

static_assert(fmt_major >= 12, "fmt version 12 or higher required");

```

## Build System Integration

Beyond compile-time checks, fmt exposes its version through standard build system interfaces for dependency management.

### CMake Detection

When using CMake, the `find_package` command reads the macro from [`include/fmt/base.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/base.h) and sets the `fmt_VERSION` variable as a dotted string:

```cmake
find_package(fmt REQUIRED)
message(STATUS "Using fmt ${fmt_VERSION}")  # Outputs: Using fmt 12.2.1

add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE fmt::fmt)

```

The extraction logic is implemented in the library's [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt) at lines 112-119, where a regex parses the macro definition from the header file.

### pkg-config Support

For systems using pkg-config, the version is embedded in the generated `fmt.pc` file, which is produced from the template `support/cmake/fmt.pc.in` at line 8:

```bash
pkg-config --modversion fmt   # Outputs: 12.2.1

```

A similar template exists at `support/cmake/fmt-c.pc.in` for the C API bindings.

## Complete Working Example

Here is a comprehensive example demonstrating runtime version formatting, compile-time conditional logic, and static assertions:

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

int main() {
    // Deconstruct version for display
    constexpr int major = FMT_VERSION / 10000;
    constexpr int minor = (FMT_VERSION / 100) % 100;
    constexpr int patch = FMT_VERSION % 100;
    
    std::cout << "fmt version: " << major << '.' << minor << '.' << patch << '\n';
    std::cout << "Raw FMT_VERSION: " << FMT_VERSION << '\n';

#if FMT_VERSION >= 120200
    fmt::print("Compiled with fmt 12.2.0 or later - modern API available\n");
#else
    std::cerr << "Warning: fmt version is older than 12.2.0\n";
#endif

    // Compile-time verification
    static_assert(FMT_VERSION >= 120000, "fmt version 12.x required");
}

```

## Summary

- **`FMT_VERSION`** is defined in [`include/fmt/base.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/base.h) as a single integer encoding the library version using `major×10000 + minor×100 + patch`
- **Compile-time detection** allows feature gating with `#if FMT_VERSION >= 120200` or extraction of components via division and modulo operations
- **CMake integration** provides the `fmt_VERSION` variable (e.g., "12.2.1") extracted from the header via regex in the repository's [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt)
- **pkg-config support** exposes the version string through `--modversion` using templates `support/cmake/fmt.pc.in` and `fmt-c.pc.in`
- **Portability** is maintained across all platforms since detection relies solely on preprocessor macros available in the standard header layout

## Frequently Asked Questions

### What header file defines the FMT_VERSION macro?

The `FMT_VERSION` macro is defined in [`include/fmt/base.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/base.h) at line 24. While other headers like [`fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/fmt/core.h) include this definition transitively, including [`fmt/base.h`](https://github.com/fmtlib/fmt/blob/main/fmt/base.h) directly ensures you can check the version before including heavy formatting headers.

### How do I check if the installed fmt version is at least 12.2.0?

Use a preprocessor directive comparing against the encoded integer: `#if FMT_VERSION >= 120200`. This works because 12×10000 + 2×100 + 0 equals 120200, making integer comparisons semantically equivalent to version tuple comparisons.

### Can I get the version string at runtime?

Yes, but you must construct it yourself from the macro components. There is no pre-built string constant; calculate the major, minor, and patch values using integer division and modulo, then format them using `fmt::format("{}.{}.{}", major, minor, patch)` or standard streams.

### Why does CMake set fmt_VERSION but the C++ macro is named FMT_VERSION?

The CMake variable `fmt_VERSION` (lowercase) contains a human-readable dotted string like "12.2.1" extracted by the build system's regex parser in [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt), while the C++ macro `FMT_VERSION` (uppercase) is the raw integer encoding (120201) defined in the header. Both derive from the same source line in [`include/fmt/base.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/base.h) but serve different consumption patterns.