在前面一篇文章中我們講了怎么在CMake里設(shè)置Qt庫的路徑、模塊添加,最后還給了完整的CMake例子。如果不出意外的話,你的CMake + Qt工程應(yīng)該能夠編譯成功了。但如果環(huán)境中找不到依賴庫,現(xiàn)在還跑不起來。這里就涉及到部署操作。
這其實(shí)是個(gè)老生常談的問題。Qt Widgets程序就很麻煩,而Qt Quick程序似乎更麻煩。我在StackOverFlow上就回答過類似問題:[What must be installed on client machine to run a QT Quick Application?]
手動(dòng)拷貝依賴庫的問題
我們平時(shí)開發(fā)的時(shí)候,可以將Qt庫路徑添加到系統(tǒng)Path環(huán)境變量里,從而讓基于Qt的程序能夠自動(dòng)加載運(yùn)行庫。單這個(gè)做法有以下問題:
- 不能用于正式發(fā)布。不能要求普通用戶安裝Qt開發(fā)環(huán)境然后在設(shè)置Path;
- 不能有效區(qū)分多個(gè)Qt版本。如果電腦上裝了多個(gè)Qt版本,那反復(fù)設(shè)置Path是很麻煩的事情。
所以更好的做法是將對應(yīng)的Qt依賴都提取出來,放在我們的可執(zhí)行程序目錄內(nèi),然后一起打包發(fā)布。LGPL協(xié)議下使用Qt的話會(huì)涉及到大量動(dòng)態(tài)鏈接庫,如果是Qt Quick程序,那么還需要帶上很多自帶的QML/Quick模塊。一種簡單粗暴的方法是先將所有可能用到的庫都拷貝過去,然后逐個(gè)嘗試刪除,直到剩下必須的。但很明顯這種方法非常麻煩,而且Qt的依賴庫的目錄結(jié)構(gòu)是有講究的,這個(gè)很多人常常弄錯(cuò)。
有人說可以用Depends等工具查看依賴,然后一個(gè)個(gè)拷貝,但這種方法只能找到C++的類庫,Qt Quick相關(guān)的模塊是查不到的,因?yàn)檫@些類庫本質(zhì)是通過Qt Plugin機(jī)制加載的,不是嚴(yán)格的運(yùn)行時(shí)依賴。所以這種方法只能針對Qt Widgets程序,而且也非常麻煩。
更好的方法是利用Qt自帶的deployqt程序。
用deployqt程序自動(dòng)部署
這個(gè)程序在bin目錄中,各個(gè)平臺上具體的名字不同,例如在Windows上是windeployqt.exe,在MacOS上是macdeployqt。它是一個(gè)命令行程序,能夠自動(dòng)分析程序,拷貝必要的依賴庫到我們的可執(zhí)行程序目錄內(nèi)。
在Windows上用CMD運(yùn)行windeployqt,可以看到它有很多參數(shù)。一般的使用方法是:
windeployqt.exe [options] 你的可執(zhí)行程序.exe
最常用的是兩個(gè):
-
--debug或者--release,告訴windeployqt你是想部署調(diào)試版依賴庫還是最終發(fā)布版依賴庫; -
--qml后面加上你的QML文件所在路徑,windeployqt會(huì)自動(dòng)分析你的QML文件中import了哪些庫,然后會(huì)自動(dòng)拷貝到當(dāng)前目錄中。
例如:
windeployqt.exe --debug --qml . demo.exe
假如你的QML文件和demo.exe放在一起,那么上面的命令運(yùn)行下來你會(huì)看到當(dāng)前目錄里添加了很多文件和文件夾。
遺留問題
deployqt也不是萬能的。經(jīng)測試,如果我們的QML文件中用了第三方或者我們自己的模塊,那這些模塊仍然需要我們手動(dòng)拷貝到可執(zhí)行程序目錄中。但這些模塊一般不多,所以問題不大。