Qt - 跨平臺程序打包發佈

Qt跨平臺

Qt 的跨平臺爲 一次編碼,處處編譯,這與 Java 依賴虛擬機實現的 一次編譯,處處運行 是不同的。

Java跨平臺實現

Java 是把針對不同平臺與操作系統的跨系統核心代碼抽象出來,形成單獨的 JVM層(java virtual machine)Java 代碼運行在 JVM 上,把跨平臺 java語言框架問題 分解爲在不同平臺上設計 JVM的問題,結構簡單、邏輯清晰、易於實現 1

爲此,Java 付出了犧牲效率的代價。Java 語言需要先通過 JVM 再映射到操作系統裏,最後由CPU 執行,執行過程多了一步。早期由於 Java語言 主要使用 解釋性編譯器,從而導致運行效率進一步降低。但是隨着 即時編譯技術(JIT) 的推出,尤其是硬件計算速度的大幅提升,Java運行效率 問題基本得到解決 1

Qt跨平臺實現

Qt平臺 封裝了針對不同平臺的類庫,API 。這些都被上層做了封裝,對我們開發者來說操作各種平臺的接口都是一樣的 1。以我最近使用的 QSerialPort 爲例子,在 Qserialport.h 中可發現以下蛛絲馬跡:

Qserialport.h(源碼可戳)

//line 74
#if defined(Q_OS_WIN32)
    typedef void* Handle;
#else
    typedef int Handle;
#endif

//line 307
#if defined(Q_OS_WIN32)
    Q_PRIVATE_SLOT(d_func(), bool _q_startAsyncWrite())
#endif

可見 QSerialPort 提供的接口是使用 做了跨平臺處理的。

那麼 Qt 爲我們提供的跨平臺接口有那些呢?

Qt的界面,Qt封裝的一些庫包,數據結構以及算法…

對於 Qt項目 中不提供跨平臺的部分,則需要我們自己實現,常用的就是

例如換行操作:

#ifdef Q_OS_WIN32
    qDebug() << "Windows換行!\r\n";
#else
	//假設是Linux
    qDebug()<<"unWindows換行!\n ";
#endif

好了下面進入正題,Qt - Windows程序及Linux程序打包發佈。

Qt - Windows打包發佈

最小依賴庫

QtCore 中,當我們把構建方式選爲Release,將生成 *.exe 文件

在這裏插入圖片描述
直接打開該文件會提示 缺少xxx.dll 等錯誤。

我們可在 Qt 的編譯器路徑下搜索缺失的 dll文件

我的路徑是 xxx\QT5.9.3\5.9.3\mingw53_32\bin,找到後將其放到可執行文件· 同一路徑 下。

下圖是我複製的 dll庫,應該是 最小依賴庫 了。

在這裏插入圖片描述

Windeployqt

作爲懶鬼,我堅信懶是人類發展的原動力。
在這裏插入圖片描述
於是我發現了一個便捷的工具 Windeployqt,它將幫助我們將依賴庫複製到指定目錄中。

例如我這在 D盤 創建了一個 UHelper文件夾 ,然後將前面生成的 UHelper.exe 移動進去。

打開Qt for Desktop
在這裏插入圖片描述
執行 windeployqt *.exe

在這裏插入圖片描述
可以發現,依賴的庫都複製進去了

在這裏插入圖片描述

Enigma Virtual Box 打包爲可獨立運行exe

我們可以將上面的 exe文件dll文件 打包給別人,但是這樣一點也不酷。
在這裏插入圖片描述
有沒有辦法直接將 exe所需的dll庫 都打包爲一個exe文件呢?

還真有,Enigma Virtual Box 就是一個不錯的選擇。

下載地址見:Enigma Virtual Box官網

在這裏插入圖片描述
ps:如果是使用 Windeployqt 添加的庫,把所有添加的 dll及文件夾都拖選添加至 Enigma Virtual Box 即可。

切記:文件夾也要,並且不要試圖去改變它。

執行完成後,就生成了一個獨立可執行程序。

在這裏插入圖片描述

Inno Setup 封裝爲安裝包

下載地址見:Inno Setup官網

使用流程可參考 2 Inno setup 打包教程

生成安裝程序如下:

在這裏插入圖片描述
安裝完成後的文件目錄如下:
在這裏插入圖片描述
有別於直接移植的是,在控制面板中是可以查找得到該程序的(即修改了註冊表)。並且它給我們提供了一個卸載程序。

如何修改版本信息

到此爲止我們生成的可執行文件都是沒有詳細信息的。

在這裏插入圖片描述

修改.pro

最簡單的方法莫過於直接在 pro文件 中添加以下代碼。

下面列舉了一些常用信息 3 4

//版本信息
VERSION = xx.xx.xx.xx
//圖標
RC_ICONS = xxxx.ico
//公司名稱
QMAKE_TARGET_COMPANY = ""
//產品名稱
QMAKE_TARGET_PRODUCT = ""
//文件說明
QMAKE_TARGET_DESCRIPTION = ""
//版權信息
QMAKE_TARGET_COPYRIGHT = ""
//中文(簡體)
RC_LANG = 0x0004

rc資源文件

由於 rc文件Windows平臺相關的東西,Qt助手 中對於 rc文件 幾乎沒有任何介紹 5

使用可查看本文參考 - 傳送門

Qt - Linux打包發佈

將項目拷貝到 Ubuntu18.04

Qt環境Windows下的相同,均爲 Qt5.9.3

移過去後,UI 顯示有點問題,於是修改了一下 UI

然後用 Release編譯,即生成可執行文件 UHelper

在這裏插入圖片描述
由於 Ubuntu自帶了Qt庫 6,我們可以直接運行:

./UHelper

程序運行效果:

在這裏插入圖片描述
若非 Ubuntu 系統則需要拷貝so庫,則可以使用 ldd命令 查看其依賴庫及路徑

ldd UHelper
//or
ldd ./UHelper

在這裏插入圖片描述
一個個複製很麻煩,爲此可以藉助 shell腳本 完成 so庫 的複製:

#!/bin/sh
# ldd $exe (所以這裏寫你的可執行文件名)
exe="UHelper"
# copy 目錄
des="/home/hsy/SW/Qt5.9.3/Project/UHelper_test"
# awk 匹配第三個參數“/”,排除掉沒有路徑的
deplist=$(ldd $exe | awk '{if (match($3,"/")){printf("%s\n"),$3}}')
# 將so庫拷貝至des目錄
# -L:--dereference 始終遵循源中的符號鏈接
# -n: --no-clobber 不要覆蓋已存在的文件
cp -L -n $deplist $des

執行

chmod 777 pack.sh
./pack.sh

當然我們也可以使用 linuxdeployqt,由於腳本更爲方便,這裏不展開。

感興趣的可參考該文 Qt ------ linux(ubuntu) 下用 linuxdeployqt 打包發佈程序

複製完以後的結果如下圖所示:

在這裏插入圖片描述
再編寫一個可執行文件;

注意:這裏的腳本名必須和可執行文件名一致。

UHelper.sh

#!/bin/sh
appname=`basename $0 | sed s,\.sh$,,`
dirname=`dirname $0`
tmp="${dirname#?}"
if [ "${dirname%$tmp}" != "/" ]; then
dirname=$PWD/$dirname
fi
LD_LIBRARY_PATH=$dirname
export LD_LIBRARY_PATH
$dirname/$appname "$@"

通過運行此腳本而不是可執行文件,可以確保動態鏈接程序將找到Qt庫 7

參考鳴謝


  1. 《Qt平臺體系與應用——Qt5.5+核心方法、技巧與案例》 ↩︎ ↩︎ ↩︎

  2. Inno setup 打包教程 ↩︎

  3. How to Get Current App Version in Qt ↩︎

  4. Qt 之生成 Window 資源文件(.rc 文件) ↩︎

  5. Qt 之添加 Windows 資源文件(.rc文件) ↩︎

  6. 01-爲什麼要用Qt開發(Qt跨平臺應用開發) ↩︎

  7. Qt for Linux/X11 - Deployment ↩︎

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