Различные статьи по Qt и c++

Установка и подключение spdlog в Qt/CMake-проект

Введение

Разберём практическую настройку — подключение spdlog (и идущего вместе с ним fmt) к CMake-проекту, продолжая подход к управлению зависимостями из основного цикла статей про CMake/Boost и vcpkg/Conan.

Концепция

spdlog доступен через основные пакетные менеджеры (vcpkg, Conan) и может использоваться как header-only библиотека (проще подключить, но дольше компилируется при частом использовании в разных единицах компиляции) или как предварительно скомпилированная статическая/динамическая библиотека (быстрее компиляция использующего кода, требует отдельного шага сборки самой библиотеки) — выбор между этими режимами делается через CMake-опцию SPDLOG_BUILD_SHARED или просто выбором соответствующего варианта пакета в vcpkg.

Пример кода: Установка и подключение

# CMakeLists.txt — подключение spdlog через vcpkg (рекомендуемый, наиболее предсказуемый способ)
cmake_minimum_required(VERSION 3.20)
project(LoggingDemo)

set(CMAKE_CXX_STANDARD 17)

find_package(spdlog CONFIG REQUIRED)
find_package(Qt6 REQUIRED COMPONENTS Core)

add_executable(LoggingDemo main.cpp)

target_link_libraries(LoggingDemo PRIVATE
    spdlog::spdlog       # предсобранная версия — быстрее компиляция использующего кода
    # spdlog::spdlog_header_only  # альтернатива: header-only вариант, не требует отдельной сборки .lib/.a
    Qt6::Core
)
# Установка через vcpkg
vcpkg install spdlog
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=[путь_к_vcpkg]/scripts/buildsystems/vcpkg.cmake
cmake --build build
// main.cpp — минимальная проверка, что подключение работает
#include <spdlog/spdlog.h>

int main()
{
    spdlog::info("spdlog подключен и работает, версия: {}.{}.{}",
                 SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH);
    return 0;
}
# Альтернатива без пакетного менеджера — через FetchContent (для проектов без vcpkg/Conan)
include(FetchContent)
FetchContent_Declare(
    spdlog
    GIT_REPOSITORY https://github.com/gabime/spdlog.git
    GIT_TAG v1.14.1
)
FetchContent_MakeAvailable(spdlog)

target_link_libraries(LoggingDemo PRIVATE spdlog::spdlog)

Пояснения к коду

find_package(spdlog CONFIG REQUIRED) подключает CMake-конфигурацию, поставляемую самим пакетом spdlog (через vcpkg toolchain-файл, указанный при конфигурации) — выбор между spdlog::spdlog (предсобранная библиотека) и spdlog::spdlog_header_only (только заголовки) определяет, компилируется ли код самой библиотеки один раз заранее, или повторно встраивается в каждую единицу компиляции, использующую spdlog, что напрямую влияет на время полной пересборки проекта. Альтернатива через FetchContent — практичный вариант для проектов, ещё не перешедших на vcpkg/Conan (основной цикл статей, статьи 33/40), позволяющий получить и собрать spdlog непосредственно из исходного репозитория без отдельной предварительной установки пакетного менеджера.

Подводные камни

  • Несовпадение версии fmt, используемой spdlog внутри, с версией fmt, которая может отдельно использоваться где-то ещё в том же проекте (например, для статьи 337) — если в проекте подключены и spdlog, и отдельно fmt как самостоятельная зависимость, важно убедиться, что используется одна и та же версия (spdlog по умолчанию использует встроенную, «bundled» версию fmt, если явно не указано иное через SPDLOG_FMT_EXTERNAL), иначе возможны конфликты символов при линковке.
  • Выбор header-only варианта для крупного проекта с большим количеством файлов, активно использующих spdlog, без замера реального влияния на время компиляции — для небольших проектов разница в большинстве случаев незаметна, но для крупной кодовой базы с десятками файлов, включающих <spdlog/spdlog.h>, переход на предсобранную библиотеку (spdlog::spdlog вместо spdlog::spdlog_header_only) может заметно сократить время полной пересборки.
  • Использование FetchContent с нефиксированной версией (например, ветка master вместо конкретного тега) — аналогично общей проблеме версионирования зависимостей из основного цикла статей про CMake, отсутствие фиксации конкретной версии делает сборки невоспроизводимыми во времени, поскольку содержимое ветки может измениться между разными запусками сборки на разных машинах или в разное время.
  • Забытое явное указание Qt6::Core или другого нужного компонента Qt при совместном использовании spdlog и Qt в одном исполняемом файле, что не является проблемой именно spdlog, но частая практическая ошибка при добавлении новой внешней зависимости в уже существующий Qt-проект — CMake-конфигурация должна продолжать явно перечислять все используемые Qt-компоненты независимо от добавления сторонних библиотек логирования.