网络库集成:使用FetchContent下载Boost.Asio、libcurl、cpp-httplib

做C++网络编程,选库是个头疼事。Boost.Asio功能全但重,libcurl老牌稳定,cpp-httplib轻量现代。我个人的习惯是,根据项目场景混着用。但不管用哪个,集成到CMake里都得花点功夫。

今天咱们就聊聊,怎么用FetchContent把这仨网络库一键拉下来,不用手动下载、不用系统安装,干净又省心。

为什么选这三个库?

先说说我的选择逻辑。你想想看,一个正经的网络模块,通常需要三样东西:

  • 异步IO能力 —— Boost.Asio 是这方面的标杆
  • HTTP客户端请求 —— libcurl 支持各种协议,稳如老狗
  • 轻量HTTP服务端 —— cpp-httplib 头文件即用,写个REST API分分钟

我在项目中遇到过好几次,团队里有人手动下载了某个库的旧版本,结果跟编译器不兼容,折腾了两天。用FetchContent统一管理版本,这种坑就再也没踩过。

FetchContent 集成 Boost.Asio

Boost.Asio 比较特殊,它本身是Boost的一部分。但好消息是,Boost现在支持单独拉取Asio模块了。我们只需要拉 boost-asio 和它依赖的 boost-systemboost-core 等几个子模块。

include(FetchContent)

FetchContent_Declare(
    boost-asio
    GIT_REPOSITORY https://github.com/boostorg/asio.git
    GIT_TAG boost-1.84.0
    GIT_SHALLOW TRUE
)

FetchContent_Declare(
    boost-system
    GIT_REPOSITORY https://github.com/boostorg/system.git
    GIT_TAG boost-1.84.0
    GIT_SHALLOW TRUE
)

FetchContent_Declare(
    boost-core
    GIT_REPOSITORY https://github.com/boostorg/core.git
    GIT_TAG boost-1.84.0
    GIT_SHALLOW TRUE
)

FetchContent_MakeAvailable(boost-asio boost-system boost-core)
小提示:GIT_SHALLOW TRUE 只拉最新提交,能省下不少下载时间。我第一次拉Boost全量包等了半小时,后来改用浅克隆,十几秒搞定。

集成之后,在CMakeLists.txt里链接:

target_link_libraries(my_app PRIVATE
    Boost::asio
    Boost::system
)

嗯,这里要注意一点:Boost.Asio 在C++17以上版本可以不用Boost.System,直接用 <system_error> 标准库。但为了兼容老项目,我一般还是带着。

FetchContent 集成 libcurl

libcurl 的集成稍微麻烦点,因为它依赖 OpenSSL 或 mbedTLS 等加密库。不过我们可以用 CURL_USE_OPENSSL 选项来控制。

FetchContent_Declare(
    curl
    GIT_REPOSITORY https://github.com/curl/curl.git
    GIT_TAG curl-8_6_0
    GIT_SHALLOW TRUE
)

set(BUILD_CURL_EXE OFF CACHE BOOL "" FORCE)
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
set(CURL_USE_OPENSSL ON CACHE BOOL "" FORCE)
set(HTTP_ONLY ON CACHE BOOL "" FORCE)

FetchContent_MakeAvailable(curl)
注意: 如果你在Windows上编译,libcurl默认会找WinSSL。我建议显式设置 CURL_USE_OPENSSL,避免跨平台时行为不一致。曾经有个项目在Linux上跑得好好的,搬到Windows上SSL握手全挂了,就是因为这个。

链接方式:

target_link_libraries(my_app PRIVATE CURL::libcurl)

FetchContent 集成 cpp-httplib

cpp-httplib 是最省心的,纯头文件库,一行代码都不用配。

FetchContent_Declare(
    cpp-httplib
    GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
    GIT_TAG v0.14.3
    GIT_SHALLOW TRUE
)

FetchContent_MakeAvailable(cpp-httplib)

使用的时候,直接 #include "httplib.h" 就行。不过要注意,如果你要用SSL功能,得先定义 CPPHTTPLIB_OPENSSL_SUPPORT 宏。

target_compile_definitions(my_app PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(my_app PRIVATE
    cpp-httplib
    OpenSSL::SSL
    OpenSSL::Crypto
)
核心要点: 这三个库的集成方式虽然不同,但核心逻辑是一样的——用FetchContent声明依赖,设置必要的编译选项,然后链接。你只要掌握了这个套路,换成其他网络库也能快速上手。

完整集成示例

下面是一个完整的CMakeLists.txt,把三个库一次性拉下来:

cmake_minimum_required(VERSION 3.14)
project(NetworkDemo CXX)

set(CMAKE_CXX_STANDARD 17)

include(FetchContent)

# ---- Boost.Asio ----
FetchContent_Declare(
    boost-asio
    GIT_REPOSITORY https://github.com/boostorg/asio.git
    GIT_TAG boost-1.84.0
    GIT_SHALLOW TRUE
)
FetchContent_Declare(
    boost-system
    GIT_REPOSITORY https://github.com/boostorg/system.git
    GIT_TAG boost-1.84.0
    GIT_SHALLOW TRUE
)
FetchContent_Declare(
    boost-core
    GIT_REPOSITORY https://github.com/boostorg/core.git
    GIT_TAG boost-1.84.0
    GIT_SHALLOW TRUE
)

# ---- libcurl ----
set(BUILD_CURL_EXE OFF)
set(BUILD_TESTING OFF)
set(CURL_USE_OPENSSL ON)
set(HTTP_ONLY ON)

FetchContent_Declare(
    curl
    GIT_REPOSITORY https://github.com/curl/curl.git
    GIT_TAG curl-8_6_0
    GIT_SHALLOW TRUE
)

# ---- cpp-httplib ----
FetchContent_Declare(
    cpp-httplib
    GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
    GIT_TAG v0.14.3
    GIT_SHALLOW TRUE
)

FetchContent_MakeAvailable(
    boost-asio boost-system boost-core
    curl
    cpp-httplib
)

add_executable(my_app main.cpp)

target_link_libraries(my_app PRIVATE
    Boost::asio
    Boost::system
    CURL::libcurl
    cpp-httplib
)

集成架构图

下面这张图展示了三个网络库在项目中的角色和依赖关系:

你的项目 Boost.Asio 异步IO / TCP/UDP libcurl HTTP客户端 / 多协议 cpp-httplib HTTP服务端 / 轻量 依赖 boost-system 依赖 OpenSSL 纯头文件,零依赖

避坑指南

集成过程中有几个容易踩的坑,我挨个说说:

  • 版本冲突: 如果项目里已经用了Boost其他模块,拉Boost.Asio时要注意版本一致。我曾经把Asio拉了1.84,但其他Boost模块是1.80,结果编译报了一堆模板错误。
  • SSL证书路径: libcurl在Linux上默认找 /etc/ssl/certs,但有些容器镜像里没有。记得用 CURLOPT_CAINFO 指定证书路径。
  • cpp-httplib的线程安全: 它的HTTP服务端默认是单线程的。如果你要处理高并发,记得设置 svr.new_task_queue = [] { return new httplib::ThreadPool(8); };
  • GitHub访问问题: 如果网络环境不好,可以考虑用Gitee镜像或者提前下载好源码包,用 URL 参数指定本地路径。
我的习惯: 在项目根目录放一个 cmake/fetch_dependencies.cmake 文件,把所有FetchContent声明都放进去。主CMakeLists.txt里只用一行 include(cmake/fetch_dependencies.cmake) 就搞定了。这样结构清晰,也好维护。

好了,三个网络库的集成方法都讲完了。说白了就是三步:声明、配置、链接。你只要把版本号和编译选项调对,剩下的FetchContent全帮你搞定。下次再有人问你「怎么在CMake里加网络库」,你可以直接把这篇甩给他。


公众号:蓝海资料掘金营,微信deep3321