![gallery-img](https://img-blog.csdnimg.cn/img_convert/65b5254d8d976005701a27c507c3de9f.png)
简介
这次讨论发布Qt应用程序的知识点。
背景
有很多人向涛哥询问,Qt程序发布的相关问题,网络上虽然可以搜到一大堆教程,但是可靠的比较少。
所以这次尽我所能,全面、详细地整理一些Qt程序发布的知识点,希望能帮助到更多人。
对老手来说,很多坑都踩过了,无非就是把正确的dll放在正确的路径。
对新手来说,细节上能多说几句,都将是莫大的帮助,少走弯路,节省几个小时、甚至几天都是有可能的。
如果有疏漏、错误,也欢迎大家补充、指正。
Qt的安装
Qt官网下载地址在这: http://download.qt.io/official_releases
离线安装包 或者 在线安装包 都行。
关于Qt版本的选择,涛哥建议:
体验新特性,就用最新版本;项目开发,用长期支持版(LTS)的最后一个修正版本,稳定、bug最少。
可以在Qt官方wiki上查看相关信息 https://wiki.qt.io/Main
目前为止(2019/9/2),最新版为5.13.0,LTS版本有5.9 和 5.12, 而5.9最后一个修正版本是5.9.8, 5.12则是到5.12.4
![预览](https://img-blog.csdnimg.cn/img_convert/74e2795d6c4994e893da2221f6fa552e.png)
例如上图是5.9.8的离线安装包,提供了windows、mac以及linux三种系统的可执行程序。
其中windows的安装程序”qt-opensource-windoiws-x86-5.9.8.exe”, 大小有2.4G,里面
包含了msvc_x86、msvc_x64、mingw、Android等多个版本的Qt工具链。在下载完成,安装
过程中可以分别勾选。其它版本也是类似的。
如何安装Qt,就不细说了,搞不定的去参考入门级教程吧…
Qt的目录结构
这里假设大家都装好了Qt,先来了解一下Qt的安装路径都有哪些东西。
涛哥用的是Windows 10系统,安装的Qt版本是5.12.4,以此为例来说明,其它系统和版本以实际为准。
Qt安装路径
涛哥安装在了D:\Qt\Online 路径下, 如图:
![预览](https://img-blog.csdnimg.cn/img_convert/3872d12413236c4ecd63ddc2810cb239.png)
其中“vcredist”文件夹包含了msvc2015 和 msvc2017的运行时库安装程序(后面会说怎么用,不是msvc编译器不需要)
![预览](https://img-blog.csdnimg.cn/img_convert/3fce795aed8df5a529677c53a7ce4cce.png)
“Tools”文件夹,包括QtCreator、OpenSSL库(可选)以及两种版本MinGW(可选)。
![预览](https://img-blog.csdnimg.cn/img_convert/7bd1ac095187a6e03e3695c3db0d5f05.png)
(图中还有Qt3DStudio,可忽略)
“5.12.4”文件夹,是Qt的核心路径, 里面包含多个版本的Qt工具链、头文件、动态链接库等
![预览](https://img-blog.csdnimg.cn/img_convert/6665a325b8cf9e6562eb6c478a90cf25.png)
这里涛哥安装了msvc2017、msvc2017_64、mingw73_64以及android_x86.
注意msvc2017是x86架构的Qt库,msvc2017_64则是x64架构的。
如果有msvc2013、msvc2015也同理。
Qt核心路径
接下来看一下重点,Qt的核心路径, 以msvc2017_64文件夹为例
![预览](https://img-blog.csdnimg.cn/img_convert/db8b06b3ecbb3c4f5f63b894a808b4b0.png)
bin文件夹包含了Qt提供的各种工具exe程序,以及动态链接库的dll
其中工具包括qmake.exe 和 windeployqt.exe,windeployqt.exe是我们今天主要讨论的工具。
动态链接库全部是两份dll,比如Qt5Cored.dll和Qt5Core.dll,文件名末尾带’d’表示debug版本的,另一个不带’d’的是release版本。
![预览](https://img-blog.csdnimg.cn/img_convert/3dd5a6aa2745204a30aba1b887ec73b2.png)
debug版本和release版本的主要区别:debug没有开编译器优化、携带了调试信息,release开了编译器优化O2,去掉了多余的信息
(图中还有pdb文件,是涛哥单独安装的,用来调试Qt源码,可以忽略)
和bin同级的,还有plugins文件夹,包含一些Qt用到的插件
![预览](https://img-blog.csdnimg.cn/img_convert/afb8abde019ed9f64f51636b1321c5dc.png)
比如imageformats文件夹中提供了jepg、gif、webp等图片格式的功能支持的插件,platforms文件夹则提供了平台插件,特别是
qwindows.dll这一个,在windows平台是必不可少的。
和bin同级的,另外一个文件夹是’qml’文件夹,包含Qml的各种功能模块。
和bin同级的其它文件夹,resources是WebEngine模块专用的,translations提供了
Qt内置的翻译文件,剩下的和发布无关,就不多说了。
HelloDeploy
这里新建一个简单的Hello World程序,名字就叫”HelloDeploy”。
同时为了说明问题,涛哥添加一些常用的模块。
在pro文件中,QT += 那一行该写的都写上:
![预览](https://img-blog.csdnimg.cn/img_convert/05bb14a1b641d4bb609f344c59bc2cd7.png)
在main.cpp中包含一下各个模块的头文件,再分别创建一个对象实例,调用一些简单的函数:
![预览](https://img-blog.csdnimg.cn/img_convert/c1aaee0d880b224018dfed89749b1d7d.png)
这样一个多模块依赖的程序就写好了。
Window编译和发布
Window 编译
这里要特别注意,编译器的选择, 以及编译用的是debug模式还是release模式。
涛哥这里是msvc2017_x64版本
![预览](https://img-blog.csdnimg.cn/img_convert/937c7db94dc9236e1a69aa1852ad9d30.png)
一般发布用release模式。
![预览](https://img-blog.csdnimg.cn/img_convert/e034d9d87d3c18a0edb40b984543b0be.png)
编译完成后,默认在build-xxxx-release/release/文件夹中会生成我们的exe程序。
![预览](https://img-blog.csdnimg.cn/img_convert/43bfd6d42919c20ade8a25731609590e.png)
![预览](https://img-blog.csdnimg.cn/img_convert/aead182cc28b075fcb21e168461e51de.png)
我们将这个exe复制出来,新建一个release文件夹,放进去
![预览](https://img-blog.csdnimg.cn/img_convert/ac97a45e67b666ba3fd51ec6f43855aa.png)
这时候可以尝试双击运行它,会提示缺少dll
![预览](https://img-blog.csdnimg.cn/img_convert/09ff73b38d2e3218e70f136525bf3268.png)
Window 发布
发布程序,其实就是把exe程序依赖的dll和相关资源都放在一起,保证双击运行即可。
我们前面提过的windeployqt.exe,是Qt提供的命令行工具,能帮助我们自动把需要的dll或资源复制过来。
- 我们先打开一个命令行
可以从开始菜单找到Qt提供的命令行
![预览](https://img-blog.csdnimg.cn/img_convert/d9f769d6cf332197b28523b0b8417e7d.png)
注意选对版本。这种命令行在启动时已经设置好了QT的环境变量,可以直接输入windeployqt.exe
也可以用普通的命令行,使用windeployqt.exe时带上绝对路径即可。
涛哥一般用普通的命令行,因为绝对路径不易出错。
- cd到release目录
这里说一个windows启动命令行的小技巧:在release文件夹中,按住键盘shift键,然后按鼠标右键,弹出的右键菜单,
会比普通的右键菜单多一个“在此处打开命令窗口”,点击就能在release文件夹打开命令行窗口。
![预览](https://img-blog.csdnimg.cn/img_convert/dffa269205408d4be77ad8614c2a567f.png)
如果没有这个功能,就得手动输入cd指令,进入release路径。
![预览](https://img-blog.csdnimg.cn/img_convert/f7a2352700c2fd0ebb1001715efd67e6.png)
- 执行windeployqt命令
这里通过绝对路径来使用windeployqt:
d:\qt\Online\5.12.4\msvc2017_64\bin\windeployqt.exe HelloDeploy.exe
![预览](https://img-blog.csdnimg.cn/img_convert/031523a4020e45ce498792519c30d306.png)
HelloDeploy这个程序还用到了Qml,用到Qml的程序,要给windeployqt加上qmldir参数,写上你的Qml文件所在文件夹
(没用到qml的程序,不要加这一步)
d:\qt\Online\5.12.4\msvc2017_64\bin\windeployqt.exe HelloDeploy.exe –qmldir .\qml
![预览](https://img-blog.csdnimg.cn/img_convert/39bf324bee33e6f5448ea44c20186532.png)
写好windeployqt命令后按回车执行
![预览](https://img-blog.csdnimg.cn/img_convert/dbe881e25eff31917ce4d3daa96176b4.png)
正确执行后,release文件夹下,多了很多dll,以及一些文件夹。
![预览](https://img-blog.csdnimg.cn/img_convert/c89fcc454fd91b1cbe570d54625efcf6.png)
这时候我们双击运行HelloDeploy.exe, 就可以正常启动了。
将整个文件夹压缩或拷贝到其它没有Qt环境的电脑上,也是可以启动的。
只要dll齐备了,制作安装包也不是问题。(后续有时间,我再写安装包制作的教程)
VS运行时库
如果是VS编译的程序,需要将QT路径下对应的vcredist_xxx.exe带上。
如果其它电脑上有vs运行时则可以直接运行,如果没有,就需要运行一下vs运行时安装包。
或者将运行时库里面的dll复制出来即可。
一般在VS的安装路径,都有展开的dll,可以直接拷贝。
例如,涛哥电脑上的vs2017路径如下:
![预览](https://img-blog.csdnimg.cn/img_convert/db0b13dea8ce68587bc638dd09b1ec7e.png)
按实际的路径找到这几个dll,全部拷贝即可。注意x86和x64,别拿错了。
常见的错误处理
一般使用windeployqt,大部分库都能自动拷贝,不需要手动处理,
只有极少数情况下,windeployqt跑完,会缺失一些库,还要手动处理一下。
遇到这种情况,用依赖检查工具Dependencies即可快速定位问题。
Dependencies下载链接: https://github.com/lucasg/Dependencies
Dependencies 下载好,点击”DependenciesGui.exe”就可以打开界面。注意是名字带Gui的那个,不带gui的“Dependencies.exe”是命令行程序。
![预览](https://img-blog.csdnimg.cn/img_convert/31696ecdc815ca2728cd19ff301318ce.png)
下面列举一些常见的错误信息
应用程序无法正常启动
![预览](https://img-blog.csdnimg.cn/img_convert/1dbd3f54bbd94329d304426ddd8de62f.png)
最容易出现这种错误的情况是,程序是64位编译出来的,而同级目录下的dll是32位的,
或者同级目录下没有dll,但是环境变量中指向了32位的dll。(所以涛哥没有设置环境变量)
32位和64位倒过来也是。
如果dll版本是匹配的,还有可能出现的情况是缺少第三方库。
这里说一个检查依赖的方法:
将HelloDeploy.exe重命名为HelloDeploy.dll,然后用Dependencies打开,就可以查看少哪些库
![预览](https://img-blog.csdnimg.cn/img_convert/849dd56c48331066d4b4c8dbedf48bc7.png)
如上图,红色问号的表示缺少的库。
找齐了依赖的库,再把程序的扩展名改回exe即可。
启动失败 - no Qt platform plugin
![预览](https://img-blog.csdnimg.cn/img_convert/86c5045025207188b1b947aad3820925.png)
这种情况,是QT路径下的 plugins/platforms/qwindows.dll文件没有复制过来。
注意这个dll文件直接复制到exe同级是不起作用的,要放在exe程序同级的platforms文件夹里,或者同级
的plugins/platforms文件夹里
OpenGL Context 创建失败
![预览](https://img-blog.csdnimg.cn/img_convert/a7c7a5b24065d3de057f28213ba1c466.png)
这种情况,一般是OpenGL相关的库没有复制过来,补上就好了
![预览](https://img-blog.csdnimg.cn/img_convert/32dbab1200f9d0945b6fe2e43693f646.png)
整理
我们看到,exe同级目录下,windeployqt将一堆的文件夹放在了那里,有些混乱。
涛哥观察并验证了一下,其实可以做个简单的整理。
Qt开头的文件夹都是qml的模块,剩下的文件夹除了translations都是Qt的插件,
所以新建两个文件夹qml和plugins, 分别把qml模块和插件归入其中。
这样的结构,和QT安装路径下的结构是相似的。
这也正是Qt支持的插件加载路径、qml模块加载路径。
同级的dll则是windows系统默认的动态库加载规则,不方便修改
可以参考msdn:
https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order
简单裁剪
如果你熟悉Qt的各个模块,可以进行一些裁剪。以下都是些个人经验。
不熟悉请慎重!
不熟悉请慎重!
不熟悉请慎重!
(当然静态编译也是一种裁剪的途径)
删减dll
首先可以把单元测试的dll去掉
Qt5Test.dll
Qt5QuickTest.dll
如果没用到windows扩展,Qt5WinExtras.dll也可以去掉
其次,如果你不需要内置的翻译文件,translations文件夹也可以删掉
删减plugins
再来看一下plugins:
其中platforms是必不可少的,剩下的HelloDeploy都没用到,可以去掉。
![预览](https://img-blog.csdnimg.cn/img_convert/aec4b2c5471acf6d0562001b133ed7d8.png)
常见程序会用的包括:
imageformats 图片格式支持
iconengines 小图标功能
sqldrivers 数据库驱动,这个保留用到的数据库足够了
其他的看情况删减。
删减qml
最后看一下Qml文件夹,如果程序完全没用qml,直接删掉就好了。
![预览](https://img-blog.csdnimg.cn/img_convert/d05f619ccef997792c2164951181baab.png)
按windeployqt给HelloDeploy提供的这些,逐个文件夹来说:
- Qt/labs 一般不推荐Qml中引入labs中的实验品,但是有些情况下功能缺失,只能引入。
如果Qml中使用了Quick.Dialog(不是labs.Dialog),它本身还是依赖的labs中的东西,一般是folderlistmodel和settings,
这时候还是不要动labs了,就按照windeployqt给的放着。
-
Qt/WebSockets Qml的Websocket功能,用了就放着,没用可以删掉。
-
QtGraphicalEffects Qml的一些ShaderEffect特效,用了就放着,没用到可以删掉
-
QtMultimedia Qml的多媒体模块,用了就放着,没用到可以删掉
-
QtQml/Models.2 数据Model, 经常用。
-
QtQuick 这里面大部分都是Qml中常用的,QtQuick/Extras可以按情况删掉
-
QtQuick.2 常用的
-
QtTest 单元测试,删掉吧
-
QtWinExtras Windows扩展,没用到可以去掉