文章目錄
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
中可發現以下蛛絲馬跡:
//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文件
中添加以下代碼。
//版本信息
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。