ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Windows下用VS2019编译paho.mqtt.cpp:从CMake配置到工程接入全指南

2026/9/8 13:38:08 拓冰建站 浏览量
Windows下用VS2019编译paho.mqtt.cpp:从CMake配置到工程接入全指南 简介针对需要在Visual Studio 2019中集成MQTT消息通信能力的C开发者这份压缩包提供了paho.mqtt.cpp库的完整编译产物并配套CSDN教程《VS2019编译MQTT库 C/C超详细含示例工程》详细讲解。paho.mqtt.cpp是Eclipse Paho MQTT的C客户端实现常用于物联网设备与云端、服务端之间的发布/订阅场景支持QoS消息服务质量、遗嘱消息、持久会话等常用特性。压缩包内既包含完整源代码又编译好了dll动态库和lib导入库同时给出一个可直接运行的示例工程开发者无需手动配置CMake、处理OpenSSL等依赖在VS2019中打开工程即可编译运行并可将生成的库文件直接引用到自己的项目中显著降低上手门槛。资源共550个文件核心类型包括cpp源文件、h头文件、vcxproj工程文件、dll/lib库文件、pdb调试符号以及tlog编译日志、obj中间文件等构建产物其中头文件和源码便于理解与二次开发pdb用于调试时精准定位日志和中间文件可辅助核对编译流程压缩包整体约64.21MB目录结构清晰按工程、源码、库文件及配置脚本分区方便快速查找。包内还附带CMake与Makefile相关配置脚本便于需要在其他版本或环境中重新生成工程的用户参考。目前已有2963人学习下载适合刚接触paho.mqtt.cpp、希望跳过繁琐编译环节、尽快在VS2019下落地MQTT客户端应用的开发者使用。 如果你在Windows上用C写MQTT客户端大概率绕不开paho.mqtt.cpp这个库。官方文档默认读者在Linux上干活apt-get一行命令库就装好了但你拿着VS2019在Windows上编译paho.mqtt.cpp就会体会到什么叫“文档没写不等于不需要”——依赖链、CMake参数、运行时库配置每一项都能卡住小半天。这篇文章就把我在VS2019下完整编译paho.mqtt.cpp的流程、参数和踩坑记录整理出来给准备用这个库做Windows上位机、物联网网关或者桌面工具的朋友做个参考。1. 为什么Windows下编译paho.mqtt.cpp会让人头疼1.1 paho.mqtt.cpp到底是干什么的paho.mqtt.cpp是Eclipse Paho项目下的MQTT C客户端库底层封装了paho.mqtt.c对外提供同步和异步两套API。同步接口用mqtt::client也就是#include mqtt/client.h适合业务逻辑简单、一个线程里按顺序处理收发消息的场景异步接口用mqtt::async_client对应mqtt/async.h内部有自己的事件循环适合需要高吞吐、断线重连、消息确认机制比较复杂的场景。这个库在Linux下几乎是零门槛但在Windows下就没有那么友好了。原因不复杂paho.mqtt.cpp本身没有发布Windows预编译二进制包官方给的编译指引也默认你熟悉CMake那一套而且它还依赖底层的paho.mqtt.c和OpenSSL——这意味着你至少要编两层库才能拿到自己想要的C接口。很多第一次接触的人就是在这里被劝退的。1.2 “Linux一条命令Windows一场手工活”的真相在Ubuntu上装这个库确实很简单sudo apt-get install libpaho-mqtt-dev一条命令头文件、动态库、CMake配置全给你安排得明明白白。但Windows没有统一的包管理机制哪怕你装了vcpkg也只是把“手工活”变成了“半自动”一旦遇到定制需求还是得回到源码编译这条路。而且paho.mqtt.cpp的依赖是分层的C库包装C库C库又依赖OpenSSL做TLS加密。每一层都有自己的一套CMake配置项编出来的库还有Debug、Release、x86、x64、静态、动态之分。用VS2019编译paho.mqtt.cpp本质上就是一个“让三层依赖在Windows工具链下对齐”的过程理解了这一点后面碰到任何编译报错都不会慌。2. 动手前的准备工具链与依赖方案选型2.1 VS2019要装到什么程度才够用先说环境。我自己用的是VS2019社区版安装时在“工作负载”里勾选了“使用C的桌面开发”。这一步看着基础但真有人栽在这里——装了VS2019却只勾了.NET桌面负载结果连C工程都建不了更别提编第三方库。Windows 10 SDK和MSVC v142这两个组件会随C负载一起装好CMake方面VS2019也自带了对CMake项目的支持但我建议你还是单独装一个CMake版本3.16以上就行。原因后面会讲命令行方式编库比在VS里点来点去要直观得多出错了也容易定位。2.2 vcpkg自动编译与源码手动编译我为什么推荐后者网上关于Windows下编译paho.mqtt.cpp的教程很大一部分会推荐vcpkggit clone https://github.com/microsoft/vcpkg.git cd vcpkg bootstrap-vcpkg.bat vcpkg install paho-mqttpp3:x64-windowsvcpkg确实能自动把paho.mqtt.c和OpenSSL一起编出来省掉很多手工步骤。但我个人还是推荐手动源码编译原因有三个对比项vcpkg自动编译源码手动编译上手速度快一条命令慢要配CMake参数依赖控制由vcpkg决定完全自己掌控二进制位置散落在vcpkg目录自己指定方便归档排错难度出问题不好查每一步都看得见版本定制受限可以任意指定tag另外vcpkg编出来的库默认和vcpkg的triplet绑定比如x64-windows是动态库模式x64-windows-static才是静态库模式很多人搞不清这一点后面接入项目时会遇到LNK2038之类的链接错误。手动编译虽然前期费点时间但每一步产出了什么、用的什么配置你都门儿清真出了问题也好排查。我自己踩过几次坑之后现在凡是用第三方C库都习惯手动编一遍顺手建一个“库档案”目录把不同版本、不同配置的产物分门别类放好见文章最后一节。3. 先搞定底层依赖paho.mqtt.c的编译全流程3.1 下载源码与版本选择paho.mqtt.cpp和paho.mqtt.c是两个独立仓库版本上有对应关系。我编译时用的是paho.mqtt.c的v1.3.12和paho.mqtt.cpp的v1.2.0这个组合比较稳。下载时注意两点一是用git clone保持仓库完整方便后面切tag二是路径不要带中文和空格CMake对中文路径的兼容性不是很好。git clone https://github.com/eclipse-paho/paho.mqtt.c.git cd paho.mqtt.c git checkout v1.3.123.2 CMake参数逐个解读paho.mqtt.c的CMake配置项不少但真正需要关心的就四个参数作用我的推荐值PAHO_WITH_SSL是否启用TLS/SSL需要加密时设TRUEPAHO_BUILD_STATIC是否生成静态库要静态库就设TRUEPAHO_ENABLE_TESTING是否编译测试程序FALSEPAHO_BUILD_SAMPLES是否编译示例代码FALSE如果PAHO_WITH_SSL设为TRUECMake会在系统里找OpenSSL。我测试时用的是Win64 OpenSSL预编译包安装后设置环境变量OPENSSL_ROOT_DIR指向安装目录即可。还有一个选择是用vcpkg装OpenSSL再通过-DCMAKE_PREFIX_PATH指定路径但为了减少变量建议直接装预编译包。这里有个容易踩的坑PAHO_BUILD_STATIC和PAHO_BUILD_SHARED是独立的两个开关可以同时打开也可以只开一个。如果你不确定自己后面要静态还是动态就先都打开编译完拿到全部产物再慢慢选。3.3 实际编译命令与产物对照确认好依赖后执行编译。我习惯用命令行方式直接在源码根目录操作cmake -B build -G Visual Studio 16 2019 -A x64 ^ -DPAHO_WITH_SSLTRUE ^ -DPAHO_BUILD_STATICTRUE ^ -DPAHO_ENABLE_TESTINGFALSE ^ -DPAHO_BUILD_SAMPLESFALSE cmake --build build --config Release cmake --build build --config Debug这里解释一下-G Visual Studio 16 2019 -A x64是指定用VS2019生成64位工程-B build是让CMake在build目录下生成中间文件和工程文件。以后凡是拿到一个带CMakeLists.txt的项目基本就是这套流程Windows通用。编译完成后在build/src/Release和build/src/Debug下会看到一堆库文件。文件名里的3a和3c很多人看不懂其实很简单paho-mqtt3a.lib/paho-mqtt3a.dll基于MQTT异步APIAsyncpaho-mqtt3c.lib/paho-mqtt3c.dll基于MQTT同步APICallback带static后缀的如paho-mqtt3a-static.lib静态库paho.mqtt.cpp的C接口底层用的是异步API所以后面链接时我们主要关心paho-mqtt3a这条线。千万别把3a和3c搞混否则链接阶段会报一堆莫名其妙的符号错误。4. 主角登场paho.mqtt.cpp的编译与产出物对照4.1 C库的CMake配置与PAHO_MQTT_C_PATHC库编好之后开始编C库。下载源码并切到对应taggit clone https://github.com/eclipse-paho/paho.mqtt.cpp.git cd paho.mqtt.cpp git checkout v1.2.0paho.mqtt.cpp的CMake配置里有一个关键参数叫PAHO_MQTT_C_PATH直接指向paho.mqtt.c的源码目录。设置这个参数后CMake会在构建C库时自动把C库一起编译并链接省得你再去手动指定C库的安装路径。实测下来这个方式比先installC库再让C库去找它要省心得多。C库的CMake参数同样有PAHO_WITH_SSL、PAHO_BUILD_STATIC、PAHO_ENABLE_TESTING、PAHO_BUILD_SAMPLES这几项含义和C库完全一致。如果你前面C库开了SSL这里也要保持TRUE两边配置不一致会导致后面的链接错误。4.2 从CMake到VS2019工程的完整命令我的编译命令如下cmake -B build -G Visual Studio 16 2019 -A x64 ^ -DPAHO_WITH_SSLTRUE ^ -DPAHO_BUILD_STATICFALSE ^ -DPAHO_MQTT_C_PATH../paho.mqtt.c ^ -DPAHO_ENABLE_TESTINGFALSE ^ -DPAHO_BUILD_SAMPLESFALSE cmake --build build --config Release cmake --build build --config Debug这里我把PAHO_BUILD_STATIC设成了FALSE只编动态库。原因是paho.mqtt.cpp在MSVC下编静态库时使用方需要额外定义PAHO_MQTT_STATIC宏否则它会默认按动态库的导入方式去查找符号非常容易出链接问题。如果你确实需要静态库记得在项目里加上这个宏并且链接时额外带上OpenSSL和C库的静态版本。编译完成后build/src/Release下会生成paho-mqttpp3.lib和paho-mqttpp3.dll这就是我们最终要的C动态库。pp代表Cplus plus3标识MQTT协议版本lib是导入库dll是运行时动态库。4.3 编译完成后你拿到了一堆什么文件一次完整编译下来你的收藏里应该有这些东西文件用途paho-mqttpp3.lib/paho-mqttpp3.dllpaho.mqtt.cpp动态库Release版paho-mqtt3a.lib/paho-mqtt3a.dllpaho.mqtt.c异步API动态库paho-mqtt3c.lib/paho-mqtt3c.dllpaho.mqtt.c同步API动态库libcrypto.lib/libssl.libOpenSSL的导入库Debug版本的对应文件调试用和Release严格分开注意Debug和Release的库千万别混用。MSVC的C运行时库在Debug版默认绑定了调试堆和调试检查你拿Release编的库去链接Debug工程或者反过来链接器会直接报LNK2038运行时库不匹配。这个错误看起来吓人原因其实就是配置没对齐。5. 把库接进你的VS2019项目配置与Demo实战5.1 VS2019工程属性配置库编好了接下来就是把它用起来。在VS2019里新建一个空项目然后打开项目属性按以下路径配置C/C → 常规 → 附加包含目录添加paho.mqtt.cpp的include目录以及paho.mqtt.c的src目录因为C库的头文件会引用C库的MQTTClient.h链接器 → 常规 → 附加库目录添加你编译产物所在的Release或Debug目录链接器 → 输入 → 附加依赖项添加paho-mqttpp3.lib; paho-mqtt3a.libC/C → 代码生成 → 运行库确认和编译库时一致动态库用/MD静态库用/MT如果你编库时用了OpenSSL这里还要在附加依赖项里加上libcrypto.lib; libssl.lib同时把OpenSSL的include目录也加进附加包含目录。5.2 一个能直接跑通的发布/订阅Demo配置好后写一个最简单的同步客户端Demo验证一下#include iostream #include mqtt/client.h const std::string SERVER_ADDRESS tcp://broker.emqx.io:1883; const std::string CLIENT_ID vs2019_paho_demo; const std::string TOPIC test/topic; int main() { mqtt::client client(SERVER_ADDRESS, CLIENT_ID); mqtt::connect_options connOpts; connOpts.set_keep_alive_interval(20); connOpts.set_clean_session(true); try { std::cout connecting... std::endl; client.connect(connOpts); std::cout connected std::endl; client.subscribe(TOPIC, 1); mqtt::message_ptr pubMsg mqtt::make_message(TOPIC, hello from vs2019); pubMsg-set_qos(1); client.publish(pubMsg); while (true) { auto msg client.consume_message(); if (msg) { std::cout recv: msg-to_string() std::endl; } } } catch (const mqtt::exception e) { std::cerr mqtt error: e.what() std::endl; return 1; } return 0; }这段代码的逻辑很简单连接公共broker订阅test/topic然后自己发一条消息再通过consume_message()把消息收回来打印。能跑通这个Demo说明库的编译、链接、运行时dll加载、网络连接四个环节全部正常。5.3 DLL部署与源码编码问题编译运行前记得把paho-mqttpp3.dll、paho-mqtt3a.dll、libcrypto.dll、libssl.dll拷贝到exe所在的输出目录。VS的调试器有时候会提示找不到dll就是这个原因。也可以把dll目录加到系统PATH里但我不建议这么做容易造成版本污染还是拷贝到exe目录最干净。另外VS2019默认的源文件编码是GBK如果你从网上下载的示例代码是UTF-8无BOM格式直接打开再编译里面的中文注释会报错或者变成乱码这其实不是代码的问题而是编辑器按GBK解析了UTF-8字符。解决方法很简单在VS里打开文件后选择“文件 → 另存为”点保存按钮旁边的箭头选“编码保存”改成“UTF-8 with BOM”再保存。这也是VS2019里“cpp文件加中文注释就报错”最常见的根源。6. 我踩过的那些坑链接错误与运行时异常排查实录6.1 LNK2038运行时库不匹配最常见也最隐蔽第一次接入项目时我卡在LNK2038这个错误上大半天。报错信息大意是RuntimeLibrary不匹配模块A用/MDd编的模块B用/MTd编的。这是我编译paho.mqtt.c时用默认配置生成了静态库而自己的主工程用的却是动态运行时库导致的。排查链路是这样的先看报错信息里提到哪个.obj文件确认是哪个库引起的回到编译库时的CMake配置看PAHO_BUILD_STATIC和PAHO_BUILD_SHARED的设置检查VS工程属性里的“运行库”选项和库编译时的选项对齐最终我的解决办法是统一用动态库PAHO_BUILD_STATICFALSEVS工程里“运行库”保持默认的/MD。这个问题在vcpkg路线下也常见因为vcpkg的x64-windows和x64-windows-static对应不同的运行时绑定混用必炸。6.2 “找不到paho-mqttpp3.lib”与dll不识别链接时报“无法打开paho-mqttpp3.lib”九成是附加库目录路径写错了或者路径里进了中文和空格。这个好排查看一眼“链接器 → 常规 → 附加库目录”就行。还有一种是x86/x64不匹配工程是x64的库目录却指向x86版本链接器同样找不到正确文件。dll不识别则通常发生在“Release库配Debug运行环境”这种场景。比如你把Release版的dll放在Debug版exe目录下程序启动时可能dll加载成功但内部符号初始化失败直接闪退。VS2019里“编译C工程闪退”的怪问题很多就是这么来的。6.3 生产环境必须启用TLS但本地测试先别急着开我测试阶段一直都是tcp://无加密连接所有编译都用PAHO_WITH_SSLFALSE省掉OpenSSL这一层的变量等整个链路跑通之后再单独编一个带SSL的版本。如果你一上来就开TLS报错了很难分清是SSL握手问题、证书问题还是库本身的问题。实际接入生产broker时把连接地址改成ssl://端口换成8883并确保编译库时开了PAHO_WITH_SSLTRUE。另外很多公共broker的证书链比较复杂Windows下OpenSSL可能找不到系统证书需要在代码里显式指定CA证书路径这个后面单独写一篇细聊。6.4 常见错误速查表报错现象可能原因解决方式无法打开paho-mqttpp3.lib附加库目录错误或位数不匹配核对路径、平台LNK2038运行时库不匹配Debug/Release混用、/MD与/MT混用统一库编译配置找不到paho-mqttpp3.dlldll未部署到exe目录拷贝dll或加PATH中文注释报错源码编码被按GBK解析保存为UTF-8 with BOM启动闪退dll版本与exe配置不一致同批次编译产物对齐7. 编译成果的归档与团队复用编译这个库本身可能只需要半小时但要是半年后同事想复用你的成果而你早就忘了当初怎么配的那才叫灾难。我现在每编译完一个第三方库都会建一个“库档案”目录结构如下3rdparty/ paho.mqtt.cpp/ v1.2.0_vs2019_x64/ include/ lib/ debug/ release/ bin/ debug/ release/ README.mdREADME里记录版本号、编译日期、CMake命令、VS版本、CMake版本、依赖的OpenSSL版本。这样无论团队成员还是未来的自己拿到这个目录直接就能在VS里配好路径使用不用重新踩一遍编译的坑。库文件本身的归档也有讲究头文件全部拷贝一份到include不直接引用源码目录因为不同版本的源码目录结构可能有变化dll统一放bin方便打包部署lib就按Debug和Release分开命名上加上配置后缀比如paho-mqttpp3d.lib这样不易混。最后再分享一个小技巧如果你只是想在Windows上快速验证paho.mqtt.cpp能不能用不想折腾编译可以先试试vcpkg跑通Demo确认功能没问题后再来手动编译。而如果你确定要长期用这个库做产品开发手动编译这套流程迟早得走一遍早点走完早省心。本文还有配套的精品资源点击获取