当前位置: 首页 > news >正文

muduo 网络库学习项目引入 Boost 依赖

文章目录

  • 下载 [Boost 源码库](https://www.boost.org/)编译
  • 通过 CMake 引入 Boost 项目
  • Boost 链接库指引文档的问题

muduo 这个项目比较老旧了,但是仍然是学习网络库实现的一个不错的参考,所以还是得看看书自己动手实践一下。

没想到跟着书上的代码练手上来就有依赖问题,boost::noncopyable 其实这个就是把拷贝构造函数和拷贝运算符 delete 了的一个基类,就算子类不显式声明拷贝构造函数和拷贝运算符删除,但是实际进行对象的拷贝构造的时候还是会链式构造递归到基类的构造过程,这个时候发现拷贝构造函数被显式地标记为 delete 就会报错了:

/home/fredom/workspace/muduo/test/misc/boost_valid.cpp: In function ‘int main()’:
/home/fredom/workspace/muduo/test/misc/boost_valid.cpp:33:20: error: use of deleted function ‘MyClass::MyClass(const MyClass&)’33 |     MyClass obj2 = obj1;  // 这里会报错,尝试拷贝构造|                    ^~~~
/home/fredom/workspace/muduo/test/misc/boost_valid.cpp:16:7: note: ‘MyClass::MyClass(const MyClass&)’ is implicitly deleted because the default definition would be ill-formed:16 | class MyClass : public NonCopyable {|       ^~~~~~~
/home/fredom/workspace/muduo/test/misc/boost_valid.cpp:16:7: error: use of deleted function ‘NonCopyable::NonCopyable(const NonCopyable&)’
/home/fredom/workspace/muduo/test/misc/boost_valid.cpp:11:5: note: declared here11 |     NonCopyable(const NonCopyable&) = delete;|     ^~~~~~~~~~~
/home/fredom/workspace/muduo/test/misc/boost_valid.cpp:35:12: error: use of deleted function ‘MyClass& MyClass::operator=(const MyClass&)’35 |     obj3 = obj1;          // 这里也会报错,尝试拷贝赋值|            ^~~~
/home/fredom/workspace/muduo/test/misc/boost_valid.cpp:16:7: note: ‘MyClass& MyClass::operator=(const MyClass&)’ is implicitly deleted because the default definition would be ill-formed:16 | class MyClass : public NonCopyable {|       ^~~~~~~
/home/fredom/workspace/muduo/test/misc/boost_valid.cpp:16:7: error: use of deleted function ‘NonCopyable& NonCopyable::operator=(const NonCopyable&)’
/home/fredom/workspace/muduo/test/misc/boost_valid.cpp:13:18: note: declared here13 |     NonCopyable& operator=(const NonCopyable&) = delete;|                  ^~~~~~~~
make[2]: *** [test/CMakeFiles/boost_valid.dir/build.make:76: test/CMakeFiles/boost_valid.dir/misc/boost_valid.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:134: test/CMakeFiles/boost_valid.dir/all] Error 2
make: *** [Makefile:136: all] Error 2
已完成 生成,但出现错误。
#include <boost/filesystem.hpp>
#include <iostream>class NonCopyable {
public:// 默认构造函数和析构函数NonCopyable() = default;~NonCopyable() = default;// 禁用拷贝构造函数NonCopyable(const NonCopyable&) = delete;// 禁用拷贝赋值运算符NonCopyable& operator=(const NonCopyable&) = delete;
};class MyClass : public NonCopyable {
public:MyClass() = default;~MyClass() = default;// 其他成员函数可以正常定义void doSomething() {// 示例操作}
};int main() {boost::filesystem::path path(".");std::cout << "Current path: " << boost::filesystem::absolute(path) << std::endl;MyClass obj1;MyClass obj2 = obj1;  // 这里会报错,尝试拷贝构造MyClass obj3;obj3 = obj1;          // 这里也会报错,尝试拷贝赋值return 0;
}

但是 Boost 库其实也为使用者提供了一个这样的基类,所以不用用户自己编写直接继承自 Boost 提供的基类完成这个功能也是可以的,而我们确实应该尽量使用公共开源的库避免重复造轮子,一个最重要的原因我认为是这些公开的库经过了社区甚至是生产环境的大量测试和验证,出问题的情况非常少,而我们自己写的轮子往往无法得到充分的测试。

下载 Boost 源码库编译

在这里插入图片描述

![[Pasted image 20240908145830.png]]

![[Pasted image 20240908150756.png]]

这里根据操作系统的平台选择对应的源码压缩包。下载下来之后解压,然后在项目根目录新建 install 目录用于存放编译产物。

./bootstrap
b2 install --prefix=$PWD/install

现在开始编译,前提是系统中已经安装了对应的编译工具链比如 MinGW 或者 GNU gcc/g++ 。这个过程可能需要等一会,然后在 install 目录下就会有编译生成的产物了。

┌[fredom@HM-3080Ti 15:11:31] ~/workspace/boost_1_86_0
└> ls
total 2.8M
-rwxrwxr-x   1 fredom fredom 721K Sep  6 17:32 b2*
drwxrwxr-x   6 fredom fredom 4.0K Sep  6 17:46 bin.v2/
drwxr-xr-x 143 fredom fredom  12K Aug  8 06:43 boost/
-rw-r--r--   1 fredom fredom  851 Aug  8 06:07 boost-build.jam
-rw-r--r--   1 fredom fredom  21K Aug  8 06:07 boostcpp.jam
-rw-r--r--   1 fredom fredom  989 Aug  8 06:07 boost.css
-rw-r--r--   1 fredom fredom 6.2K Aug  8 06:07 boost.png
-rw-r--r--   1 fredom fredom 2.5K Aug  8 06:07 bootstrap.bat
-rwxr-xr-x   1 fredom fredom  11K Aug  8 06:07 bootstrap.sh*
-rw-rw-r--   1 fredom fredom 1.9M Sep  6 17:46 build.log
drwxr-xr-x   8 fredom fredom 4.0K Aug  8 06:43 doc/
-rw-r--r--   1 fredom fredom  769 Aug  8 06:07 index.htm
-rw-r--r--   1 fredom fredom 5.3K Aug  8 06:43 index.html
drwxrwxr-x   4 fredom fredom 4.0K Sep  6 17:45 install/
-rw-r--r--   1 fredom fredom  291 Aug  8 06:07 INSTALL
-rw-r--r--   1 fredom fredom  17K Aug  8 06:07 Jamroot
drwxr-xr-x 152 fredom fredom 4.0K Aug  8 06:43 libs/
-rw-r--r--   1 fredom fredom 1.4K Aug  8 06:07 LICENSE_1_0.txt
drwxr-xr-x   4 fredom fredom 4.0K Aug  8 06:07 more/
-rw-rw-r--   1 fredom fredom  986 Sep  6 17:32 project-config.jam
-rw-r--r--   1 fredom fredom  541 Aug  8 06:07 README.md
-rw-r--r--   1 fredom fredom 2.6K Aug  8 06:07 rst.css
drwxr-xr-x   2 fredom fredom 4.0K Aug  8 06:07 status/
drwxr-xr-x  14 fredom fredom 4.0K Aug  8 06:07 tools/┌[fredom@HM-3080Ti 15:11:33] ~/workspace/boost_1_86_0
└> duone
1M      ./more
180M    ./boost
287M    ./bin.v2
227M    ./install
5M      ./status
28M     ./tools
613M    ./libs
121M    ./doc
1462M   .┌[fredom@HM-3080Ti 15:12:27] ~/workspace/boost_1_86_0/install
└> tree . -L 2
.
├── include
│   └── boost
└── lib└── cmake

通过 CMake 引入 Boost 项目

Boost 程序库大部分都是头文件库,也就是通过 include 头文件到源文件中直接编译即可获得对应的功能,但是部分常用库还是需要额外的源文件生成的库通过链接之后才能使用,因此需要在 CMake 中指定这些需要链接的库的引入方式。

在配置 Boost 的 CMake 中,学习到了一些 CMake 的相关知识。一般 CMake 引入外部项目都是通过 find_package 完成,然后外部项目对应的需要提供 Find<PackageName>.cmake 或者 <PackageName>Config.cmake / <packagename>-config.cmake 文件,其中前者是比较早期的 CMake 引入项目的模式,现在是推荐使用 config 模式来引入项目,两者对应的用户设置搜索路径为:

  1. module modeset(CMAKE_MODULE_PATH path/to/FindXXX.cmake)
  2. config modeset(CMAKE_PREFIX_PATH) path/to/XXXConfig.cmake)

CMake constructs a set of possible installation prefixes for the package. Under each prefix several directories are searched for a configuration file. The tables below show the directories searched. Each entry is meant for installation trees following Windows (W), UNIX (U), or Apple (A) conventions

EntryConvention
<prefix>/W
<prefix>/(cmake|CMake)/W
<prefix>/<name>*/W
<prefix>/<name>*/(cmake|CMake)/W
<prefix>/<name>*/(cmake|CMake)/<name>*/ 1W
<prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/U
<prefix>/(lib/<arch>|lib*|share)/<name>*/U
<prefix>/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/U
<prefix>/<name>*/(lib/<arch>|lib*|share)/cmake/<name>*/W/U
<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/W/U
<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/W/U

所以这里我踩了一个坑,把 install/lib/cmake 目录复制到当前的 muduo 学习项目的 cmake 目录中,然后设置 CMAKE_PREFIX_PATH 指向这个目录,虽然这样子确实能找到指定版本的 Boost ,并且设置了变量 Boost_FOUND=TRUE ,但是实际上给出的变量展开的值全都是错误的(比如头文件 include 目录居然指向的是 muduo 项目下一个不存在的目录),可以看一眼 Boost 的头文件查找变量是如何设置的:

┌[fredom@HM-3080Ti 15:22:02] ~/workspace/boost_1_86_0/install/lib/cmake/boost_headers-1.86.0
└> cat boost_headers-config.cmake 
# Generated by Boost 1.86.0if(TARGET Boost::headers)return()
endif()if(Boost_VERBOSE OR Boost_DEBUG)message(STATUS "Found boost_headers ${boost_headers_VERSION} at ${boost_headers_DIR}")
endif()mark_as_advanced(boost_headers_DIR)# Compute the include and library directories relative to this file.get_filename_component(_BOOST_CMAKEDIR "${CMAKE_CURRENT_LIST_DIR}/../" REALPATH)# If the computed and the original directories are symlink-equivalent, use original
if(EXISTS "/home/fredom/workspace/boost_1_86_0/install/lib/cmake")get_filename_component(_BOOST_CMAKEDIR_ORIGINAL "/home/fredom/workspace/boost_1_86_0/install/lib/cmake" REALPATH)if(_BOOST_CMAKEDIR STREQUAL _BOOST_CMAKEDIR_ORIGINAL)set(_BOOST_CMAKEDIR "/home/fredom/workspace/boost_1_86_0/install/lib/cmake")endif()unset(_BOOST_CMAKEDIR_ORIGINAL)
endif()get_filename_component(_BOOST_INCLUDEDIR "${_BOOST_CMAKEDIR}/../../include/" ABSOLUTE)add_library(Boost::headers INTERFACE IMPORTED)set_target_properties(Boost::headers PROPERTIESINTERFACE_INCLUDE_DIRECTORIES "${_BOOST_INCLUDEDIR}"
)unset(_BOOST_INCLUDEDIR)
unset(_BOOST_CMAKEDIR)

注意到这一行:

get_filename_component(_BOOST_INCLUDEDIR "${_BOOST_CMAKEDIR}/../../include/" ABSOLUTE)

所以说 Boost 是通过相对于这个 config 文件所在的路径来写死 BOOST_INCLUDE_DIRS ,怪不得移动了 Boost 的 cmake 目录到其他项目下没法用,所以只能额外在项目目录下设置 Boost 库的安装路径(这里有点膈应,万一我想把这个项目和它的依赖都打包到另一个主机上开发怎么办,这路径全都不对了,还必须去另外一台主机上编译安装一遍,我就是因为自己的云服务器性能不够换到实验室的机器上来编译 Boost,但是还是想回云服务器开发的)。

以下是我的 muduo 项目目录 CMakeLists.txt 配置,引入 Boost 1.86.0 。

cmake_minimum_required(VERSION 3.20)
project(muduo)cmake_policy(SET CMP0167 OLD)set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/lib)
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/install)
set(CMAKE_PREFIX_PATH /home/fredom/workspace/boost_1_86_0/install/lib/cmake)
# set(CMAKE_MODULE_PATH /home/fredom/workspace/boost_1_86_0/install/lib/cmake) # outdatedmessage("build type ${CMAKE_BUILD_TYPE}")set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)include_directories(include)# other dependencies
find_package(Boost 1.86.0 EXACT REQUIRED CONFIGCOMPONENTS filesystemregexatomicchrono
)
if (Boost_FOUND)message("found boost ${Boost_VERSION}")message("Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIRS}")message("Boost_LIBRARIES ${Boost_LIBRARIES}")include_directories(${Boost_INCLUDE_DIRS})set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_MULTITHREADED ON)  set(Boost_USE_STATIC_RUNTIME OFF)
endif()add_subdirectory(src)
add_subdirectory(app)
add_subdirectory(test)install(FILES README.mdDESTINATION ${CMAKE_INSTALL_PREFIX}/share
)

CMake 配置输出:

[cmake] build type Debug
[cmake] Not searching for unused variables given on the command line.
[cmake] found boost 1.86.0
[cmake] Boost_INCLUDE_DIRS /home/fredom/workspace/boost_1_86_0/install/include
[cmake] Boost_LIBRARIES Boost::filesystem;Boost::regex;Boost::atomic;Boost::chrono
[cmake] -- Configuring done (0.0s)
[cmake] -- Generating done (0.0s)
[cmake] -- Build files have been written to: /home/fredom/workspace/muduo/build

可以看到引入的 COMPONENTS 组件对应的依赖 target 都引入了。

这里我在 find_package 时指定了 EXACT 关键字参数,因为实验室服务器用的人太多了,所以早就安装了另一个版本的 Boost 到 /usr/local/include 里面,这个路径也在 CMake 的默认查找路径里,但是我不想用那个比较旧的版本,所以指定必须搜索用户给定的版本否则报错中止 CMake 配置流程。

SET(sub_dir_listmisc
)SET(cpp_src_list)
# SET(c_src_list)FOREACH(_sub_dir ${sub_dir_list})FILE(GLOB sub_dir_src_list ${_sub_dir}/*.cpp)LIST(APPEND cpp_src_list ${sub_dir_src_list})# FILE(#     GLOB sub_dir_src_list ${_sub_dir}/*.c# )# LIST(APPEND c_src_list ${sub_dir_src_list})
ENDFOREACH()FOREACH(_src_file ${cpp_src_list})GET_FILENAME_COMPONENT(_src_name ${_src_file} NAME_WE)ADD_EXECUTABLE(${_src_name} ${_src_file})TARGET_LINK_LIBRARIES(${_src_name} PRIVATE ${Boost_LIBRARIES})
ENDFOREACH()

然后在其他源码子目录使用 ${Boost_LIBRARIES} 就可以指代引入的 COMPONENTS 组件的依赖库了,目前“组件”这个概念我还不是很清楚怎么在 CMake 中使用,反正如果自己想做一个开源的项目分发给其他人用,有关 CMake 的打包、安装、组件的知识是必须掌握的,这部分后面要继续学习。如果在 find_package 中没有指定任何 COMPONENTS 那么 ${Boost_LIBRARIES} 变量为空,这有点奇怪,另外 CMake 有没有能在导入项目的时候如果项目设置了 COMPONENTS 自动输出导入了哪些 COMPONENTS ?不然每次使用 Boost 库还要对着网络上的 Boost 文档吗,这也太不方便了,对网络的依赖性太强这可不好,我在公司万一只有内网,主板也没有 WIFI 连接手机热点,那咋办?

Boost 链接库指引文档的问题

官方给的一个链接库的测试例程:

![[Pasted image 20240908153540.png]]

问题是 Boost::regex 这个模块不链接动态库/静态库好像也能编译成功啊?我后面是使用 Boost::filesystemBoost::system 完成库链接的验证。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • “设计模式双剑合璧:工厂模式与策略模式在支付系统中的完美结合”
  • JLabel设置字体大小颜色背景色
  • 数据结构与算法03 顺序表+链表
  • 数字化转型专家讲师培训师唐兴通中欧国际工商学院数字化转型战略与实现路径AIGC人工智能数字化战略数字商业模式创新
  • Docker 详解及详细配置讲解
  • Linux安装Jenkins详细步骤分解
  • 前向渲染路径
  • js 查找数组对象中id相同的元素,把他们放到新数组对象中
  • 【系统架构设计师】管道-过滤器架构
  • 【Redis】Redis 主从复制原理与配置详解:解决单点故障与性能瓶颈的最佳方案
  • c++的初始化列表与const成员
  • python(进阶2)实现自动化注册和登录
  • 漫谈设计模式 [17]:状态模式
  • ✨机器学习笔记(二)—— 线性回归、代价函数、梯度下降
  • Windows本地制作nginx证书
  • [case10]使用RSQL实现端到端的动态查询
  • angular2开源库收集
  • css属性的继承、初识值、计算值、当前值、应用值
  • Flex布局到底解决了什么问题
  • GitUp, 你不可错过的秀外慧中的git工具
  • HomeBrew常规使用教程
  • JavaScript实现分页效果
  • leetcode46 Permutation 排列组合
  • Python - 闭包Closure
  • Ruby 2.x 源代码分析:扩展 概述
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • Swift 中的尾递归和蹦床
  • 看域名解析域名安全对SEO的影响
  • 前端相关框架总和
  • 设计模式(12)迭代器模式(讲解+应用)
  • 因为阿里,他们成了“杭漂”
  • 正则表达式小结
  • Java总结 - String - 这篇请使劲喷我
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • # 数据结构
  • (C++哈希表01)
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (vue)el-cascader级联选择器按勾选的顺序传值,摆脱层级约束
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (九十四)函数和二维数组
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (算法)大数的进制转换
  • (五)MySQL的备份及恢复
  • (原)本想说脏话,奈何已放下
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (原创)可支持最大高度的NestedScrollView
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转)关于pipe()的详细解析
  • (转)人的集合论——移山之道
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .aanva
  • .dat文件写入byte类型数组_用Python从Abaqus导出txt、dat数据
  • .helper勒索病毒的最新威胁:如何恢复您的数据?