談談 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/

標題無“轉載”即原創文章,版權所有。轉載請註明來源:http://hgoldfish.com/blogs/article/103/

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章