前言
在ubuntu上發佈qt程序相對還好,使用腳本,但是在統信UOS麒麟上發佈的時候,因爲銀河麒麟等不同版本,使用腳本就不太兼容,同時爲了實現直接點擊應用可以啓動應用的效果,使用linuxdeployqt發佈qt程序。
本篇文章,最終手動結合幾個方式成功,花費不少時間研究,推斷是終端直接ldd之後強制進入了一個另外的環境變量,導致無法連接成功,也就是,第一層是成功的,第一層的庫又調用ldd依賴的這一步的環境變量被強了。
但是最後通過手動來實現linuxdeplopyqt和編譯配置來實現打包部署了。
系統版本:
Linux部署工具linuxdeployqt將應用程序作爲輸入,並通過將應用程序使用的資源(如庫、圖形和插件)複製到一個包中使其自包含。結果包可以作爲AppDir或AppImage分發給用戶,也可以放入交叉分發包中。它可以作爲構建過程的一部分,在CMake、qmake和make等系統中部署用C、C++和其他編譯語言編寫的應用程序。當用於基於Qt的應用程序時,它可以綁定運行應用程序所需的Qt的特定最小子集。
找到main.cpp源碼,將這一段(在192行左右)註釋掉(這裏通過看源碼,實際上是可以通過配置去控制的(研究源碼發現的,但是我們不再動作了,只是貼出來):
還是老方法繼續修改:
vi linuxdeployqt-master/tools/linuxdeployqt/main.cpp
cd linuxdeployqt-master
cmake CMakeLists.txt
因爲安裝了git與這個工程可能不對,我們直接使用源碼修改大法,直接定位到代碼給刪掉:
vi CMakeList.txt
直接刪掉目錄下的緩存文件:CMakeCache.txt,然後繼續:
繼續cmake CMakeList.txt
麒麟系統本身自帶了qt5庫(未帶開發相關的庫),而我們使用了另外安裝的qt5,所以依賴需要引入我們自己安裝的qt5上。
爲了方便配置,也不影響系統我們裝上cmake的gui版本:
sudo yum install cmake-gui
cmake-gui
選擇對應的路徑,然後使用默認unix makefile方式配置:
切入build目錄,並且使用make命令即可:
make
測試程序:
沒有make install這個,手動移動到/usr/local/bin
sudo cp tools/linuxdeployqt/linuxdeployqt /usr/local/bin/
(PS:虛擬機打包好之後,退回到裸機版本,再測試)
新建一個工程
然後,找個空目錄:
未打包在開發機上也可以運行(裸機不行):
這裏要將Qt引入環境,爲了不影響系統,使用source腳本引入,每次使用之前使用source env.sh引入即可。
touch env.sh
然後輸入如下(QT_DIR爲安裝Qt的路徑):
#!/bin/sh
QT_DIR=/home/yang/Qt5.12.8/5.12.8/gcc_64
export PATH=${QT_DIR}/bin:$PATH
export LIB_PATH=${QT_DIR}/lib:$LIB_PATH
export PLUGIN_PATH=${QT_DIR}/plugins:$PLUGIN_PATH
export QML2_PATH=${QT_DIR}/qml:$QML2_PATH
export LD_LIBRARY_PATH=${QT_DIR}/lib:$LD_LIBRARY_PATH
echo $PATH
echo $LIB_PATH
echo $PLUGIN_PATH
echo $QML2_PATH
echo $LD_LIBRARY_PATH
引入環境:
下次打包遵循此流程即可,繼續打包:
(PS:這裏是沒有使用sudo進行的打包的,可能對權限管控比較嚴格,查看“入坑二”)
下面使用sudo打包:
sudo linuxdeployqt testDemo -verbose2
上面是Qt5Widget的庫連接到系統庫上去了,版本不一樣找不到api
下面是未打包的testDemo在開發機上:
下面是未打包的testDemo在裸機上:
(這是開發機,直接運行也是可以的)
這個文件最重要,他就是調用testDemo應用時候,先加載然後去搜索庫路徑的配置,沒有他則走向系統環境變量了。
touch qt.conf
vi qt.conf
內容,是我們從另外國產麒麟打包的該文件複製的,如下:
# Generated by linuxdeployqt
# https://github.com/probonopd/linuxdeployqt/
[Paths]
Prefix = ./
Plugins = plugins
Imports = qml
Qml2Imports = qml
這個時候,我們再運行一次:
路徑從本地開始找了。
ls -l
cp /home/yang/Qt5.12.8/5.12.8/gcc_64/translations/ . -rf
cp /home/yang/Qt5.12.8/5.12.8/gcc_64/plugins/ . -rf
cp /home/yang/Qt5.12.8/5.12.8/gcc_64/lib/ . -rf
ls -lh
測試本機可運行了:
(PS:這裏是全部copy了庫,沒有進行依賴裁剪的,暫時不管了,花費時間遠超預期了)
因爲沒有裁剪,所以包比較大:
cd ..
tar cvf outManual.tar outManual
ls -l outManual.tar
拷貝到裸機上去。
還是失敗,如下:
這還是之前一樣,libQt5Widget.so.5依賴libQt5Core.so.5,前面是用當前配置的,然後庫的依賴庫就強制引入到了/usr/lib64,跟之前linuxdeployqt打包一樣的問題。
然後有個念頭,於是嘗試加上LD_LIBRARY_PATH測試,可以運行成功,具體查看“入坑四”。
爲了不在運行時額外添加環境變量,爲了打包不出現xcb問題,還得修改一下.pro文件如下圖:
# 這裏是添加運行應用的時候的運行包,此處避免額外設置LD_LIBRARY_PATH
QMAKE_RPATHDIR = ./lib
編譯出來,單獨將testDemo2放置到原來的部署裸機上:
最終,直接點擊可以運行成功。
開始編譯的時候,讓其依賴了系統,直接導致就算引入了其他qt的環境變量,打包也是依賴系統,直接不打包
懷疑是跟編譯linuxdeployqt的依賴有關,所以重做一遍自己安裝Qt的cmake。
重做一遍自己安裝Qt的cmake後編譯,也還是一樣的。
如前面的入坑,就是不復制,與編譯依賴沒關係。
沒有辦法,直接幹linuxdeployqt的main.cpp的源碼:
1.先調試哪裏沒有打印,每次修改源碼重新編譯之後,部署再打包看輸出結果。 (PS:發現qDebug()不輸出,輸出的是qInfo())
將所有LogError換爲qInfo(),如下圖:
還是不行:
繼續:
棘手的問題:
至此可以確認是兼容性問題,這個問題比較棘手,短期內調不好了。
Linuxdeployqt方式暫未解決,可以換個linuxdeployqt的版本,也許不同的uos版本也不會又這個問題了,很奇怪連LogError和qDebug都不出來。
後續,第二天突然想到是否需要sodu權限,嘗試了下,確實是的:
所以又重做,使用sudo來打包了。
這是和系統的衝突了。
編譯的時候也是使用的安裝包的:
無解,qmake路徑和環境變相也都沒有問題
檢查linuxdeployqt
拍快照,然後目錄下的所有/usr/lib64/Qt5*刪除,首先檢查系統是否正常啓用,再打包嘗試。
sudo rm /usr/lib64/libQt5*
重啓,確實,系統起不來了,系統依賴Qt5.11下的庫。
所以不能刪除,此路不通。
拍快照,然後將安裝的Qt5庫copy過去,首先檢查系統是否正常啓用,再打包嘗試。
執行copy指令,直接立即黑屏,此路不同。
所以,/usr/lib64下的庫是不能動的。
這裏懷疑,從進入終端開始就進入了固定的優先環境變量,只是推測,目前linuxdeployqt又花費半天,暫時仍然無解。
找不到一個庫就刪掉一個庫,此時系統是已經將庫加載進內存運行,是不影響正在運行的系統,但是無法重啓,如下:
sudo linuxdeployqt testDemo -verbose2
sudo rm /usr/lib64/libQt5Gui.so*
sudo linuxdeployqt testDemo -verbose2
sudo rm /usr/lib64/libQt5Core.so*
sudo linuxdeployqt testDemo -verbose2
sudo cp /home/yang/Qt5.12.8/5.12.8/gcc_64/lib/libicuuc.so* /usr/lib64/
sudo linuxdeployqt testDemo -verbose2
sudo cp /home/yang/Qt5.12.8/5.12.8/gcc_64/lib/libicudata.so* /usr/lib64/
sudo linuxdeployqt testDemo -verbose2
sudo yum install patchelf
sudo linuxdeployqt testDemo -verbose2
可以,uos你贏了,我放棄了!!!
分析該系統第二次搜索庫,總是會引入到/usr/lib64,這個問題很操蛋,從一開始linuxdeployqt打包不行就是這個根本原因。
直接在編譯的時候,最優先的方式,讓應用去運行時先依賴相對路徑,而不是去依靠運行時的環境變量和配置文件了。
pro加入配置文件:
# 這裏是添加運行應用的時候的運行包,此處避免額外設置LD_LIBRARY_PATH
QMAKE_RPATHDIR = ./lib
點擊應用運氣的時候,應用自身會先依賴./lib下的庫查找。