How to Integrate spdlog into a CMake Project: Complete Guide
To integrate spdlog into a CMake project, add the repository as a subdirectory and link against either spdlog::spdlog for compiled library usage or spdlog::spdlog_header_only for header-only integration.
The gabime/spdlog repository provides a comprehensive CMake build system defined in the top-level CMakeLists.txt that supports both compiled and header-only modes. This guide covers the exact targets, configuration options, and source file locations you need to successfully integrate spdlog into your CMake-based C++ project.
CMake Targets and Build Options
The root CMakeLists.txt creates two primary targets that determine how spdlog is consumed:
spdlog::spdlog– A compiled library (static by default, or shared whenSPDLOG_BUILD_SHAREDis enabled). Linking this target automatically adds theinclude/directory and linksThreads::Threads.spdlog::spdlog_header_only– An INTERFACE target for header-only usage that requires no compiled objects. This also propagates include directories and threading dependencies.
Both targets handle transitive dependencies automatically. When you enable external fmt support via SPDLOG_FMT_EXTERNAL or SPDLOG_FMT_EXTERNAL_HO, the targets additionally link fmt::fmt or fmt::fmt-header-only respectively.
Key configuration options defined in CMakeLists.txt include:
SPDLOG_BUILD_SHARED– Force shared library build (respectsBUILD_SHARED_LIBSif undefined)SPDLOG_FMT_EXTERNAL– Link against system-installed fmt librarySPDLOG_FMT_EXTERNAL_HO– Use system fmt in header-only modeSPDLOG_USE_STD_FORMAT– Enable C++20std::formatsupport (requires C++20)
Step-by-Step Integration Methods
Compiled Static or Shared Library
The default integration method builds spdlog as a compiled library. Add the subdirectory before defining your executable or library:
add_subdirectory(path/to/spdlog)
Then link the compiled target:
target_link_libraries(my_app PRIVATE spdlog::spdlog)
This approach produces either libspdlog.a (static) or libspdlog.so/spdlog.dll (shared) depending on your SPDLOG_BUILD_SHARED setting.
Header-Only Usage
For header-only integration—useful when you want minimal build artifacts—link against the interface target instead:
add_subdirectory(spdlog)
target_link_libraries(my_app PRIVATE spdlog::spdlog_header_only)
The spdlog::spdlog_header_only target is defined as an INTERFACE library in CMakeLists.txt, meaning it carries no compiled objects but provides all necessary include paths and compiler definitions.
Using External fmt Library
By default, spdlog bundles its own copy of the fmt library. To use a system-installed version, set the appropriate option before calling add_subdirectory():
set(SPDLOG_FMT_EXTERNAL ON) # For compiled fmt
# OR
set(SPDLOG_FMT_EXTERNAL_HO ON) # For header-only fmt
add_subdirectory(spdlog)
When enabled, the spdlog targets will link against fmt::fmt or fmt::fmt-header-only rather than the bundled headers in include/spdlog/fmt/bundled/.
Advanced Configuration Options
Enabling C++20 std::format Support
To use C++20's std::format instead of the bundled fmt library, enable SPDLOG_USE_STD_FORMAT. This requires C++20 compiler support:
set(SPDLOG_USE_STD_FORMAT ON)
add_subdirectory(spdlog)
When this option is active, spdlog utilizes <format> instead of the internal formatting engine, reducing dependencies but increasing the minimum C++ standard requirement from C++11 to C++20.
Controlling Library Type (Static vs Shared)
Control whether spdlog builds as a static or shared library using SPDLOG_BUILD_SHARED or the generic CMake BUILD_SHARED_LIBS variable:
set(SPDLOG_BUILD_SHARED ON) # Build libspdlog.so or spdlog.dll
add_subdirectory(spdlog)
If neither variable is set, the default is a static library. The CMakeLists.txt logic checks these variables to determine the library type when creating the spdlog::spdlog target.
Complete CMake Examples
Example 1: Compiled Static Library
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)
Example 2: Header-Only 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)
Example 3: Shared Library with C++20 std::format
cmake_minimum_required(VERSION 3.10)
project(my_app LANGUAGES CXX)
set(SPDLOG_BUILD_SHARED ON)
set(SPDLOG_USE_STD_FORMAT ON)
add_subdirectory(spdlog)
add_executable(my_app src/main.cpp)
target_link_libraries(my_app PRIVATE spdlog::spdlog)
Key Source Files and Implementation Details
Understanding the following files in the gabime/spdlog repository helps with advanced customization:
CMakeLists.txt(root) – Defines all build options, creates thespdlogandspdlog_header_onlytargets, handles external fmt linkage, and sets up installation rules. This file implements the logic forSPDLOG_BUILD_SHARED,SPDLOG_FMT_EXTERNAL, andSPDLOG_USE_STD_FORMAT.cmake/utils.cmake– Contains helper functions likespdlog_extract_version()and compiler warning configurations.cmake/ide.cmake– Provides IDE-specific configurations for development environments like VSCode and CLion.include/spdlog/spdlog.h– The primary public header that user code includes after linking the CMake targets.example/CMakeLists.txt– Demonstrates minimal usage patterns for both compiled and header-only integration modes.
The build system automatically handles threading support by linking Threads::Threads through the spdlog targets, eliminating the need for manual find_package(Threads) calls in consuming projects.
Summary
- Use
add_subdirectory(spdlog)to import the build system from thegabime/spdlogrepository. - Link
spdlog::spdlogfor compiled library usage orspdlog::spdlog_header_onlyfor header-only integration. - Set
SPDLOG_FMT_EXTERNALorSPDLOG_FMT_EXTERNAL_HObefore the subdirectory call to use system-installed fmt instead of the bundled version. - Enable
SPDLOG_BUILD_SHAREDto produce shared libraries instead of static archives. - Enable
SPDLOG_USE_STD_FORMATfor C++20std::formatsupport, though this requires C++20 compliance. - The root
CMakeLists.txtautomatically propagates include directories and threading dependencies through the exported targets.
Frequently Asked Questions
What is the difference between spdlog::spdlog and spdlog::spdlog_header_only?
The spdlog::spdlog target references a compiled library (static or shared) that requires linking against built object files, while spdlog::spdlog_header_only is an INTERFACE target defined in CMakeLists.txt that provides all functionality through headers without compiled binaries. The header-only target is useful for reducing build complexity, whereas the compiled library reduces compilation times in larger projects by avoiding repeated template instantiation.
How do I integrate spdlog with an external fmt library?
Set SPDLOG_FMT_EXTERNAL=ON for a compiled external fmt or SPDLOG_FMT_EXTERNAL_HO=ON for header-only external fmt before calling add_subdirectory(spdlog). This configuration tells the spdlog build system to link against fmt::fmt or fmt::fmt-header-only targets rather than using the bundled fmt headers located in include/spdlog/fmt/bundled/.
Can I build spdlog as a shared library?
Yes. Set SPDLOG_BUILD_SHARED=ON before adding the spdlog subdirectory, or set the generic CMake variable BUILD_SHARED_LIBS=ON. This causes the spdlog::spdlog target to reference a shared library (libspdlog.so on Linux, spdlog.dll on Windows) instead of a static archive.
What C++ standard does spdlog require?
By default, spdlog requires C++11. However, if you enable SPDLOG_USE_STD_FORMAT=ON, the library requires C++20 to support the standard library's <format> header. The CMakeLists.txt enforces these requirements through target_compile_features checks when this option is enabled.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →