Qt以直接包含源码的方式引用spdlog

在Qt项目中直接包含spdlog源码是最简单且跨平台的集成方式。以下是详细的实现步骤:

1. 下载spdlog源码

通过spdlog的GitHub仓库下载源码:v1.15.3.zip

将v1.15.3.zip解压缩,拷贝include、src文件夹到third_party/spdlog,Qt项目结构如下:

my_qt_project/
├── my_qt_project.pro
├── main.cpp
├── ... (其他源文件)
└── third_party/   # 新建这个目录
    └── spdlog/    # 从GitHub下载的spdlog源码
        ├── include/
        │   └── spdlog/
        └── src/

2. 修改.pro文件

在.pro文件中添加下面的内容:

# spdlog需要C++11及以上
CONFIG += c++11

# 添加spdlog头文件路径
INCLUDEPATH += $$PWD/third_party/spdlog/include

# 定义spdlog配置宏
DEFINES += SPDLOG_COMPILED_LIB

# 添加spdlog源文件
SOURCES += \
    third_party/spdlog/src/async.cpp \
    third_party/spdlog/src/bundled_fmtlib_format.cpp \
    third_party/spdlog/src/cfg.cpp \
    third_party/spdlog/src/color_sinks.cpp \
    third_party/spdlog/src/file_sinks.cpp \
    third_party/spdlog/src/spdlog.cpp \
    third_party/spdlog/src/stdout_sinks.cpp \

3. 创建日志服务

3.1 日志服务头文件 (LogService.h)

#ifndef LOGSERVICE_H
#define LOGSERVICE_H

#include <QString>
#include <spdlog/spdlog.h>

class LogService
{
public:
    LogService();

    void startup();
    void shutdown();

    inline void trace(const QString &msg)
    {
        spdlog::trace(msg.toStdString().c_str());
    }

    inline void debug(const QString &msg)
    {
        spdlog::debug(msg.toStdString().c_str());
    }

    inline void info(const QString &msg)
    {
        spdlog::info(msg.toStdString().c_str());
    }

    inline void warn(const QString &msg)
    {
        spdlog::warn(msg.toStdString().c_str());
    }

    inline void error(const QString &msg)
    {
        spdlog::error(msg.toStdString().c_str());
    }

    inline void critical(const QString &msg)
    {
        spdlog::critical(msg.toStdString().c_str());
    }
};

#endif // LOGSERVICE_H

3.2 日志服务实现 (LogService.cpp)

#include <QDir>
#include <QMessageBox>
#include <QString>

#include <spdlog/spdlog.h>
#include <spdlog/sinks/rotating_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/async.h>

#include "LogService.h"

LogService::LogService()
{

}

void LogService::startup()
{
    try
    {
        // 创建日志目录
        QDir logDir("logs");
        if (!logDir.exists() && !logDir.mkpath("."))
        {
            QMessageBox::critical(nullptr, "日志错误", "无法创建日志目录");
            return;
        }

        // 初始化线程池(8192个消息,1个后台线程)
        spdlog::init_thread_pool(8192, 1);

        // 设置自动刷新
        spdlog::flush_every(std::chrono::seconds(5));

        // 创建滚动文件sink(最大5MB,保留3个备份)
        auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
                    "logs/app.log", 1024 * 1024 * 5, 100);

        // 创建控制台sink(带颜色)
        auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();

        // 组合sinks
        std::vector<spdlog::sink_ptr> sinks{rotating_sink, console_sink};

        // 创建异步日志器
        auto logger = std::make_shared<spdlog::async_logger>(
                    "qt_logger",
                    sinks.begin(),
                    sinks.end(),
                    spdlog::thread_pool(),
                    spdlog::async_overflow_policy::block
                    );

        // 设置日志格式
        logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [thread %t] %v");

        // 设置全局日志器
        spdlog::set_default_logger(logger);

        // 设置日志级别
#ifdef QT_DEBUG
        spdlog::set_level(spdlog::level::debug);
#else
        spdlog::set_level(spdlog::level::info);
#endif

        // 刷新错误立即写入
        logger->flush_on(spdlog::level::err);

        spdlog::info("====== Application startup ======");
        spdlog::debug("Enable debug log");

        // 获取Qt的版本号
        spdlog::info("Current Qt version: {}", qVersion());

        // 获取SPDLOG版本号
        auto logVersion = QString("%1.%2.%3").arg(QString::number(SPDLOG_VER_MAJOR),
                                                  QString::number(SPDLOG_VER_MINOR),
                                                  QString::number(SPDLOG_VER_PATCH)
                                                  ).toStdString();
        spdlog::info("Current spdlog version: {}", logVersion.c_str());
    }
    catch (const spdlog::spdlog_ex& ex)
    {
        QMessageBox::critical(nullptr, "日志初始化错误",
                              QString("日志系统初始化失败: %1").arg(ex.what()));
    }
}

void LogService::shutdown()
{
    // 清理日志系统
    spdlog::info("====== Application shutdown ======");
    spdlog::shutdown();
}

4. 使用日志服务记录日志

4.1 主窗口头文件 (mainwindow.h)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "LogService.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    LogService *m_logService;
};
#endif // MAINWINDOW_H

4.2 主窗口实现 (mainwindow.cpp)

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    m_logService = new LogService();
    m_logService->startup();
}

MainWindow::~MainWindow()
{
    m_logService->shutdown();
    delete m_logService;
}
posted @ 2025-07-05 21:45  xhubobo  阅读(239)  评论(0)    收藏  举报