《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》
🎬 艾莉丝的简介:

文章目录

1 ~> ChatServer项目CMake构建实战
1.1 项目背景与构建前置要求
- 项目:
AIChatServer,C++聊天服务器项目,依赖自研SDK静态库与第三方开源库 - 编译前置条件
- 已经完成
main.cpp、ChatServer.cpp业务源码开发 - 自研SDK静态库
libai_chat_sdk.a已经编译安装至/usr/local/lib - 系统预先部署依赖库:OpenSSL、jsoncpp、fmt、spdlog、gflags、sqlite3
- CMake最低版本要求:3.10,C++标准采用C++17
- 已经完成
- 工程目录规范
- 采用外部构建(out‑of‑source build),创建独立
build编译目录,避免编译产物污染源码目录
- 采用外部构建(out‑of‑source build),创建独立
1.2 CMakeLists.txt编写、错误修正与完整可用代码
1.2.1 原始素材中存在的典型错误
- 变量名拼写错误:
CHAKE_*系列,正确前缀为CMAKE_ target_link_libraries错误填写静态库全名libai_chat_sdk,‑l链接器参数不需要前缀lib与后缀.a- 重复添加链接库
gflags - 依赖库
OpenSSL现代CMake规范使用导入目标OpenSSL::SSL、OpenSSL::Crypto link_directories作用:指定静态库搜索路径,必须写在add_executable之前,对后续target生效EXECUTABLE_OUTPUT_PATH旧变量,现代CMake推荐使用CMAKE_RUNTIME_OUTPUT_DIRECTORY
1.2.2 修正完成完整CMakeLists.txt
# 指定CMake最低版本
cmake_minimum_required(VERSION 3.10)
# 定义项目名称
project(AIChatServer)
# 设置C++编译标准 C++17
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 设置默认构建类型,调试使用Debug;发布版本编译改为Release
set(CMAKE_BUILD_TYPE Debug)
# 设置静态库搜索路径,必须放置在add_executable之前
link_directories(/usr/local/lib)
# 生成可执行程序,指定项目源码文件
add_executable(AIChatServer
main.cpp
ChatServer.cpp
)
# 设置可执行文件输出目录,输出至build目录下
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
# 查找系统OpenSSL依赖库
find_package(OpenSSL REQUIRED)
# 添加编译宏定义,启用cpp‑httplib的OpenSSL HTTPS支持
target_compile_definitions(AIChatServer PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
# 链接所有依赖库
# 自研静态库ai_chat_sdk,不要写lib前缀,不要写.a后缀
target_link_libraries(AIChatServer
ai_chat_sdk # 自研SDK静态库 libai_chat_sdk.a
jsoncpp
fmt
spdlog
gflags
OpenSSL::SSL
OpenSSL::Crypto
sqlite3
)
1.3 CMake关键指令原理梳理
1.3.1 link_directories
- 功能:告诉链接器去哪里搜索静态/动态库文件
- 语法:
link_directories(目录路径) - 重要注意事项
- 该指令作用域为后续所有target,必须放在add_executable / add_library前面,写在后面不会生效
- 现代CMake优先使用
find_package导入目标,link_directories多用于本地自定义静态库 - 示例:
link_directories(/usr/local/lib),用于读取安装到此路径下自研静态库
1.3.2 target_link_libraries 链接库规则
- Linux下静态库命名规范:
libxxx.a、动态库libxxx.so - CMake填写规则:只写中间库名
xxx,CMake自动补全lib前缀,传递‑lxxx给gcc链接器 - 错误案例:静态库文件
libai_chat_sdk.a,写libai_chat_sdk→ 传递参数‑llibai_chat_sdk,链接器查找liblibai_chat_sdk.a,文件不存在直接报错 - 报错信息识别:
cannot find -llibai_chat_sdk: No such file or directory,就是库名多写lib前缀导致
1.3.3 构建类型 CMAKE_BUILD_TYPE
Debug:调试模式,开启调试符号‑g,不做代码优化,开发调试阶段使用Release:发布模式,开启代码优化,去除调试符号,正式上线发布编译使用- 修改方式:修改CMakeLists内
CMAKE_BUILD_TYPE变量,或者cmake命令行传入参数‑DCMAKE_BUILD_TYPE=Release
1.3.4 target_compile_definitions
- 作用:为指定编译目标添加预编译宏
- 示例:
CPPHTTPLIB_OPENSSL_SUPPORT,开启http‑lib库的SSL HTTPS能力,没有该宏会无法启用HTTPS
1.4 完整编译流程(外部构建 out‑of‑source build)
1.4.1 创建构建目录并进入
# 在ChatServer源码目录下创建build文件夹
mkdir -p build
cd build
1.4.2 执行CMake配置
# cmake .. 代表读取上一级目录的CMakeLists.txt,生成Makefile构建脚本
cmake ..
- 成功输出标志:
Configuring done、Generating done,生成Makefile与CMake缓存文件 - 失败场景:依赖库缺失(OpenSSL未安装等),
find_package会直接报错终止配置
1.4.3 执行编译链接
make
- 编译阶段:把
.cpp源码编译为.o目标文件 - 链接阶段:把目标文件 + 所有指定静态/动态库合并,生成最终可执行文件
AIChatServer - 成功标志:
[100%] Built target AIChatServer,可执行文件生成在build目录
1.5 高频踩坑问题与排错方案
1.5.1 链接报错:找不到自定义静态库
- 报错:
cannot find -lxxx: No such file or directory排查步骤
- 确认静态库真实存在:
ls /usr/local/lib/libai_chat_sdk.a,确认库文件已经部署 - 确认
link_directories(/usr/local/lib)写在add_executable之前 target_link_libraries库名不要写lib前缀,不要写.a后缀- 如果特殊情况,强制指定完整库文件:
‑l:libai_chat_sdk.a
1.5.2 编译通过,链接阶段报符号未定义
- 现象:编译cpp源文件正常,链接报类、函数未定义(例如日志器、ChatSDK相关符号找不到)
- 根因:没有链接自研SDK静态库,或者静态库编译ABI不匹配(Debug/Release模式不一致,C++标准不一致)
- 解决方案:确认
target_link_libraries加入自研库,确认SDK库编译C++标准、构建类型和当前项目完全一致
1.5.3 头文件找不到
- 解决方案:使用
include_directories()或者target_include_directories()添加头文件搜索路径
# 推荐现代写法,仅对AIChatServer目标生效
target_include_directories(AIChatServer PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../sdk/include
)
1.6 Release发布版本编译
两种方式切换Release模式
- 修改CMakeLists.txt:
set(CMAKE_BUILD_TYPE Release),重新执行cmake … && make - 命令行传入参数,不修改文件
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make
1.7 补充CMake概念拓展面试要点
- 外部构建(out‑of‑source):编译产物全部放到build,源码目录保持干净,是工业界标准做法,禁止在源码目录直接执行cmake
- PRIVATE/PUBLIC/INTERFACE
- PRIVATE:仅当前编译目标生效,不会传递给依赖它的其他target
- PUBLIC:当前目标 + 依赖本目标的其他target都会生效
- INTERFACE:仅依赖本目标的target生效,自身不生效
find_package(OpenSSL REQUIRED):REQUIRED代表找不到库直接终止CMake配置,不会静默失败- link_directories的缺点:全局生效,现代CMake优先使用导入目标(例如
OpenSSL::SSL),导入目标自带库路径、头文件路径,不需要手动配置link_directories
结尾
uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!
|
结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主“一键四连”哦!
往期回顾:
🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/2401_89899187/article/details/168885168





