這是本系列的第三篇文章,前兩篇我們講了qt的安裝和編譯,今天我們講一講程式的打包。 好像我們現在都沒怎麼講到qt的使用,因為想要放開手腳寫代碼,一些基礎是要打牢的。 不過請放心,下一篇文章開始我們就會真正進入正題了。 打包 首先我們做一些打包前的準備工作,沒錯,做事之前先做好準備是個好習慣:-p。 ...
這是本系列的第三篇文章,前兩篇我們講了qt的安裝和編譯,今天我們講一講程式的打包。
好像我們現在都沒怎麼講到qt的使用,因為想要放開手腳寫代碼,一些基礎是要打牢的。
不過請放心,下一篇文章開始我們就會真正進入正題了。
這是針對使用qtdeploy時的打包教程,不適用於使用qt-tools + go build進行構建的情況。
打包
首先我們做一些打包前的準備工作,沒錯,做事之前先做好準備是個好習慣:-p。
這次用於打包的仍然是一個小例子,將一張圖片縮小一半顯示出來,這個例子正好需要使用外部資源,因此我也會在其中展示qrc的用法。
項目結構:
tree makedeb
makedeb ├── images │ └── 1.jpg ├── main.go └── makedeb.qrc
沒錯,images里的就是我們要顯示的圖片,makedeb.qrc是我們的資源配置文件,因為是打包發佈,所以我們使用qrc來同一管理外部資源。
<!DOCTYPE RCC><RCC version="1.0"> <qresource> <file>images/1.jpg</file> </qresource> </RCC>
qrc的配置和原生Qt一樣,這裡不多做解釋。
下麵是主程式:
1 package main 2 3 import ( 4 "os" 5 6 "github.com/therecipe/qt/gui" 7 "github.com/therecipe/qt/core" 8 "github.com/therecipe/qt/widgets" 9 ) 10 11 func main() { 12 widgets.NewQApplication(len(os.Args), os.Args) 13 14 window := widgets.NewQMainWindow(nil, 0) 15 window.SetWindowTitle("Test deb package") 16 17 img := gui.NewQPixmap5(":/images/1.jpg", "", core.Qt__AutoColor) 18 size := img.Size() 19 img = img.ScaledToHeight(size.Height()/2, core.Qt__FastTransformation) 20 img = img.ScaledToWidth(size.Width()/2, core.Qt__FastTransformation) 21 22 canvas := widgets.NewQLabel(window, 0) 23 canvas.SetPixmap(img) 24 25 window.SetCentralWidget(canvas) 26 window.Show() 27 28 widgets.QApplication_Exec() 29 }
將圖片讀取至QPixmap,然後在使用QLabel來顯示的簡單例子,其中
img := gui.NewQPixmap5(":/images/1.jpg", "", core.Qt__AutoColor)
“:/images/1.jpg”表示按照.qrc指定的規則來獲取資源文件1.jpg。
接下來就是編譯了,只需要簡單的一條代碼
qtdelpoy build desktop makedeb
再看一看現在的目錄結構:
makedeb ├── deploy │ └── linux │ ├── lib │ ├── makedeb │ ├── makedeb.sh │ ├── plugins │ └── qml ├── images │ └── 1.jpg ├── linux ├── main.go ├── makedeb.qrc ├── rcc_cgo_linux_linux_amd64.go └── rcc.cppView Code
如上一篇文章所說,qtdeploy會自動調用qtrcc去解析.qrc文件生成rcc.cpp和rcc_cgo_*.go,裡面包含有我們在.qrc文件里指定的資源。
下麵我們對生成的目標打包,如何製作deb包可以點擊這裡。
我們需要新建一個用於打包的目錄:build
然後在build里創建目錄DEBIAN,這個目錄里的文件用於控制包的信息和安裝/卸載前後的行為。
mkdir build && cd build mkdir DEBIAN
打包時會把指定目錄下所有文件包含進去,解包時會將除了DEBIAN目錄之外所有目錄和文件按照在build目錄里的結構解壓到根目錄/ 之下。
舉個例子,build里有個目錄usr/local/bin/test,打包後安裝時會被安裝到/usr/local/bin/test,如果有etc/test那麼就會安裝到/etc/test。
所以我們需要根據想要的安裝路徑來在build目錄里創建這些目錄,我想把程式安裝在/usr/local/bin下,所以這樣創建目錄:
mkdir usr/local/bin/
根據上一篇文章的講解,運行我們的程式需要deploy/linux里的lib,plugins,qml這三個目錄和makedeb,makedeb.sh這兩個文件,所以我們把他們複製到打包的目錄里:
mkdir usr/local/bin/makedeb_bin
cp -r ../deploy/linux/lib usr/loacl/bin/makedeb_bin/ cp -r ../deploy/linux/plugins usr/local/bin/makedeb_bin/ cp -r ../deploy/linux/qml usr/local/bin/makedeb_bin/ cp ../deploy/linux/makedeb usr/local/bin/makedeb_bin/
為什麼我們沒有複製makedeb.sh?而且makedeb_bin目錄建立的意義是什麼?
因為一篇文章里說過,這個腳本在打包時有問題需要一點改造,現在我們就來改造它了。
原先的腳本只能在和程式同一目錄下才能工作,所以我們想使用它的話就要把deploy/linux/...直接複製到usr/local/bin里,如果只有這一個包那麼沒問題,但是如果你寫了其他的Qt程式,然後打包安裝在了同一目錄下,那麼這個安裝目錄里就會有兩個lib目錄,兩個plugins目錄。。。。當然同時存在兩個同名目錄是不可能的,後一個會覆蓋前項,如此一來之前安裝的程式很可能就會因為使用了錯誤的依賴項導致異常,這是不可接受的。
解決辦法並不複雜,我們把程式和他的依賴放入一個projectname_bin的目錄里,然後在這個目錄的外層目錄使用改造的腳本調用它,這樣的話不管安裝多少個你打包的qt程式也不會發生衝突了。下麵是改造後的makedeb.sh,為了能在命令行里用makedeb啟動程式,可以將.sh尾碼刪除:
1 #!/bin/bash 2 app=`basename $0` 3 appdir=`dirname $0`/${app}_bin 4 5 export LD_LIBRARY_PATH=$appdir/lib 6 export QT_PLUGIN_PATH=$appdir/plugins 7 export QML_IMPORT_PATH=$appdir/qml 8 export QML2_IMPORT_PATH=$appdir/qml 9 $appdir/$app "$@"makedeb.sh
聰明的你或許已經發現了,這個腳本是可以復用到任何項目打包里的!只需要把文件名改成項目名稱即可。
之後按照這裡的教程配置好之後就可以用
# 打包需要許可權 sudo dpkg -b . # 我們當前正在build目錄里
來打包了,打包完成後的build目錄結構:
build ├── DEBIAN │ └── control ├── makedeb.deb └── usr └── local └── bin ├── makedeb └── makedeb_binView Code
那個在build目錄下的makedeb.deb就是我們打包的程式啦,接下來你可用dpkg -i來安裝,也可以將他發佈出去。
自動化
如果你覺得這個過程太繁瑣,那麼我提供了自動化工具:-p。
工具地址:https://github.com/apocelipes/golang_qt2deb
具體使用方法:
golang_qt2deb.sh -t makedeb --prefix '/usr/local/bin'
程式會尋問control需要的配置信息,然後自動幫你構建deb包。
你也可以通過 --nobuild 參數來只生成配置和必要的數據複製,而不構建deb包文件,這樣你可以添加和修改自己需要的配置。
更多參數和用法可以在項目主頁找到,同時也歡迎提出意見和建議。
祝玩得愉快!