
简介cpr-1.3.0 是 C 开发者常用的 HTTP 网络请求库API 风格简洁类似 Python requests适合编写网络爬虫、访问 REST API 以及进行服务端接口调试。面向 VS2015 环境预编译库文件包省去自行编译与配置依赖的繁琐过程可直接将库和头文件接入项目使用。压缩包共 27 个文件包括 21 个头文件、4 个 .lib 链接库与 2 个 DLL 动态库库内部基于 libcurl 实现因此附带 libcurl.dll 与对应的导入库且区分 Debug 与 Release 两个版本分别存放于 DebugDLL 和 ReleaseDLL 目录中便于不同构建配置时选用整个包体仅 738KB。目前已有 687 人浏览学习对需要快速集成 HTTP 请求能力的 C 开发者尤其适用包内头文件齐全使用方式与官方源码一致便于对照文档二次开发同时免去源码编译环境配置。1. 别急着编译先把 cpr 1.3.0 和“库文件”两件事对齐前段时间帮一个维护了四五年的老项目升级HTTP通信模块代码库里还躺着一个老的 cpr 库文件版本号正好就是 1.3.0。查了一圈发现官方主线虽然早就往前走了很远但 1.3.0 这个版本在不少存量工程、高校实验课和嵌入式项目里依然坚挺。所谓 cpr通俗说就是 C 写的 HTTP 客户端封装库底层基于 libcurl但把接口设计成了类似 Python requests 的风格——不用再手写一堆 curl_easy_setopt几行代码就能发 GET、POST处理 header、session、超时这些事都顺手得多。那“库文件”到底是什么这是很多人卡住的第一步。cpr 本身是源码形态交付的你从 GitHub 拉下来是一堆 .cpp 和 .h不能直接扔给同事或者塞进设备里用。你得先通过 CMake 把它编译成特定平台下的二进制产物Linux 下是 libcpr.a静态库或者 libcpr.so动态库Windows 下是 cpr_static.lib静态库、cpr.dll 导入库动态库macOS 下则是 .a 或 .dylib。编译产物才是所谓的“库文件”它包含了 cpr 所有功能的机器码调用方只需要头文件加库文件就能用不需要把整个源码工程拷过去。为什么要单独找一个历史版本1.3.0 在 2018 年前后算是很活跃的版本接口稳定、依赖简单核心依赖基本只有 libcurl 和 C11 编译器不像现在的版本还牵扯到很多新特性和可选模块。对于只想要一个能跑的 HTTP 客户端、又不想被持续集成折腾的人来说这个版本反而省心。但问题是网上这一版的资料大多是讲“怎么用”真正把“怎么从源码生成库文件”的完整流程写清楚的很少。这篇文章就把我实测过编译、打包、集成全套过程拆开讲一遍环境分别是 Ubuntu 20.04 和 Windows 10 Visual Studio 2019思路在 ARM 板子上也适用。2. 生成库文件之前依赖链必须按这个顺序理清2.1 核心依赖libcurl、OpenSSL、CMake、编译器cpr 1.3.0 的底层是 libcurl所以编 cpr 之前必须先保证系统里有一个能用的 curl 开发库。千万不要觉得“我机器上装了 curl 命令”就等于“有 curl 开发库”。curl 命令行工具和 libcurl 开发头文件curl.h、库文件libcurl.a / libcurl.so是两码事。编译 cpr 时 CMake 会通过 find_package(CURL) 去找头文件和库找不到直接报错。Linux 下我推荐直接用系统源安装干净利落sudo apt update sudo apt install libcurl4-openssl-dev cmake g这里有个细节Ubuntu 上 libcurl4-openssl-dev 这个包会把 OpenSSL 也带进来因为 curl 默认支持 HTTPS 就需要 OpenSSL。cpr 只负责 HTTP 协议层的封装SSL 握手和证书校验全交给 libcurl OpenSSL 搞定。所以依赖顺序是 cpr → libcurl → OpenSSL缺任何一层都不行。Windows 下就没有 apt 这么好用了。我试过两种方式第一种是去 curl 官网下载官方预编译的开发包把 include、lib 目录解压出来然后在 CMake 配置时手动指定位置第二种是直接用 vcpkg 装 curl命令是vcpkg install curl:x64-windows装完交给 vcpkg 的 toolchain 处理。两种都行但第一种对老工程更友好因为你最终是要生成“库文件”交付给别人不太想引入 vcpkg 那套对使用者来说不必要的依赖。2.2 编译器与 CMake 最低版本1.3.0 要求 C11所以编译器最低门槛很低GCC 4.9、Clang 3.5、Visual Studio 2015 都可以。我实际用的是 GCC 9.4 和 VS2019都没有任何问题。CMake 版本建议 3.10 以上虽然这个版本源码里写的 cmake_minimum_required 不高但新版 CMake 对 FIND_PACKAGE 的处理更友好能避免一些奇怪的兼容问题。2.3 版本匹配cpr、libcurl、OpenSSL 三者的“三角关系”很多人编译失败都栽在版本组合上。举例来说如果你系统里装的是 libcurl4 的最新版而 OpenSSL 是老版本或者用了系统的 curl 但没带 HTTPS 支持那编出来的 cpr 库文件要么在 CMake 阶段就失败要么能编出来但运行时请求 HTTPS 链接直接报错。建议的做法是先执行一下curl-config --version和curl-config --features确认 curl 版本和功能特性里包含 SSL 和 HTTPS。如果是“settled”状态的老环境这个检查能帮你节省一整天。Windows 预处理相对简单选 curl 包时直接用带 SSL 的版本比如选择 WITH_SSLON 构建或者官方预编译里的 winssl 版本这样就不会遇到“HTTPS 打不开”的隐性坑。3. 逐步实操在 Linux 和 Windows 下把 cpr 1.3.0 编成静态库3.1 获取源码并锁定 tag先去 GitHub 把源码拉下来然后切到 1.3.0 这个 tag。不要图省事直接拉 master因为新版接口和目录结构都变了后面的参数也不适用。建议这样操作git clone https://github.com/whoshuu/cpr.git cd cpr git checkout 1.3.0切完 tag 后先看一眼目录结构。你会看到根目录有 CMakeLists.txt子目录 include/cpr 和 cpr 里分别是头文件和实现文件。如果后面手动集成项目这个目录结构就是你的参照物。3.2 CMake 配置开关怎么选、为什么这么选在项目根目录下建一个 build 目录然后执行cmake -S . -B build \ -DCPR_BUILD_TESTSOFF \ -DCPR_BUILD_EXAMPLESOFF \ -DBUILD_SHARED_LIBSOFF \ -DCMAKE_BUILD_TYPERelease \ -DCMAKE_INSTALL_PREFIX$PWD/install几个开关的意义我逐个说CPR_BUILD_TESTSOFF和CPR_BUILD_EXAMPLESOFF关掉测试和示例只编库本身缩短编译时间也避免测试代码引入额外依赖。BUILD_SHARED_LIBSOFF生成静态库。为什么默认偏好静态库因为静态库会把 cpr 的逻辑直接打进你的可执行文件部署时不用额外拷 .so 或 .dll对交付场景来说省心。如果某些平台只允许动态库再把这条改成 ON 即可后面我会讲动态库要注意什么。CMAKE_BUILD_TYPERelease编译优化用 Release避免 debug 模式下错误消息缺失或者链接了调试运行时。CMAKE_INSTALL_PREFIX指定安装目录等会儿会用 install 命令把头文件和库文件统一放到这个目录下方便打包。3.3 正式构建并检查产物cmake --build build --config Release -j4 cmake --install build跑完之后install 目录下的内容应该长这样install/ ├── include/ │ └── cpr/ │ ├── cpr.h │ ├── auth.h │ ├── ... └── lib/ ├── libcpr.a └── cmake/ └── cpr/ ├── cprConfig.cmake └── ...libcpr.a 就是最终要交付的静态库文件。可以用ar -t libcpr.a看一下里面包含哪些对象文件确认不是空库。还有一个更关键的验证方式写个最简单的 main.cpp只调 cpr 的 GET 接口然后手动链接这个库看能不能出可执行文件。这一步非常重要比任何“编译成功”提示都可靠。3.4 Windows 下的额外注意事项Windows 上的流程和 Linux 几乎一样换成 Visual Studio 的生成器后编译出来的静态库文件名一般是 cpr_static.lib取决于配置CMake 安装后也会生成对应的 cprConfig.cmake。唯一要特别注意的是运行时库的匹配VC 编译时有个 /MT静态运行时和 /MD动态运行时的区别如果 cpr 库是用 /MD 编的而你的项目其他模块统一用 /MT链接阶段会冒出一堆 MSVCRT 符号冲突的报错。这不是 cpr 的锅是 Windows 生态的老规矩。你在 CMake 配置时给 cpr 加上/MD或/MT的编译选项和使用方保持一致就行了。最简单的排查办法是问自己一句这个库文件最终会被哪种配置的工程调用先定宏再编译。4. 编译期与链接期最容易翻车的三个现场4.1 CMake 找不到 CURL 的典型报错与手工指定最常见的报错是Could NOT find CURL (missing: CURL_LIBRARY CURL_INCLUDE_DIR)这就是我前面说的“curl 开发环境没装好”。Linux 上通常是缺 libcurl4-openssl-devWindows 上则是 CMake 默认去系统 PATH 里找找不到你的预编译 curl 目录。解决办法是打开 CMake 的缓存变量手动指定-DCURL_INCLUDE_DIRSC:/curl-8.5.0/include \ -DCURL_LIBRARYC:/curl-8.5.0/lib/libcurl.lib这个写法 Linux 下也通用只不过路径换成你自己的。注意变量名不能写错写错 CMake 照样找不到而且不会给你很明确的提示。我第一次在 Windows 下编的时候就把CURL_LIBRARY写成了CURL_LIBRARIES结果搞了半个小时才意识到是变量名的问题。4.2 静态库链接顺序为什么单独链接 cpr 还是报未定义符号编出 libcpr.a 之后如果你在自己的工程里手动链接g main.cpp libcpr.a -o app你大概率会看到一堆 undefined reference比如curl_easy_init、curl_easy_perform。这是静态库链接的经典问题静态库按顺序处理符号libcurl 在 libcpr.a 后面它的符号没有解析到链接器就直接报错。正确做法是让 libcurl 跟在 libcpr 后面同时把 OpenSSL 相关库也放上g main.cpp -L./install/lib -lcpr -lcurl -lssl -lcrypto -o app更稳妥的方式是直接用 CMake 链接中的target_link_libraries(app PRIVATE cpr::cpr)让配置好的 import target 自动处理依赖排序。如果你非要手写链接命令记住一条原则被依赖的库放在最右边越是底层越靠后。curl 依赖 ssl、crypto所以 curl 在它俩左边cpr 依赖 curl所以 cpr 在最左边。4.3 Windows 动态库导出符号CPR_DLL 宏别忘加如果你在 Windows 上构建的是动态库BUILD_SHARED_LIBSON那链接 cpr 时还有一个隐蔽的雷。cpr 的头文件里有CPR_API这样的导出宏它是根据你是否定义CPR_DLL来决定__declspec(dllexport)/__declspec(dllimport)的。也就是说你的应用程序在包含 cpr 头文件之前必须在预处理宏里加上CPR_DLL否则 MSVC 会找不到 cpr 的导出符号链接时给你一个 LNK2019。解决方案有两个一是项目里直接加ADD_DEFINITIONS(-DCPR_DLL)或 VS 里在预处理器定义里写上 CPR_DLL二是我更推荐的静态链接 cpr把 BUILD_SHARED_LIBS 关掉就不用关心这个宏了。静态库虽然文件大一点但省掉了一系列 Windows DLL 带来的动态库加载、路径、宏定义问题稳。5. 拿到 .a / .lib 之后集成到业务项目里的两条路线5.1 最顺的做法find_package(cpr) cpr::cpr如果使用方也是 CMake 工程那集成是最省事的。因为你刚才 cmake --install 的时候已经生成了一套 CMake 配置文件cprConfig.cmake使用方不需要自己写任何查找逻辑只需要在 CMakeLists.txt 里写find_package(cpr REQUIRED) target_link_libraries(your_application PRIVATE cpr::cpr)关键是这个cpr::cprtarget 会自动传递 libcurl 的链接关系。也就是说使用方看不见复杂的 -lcurl -lssl -lcrypto只要系统里能找到 cpr 的 CMake 配置文件缺的依赖 CMake 会自己宣告。这也是为什么我强烈建议生成库文件的时候顺带把 install 目录整个打包交付而不是只拷一个 .a 文件。如果使用方没有把 cpr 装到系统默认搜索路径那调用时要用-DCMAKE_PREFIX_PATH路径指定安装目录。这个参数类似于告诉 CMake“去这里找 find_package 能用的配置文件”很多人在这一步卡住其实就这么一层窗户纸。5.2 手动链接适合老工程、Makefile、嵌入式交叉编译遇到非 CMake 工程或者 makefile 手工维护的老项目就只能手动加头文件和库路径。第一步把 install/include 里的 cpr 目录整个拷到项目的第三方 include 目录第二步把 install/lib 下的 libcpr.a 放到 libs 目录第三步在 Makefile 里加上 -I 和 -L 以及 -lcpr -lcurl并且记得带 ssl、crypto、pthread、dl 这些在 Linux 下常见的附加库CXXFLAGS -I./third_party/include -L./third_party/libs -lcpr -lcurl -lssl -lcrypto -lpthread -ldl这个过程中最常见的坑是libcpr.a 编译成功了拿到另一个环境后却提示缺少 libcurl。实际上它是把 libcurl 的动态符号留到了运行时解析于是运行环境里也得有 libcurl.so。想彻底脱离环境你可以把 libcurl 也用静态库编进来这样整条 HTTP 链路都不依赖系统动态库。代价是最终的二进制文件体积会变大不少但交给客户、板卡或者嵌入式环境时非常省心。5.3 嵌入式场景交叉编译时怎么移植库文件不少做设备的人喜欢问“能不能把 cpr 编到 ARM 板上”。可以但交叉编译库文件时有三件事要做第一用交叉编译器如 aarch64-linux-gnu-g跑 CMake 时指定好 CMAKE_SYSTEM_NAMELinux 和 CMAKE_CXX_COMPILER第二把交叉编译好的 libcurl 也准备好并且让 CMake 优先找这个交叉编译版本而不是宿主机上的 x86 版本否则你会出现“板子上文件拷进去了但一跑就 Segmentation Fault”的问题第三最后集成时使用的头文件、库文件必须都来自交叉编译系统混用 x86 和 arm 的库文件是最容易踩的跨平台大坑。6. 关于“单独生成库文件”和“直接合入源码”我的最终建议用了 cpr 1.3.0 这么长时间我的习惯是如果只是自己做一个小工具的依赖直接在 CMake 里 add_subdirectory(cpr) 合入源码让整体一起编译是最省事的也不需要考虑库文件版本、依赖传递这类事情。但凡是多团队协作、交付给第三方、适配到嵌入式板卡或者项目里同时有好几个模块都要用同一个 HTTP 客户端那就一定要先生成好稳定版本的库文件连同头文件和 CMake 配置一起作为一个“交付物”给出去。一来版本可控二来别人接的时候也快。还有一个小经验想分享在生成库文件的同一批环境变量里最好记一下编译命令、源码 tag、curl 版本整理成一个 README 放进交付包里。很多时候库文件本身没问题倒是三个月后没人记得这个 1.3.0 是怎么编出来的那时候才真叫焦头烂额。我现在每个第三方库的交付目录里都会放一行cmake -S . -B build -DCPR_BUILD_TESTSOFF ...这样的命令后边再维护的人包括未来的我自己至少不用对着一个孤零零的 .a 文件猜来猜去。本文还有配套的精品资源点击获取