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

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 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 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:

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.
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_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_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_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 (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 – 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →