# How to Use spdlog with CMake: Integration Guide for Header-Only and Compiled Builds

> Learn how to use spdlog with CMake for header-only or compiled builds. Effortlessly integrate spdlog into your C++ projects by following this comprehensive guide.

- Repository: [Gabi Melman/spdlog](https://github.com/gabime/spdlog)
- Tags: how-to-guide
- Published: 2026-07-15

---

**Use `add_subdirectory(path/to/spdlog)` to create the `spdlog::spdlog` or `spdlog::spdlog_header_only` targets, then link them with `target_link_libraries(your_target PRIVATE spdlog::spdlog)`.**

The `gabime/spdlog` repository provides a comprehensive CMake build system that supports both header-only and compiled library configurations. Located at the root of the repository, the [`CMakeLists.txt`](https://github.com/gabime/spdlog/blob/main/CMakeLists.txt) file defines convenient import targets and cache options that control linking behavior, external dependencies, and C++ standard requirements. This flexibility allows you to integrate spdlog into existing CMake projects using either a bundled source subdirectory or as an installed system package.

## CMake Build Options and Configuration

The top-level [`CMakeLists.txt`](https://github.com/gabime/spdlog/blob/main/CMakeLists.txt) exposes several boolean options that determine how the library is built and consumed. These options must be set **before** calling `add_subdirectory(spdlog)` to take effect.

### Static vs. Shared Library Selection

By default, spdlog builds as a static library. To create a shared library instead, set `SPDLOG_BUILD_SHARED` to `ON` before including the subdirectory:

```cmake
set(SPDLOG_BUILD_SHARED ON)
add_subdirectory(spdlog)

```

This option respects the standard CMake `BUILD_SHARED_LIBS` variable if `SPDLOG_BUILD_SHARED` is not explicitly defined.

### Header-Only vs. Compiled Mode

The build system generates two distinct targets:
- **`spdlog::spdlog`** – A compiled static or shared library containing the implementation objects.
- **`spdlog::spdlog_header_only`** – An **INTERFACE** target that adds include directories without compiling separate objects.

Link against `spdlog::spdlog_header_only` when you want zero compilation overhead and do not need to maintain a separate spdlog binary.

### External fmt Library Support

By default, spdlog bundles its own `fmt` library. To link against a system-installed version, enable one of these options before `add_subdirectory`:

- **`SPDLOG_FMT_EXTERNAL`** – Links against `fmt::fmt` (compiled).
- **`SPDLOG_FMT_EXTERNAL_HO`** – Links against `fmt::fmt-header-only`.

```cmake
set(SPDLOG_FMT_EXTERNAL ON)
add_subdirectory(spdlog)

```

## Linking spdlog Targets in Your Project

Both targets automatically propagate include directories (`include/`) and the thread library (`Threads::Threads`) to your project. Choose the appropriate target based on your deployment needs:

| Target | Library Type | Use Case |
|--------|-------------|----------|
| **spdlog::spdlog** | STATIC or SHARED | When you want faster compile times and a separate library file |
| **spdlog::spdlog_header_only** | INTERFACE (header-only) | When you want simple integration without extra build artifacts |

Both targets automatically handle the required include directories and threading support.

## Step-by-Step Integration Examples

### Compiled Static Library Setup

The most common approach bundles spdlog as a compiled static dependency:

```cmake
cmake_minimum_required(VERSION 3.10)
project(my_app LANGUAGES CXX)

# Build spdlog as a static library (default)

add_subdirectory(spdlog)

add_executable(my_app src/main.cpp)
target_link_libraries(my_app PRIVATE spdlog::spdlog)

```

### Header-Only with External fmt

For projects that already use the `{fmt}` library, avoid duplication by using the header-only spdlog target with external fmt:

```cmake
cmake_minimum_required(VERSION 3.10)
project(my_app LANGUAGES CXX)

set(SPDLOG_FMT_EXTERNAL_HO ON)
add_subdirectory(spdlog)

add_executable(my_app src/main.cpp)
target_link_libraries(my_app PRIVATE spdlog::spdlog_header_only)

```

### Shared Library with C++20 std::format

To utilize C++20's `std::format` instead of the bundled fmt library, enable `SPDLOG_USE_STD_FORMAT`. This requires a C++20 compliant compiler:

```cmake
cmake_minimum_required(VERSION 3.10)
project(my_app LANGUAGES CXX)

set(SPDLOG_BUILD_SHARED ON)       # Produce libspdlog.so / spdlog.dll

set(SPDLOG_USE_STD_FORMAT ON)     # Require C++20

add_subdirectory(spdlog)

add_executable(my_app src/main.cpp)
target_link_libraries(my_app PRIVATE spdlog::spdlog)

```

## Key CMake Files in the Repository

Understanding the repository structure helps when debugging build issues or extending the configuration:

- **[`CMakeLists.txt`](https://github.com/gabime/spdlog/blob/main/CMakeLists.txt)** (root) – Defines `spdlog` and `spdlog_header_only` targets, handles `SPDLOG_FMT_EXTERNAL` logic, and sets installation rules.
- **`cmake/utils.cmake`** – Contains helper functions like `spdlog_extract_version()` and compiler warning configurations.
- **[`example/CMakeLists.txt`](https://github.com/gabime/spdlog/blob/main/example/CMakeLists.txt)** – Provides a minimal working example demonstrating both compiled and header-only linkage patterns.

## Summary

- **Include spdlog** using `add_subdirectory(path/to/spdlog)` to create the CMake targets.
- **Choose your target**: `spdlog::spdlog` for compiled, `spdlog::spdlog_header_only` for header-only.
- **Set options before inclusion**: `SPDLOG_BUILD_SHARED`, `SPDLOG_FMT_EXTERNAL`, and `SPDLOG_USE_STD_FORMAT` must be defined prior to the `add_subdirectory` call.
- **External dependencies** are handled automatically; linking either target propagates include directories and threading libraries.
- **Reference implementation** details are found in [`CMakeLists.txt`](https://github.com/gabime/spdlog/blob/main/CMakeLists.txt) at the repository root and `cmake/utils.cmake`.

## Frequently Asked Questions

### Should I use header-only or compiled spdlog?

Use **spdlog::spdlog_header_only** for quick prototyping or when you want to avoid maintaining a separate library file. Use **spdlog::spdlog** for larger projects where compile times matter, as the compiled library prevents recompiling spdlog's implementation with every translation unit that includes its headers.

### How do I use spdlog with a system-installed fmt?

Set `SPDLOG_FMT_EXTERNAL` to `ON` before adding the subdirectory. This links `spdlog::spdlog` against `fmt::fmt` from your system package manager instead of the bundled copy. For header-only fmt usage, use `SPDLOG_FMT_EXTERNAL_HO` instead.

### Can I build spdlog as a shared library?

Yes. Set `SPDLOG_BUILD_SHARED` to `ON` before calling `add_subdirectory(spdlog)`. This generates `libspdlog.so` on Linux or `spdlog.dll` on Windows. When linking against the shared library, ensure your executable can locate the DLL at runtime.

### What C++ standard does spdlog require?

By default, spdlog requires **C++11**. If you enable `SPDLOG_USE_STD_FORMAT`, the requirement increases to **C++20** to support `std::format`. The CMake configuration automatically checks compiler capabilities and will fail configuration if the standard is insufficient.