# How to Build fmtlib as a C++ Module Library with FMT_MODULE

> Build fmtlib as a C++ module library using the FMT_MODULE CMake option. Learn to import the fmt::fmt-module target and use import fmt; for cleaner C++20 module integration.

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

---

**Enable the `FMT_MODULE` CMake option when configuring {fmt} to generate the `fmt::fmt-module` target, allowing downstream projects to import the library via `import fmt;` instead of including individual headers.**

The {fmt} library (fmtlib/fmt) provides first-class support for **C++20 modules**, enabling faster compilation and cleaner dependency management compared to traditional header inclusion. By toggling the **FMT_MODULE** option during CMake configuration, you instruct the build system to compile the library as a named module rather than a static or shared library. This article explains the toolchain requirements, build configuration, and consumption patterns based on the current implementation in the main branch.

## Prerequisites for C++20 Module Support

Before enabling **FMT_MODULE**, your build environment must satisfy strict toolchain requirements. In [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt) (lines 53-73), the project detects whether the compiler and generator support the C++ module interface by checking the CMake version, generator type, and compiler capabilities:

- **CMake** ≥ 3.28
- **C++ Standard** ≥ 20 (`CMAKE_CXX_STANDARD=20`)
- **Generators**: Ninja ≥ 1.11 or Visual Studio ≥ 17.4
- **Compilers**: GCC ≥ 15, Clang ≥ 16, or MSVC ≥ 1934

If these conditions are met, the internal variable `FMT_USE_CMAKE_MODULES` evaluates to `ON`, making the module build available.

## Enabling the FMT_MODULE CMake Option

The **FMT_MODULE** option is defined in [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt) (lines 86-88) and defaults to the value of `FMT_USE_CMAKE_MODULES`. When set to `ON`, CMake creates the **fmt::fmt-module** target (around line 330) instead of the standard `fmt::fmt` target.

Configure the build with the following command:

```bash
git clone https://github.com/fmtlib/fmt.git
cd fmt
cmake -B build -S . \
  -DCMAKE_CXX_STANDARD=20 \
  -DFMT_MODULE=ON \
  -G Ninja
cmake --build build

```

If your environment does not satisfy the module prerequisites, **FMT_MODULE** automatically falls back to `OFF`, and the build proceeds as a conventional static library.

## Module Implementation in src/fmt.cc

The module interface is defined in `src/fmt.cc`. The file begins with a **global module fragment** followed by the export declaration (lines 1-12 and 108-110):

```cpp
module;

#include <__config>  // Global module fragment for includes

export module fmt;

// All public headers are included here to expose their symbols
#include <fmt/format.h>
#include <fmt/ostream.h>
// ... additional headers

```

This structure ensures that all library symbols—including `fmt::print`, `fmt::format`, and formatting utilities—are encapsulated within the `fmt` named module. The **export module fmt** statement marks this translation unit as the primary interface for consumers.

## Consuming the fmt Module in Your Project

After building {fmt} with **FMT_MODULE** enabled, consuming projects link against **fmt::fmt-module** and import the module in their source code.

### CMake Configuration

In your project's [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt), locate the package and link to the module target:

```cmake
cmake_minimum_required(VERSION 3.28)
project(my_app LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)

find_package(fmt REQUIRED)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE fmt::fmt-module)

```

### C++ Source Code

Replace traditional `#include` directives with the **import fmt** statement:

```cpp
import fmt;

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

```

Using `import fmt;` eliminates the need for `#include <fmt/format.h>` or other header files, enabling the compiler to perform cross-translation-unit optimizations and reducing compile times in large projects.

## Summary

- **FMT_MODULE** is a CMake option in `fmtlib/fmt` that enables C++20 module compilation when toggled `ON`.
- The option requires CMake ≥ 3.28, C++20, and recent versions of GCC, Clang, or MSVC with module-capable generators like Ninja 1.11+.
- The module interface is implemented in `src/fmt.cc` using `export module fmt;` and includes all public headers within the module purview.
- Consumers link against **fmt::fmt-module** and use `import fmt;` to access the API without header includes.
- If toolchain requirements are unmet, the build automatically falls back to the traditional `fmt::fmt` static library target.

## Frequently Asked Questions

### What happens if I enable FMT_MODULE with an unsupported compiler?

CMake will detect the incompatibility in [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt) (lines 53-73) and silently disable **FMT_MODULE**, falling back to building {fmt} as a standard static or shared library (`fmt::fmt`). Your build will succeed, but you will not be able to use `import fmt;` and must instead include the header files traditionally.

### Can I mix header includes and module imports in the same project?

No, mixing **import fmt** with `#include <fmt/format.h>` in the same project can lead to **One Definition Rule (ODR)** violations and conflicting symbol definitions. The `test/module-test.cc` file in the repository demonstrates proper isolated usage of the module target. Choose one approach per translation unit and consistently link against either `fmt::fmt-module` or `fmt::fmt`.

### Does using the module target change the fmt API?

No, the API remains identical. Whether you include headers or import the module, functions like `fmt::format`, `fmt::print`, and custom formatting extensions work exactly the same. The only difference is the import mechanism: `import fmt;` replaces the need for multiple `#include` directives and provides better build performance through the module interface.

### How do I verify that the module is being built correctly?

Check that CMake reports `FMT_MODULE: ON` during configuration, and verify that the build generates a module interface file (`.gcm` for GCC, `.pcm` for Clang, or `.ifc` for MSVC). You can also inspect the generated build files to confirm that `src/fmt.cc` is being compiled with the `module` keyword rather than as a standard source file, and that your executable links against the `fmt::fmt-module` target rather than `fmt::fmt`.