1. 为什么Qt程序连不上MySQL——一个被反复踩烂却总被忽略的底层断点
你写好了Qt界面,数据库逻辑也跑通了,QSqlDatabase::addDatabase("QMYSQL")一行代码看着毫无破绽。可一运行,弹窗就冷冰冰地甩出一句:QSqlDatabase: QMYSQL driver not loaded。再查QSqlDatabase::drivers(),返回的列表里压根没有"QMYSQL"。这时候你大概率会去翻Qt官方文档,看那几行“编译MySQL驱动”的说明,然后照着敲命令、改路径、重装CMake……折腾两小时,最后发现还是不行。
这不是你手生,也不是运气差。这是Qt在Windows上连接MySQL最经典、最顽固的一类问题——驱动未加载,本质不是代码写错了,而是二进制依赖链在某个环节彻底断裂了。它不像Linux下ldd一查就能看到缺哪个so,也不像macOS用otool -L能快速定位dylib缺失;Windows的DLL加载机制更隐蔽,错误提示更模糊,而Qt官方文档对mingw64+MySQL这一组合的支持描述又极其简略,甚至存在版本错位(比如5.14.1的文档仍指向老版MySQL Connector/C的下载页)。我见过太多项目卡在这一步:某高校实验室的图像处理Demo,因数据库驱动没起来,整个数据回传模块停摆两周;某公司跨平台系统在Windows端测试时,开发机本地能连,打包发给客户后全军覆没——原因都是同一个:libmysql.dll没放对地方,或者放对了但Qt根本没找到它。
这个标题里的“Qt5.14.1 + mingw64 + MySQL5.7”不是随意拼凑的版本号。它代表了一个真实存在的技术交界带:Qt 5.14.x是最后一个对mingw64支持完整、且尚未全面转向CMake构建体系的稳定大版本;mingw64(特指x86_64-8.1.0-release-posix-seh-rt_v6-rev0)是当时Qt官方预编译包默认捆绑的工具链,ABI兼容性极强;MySQL 5.7则是企业级项目中至今仍在大量服役的长期支持版本,其客户端库libmysql.dll的导出符号、线程模型与新版MySQL 8.0有实质性差异。三者叠加,意味着你不能简单套用Qt 6.x的CMakeLists写法,也不能直接拿MySQL 8.0的connector来编译——稍有偏差,链接器就会静默失败,而Qt运行时只会报一句“driver not loaded”,把人逼到怀疑人生。
所以这篇文章不讲“怎么安装Qt”,也不讲“怎么下载MySQL”,更不讲“如何写SQL语句”。我们只聚焦一件事:让qsqlmysql.dll这个文件,从源码编译出来,到被Qt运行时成功加载,中间每一步的物理路径、二进制依赖、环境变量作用域,全部掰开揉碎,实测验证。你会看到,一个看似简单的驱动编译,背后牵扯到Qt的插件搜索机制、mingw64的链接器行为、Windows的DLL加载顺序、MySQL客户端库的ABI版本匹配,以及——最容易被忽略的,Qt Creator工程配置与系统PATH环境变量之间那微妙到几乎不可见的冲突。
提示:本文所有操作均基于纯净Windows 10 20H2系统(无其他Qt多版本共存干扰),使用Qt 5.14.1 MinGW 64-bit官方离线安装包(
qt-opensource-windows-x86-5.14.1.exe),MySQL 5.7.33社区版(mysql-5.7.33-winx64.zip),以及配套的MySQL Connector/C 6.1.11(mysql-connector-c-6.1.11-winx64.zip)。版本精确性不是教条,而是为了复现那个“刚好能跑通”的确定性状态——因为在这个领域,差一个小版本,可能就是undefined reference to 'mysql_init@4'和undefined reference to 'mysql_init@8'的区别。
2. 编译前必须厘清的四个物理事实:路径、头文件、库文件、插件目录
很多教程一上来就让你cd进%QTDIR%\Src\qtbase\src\plugins\sqldrivers\mysql,然后qmake、mingw32-make。这步没错,但如果你没提前确认以下四件事的物理存在性与一致性,后续90%的概率会卡在链接阶段,报一堆undefined reference。这不是命令没敲对,而是你的构建环境本身就不满足最基本的前提条件。
2.1 Qt源码必须与预编译二进制完全匹配
Qt 5.14.1官方安装包默认不附带源码。你必须单独下载对应版本的源码包(qt-everywhere-src-5.14.1.zip),并严格解压到与Qt安装目录同级的路径下。例如,若你的Qt安装在C:\Qt\5.14.1\mingw64,那么源码就必须放在C:\Qt\5.14.1\Src(注意是Src,不是src,大小写敏感)。为什么?因为qmake在生成Makefile时,会硬编码QT_SOURCE_TREE变量,该变量指向$[QT_INSTALL_PREFIX]/../Src。如果源码路径不对,#include <QtSql/private/qsql_mysql_p.h>这类私有头文件就会找不到,编译直接中断。
更关键的是,源码包必须与你使用的Qt二进制版本完全一致。Qt 5.14.1有多个子版本(如5.14.1、5.14.1-0、5.14.1-1),它们的内部API可能有细微差别。我曾用5.14.1-1的源码去编译5.14.1的二进制,结果在qsqlmysql.cpp里遇到QScopedPointer<QSqlDriverPrivate>的构造函数签名不匹配——因为私有类QSqlDriverPrivate的成员变量布局在两个子版本间发生了偏移。这种错误不会在编译时报错,而是在运行时导致qsqlmysql.dll加载后立即崩溃。解决方案只有一个:去Qt官网archive页面,下载qt-everywhere-src-5.14.1.tar.xz(或zip),SHA256校验码必须与官网公布的一致。
2.2 MySQL头文件与库文件必须来自Connector/C,而非MySQL Server
这是一个高频误区。很多人直接把MySQL Server安装目录下的include和lib文件夹拿来用。这是危险的。MySQL Server的lib目录下通常是mysqlclient.lib(静态导入库)或libmysql.lib(旧版静态库),而mingw64链接器(g++)需要的是.a格式的静态库,或者能被dlltool处理的.def文件。更重要的是,Server版的libmysql.dll是为Visual Studio编译的,其导出符号采用__cdecl调用约定,而mingw64默认使用__stdcall,两者ABI不兼容,强行链接会导致运行时堆栈错乱。
正确做法是下载MySQL Connector/C 6.1.11(专为C语言客户端设计,ABI稳定,mingw64友好)。解压后,你会得到标准的include和lib目录:
include/mysql.h,include/my_global.h等头文件,路径记为C:\mysql-connector-c-6.1.11-winx64\includelib\libmysql.dll(运行时动态库)和lib\libmysql.a(mingw64链接用的静态库),路径记为C:\mysql-connector-c-6.1.11-winx64\lib
注意:Connector/C 6.1.11是MySQL 5.7的官方配套版本。它与MySQL 5.7.33的协议完全兼容,且其
libmysql.dll导出的函数符号(如mysql_real_connect@24)与Qt 5.14.1的qsqlmysql.cpp中调用的符号完全匹配。跳过这一步,直接用Connector/C 8.0,你会立刻遇到mysql_ssl_set等函数不存在的链接错误——因为8.0已废弃SSL相关旧接口。
2.3 Qt的插件目录结构是硬编码的,不能靠环境变量绕过
Qt运行时查找SQL驱动的路径是固定的,由QCoreApplication::libraryPaths()决定,其默认值为:
QTDIR/plugins/sqldrivers/(Qt安装目录下的plugins子目录)APPDIR/plugins/sqldrivers/(你的应用程序exe所在目录下的plugins子目录)
这里的关键是:qsqlmysql.dll必须放在sqldrivers这个确切的子目录名下,且该目录必须位于上述两个路径之一。你不能把它丢在C:\mylibs\然后指望设置PATH就能生效。PATH只影响libmysql.dll的加载,不影响Qt插件本身的发现机制。我曾见过有人把qsqlmysql.dll放在C:\Qt\5.14.1\mingw64\bin\下,认为Qt会自动扫描bin目录——这是完全错误的。bin目录只存放Qt自身的可执行文件(如qmake.exe,moc.exe),插件有自己专属的plugins目录树。
因此,在编译前,请手动创建目录:C:\Qt\5.14.1\mingw64\plugins\sqldrivers\。这个路径将作为qsqlmysql.dll的最终落点。后续所有make install操作,目标路径都应指向此处。
2.4 环境变量PATH的修改时机,决定了libmysql.dll能否被找到
qsqlmysql.dll本身不包含libmysql.dll的代码,它只是个薄层封装,所有实际的网络通信、协议解析都委托给libmysql.dll完成。因此,当你的Qt程序启动,并尝试加载qsqlmysql.dll时,Windows加载器会立即去寻找libmysql.dll。如果找不到,qsqlmysql.dll的加载就会失败,Qt则报“driver not loaded”。
libmysql.dll的搜索顺序是:
- 应用程序exe所在目录
PATH环境变量中列出的目录(按顺序)- Windows系统目录(
System32等)
最佳实践是:将libmysql.dll复制到你的Qt应用程序exe的同一目录下。这样最直接、最可靠,不依赖全局PATH,避免与其他项目冲突。但如果你希望统一管理,也可以将其放入C:\Qt\5.14.1\mingw64\bin\,然后确保该路径已加入系统PATH。注意:修改PATH后,必须重启Qt Creator(或命令行终端),否则新环境变量对当前进程无效。我曾因忘记重启Qt Creator,导致qmake能正常找到头文件,但运行时死活找不到libmysql.dll,排查了整整一个下午才意识到是环境变量没生效。
3. 从零开始编译qsqlmysql.dll:逐行解析qmake与make的隐含逻辑
现在,所有物理前提都已确认。我们进入真正的编译环节。这一步不是机械执行命令,而是要理解每一行命令背后,qmake和mingw32-make究竟在做什么。
3.1 进入正确的源码目录并执行qmake
打开Qt自带的“MinGW 64-bit”命令行终端(不是Windows PowerShell,也不是Git Bash,必须是Qt安装包自带的那个,它已预设好所有环境变量)。执行:
cd C:\Qt\5.14.1\Src\qtbase\src\plugins\sqldrivers\mysql qmake "INCLUDEPATH+=C:\mysql-connector-c-6.1.11-winx64\include" "LIBS+=-LC:\mysql-connector-c-6.1.11-winx64\lib -lmysql" mysql.pro这条命令拆解如下:
cd ...:切换到MySQL驱动源码目录。注意路径中的mysql是目录名,不是项目名。qmake ... mysql.pro:qmake读取mysql.pro这个项目文件。该文件定义了源码文件列表、目标类型(TEMPLATE = lib)、输出名称(TARGET = qsqlmysql)等元信息。"INCLUDEPATH+=...":向编译器传递头文件搜索路径。+=表示追加,而非覆盖。这里告诉g++,当遇到#include <mysql.h>时,去C:\mysql-connector-c-6.1.11-winx64\include下找。"LIBS+=...":向链接器传递库链接参数。-L指定库文件搜索路径,-lmysql告诉链接器链接libmysql.a(注意:mingw64下-lmysql会自动寻找libmysql.a,而非libmysql.dll)。
关键细节:
qmake生成的Makefile中,LIBS变量会被展开为g++ -shared -o qsqlmysql.dll ... -LC:\mysql-connector-c-6.1.11-winx64\lib -lmysql。这意味着链接阶段,链接器会从libmysql.a中提取所有被qsqlmysql.cpp调用的函数符号,并将它们的地址硬编码进qsqlmysql.dll。因此,libmysql.a必须是完整的、未被strip过的静态库。Connector/C 6.1.11提供的libmysql.a正是如此。
3.2 执行mingw32-make并观察关键输出
在qmake成功返回后,执行:
mingw32-make此时,控制台会滚动大量编译输出。你需要重点关注以下几行:
g++ -c -pipe -fno-keep-inline-dllexport -O2 -std=gnu++1y -Wall -W -DUNICODE -D_UNICODE -DWIN32 -DQT_NO_DEBUG -DQT_PLUGIN -DQT_SQL_LIB -DQT_CORE_LIB -I. -IC:/Qt/5.14.1/Src/qtbase/src/sql/kernel -IC:/Qt/5.14.1/Src/qtbase/include/QtSql/5.14.1 -IC:/Qt/5.14.1/Src/qtbase/include/QtSql/5.14.1/QtSql -IC:/Qt/5.14.1/Src/qtbase/include/QtCore/5.14.1 -IC:/Qt/5.14.1/Src/qtbase/include/QtCore/5.14.1/QtCore -IC:/Qt/5.14.1/Src/qtbase/include -IC:/Qt/5.14.1/Src/qtbase/include/QtSql -IC:/Qt/5.14.1/Src/qtbase/include/QtCore -IC:/mysql-connector-c-6.1.11-winx64/include -I. -I"C:\Qt\5.14.1\mingw64\mkspecs\win32-g++" -o .obj\release\main.o main.cpp这行显示了g++的完整编译命令。请检查-IC:/mysql-connector-c-6.1.11-winx64/include是否在其中。如果不在,说明qmake的INCLUDEPATH参数没生效,编译会因找不到mysql.h而失败。
紧接着是链接命令:
g++ -shared -o ..\..\..\plugins\sqldrivers\qsqlmysql.dll .obj\release\main.o .obj\release\qsql_mysql.o .obj\release\qsqlmysqldriver.o -LC:\mysql-connector-c-6.1.11-winx64\lib -lmysql -LC:\Qt\5.14.1\mingw64\lib -lQt5Sql -lQt5Core -lws2_32 -ladvapi32 -lshell32 -luser32 -lkernel32重点看-LC:\mysql-connector-c-6.1.11-winx64\lib -lmysql是否出现。如果缺失,链接器会报undefined reference to 'mysql_init'等错误。这是因为qsqlmysql.dll的代码里调用了这些函数,但链接器不知道去哪里找它们的实现。
3.3 make install:将dll复制到Qt插件目录的精确过程
编译成功后,qsqlmysql.dll会生成在当前目录下的release子目录中(即C:\Qt\5.14.1\Src\qtbase\src\plugins\sqldrivers\mysql\release\qsqlmysql.dll)。但这还不是终点。你需要把它放到Qt能自动发现的位置。
执行:
mingw32-make installmake install的行为由mysql.pro文件中的target.path变量控制。默认情况下,它被设置为$$[QT_INSTALL_PLUGINS]/sqldrivers。$$[QT_INSTALL_PLUGINS]是一个qmake内置变量,其值等于C:\Qt\5.14.1\mingw64\plugins(即Qt安装目录下的plugins)。因此,make install会将qsqlmysql.dll从release\目录,复制到C:\Qt\5.14.1\mingw64\plugins\sqldrivers\。
你可以手动验证:
- 打开文件管理器,导航至
C:\Qt\5.14.1\mingw64\plugins\sqldrivers\ - 确认
qsqlmysql.dll文件存在,且文件大小在300KB左右(太小说明链接失败,太大说明包含了调试信息)
实操心得:
make install命令有时会因权限问题失败(尤其在Windows 10 UAC开启时)。如果看到install: cannot create regular file ... Permission denied,请右键点击Qt Creator的“MinGW 64-bit”终端,选择“以管理员身份运行”,然后重新执行mingw32-make install。不要试图手动复制dll——make install还会处理一些隐式的文件属性设置,手动复制可能遗漏。
4. 驱动加载失败的终极排查链路:从Qt日志到Dependency Walker的全栈诊断
即使你完美执行了上述所有步骤,QSqlDatabase::drivers()里依然看不到"QMYSQL",或者程序启动时弹出"QSqlDatabase: QMYSQL driver not loaded"。这时,你需要一套系统性的、自上而下的排查链路。这不是靠运气,而是按顺序排除每一个可能的故障点。
4.1 启用Qt的详细插件日志,定位加载失败的第一现场
Qt提供了一个隐藏的环境变量QT_DEBUG_PLUGINS=1,它可以让你看到插件加载器的每一步决策。在Qt Creator中,打开你的项目,进入“Projects”模式,选择“Run”设置页,在“Run Environment”区域点击“Details”旁的“Add”按钮,添加一个新的环境变量:
- Name:
QT_DEBUG_PLUGINS - Value:
1
然后运行你的程序。控制台(Application Output)会输出大量日志,形如:
QFactoryLoader::QFactoryLoader() checking directory path "C:/Qt/5.14.1/mingw64/plugins/sqldrivers" ... QFactoryLoader::QFactoryLoader() looking at "C:/Qt/5.14.1/mingw64/plugins/sqldrivers/qsqlmysql.dll" Found metadata in lib C:/Qt/5.14.1/mingw64/plugins/sqldrivers/qsqlmysql.dll, metadata= { "IID": "org.qt-project.Qt.QSqlDriverFactoryInterface", "MetaData": { "Keys": ["QMYSQL"] }, "className": "QMYSQLDriverPlugin", "debug": false, "version": 331520 } Got keys from plugin meta data ("QMYSQL") QFactoryLoader::QFactoryLoader() checking directory path "C:/myapp/build-myapp-Desktop_Qt_5_14_1_MinGW_64_bit-Debug/plugins/sqldrivers" ... ... Cannot load library C:/Qt/5.14.1/mingw64/plugins/sqldrivers/qsqlmysql.dll: The specified module could not be found.最后一行Cannot load library ... The specified module could not be found.是关键。它明确告诉你:qsqlmysql.dll这个文件本身找到了,但在加载它时,其依赖的某个模块(DLL)缺失了。这个“某个模块”,99%的情况下就是libmysql.dll。
4.2 使用Dependency Walker(depends.exe)进行二进制依赖分析
qsqlmysql.dll是一个动态链接库,它自身依赖于其他DLL。Windows的dumpbin /dependents命令功能有限,而老牌工具Dependency Walker(depends.exe)能清晰展示整个依赖树。
下载depends.exe(微软官方已停止维护,但v2.2版本在Win10上完全可用),然后:
- 将
C:\Qt\5.14.1\mingw64\plugins\sqldrivers\qsqlmysql.dll拖入depends.exe窗口 - 观察左侧树状图,展开
qsqlmysql.dll节点
你会看到类似这样的依赖列表:
Qt5Sql.dll(OK)Qt5Core.dll(OK)libmysql.dll(ERROR: Not Found)KERNEL32.dll(OK)WS2_32.dll(OK)
libmysql.dll旁边标着红色叉号,状态为Error opening file. The system cannot find the file specified.。这证实了日志中的判断:qsqlmysql.dll找不到它的“心脏”libmysql.dll。
注意:
depends.exe有时会误报MSVCP140.dll等VC运行时库。Qt 5.14.1 mingw64版不依赖VC运行时,它依赖的是libwinpthread-1.dll和libgcc_s_seh-1.dll,这两个库已随Qt安装包一同部署在C:\Qt\5.14.1\mingw64\bin\下。只要你的PATH包含此路径,它们就不会报错。真正需要你操心的,只有libmysql.dll。
4.3 验证libmysql.dll的完整性与架构匹配
即使你把libmysql.dll放在了exe目录下,它也可能无法加载。原因有两个:
- 架构不匹配:你的Qt是x86_64(64位)版本,而你放的
libmysql.dll却是x86(32位)的。Windows会静默拒绝加载,不报任何错误,只是让qsqlmysql.dll加载失败。 - 依赖缺失:
libmysql.dll自身还依赖于VCRUNTIME140.dll和UCRTBASE.DLL(Universal CRT)。虽然Connector/C 6.1.11是纯C实现,理论上不依赖VC运行时,但某些编译版本可能链接了它。
验证方法:
右键点击
libmysql.dll-> “属性” -> “详细信息”选项卡,查看“文件版本”和“产品版本”。Connector/C 6.1.11的版本号应为6.1.11.0。更可靠的方法是用
file命令(需安装MinGW的binutils):file C:\mysql-connector-c-6.1.11-winx64\lib\libmysql.dll输出应为:
PE32+ executable (DLL) (GUI) x86-64, for MS Windows。如果显示PE32,那就是32位,必须更换。检查
libmysql.dll的直接依赖:depends.exe C:\mysql-connector-c-6.1.11-winx64\lib\libmysql.dll它应该只依赖
KERNEL32.dll,WS2_32.dll,ADVAPI32.dll,USER32.dll,GDI32.dll等系统DLL。如果出现VCRUNTIME140.dll,说明你下载的Connector/C版本有问题,应换回官方6.1.11。
4.4 最后的杀手锏:Process Monitor实时监控文件访问
当以上所有方法都失效,qsqlmysql.dll和libmysql.dll明明都在正确路径,却依然报错,你需要祭出Sysinternals的ProcMon.exe。它能记录Windows内核级别的每一个文件、注册表访问请求。
操作步骤:
- 下载
ProcMon.exe,以管理员身份运行 - 点击“Filter” -> “Filter...”,添加过滤规则:
Process Nameisyourapp.exeIncludeOperationisCreateFileIncludePathcontainslibmysqlInclude
- 点击“Capture Events”开始监控
- 运行你的Qt程序
- 停止捕获,观察日志
你会看到类似这样的记录:
yourapp.exeCreateFileC:\myapp\libmysql.dllNAME NOT FOUNDyourapp.exeCreateFileC:\Qt\5.14.1\mingw64\bin\libmysql.dllNAME NOT FOUNDyourapp.exeCreateFileC:\Windows\System32\libmysql.dllNAME NOT FOUND
这清楚地告诉你,程序确实在按顺序搜索libmysql.dll,但它在所有路径下都没找到。此时,你只需把正确的libmysql.dll(64位,6.1.11版)复制到C:\myapp\目录下,问题即刻解决。ProcMon不会撒谎,它把操作系统的真实行为赤裸裸地展现在你面前。
5. 在Qt Creator中集成MySQL驱动:从新建项目到真机部署的全流程闭环
编译成功、驱动加载无误,只是万里长征第一步。真正考验功力的,是如何把这个能力无缝集成进日常开发流程,让团队其他成员无需重复踩坑。下面是以Qt Creator为IDE,从零开始创建一个能连接MySQL的Qt Widgets Application的完整闭环。
5.1 创建项目并配置.pro文件的最小化改动
新建一个Qt Widgets Application项目(命名为mysql_demo),在生成的mysql_demo.pro文件末尾,添加两行:
QT += sql CONFIG += c++11QT += sql是必须的,它告诉qmake链接Qt5Sql.dll。CONFIG += c++11是推荐的,因为MySQL Connector/C的头文件中使用了C++11特性。
切记:不要在这里添加LIBS += ...或INCLUDEPATH += ...!因为你的项目并不直接调用MySQL C API,它只通过Qt的QSqlDatabase接口。所有底层依赖都已由qsqlmysql.dll封装完毕。在.pro里硬编码MySQL路径,反而会污染项目,使其失去可移植性。
5.2 编写核心连接代码并规避常见陷阱
在mainwindow.cpp的构造函数中,添加以下代码:
#include <QSqlDatabase> #include <QSqlError> #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 1. 检查驱动是否可用 QStringList drivers = QSqlDatabase::drivers(); qDebug() << "Available SQL drivers:" << drivers; if (!drivers.contains("QMYSQL")) { qDebug() << "QMYSQL driver is NOT loaded!"; return; } // 2. 创建数据库连接 QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); db.setHostName("127.0.0.1"); // 或你的MySQL服务器IP db.setDatabaseName("testdb"); db.setUserName("root"); db.setPassword("your_password"); db.setPort(3306); // 3. 尝试打开连接 if (!db.open()) { qDebug() << "Failed to connect to database:" << db.lastError().text(); return; } qDebug() << "Connected to MySQL successfully!"; }这段代码有三个关键点:
- 先检查
QSqlDatabase::drivers():这是最廉价的健康检查。如果这里就失败,说明驱动根本没加载,无需往下走。 - 显式调用
db.open():很多新手以为addDatabase就等于连接上了,其实不然。addDatabase只是注册一个连接配置,open()才是发起TCP握手、认证、初始化会话的真正动作。 - 打印
db.lastError().text():当open()失败时,这个字符串会告诉你具体原因。可能是网络不通(Can't connect to MySQL server on '127.0.0.1'),也可能是认证失败(Access denied for user 'root'@'localhost'),甚至是驱动问题(Driver not loaded)。它是你排错的第一手信息。
5.3 构建与部署:如何让程序在没有Qt开发环境的机器上运行
当你在开发机上测试通过后,下一步是打包发布。Qt官方提供了windeployqt.exe工具,但它对第三方插件(如qsqlmysql.dll)的支持是半自动的。
标准流程:
- 使用Qt Creator的“Release”模式构建你的项目,生成
mysql_demo.exe。 - 打开“MinGW 64-bit”命令行,
cd到你的build-mysql_demo-...-Release目录。 - 执行:
这会将Qt自身所需的DLL(windeployqt --dir ./deploy --plugindir ./deploy/plugins --qmldir ./deploy/qml --no-opengl-sw mysql_demo.exeQt5Core.dll,Qt5Gui.dll等)以及platforms\qwindows.dll复制到./deploy目录下。 - 手动复制MySQL相关文件:
- 将
C:\Qt\5.14.1\mingw64\plugins\sqldrivers\qsqlmysql.dll复制到./deploy/plugins/sqldrivers/ - 将
C:\mysql-connector-c-6.1.11-winx64\lib\libmysql.dll复制到./deploy/(与mysql_demo.exe同级)
- 将
最终,./deploy目录的结构应为:
./deploy/ ├── mysql_demo.exe ├── libmysql.dll <-- 必须在此 ├── Qt5Core.dll ├── Qt5Gui.dll ├── ... └── plugins/ └── sqldrivers/ └── qsqlmysql.dll <-- 必须在此实操心得:
windeployqt不会自动复制qsqlmysql.dll,因为它不知道你用了哪个SQL驱动。你必须手动完成这一步。同样,它也不会复制libmysql.dll,因为这不是Qt的一部分。很多线上部署失败,根源就在于漏掉了这两个文件。建议写一个简单的批处理脚本(.bat),把windeployqt和手动复制的命令都写进去,每次发布一键执行,杜绝人为疏忽。
5.4 跨版本适配指南:Qt 5.12.x / 5.15.x 的关键差异点
标题里说“其他版本Qt也类似”,这没错,但“类似”不等于“相同”。不同Qt小版本在驱动编译上存在几个关键差异,必须提前知晓:
Qt 5.12.x:这是LTS(长期支持)版本,其源码结构与5.14.1基本一致。唯一区别是,5.12.x的
mysql.pro文件中,TARGET变量可能被写死为qsqlmysql5(带版本号后缀)。编译出的dll名为qsqlmysql5.dll,但Qt运行时仍能识别它,因为其插件元数据(Keys字段)仍是["QMYSQL"]。你只需确保make install后,plugins/sqldrivers/目录下是qsqlmysql5.dll即可。Qt 5.15.x:这是5.x系列的最后一个版本,也是向Qt 6过渡的桥梁。它引入了新的
cmake构建支持,但qmake依然可用。最大的变化是,5.15.x的mysql.pro文件中,LIBS的写法更严格,要求显式指定-lmysqlclient(而非-lmysql),并且需要额外链接-lzlib(因为MySQL 5.7启用了压缩协议)。如果你用5.15.x编译,qmake命令应改为:qmake "INCLUDEPATH+=C:\mysql-connector-c-6.1.11-winx64\include" "LIBS+=-LC:\mysql-connector-c-6.1.11-winx64\lib -lmysqlclient -lzlib" mysql.proQt 6.x:完全摒弃
qmake,强制使用CMake。其驱动编译流程与5.x截然不同,需要编写CMakeLists.txt,并使用find_package(MySQL REQUIRED)。因此,标题中的“其他版本Qt也类似”,仅适用于Qt 5.x系列(5.9 ~ 5.15)。Qt 6.x是另一个世界,不应混为一谈。
6. 我在实际项目中踩过的三个深坑与对应的硬核解决方案
理论讲完,现在分享我在某公司跨平台数据采集系统中,为Qt 5.14.1集成MySQL驱动时,踩过的三个最深、最隐蔽、也最具代表性的坑。它们都不在任何官方文档里,但每个都足以让一个项目停滞数天。
6.1 坑:Qt Creator的“Shadow Build”路径导致qmake找不到源码
现象:在Qt Creator中,我勾选了“Shadow build”,构建目录设为C:\build\mysql_demo。当我执行qmake命令时,它却报错Project ERROR: Cannot find MySQL header files,尽管INCLUDEPATH参数明明写对了。
根因:Qt Creator的“Shadow build”功能,会在构建时自动创建一个独立的、与源码分离的构建目录。但qmake命令本身是在这个构建目录下执行的。而qmake在解析`mysql