QT windeployqt 数据库驱动问题
测试一个数据库管理模块。环境Win7_32,Qt 5.12.9, mingw73_32, 自行编译的Mysql和oracle数据库驱动。
集成环境下程序一切正常,debug,release模式都好用。用windeployqt发布之后发现数据库无法工作。多方测试没有头绪。
在网上发现有人有类似经历,用覆盖dll的方法解决。就是把 mingw73_32/bin目录里的东西全复制到目标文件夹,然后在程序启动之后全删除,因为正在使用的dll无法删除,所以能剩下的就是有用的。试一下居然管用,可也像别人说的一样,留下来的文件和windeployqt发布出来的一模一样。可我想既然运行结果不一样,那这些文件也一定不一样。
把windeployqt发布出来的dll和复制过来的dll逐一对比,发现这些文件大小完全一样,唯一有一个文件, Qt5Core.dll 日期不一致。windeployqt过来的日期是deploy执行的时间,复制过来的日期是QT安装时间。
多次试验发现,解决问题并不需要复制全部dll再删除,只需要复制这一个Qt5Core.dll就可以。
Qt5Core.dll这个文件一定有一些特殊机制。系统里其它的dll日期都是固定的,这个Qt5Core.dll的日期却是QT安装时修改的。我在单位的机器里面,同样安装包安装的环境,这个文件日期和家里的日期就不一样。每次windeployqt时复制过去的这个文件日期都是deploy执行的时间。不知道在这个发布过程中这个文件内部做了些什么修改?
FQ出去在一个外面网站上找到了线索。
那篇贴子说为了避免路径以硬编码形式写在程序里,windeployqt在向目标文件夹复制Qt5Core.dll时会把文件内部的硬编码路径改成相对路径。
这样Qt5Core.dll文件时间的问题就解释通了。安装QT时,系统会根据具体的安装路径修改Qt5Core.dll里面的路径,所以这个文件的日期总是安装日期。发布时又会变更成相对路径,所以发布出去的Qt5Core.dll日期和安装的又会不同。
用二进制编辑工具(我用的ultraEdit)对比一下安装和发布两个版本的Qt5Core.dll,发现在文件大约中部位置有一个qt_prfxpath字串,发布版本的是 :
qt_prfxpath=.
安装版本的是 :
qt_prfxpath=E:\Qt5\5.12.9\mingw73_32,就是我机器里Qt的实际安装位置。
之前覆盖dll的方法之所以能解决问题,是因为自己的机器里有硬路径指向的Qt,但把这个发布文件打包传送到一个没安装过Qt的环境就又不好使了。
按理说相对路径指向的是可执行文件的位置,它为什么它会不好使呢?
研究一下安装版本qt_prfxpath,它指向的位置是mingw73_32,在Qt安装目录里,mingw73_32下面还有bin、doc、plugins等一系列子文件夹,数据库驱动在plugins/sqldrivers下面。
可deploy复制过来的sqlrivers文件夹和可执行文件在同一层文件夹,跳过了plugins这一层。
也就是说,如果以 qt_prfxpath 为文件夹起点,本地开发环境的数据库驱动在./plugins/sqldrivers下面去,发布环境的数据库驱动却放在./sqldrivers下面。
会不会是路径结构不一致引起的数据库驱动无法工作呢?
试验一下,在发布环境可执行文件同级建立一个plugins文件夹,把deploy过来的文件夹全都移动进去,居然猜对了,大功告成。
还有一个需要注意的问题,自行编译的数据库驱动,有一些支持库deploy不会自动复制,需要自己手动复制一下。
mysql数据库需要libmysql.dll,oracle数据库需要oci.dll和oraociei11.dll。这几个文件需要复制到发布环境可执行文件的同级位置。
这应该算是Qt的一个bug了。不知道后续其它版本Qt有没有同样问题。