【C++ 基于微服务的即时通讯系统】基建三件套:gflags + gtest + spdlog 源码编译安装与实战入门


🔥草莓熊Lotso: 个人主页
❄️个人专栏: 《C++知识分享》 《Linux 入门到实践:零基础也能懂》
✨生活是默默的坚持,毅力是永久的享受!


🎬 博主简介:


前言:

做 C++ 高性能后端开发这么多年,我见过太多新人一头扎进业务逻辑里,却忽略了最基础的工程化工具。命令行参数靠手搓、打日志全用 printf、单元测试全靠肉眼跑,不仅开发效率低,出了问题排查起来更是灾难。尤其是做 Redis 二次开发、微服务组件这类底层项目,gflags、gtest、spdlog 这三个基本是行业标配:gflags 搞定灵活的命令行参数管理,gtest 守住单元测试的质量关,spdlog 提供高性能的日志输出。今天就带大家从源码编译开始,从零到一搞定这三个工具的安装和基础使用,路上踩过的坑都给大家标得明明白白。


一. gflags:Google 命令行参数解析库

1.1 工具简介

gflags 是 Google 开源的命令行参数解析库,相比 C 标准库的 getopt,它的优势非常突出:

  • 支持类型安全的参数定义,自动做类型校验,不用自己写转换逻辑
  • 参数可以分散定义在各个源文件中,全局生效,非常适合大型多模块项目
  • 原生支持默认值、参数说明、布尔参数快捷开关
  • 很多知名开源项目(brpc、leveldb、Ceph)都在使用,是 C++ 项目的事实标准之一

1.2 源码编译与安装

这里我们用官方源码编译安装,避免系统包管理器版本过旧、特性缺失的问题。

步骤 1:下载源码

bash 复制代码
git clone https://github.com/gflags/gflags.git
cd gflags

步骤 2:CMake 配置

推荐单独创建 build 目录做外编译,避免污染源码目录。

bash 复制代码
mkdir build && cd build
# 配置安装路径到/usr/local,编译动态库
cmake .. \
  -DCMAKE_INSTALL_PREFIX=/usr/local \
  -DBUILD_SHARED_LIBS=ON \
  -DGFLAGS_BUILD_STATIC_LIBS=OFF

踩坑提醒:默认情况下 gflags 只编译静态库,必须加上BUILD_SHARED_LIBS=ON才会生成动态库,方便后续项目动态链接。

步骤 3:编译与安装

bash 复制代码
# 并行编译,核心数根据自己机器配置调整
make -j$(nproc)
# 安装到系统目录
sudo make install

步骤 4:验证安装

安装完成后,可以用 pkg-config 查看版本,确认安装成功:

bash 复制代码
pkg-config --modversion gflags

正常输出版本号就说明安装路径、库文件都没问题。

1.3 基础使用示例

我们写一个最简单的 Redis 连接参数示例,看看 gflags 在实际项目里怎么用。

创建demo_gflags.cpp:

cpp 复制代码
#include <iostream>
#include <gflags/gflags.h>

// 定义命令行参数:类型,参数名,默认值,参数说明
DEFINE_string(redis_host, "127.0.0.1", "Redis服务器地址");
DEFINE_int32(redis_port, 6379, "Redis服务器端口");
DEFINE_bool(enable_debug_log, true, "是否开启调试日志");

int main(int argc, char* argv[]) {
    // 解析命令行参数,第三个参数表示是否移除已解析的参数
    google::ParseCommandLineFlags(&argc, &argv, true);

    std::cout << "正在连接Redis:" 
              << FLAGS_redis_host << ":" << FLAGS_redis_port 
              << std::endl;
    std::cout << "调试日志状态:" 
              << std::boolalpha << FLAGS_enable_debug_log 
              << std::endl;

    return 0;
}

编译运行:

bash 复制代码
g++ demo_gflags.cpp -o demo_gflags -lgflags
# 默认参数运行
./demo_gflags
# 传参运行
./demo_gflags --redis_host=192.168.1.100 --redis_port=6380 --noenable_debug_log

可以看到,通过--参数名=值的方式就能传入参数,布尔参数还支持--no参数名的快捷关闭方式,非常符合工程使用习惯。


二. gtest:Google 单元测试框架

2.1 工具简介

gtest(Google Test)是目前 C++ 领域最主流的单元测试框架,功能全面且上手简单:

  • 提供丰富的断言宏,覆盖值判断、布尔判断、字符串比较、浮点数比较等场景
  • 支持测试套件、测试用例的分层组织,代码结构清晰
  • 支持死亡测试、类型参数化、值参数化等高级测试功能
  • 配合 gmock 可以实现接口 Mock,适合复杂依赖的项目做单元隔离

2.2 源码编译与安装

现在 gtest 和 gmock 已经合并在同一个官方仓库里,一次编译就能全部安装。

步骤 1:下载源码

bash 复制代码
git clone https://github.com/google/googletest.git
cd googletest

步骤 2:CMake 配置

bash 复制代码
mkdir build && cd build
cmake .. \
  -DCMAKE_INSTALL_PREFIX=/usr/local \
  -DBUILD_SHARED_LIBS=ON \
  -DINSTALL_GTEST=ON

注意:部分老版本 gtest 默认不开启安装选项,加上INSTALL_GTEST=ON更稳妥,保证执行 make install 时能正确安装头文件和库。

步骤 3:编译与安装

bash 复制代码
make -j$(nproc)
sudo make install

安装完成后,系统会生成 gtest、gtest_main、gmock、gmock_main 四个库,以及对应的头文件。

2.3 基础使用示例

我们写一个简单的字符串工具函数,然后用 gtest 编写单元测试。

创建demo_gtest.cpp:

cpp 复制代码
#include <gtest/gtest.h>
#include <string>
#include <cctype>

// 待测试的函数:字符串转大写
std::string stringToUpper(const std::string& str) {
    std::string result = str;
    for (char& ch : result) {
        ch = static_cast<char>(toupper(ch));
    }
    return result;
}

// 测试用例:第一个参数是测试套件名,第二个是测试用例名
TEST(StringUtilTest, ToUpperNormalString) {
    EXPECT_EQ(stringToUpper("hello redis"), "HELLO REDIS");
    EXPECT_EQ(stringToUpper("spdlog"), "SPDLOG");
}

TEST(StringUtilTest, ToUpperEmptyString) {
    EXPECT_EQ(stringToUpper(""), "");
}

TEST(StringUtilTest, ToUpperAlreadyUpper) {
    EXPECT_EQ(stringToUpper("GTEST"), "GTEST");
}

int main(int argc, char* argv[]) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

编译运行:

bash 复制代码
g++ demo_gtest.cpp -o demo_gtest -lgtest -lpthread
./demo_gtest

运行后会输出完整的测试结果,每个用例是否通过、耗时多少都一目了然。如果有断言失败,还会精准定位到代码行号,排查问题非常高效。


三. spdlog:高性能 C++ 日志库

3.1 工具简介

spdlog 是现在 C++ 圈子里最主流的高性能日志库,性能和易用性都拉满:

  • 支持 header-only 模式,也可以编译成库使用,集成非常方便
  • 性能远超 log4cpp、glog 等传统日志库,异步模式下能达到每秒百万级日志输出
  • 支持多种日志级别、多种输出目标(控制台、文件、滚动文件、syslog 等)
  • 原生支持 fmt 格式化,用法和 Python 的 format 类似,写起来非常顺手

做高性能服务、Redis 组件开发的话,日志绝对不能成为性能瓶颈,spdlog 基本是首选。

3.2 源码编译与安装

spdlog 有两种使用方式:直接复制头文件使用,或者编译成库安装。这里我们用编译安装的方式,更适合正规项目。

步骤 1:下载源码

bash 复制代码
git clone https://github.com/gabime/spdlog.git
cd spdlog

步骤 2:CMake 配置

bash 复制代码
mkdir build && cd build
cmake .. \
  -DCMAKE_INSTALL_PREFIX=/usr/local \
  -DSPDLOG_BUILD_SHARED=ON \
  -DSPDLOG_FMT_EXTERNAL=OFF

说明:SPDLOG_FMT_EXTERNAL=OFF表示使用 spdlog 自带的 fmt 库,不用系统单独安装 fmt,减少外部依赖。

补充:如果是小型项目,也可以不用编译,直接把源码里的include/spdlog目录复制到项目头文件路径里,spdlog 是 header-only 的,直接包含就能用,零依赖。

步骤 3:编译与安装

bash 复制代码
make -j$(nproc)
sudo make install

3.3 基础使用示例

创建demo_spdlog.cpp,演示控制台日志和文件日志的基础用法:

cpp 复制代码
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>

int main() {
    // 设置全局日志级别
    spdlog::set_level(spdlog::level::debug);

    // 控制台输出不同级别的日志
    spdlog::info("Redis连接成功,地址:{}:{}", "127.0.0.1", 6379);
    spdlog::debug("当前连接池数量:{}", 8);
    spdlog::warn("Redis内存使用率超过80%");
    spdlog::error("写入Key失败,key:{}", "user:profile:1001");

    // 创建文件日志器,输出到app.log
    auto file_logger = spdlog::basic_logger_mt("file_logger", "app.log");
    file_logger->info("服务启动完成,运行正常");

    return 0;
}

编译运行:

bash 复制代码
g++ demo_spdlog.cpp -o demo_spdlog -lspdlog -lpthread
./demo_spdlog

运行后控制台会输出带时间戳、带颜色的格式化日志,同时当前目录下会生成app.log文件,里面也有对应的日志内容。


四. 三套件整合:CMake 项目实战

单独使用没问题,实际项目里一般是三个工具搭配使用。这里给大家一个完整的 CMakeLists.txt 示例,演示怎么把三个工具规范地整合到一个项目里。

项目目录结构:

Plain 复制代码
redis_demo/
├── CMakeLists.txt
├── src/
│   └── main.cpp
└── test/
    └── test_main.cpp

CMakeLists.txt:

cmake 复制代码
cmake_minimum_required(VERSION 3.10)
project(redis_demo)

# 使用C++17标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 查找系统中的依赖库
find_package(gflags REQUIRED)
find_package(GTest REQUIRED)
find_package(spdlog REQUIRED)

# 主程序
add_executable(redis_demo src/main.cpp)
target_link_libraries(redis_demo 
    gflags::gflags 
    spdlog::spdlog 
    pthread
)

# 单元测试程序
enable_testing()
add_executable(unit_test test/test_main.cpp)
target_link_libraries(unit_test 
    GTest::gtest 
    GTest::gtest_main 
    pthread
)
add_test(NAME unit_test COMMAND unit_test)

这样配置之后,直接用 cmake 编译就能自动链接三个库,工程结构清晰,依赖管理规范。


五. 核心要点总结

最后给大家提炼一下这三个工具安装和使用的核心要点,帮大家避开常见的坑:

  1. 优先源码编译安装:系统包管理器的版本往往滞后很多,源码编译可以自由控制版本,也能根据需求开启或关闭特性,更好地适配自己的编译环境。
  2. 动静态库按需选择:开发阶段推荐用动态库,编译速度快;发布部署阶段可以用静态库,减少运行时依赖,根据自己的场景选择即可。
  3. 工具定位清晰分工:gflags 管参数配置、gtest 管单元测试、spdlog 管日志输出,三者各司其职,是 C++ 后端项目的标准工程化配置。
  4. 注意库路径配置 :默认安装到/usr/local下一般不需要额外配置路径;如果安装到自定义目录,记得把库路径加到LD_LIBRARY_PATH环境变量里,避免运行时找不到动态库。

结语:

html 复制代码
🍓 我是草莓熊 Lotso!若这篇技术干货帮你打通了学习中的卡点:
👀 【关注】跟我一起深耕技术领域,从基础到进阶,见证每一次成长
❤️ 【点赞】让优质内容被更多人看见,让知识传递更有力量
⭐ 【收藏】把核心知识点、实战技巧存好,需要时直接查、随时用
💬 【评论】分享你的经验或疑问(比如曾踩过的技术坑?),一起交流避坑
🗳️ 【投票】用你的选择助力社区内容方向,告诉大家哪个技术点最该重点拆解
技术之路难免有困惑,但同行的人会让前进更有方向~愿我们都能在自己专注的领域里,一步步靠近心中的技术目标!

结语:其实做底层开发越久,越能体会到 "工欲善其事,必先利其器" 的道理。这三个工具看似都是不起眼的基础组件,却是整个项目工程化的基石。参数管理规范了,测试覆盖到位了,日志输出清晰了,后面开发业务、排查问题才能事半功倍。后续我也会继续分享更多 C++ 后端、Redis 相关的开发技巧和底层原理,大家有什么想看的内容,或者编译安装遇到什么问题,欢迎在评论区留言交流。

✨把这些内容吃透超牛的!放松下吧✨ ʕ˘ᴥ˘ʔ づきらど

相关推荐
jaronho1 小时前
【脚本】 【Linux】启动所有网卡
linux·运维·服务器
bksczm1 小时前
Redis基础篇之初识分布式
数据库·redis·分布式
叶总没有会1 小时前
Gateway--网关
spring cloud·微服务·gateway
H.莓飛1 小时前
【C++】类与对象(末):static、友元与拷贝优化
linux·开发语言·c++·visual studio
for_ever_love__1 小时前
MySQL 索引类型全解:B+Tree / Hash / R-Tree / 全文 的底层差异,以及一次性建对的选型表
数据库·mysql·b+树·唯一索引·全文索引·索引类型·索引分类
仍然.10 小时前
Redis---缓存
数据库·redis·缓存
Aloudata10 小时前
LookML 语义模型 vs 企业级独立语义层:BI 建模语言能否承担企业语义底座?
数据库·人工智能·数据分析·数据资产·dataagent
程序员-Benothing10 小时前
Vim编辑器从入门到精通:模式、快捷键、配置、插件
linux·运维·服务器
细嗅蔷薇@10 小时前
排序和分⻚(order by 、limit)
数据库·oracle