简介:面向在视窗操作系统上使用微软Visual Studio 2013开发环境的C++程序员,这份资源是MySQL官方连接器在三十二位与六十四位平台下的完整编译成果,同时附带了示例工程,用于解决自行编译过程中常见的依赖库缺失、头文件路径错误以及链接配置复杂等问题。资源包共收录六十三个文件,压缩后大小约二十四点九八兆字节;其中包含二十一个头文件、二十个静态库或导入库、九个动态链接库、两个C++源文件,以及项目解决方案、工程配置和调试符号文件等,并按调试版本、发布版本和三十二位、六十四位分类存放,便于按需选用。示例代码从创建驱动实例开始,依次演示了建立连接、执行SQL语句、遍历结果集以及关闭资源等关键步骤,同时提供了异常处理的思路,可作为编写数据库操作模块的参考模板。目前已有五百一十人学习使用,解压后只需配置好头文件包含路径和附加依赖项,即可快速集成到自己的项目中,显著缩短开发周期。 前一阵子帮朋友处理一个老项目的迁移,从32位升级到64位,代码本身没费什么劲,反而卡在最不起眼的一环——MySQL Connector/C++ 的动态库对不上。他开发机装的是VS2013,而官方预编译包里的Connector/C++ 8.x是用VS2015/2017编译的,直接把lib塞进工程,链接阶段就开始报LNK2038、LNK2019,头大。最后只能亲自动手,用VS2013从源码编译一套匹配的MySQL Connector/C++,顺便把win32和win64两份都出了。今天把整个流程完整复盘一下,包括版本选型、CMake配置、编译步骤、部署细节,以及一段可以直接跑通的示例代码,专门写给还在维护VS2013老项目的同行。如果你也在被第三方库版本不匹配折磨,这篇文章应该能帮你省下至少一个下午的时间。
1. 为什么放着官方包不用,非要自己编译
1.1 官方二进制包的“版本陷阱”
MySQL官方提供的Connector/C++预编译二进制包,通常是用当前较新的MSVC版本编译的,比如VS2015、VS2017甚至VS2019。这在绝大多数场景下没问题,因为大家基本跟随新工具链走。但VS2013这个版本比较特殊,它的C++运行库是msvcr120.dll,编译器生成的MSC_VER是1800,而VS2015对应1900、VS2017对应1910以上。MSVC在VS2015之后对C++标准库做了大量ABI调整,前后版本编译出来的库混着链接,轻则链接报错,重则运行期莫名崩溃。
说白了,C/C++的库不像Java的jar包那样“一次编译到处运行”,它与编译器版本、运行库版本、甚至Debug/Release模式强绑。你在VS2013里链接一个VS2017编译出来的MySQL Connector/C++库,就像把带国标插头的设备怼进英标插座——接口长得像,实际上不通。官方包默认用新工具链编译,这决定了很多老版本IDE用户必须走“自行编译”这条路。
1.2 老项目有自己的“脾气”:工具链锁定
很多传统企业里的老项目,尤其是工控、银行、制造业内部系统,开发环境说锁死就锁死。VS2013在这个圈子里渗透率极高,因为项目里可能还依赖了某些只能在VS2013下正常编译的ActiveX控件、第三方MFC库,或者干脆是公司IT策略不允许换IDE。这时候你不可能因为一个连接库去升级整个工具链,只能让第三方依赖去适配IDE。所以这里的核心思路是:连接库自编译,平台工具集固定为Visual Studio 2013(v120),用和项目一致的方式产出库文件。
另外还有一个隐性好处:自己编译可以自主控制是否使用静态运行时库(/MT、/MTd)。如果采用静态链接,部署时不需要目标机器安装VS2013运行库,也不用拷一堆msvcr120.dll,专治各种“装到客户机器上跑不起来”的疑难杂症。这个选项在官方预编译包里是没法自由切换的。
2. 编译前的准备:版本选型与依赖下载
2.1 版本对照表:不是越新越好
刚开始我也踩过“拿最新版连接器源码编译”的坑。MySQL Connector/C++ 8.0.x虽然也支持CMake配置,但它的API和1.1.x完全是两代人,而且对CMake版本、Boost版本的要求都比较挑剔,在VS2013上编译经常报“语法不兼容”。试了一圈之后,我锁定了1.1.x系列,这在老项目里是最稳的选择。具体推荐版本见下表:
| 依赖项 | 推荐版本 | 说明 |
|---|---|---|
| MySQL Connector/C++ | 1.1.6 或 1.1.x 最新 | API简单,兼容VS2013,不需要额外安装C Connector库 |
| Boost | 1.59.0 | 连接器编译时只依赖Boost头文件,1.59完全够用 |
| OpenSSL | 不需要(可禁用) | 如果不做SSL加密连接,CMake里直接关掉 |
| CMake | 3.15.5 | 支持VS2013生成器,操作界面也顺手 |
| MySQL Server | 5.7 / 8.0 | 用于最终测试连接,版本不影响编译 |
这里最需要留意的是Boost。Connector/C++ 1.1.x在CMake配置阶段会强制检查Boost头文件,没配好直接报错。不过它只是用到Boost的智能指针、线程相关头文件,不需要把Boost整个编译一遍,所以准备一份解压后的Boost源码目录就够了。
2.2 目录规划和下载注意事项
建议把所有源码下载到一个纯英文路径下,比如D:\dev\src,不要放桌面、不要带中文和空格。目录带空格虽然大多数时候没事,但在CMake和VS2013搭配时偶尔会触发一些诡异错误,不值得冒险。
下载MySQL Connector/C++源码时,务必选“Source Code”ZIP包,不要去下二进制包。Boost直接去官方或镜像站下载boost_1_59_0.zip,解压即可。CMake在3.15左右对VS2013生成器的支持都很稳定,我用3.15.5跑完整个流程没有任何问题,装的时候记得勾选“Add CMake to system PATH”。
3. 完整编译流程:从CMake配置到库文件落地
3.1 CMake配置项逐个解释
打开CMake GUI之后,第一行填源码路径,比如D:/dev/src/mysql-connector-cpp-1.1.6;第二行填构建路径,我习惯在源码目录外单独建一个build目录,比如D:/dev/build/connector-vs2013-x64。第一次点Configure时,会弹出生成器选择窗口,这时需要根据目标平台选择:
- 编译win32(32位):选择“Visual Studio 12 2013”
- 编译win64(64位):选择“Visual Studio 12 2013 Win64”
选择完成后,CMake会进行第一轮探测,几乎必然会在红色报错区域提示找不到依赖。此时在变量列表里配置以下几个关键项:
| 变量名 | 取值 | 作用 |
|---|---|---|
| CMAKE_INSTALL_PREFIX | D:/dev/dist/connector-x64 | 最终安装路径,头文件、库文件都会集中到这里 |
| WITH_BOOST | D:/dev/src/boost_1_59_0 | Boost源码解压后的根目录 |
| WITH_SSL | 0 | 关闭SSL依赖,不做加密连接时强烈建议设为0 |
| DYNAMIC_LIB | 1 | 编译动态库(生成DLL+导入库);设为0则编译静态库 |
这几个变量里最容易出坑的是WITH_SSL。Connector/C++ 1.1.x在默认情况下会尝试寻找OpenSSL,如果你机器上恰好没有配置好的OpenSSL开发库,又不主动关掉,Configure阶段会一直卡在“找不到OpenSSL”的红字上。实测如果应用走内网、不需要SSL加密连接,完全可以直接设为0,省掉一整条依赖链。
3.2 生成工程并执行编译
确认所有变量配置完成后,再次点击Configure,直到红色报错消失。然后点Generate,CMake会在构建目录下生成一个MySQL_Connector.sln(具体名称随版本略有差异)。用VS2013打开这个解决方案,先在工具栏的解决方案配置里选好Release,然后在“配置管理器”里核对活动解决方案平台——如果是64位编译,这里应该显示x64,如果是win32则显示Win32。
接下来右键“ALL_BUILD”项目,选择“生成”。整个编译过程大概5到10分钟,视机器性能而定。编译完成后,在构建目录下的lib\Release里能看到产物:
- 动态库模式:mysqlcppconn.dll、mysqlcppconn.lib(Debug模式会多一个带d后缀的版本,比如mysqlcppconn-d.lib)
- 静态库模式:mysqlcppconn-static.lib
顺带提一句,编译64位版本时,输出目录通常在x64\Release下,而32位版本直接在Release下,找文件的时候别走错目录。
3.3 Install步骤:让产物集中管理
每次编译完都在build目录里翻文件,比较零散。我的习惯是在VS2013里再生成一次“INSTALL”项目,它会把头文件、库文件、DLL按目录结构复制到CMAKE_INSTALL_PREFIX指定的位置。这样后续给多个工程引用时,只需配置一个统一路径,升级版本时替换整个目录即可。安装完成后,D:\dev\dist\connector-x64下会看到include、lib、bin三个子目录,结构清爽,拷贝给别人用也方便。
3.4 win32和win64差异处理
如果你和一样,需要同时产出32位和64位两套库,建议分两个构建目录跑两次CMake,比如build-vs2013-win32和build-vs2013-x64。第二次Configure时注意换生成器,别用同一目录,否则CMake的缓存会串。两份库编译完成后,把安装目录分别命名为connector-win32、connector-x64,后续在工程里按目标平台切换引用即可。
4. 示例代码与VS2013工程配置
4.1 建表与示例代码
假设MySQL里已经有一个测试库test_db,里面有一张users表,结构很简单:id自增主键、name为用户名。示例代码要做的事情就是建立连接、执行一条查询、遍历结果集并打印。
CREATE DATABASE IF NOT EXISTS test_db DEFAULT CHARACTER SET utf8mb4; USE test_db; CREATE TABLE IF NOT EXISTS users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(64) NOT NULL ); INSERT INTO users (name) VALUES ('Alice'), ('Bob'), ('Charlie');接下来是C++代码,我尽量把异常处理和资源管理写得贴近实际生产可用,而不是玩具代码:
#include <iostream> #include <memory> #include <mysql_connection.h> #include <mysql_driver.h> #include <cppconn/statement.h> #include <cppconn/resultset.h> #include <cppconn/exception.h> int main() { try { sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance(); std::unique_ptr<sql::Connection> conn( driver->connect("tcp://127.0.0.1:3306", "root", "your_password")); conn->setSchema("test_db"); conn->setSessionVariable("character_set_results", "utf8mb4"); std::unique_ptr<sql::Statement> stmt(conn->createStatement()); std::unique_ptr<sql::ResultSet> res( stmt->executeQuery("SELECT id, name FROM users ORDER BY id")); while (res->next()) { std::cout << "id=" << res->getInt("id") << ", name=" << res->getString("name") << std::endl; } } catch (sql::SQLException& e) { std::cerr << "SQL ERROR: " << e.what() << ", code=" << e.getErrorCode() << std::endl; return 1; } return 0; }4.2 工程引用配置
在VS2013里新建一个空的控制台工程,然后在“项目属性”里做四件事:
- C/C++ -> 常规 -> 附加包含目录:填入安装目录的include路径,比如D:\dev\dist\connector-x64\include;
- 链接器 -> 常规 -> 附加库目录:填入安装目录的lib路径;
- 链接器 -> 输入 -> 附加依赖项:手动加上mysqlcppconn.lib(如果编译的是Debug模式,注意文件名可能是mysqlcppconn-d.lib);
- 配置管理器里确认平台是x64或Win32,必须和库的位数一致。
这里必须强调Debug和Release不能混用。VS2013里Debug和Release的运行时库不同,连Debug版本的库时如果工程是Release模式,链接器会报“LNK2038 mismatch detected”,措辞是运行时库不匹配,实际就是Debug/Release串了。
4.3 运行部署阶段的DLL处理
以动态库模式编译时,程序运行需要mysqlcppconn.dll,最简单的办法是把它复制到exe同目录下。我试过把它加入系统PATH,也能跑,但部署到客户机器时不如直接放exe同目录省事。另外,如果你的安装包工具支持,可以把DLL放到和exe同目录,然后设置“安装目录/应用程序目录”优先搜索路径,这样更规范。
如果编译时选的是静态库(DYNAMIC_LIB=0),那就不需要带DLL,但前提是项目里所有模块的运行库设置一致,比如统一使用“多线程调试(/MTd)”或“多线程(/MT)”。静态模式下若混用/MT和/MD,同样会撞LNK2038。
5. 常见问题与排查技巧实录
5.1 CMake与编译期高频报错
我整理了这次编译及后续帮别人处理时遇到频率最高的几个问题,直接做成了速查表:
| 报错现场 | 原因分析 | 解决办法 |
|---|---|---|
| 提示找不到Boost | WITH_BOOST路径没配,或路径指到了Boost内部层目录 | 确认路径指向包含boost文件夹的根目录,例如boost_1_59_0 |
| 提示找不到OpenSSL | 机器上没有配置OpenSSL开发库 | 用不到SSL加密时,把WITH_SSL设为0 |
| fatal error C1083: 无法打开包括文件: openssl/ssl.h | 上一条的衍生问题 | 同上,或者配合WITH_SSL的OpenSSL根目录 |
| LNK2019 unresolved external symbol | 库没链接、位数不匹配、Debug/Release混用 | 检查附加依赖项,核对库名称及平台 |
| LNK2038 runtime library mismatch | 运行库不一致 | 统一/MT或/MD,注意Debug/Release对称 |
| 运行提示找不到mysqlcppconn.dll | 动态库没有被放到加载路径 | 将DLL放入exe同目录,或加入PATH |
其中LNK2038这个错值得展开说一下。它本质上是MSVC在链接新版标准库代码时插入的版本标记检测,用来防止“C++标准库实现不一致”的二进制混用。VS2013的MSC_VER是1800,VS2015是1900,两者编译出的库文件在静态变量布局上可能就不一致,强行链接轻则报警重则崩溃。自编译连接器,本质上就是保证“链接双方编译环境同源”,所以才需要在VS2013里从源码走一趟。
5.2 连接MySQL时的认证与字符集坑
库编译好了,程序也编过了,运行阶段同样有经典坑。最典型的是连接MySQL 8.0时,用户认证插件默认是caching_sha2_password,而Connector/C++ 1.1.x年代太早,不认识这个认证方式,会直接报“Authentication plugin 'caching_sha2_password' cannot be loaded”。解决办法有两个:一个是把MySQL用户的认证方式改回mysql_native_password,在MySQL里执行:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';另一个是换用新版连接器。在老项目锁定VS2013的前提下,我一般建议用第一种,简单直接。
字符集问题也容易踩。连接之后插入或查询中文乱码,十有八九是会话字符集没指定。在示例代码里我加了一行setSessionVariable("character_set_results", "utf8mb4"),这是比较稳妥的做法;也可以在连接后直接执行SET NAMES utf8mb4,效果一样。注意MySQL的字符集名称是utf8mb4,不是utf8,不少人在这个细节上翻车。
5.3 双平台编译的“缓存陷阱”
如果同时编译win32和win64两套库,务必分两个构建目录,千万不要偷懒在同一个目录里反复切换生成器。CMake的缓存(CMakeCache.txt)只要生成过,就记住了第一轮的生成器类型和变量值,第二次就算你在GUI里改了生成器,也有很多配置项不会真正刷新。我一开始图省事在同一个build目录里来回切,结果64位的库文件里混入了32位的链接参数,导致例程链接时一直报无法解析的外部符号,白白折腾了两小时。类似地,如果你改了WITH_BOOST或WITH_SSL,保险起见也可以删掉构建目录重新Configure,CMake有时候并不像你想象的那么智能。
6. 实测中的一点个人体会
这次在VS2013下编译MySQL Connector/C++,整体思路其实可以抽象成一句话:老工具链的项目,第三方依赖库最可靠的来源永远是“和你同一环境现编出来的”。网上能找到各种编译好的版本,但MSVC版本的兼容性玄学太多,编译器之间的ABI裂缝是你无法通过改代码绕过去的。自己走一遍CMake流程,反而能把工具链版本、运行时库、依赖关系全部理清楚,后面再遇到其他C/C++库的适配问题,也都是同一个套路。
最后再分享一个实用小技巧:编译完成的库文件,建议连同include目录、dll一起打包成一个压缩包,按“连接器版本-平台-编译时间”命名,比如mysql_connector_cpp_1.1.6_vs2013_x64_20231215.zip。这个习惯帮我解决了很多次“两个月后重新搭环境”的麻烦,比临时翻源码再编译一遍省事太多。
本文还有配套的精品资源,点击获取