谈谈 Qt 程序安装包的大小,以及简要打包指南

(本文是水木社区KDE与Qt编程技术版版主的文章,我觉得写的很好,就转载过来了,原文地址:http://hgoldfish.com/blogs/article/103/

经常看到网上有些论调说 Qt 程序无比庞大,甚至拿 .NET 程序来比,说 Qt 程序打包以后跟 .NET 安装包差不多大。由此影响了很多人对 Qt 的选择。我觉得有必要对此做一些澄清——

显然这个说法是错误的!!

很容易理解,虽然 Qt 提供了很多组件,但并非所有的组件都会被程序使用,也并非所有的组件都需要打包到程序安装包里面。以 Qt 5.7 为例,一个可以正常使用的 helloworld.exe 程序未压缩不过 20M,使用 lzma 压缩算法,压缩率 25%,压缩完才 6M!

那盛传的 Qt 上百 M 的容量又是怎么回事呢?

这事从头说起。

Qt4.4 引入了 Webkit 方便程序员往自己的程序里面嵌入 HTML 页面。刚开始倒也没事,反正不主动包含到项目里面的话,程序安装包并不会变大。那会儿,Qt 程序只要 8M(压缩到3M)就搞定了。到了 Qt5 的时候 Webkit 换成了 Chromium 内核 Blink,名字改成了 QtWebEngine. Qt 开发者发现 Blink 使用的 ICU,提供了比旧版本 Qt 更完整的国际化能力。于是,据说是因为一个误会,Qt 开发者就在 Qt 5.0 里面强制依赖于 ICU 了。这个 ICU 包含了大量的国际化元信息,一下子增长了近 30M 的容量。。

导致 Qt 容易增长还有另外一个重要原因,也就是 Qt 自从 4.7 以后引入的 QML。这是一个基于 ECMAScript 改造的语言。从此以后,Qt 开发就有两种流派,一者使用原来的 C++ 语言进行开发,另外一种使用 QML 语言进行开发。两者共享一样的底层设施,比如各种数据结构与事件循环 QtCore 和 带有 OpenGL 支持的 QtGui。但在上层,Qt 为 C++ 开发者们提供了 QtWidgets,又为 QML 开发者提供了独立的 QtQuick.

QtQuick 本身只有简单的布局语言,Qt 又在这个基础上提供了 QtControls 模拟 Android,iOS 和 Windows 程序的外观。早期的 Qt5 没有设计好,导致使用 QML 时要引入一大堆程序可能用到的组件。所以一个 helloworld 下来,相当巨大。而且很奇怪的事,以 QtWidgets/C++ 的方式使用了 QtWebEngine 的话,也会引入几乎所有的 QML 模块,那会儿一个简单的程序会达到一百多兆的大小!

Windows 平台还有一个特殊的问题。现在 Qt 的图形架构调用 OpenGL ES 2.0 进行底层的渲染,但刚安装完的 Windows 只支持到 OpenGL 1.1,针对这个问题,早期的 Qt 在 configure 阶段提供了两种选项,一是使用与 Chromium 一样的 ANGLE,把 OpenGL 调用翻译成 DirectX 调用,二者假定用户的系统安装了显卡驱动,能够支持 OpenGL 2.0。前者需要包含几个 ANGLE 的 DLL,直接又增加了 17M 的容量!

所幸这些事情现在都解决了。

首先,Qt 5 的早期版本已经提供了一个 configure 选项,可以不把 ICU 编译到 Qt 里面,但是官方下载版本仍然默认包含 ICU,后来 Qt 直接去掉了对 ICU 的依赖。现在的 Qt 在运行时找到 ICU 的 DLL 就会使用 ICU,否则调用系统的 API,如果都没有,就凑合着用 Qt 内置的算法处理国际化。

其次,QML 一些奇怪的依赖现在也去掉了。所以现在无论使用 QtWidgets 还是使用 QML,未压缩时都只有 20M 左右的容量。

最后一个,现在有多少用户的电脑是没有安装显卡驱动的呢?好吧,好像还真有,vmware 的虚拟机。但我觉得正常直接用系统自带的 OpenGL 驱动足矣。Qt 现在会在运行的时候自动探测 ANGLE 是否存在,如果存在,就使用 ANGLE,如果不存在,就使用系统自带的 OpenGL,不必像以前那样在 configure 阶段就配置好。另外,QtWidgets 没有使用 OpenGL,所以使用 QtWidgets/C++ 的程序也可以把 ANGLE 的 DLL 都去掉。

说这么多,具体怎么操作呢。非常简单,用 Qt 5.7 来说,现在提供了一个名为 windeployqt.exe 的程序,位于 Qt 的 bin 目录里面。运行这个程序,后面带程序名称就行了:

  1. 创建一个 dist 目录
  2. 把编译好的 qttest.exe 复制到 dist 目录。
  3. 打开 cmd.exe,cd 到 dist 目录
    4.1 运行 c:\qt5\bin\windeployqt.exe qttest.exe
    4.2 对于 QML 程序,需要指定 QML 目录: c:\qt5\bin\windeployqt.exe –qmldir d:\qttest qttest.exe

这时候就会看到 qt 已经把需要用到的 DLL 都复制过来了。我会在这个基础上再根据需要去掉一些东东:

  1. libEGL.dll, libGLESV2.dll 这两个文件是 ANGLE 的文件,可以去掉。opengl32sw.dll 是软件模拟 OpenGL,除非用户的系统连 DirectX 支持都不完整——虚拟机环境就是这样——不然这个文件也完全没有用。 QtWidgets/C++ 程序都不用 OpenGL,所以直接去掉即可。可在调用 windeployqt.exe 时加”–no-angle” 和 “–no-opengl-sw” 这两个参数。
  2. 如果没有使用 svg 的话,iconengines\qsvgicon.dll, imageformats\qsvg.dll, Qt5Svg.dll 这三个文件也可以删掉
  3. 如果没有国际化用户的话,translations 里面的翻译文件也可以删掉。
  4. QML 程序没有使用 QtWidgets/C++ 可以删掉 Qt5Widgets.dll
  5. 如果 imageformats 目录里面有几种图像格式没用上,也可以删掉。我自己通常把整个目录都删掉,Qt已经编译了 png 的支持,能读写程序包含的图标就够,其它格式不重要。
  6. qmltooling 和 Qt5Network.dll 是用于 QML 调试用的,可以删掉。

经过以上裁剪,使用 7zip 压缩完以后,一个 QtWidgets/C++ helloworld 程序最终只剩下 5.64M,一个 QtControls 程序是 5.86M, QtQuick 程序还会更小一些。

附注:

截止本文写作时,Qt 5.8 已经发布了。在这个版本里面,不再依赖于 OpenGL ES 2.0,而是绕过 ANGLE,直接调用 DirectX 渲染,到 Qt 5.10 还要直接支持 Vulkan API。不过目前仍然是试验性的,有兴趣的话可以看看 configure 的说明。

新的 Qt 5.8 重写了 configure 系统,能够更深入地裁剪 Qt。最小未压缩 5M 即可布署一个 QML 程序。

参考资料:

  1. Qt 5 ICU
    https://wiki.qt.io/Qt_5_ICU
    http://wiki.qt.io/Qt-5-QLocale

  2. Dynamically Loading Graphics Drivers
    http://doc.qt.io/qt-5/windows-requirements.html

  3. Qt Lite
    http://blog.qt.io/blog/2017/01/23/qt-5-8-released/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • 界面 主窗口界面设计 标题栏:直接设Window-Title属性;Window-icon属性可加图标。底部状态栏:...
    码园老农阅读 3,713评论 1 13
  • Qt是属于一个跨平台的GUI开发软件,支持的平台有Unix、Linux、Windows/WinCE、IOS等。 Q...
    一叶之界阅读 8,126评论 0 17
  • 「博客搬家」 原地址: CSDN 原发表时间: 2016-06-04 本文讨论在 Windows 平台下编译成...
    雪中亮阅读 7,513评论 0 10
  • 第一次做Qt,这里把主要的坑列出来。 连接Mysql Qt连接mysql的时候,会遇到: QSqlDatabase...
    偷风筝的人_阅读 3,478评论 1 3
  • How many roads must a man walk down ,一个男人要走多远的路,Before th...
    楚少寒阅读 399评论 0 0