用到了高版本Qt庫,但Ubuntu更新不到那麼高的Qt版本,自己拷貝高版本Qt庫過去又有問題,怎麼辦?

操作系統:Ubuntu 16.04 LTS;

編譯器:Qt Creator

Qt:5.9.0

我在Ubuntu上安裝的是Qt5.9.0,寫一個最簡單的HelloWorld程序,將程序放在沒有安裝Qt5.9.0的Ubuntu上去使用,運行時,首先提示的是無法找到5.9.0版本的Qt庫,我使用apt-get update、apt-get install和apt-get upgrade來更新Qt庫,最終在Ubuntu16.04上只能更新到Qt5.5.1,無法更新到5.9.0版本,我手動把libQt5Core.so.5.9.0拷貝到Ubuntu的/usr/lib/x86_64-linux-gnu目錄中並使用ldconfig命令使libQt5Core.so.5的符號鏈接指向libQt5Core.so.5.9.0,對libQt5Gui和libQt5Widgets也做了同樣的處理,這樣之後,HelloWorld可以運行了,但是Ubuntu重啟之後,卻出現了這樣的問題

可以確定出現這個問題是因為我添加了libQt5Core.so.5.9.0、libQt5Gui.so.5.9.0和libQt5Widgets.so.5.9.0引起的,我刪除了這三個庫,並使用ldconfig使得符號鏈接重新指向5.5.1的庫之後,系統就恢復正常了。

我想知道這種情況下應該怎麼辦,這種情況指的是:我用到了高版本的Qt庫,但是Ubuntu無法更新到那麼高的Qt版本,自己把高版本的Qt庫拷貝過去吧又有問題。

-----------------------------------

(題外話,萬般無奈下,我在寫程序時改用了Qt5.5.1的版本,結果發現寫好的程序在另外的Ubuntu16.04系統中運行都很正確,不過,我不想改用5.5.1,還是想用目前的5.9.0)。


http://sqlitestudio.pl/files/sqlitestudio3/complete/

你可以參考SQLiteStudio這個Qt寫的跨平台SQLite管理工具,它自己打包了依賴的Qt庫,可以做到解壓即用,兼容不同Linux發行版.道理其實跟Windows版Qt程序自帶Qt庫差不多.

編譯前給連接器傳一個參數:

export LDFLAGS="-Wl,-rpath,$ORIGIN/lib"

說明:

-Wl 表示告訴編譯器將後面的參數傳遞給鏈接器.

rpath是gcc的一個參數,當程序被載入時,會搜尋rpath目錄,尋找共享庫.

rpath添加的目錄信息保存在可執行文件中.

$ORIGIN表示可執行文件所在的目錄.

也就是運行時程序會先去自己所在的目錄的lib里去載入依賴庫,沒有的話再去系統庫里找.

如果你的程序在編譯時沒有傳遞rpath參數,那你也可以用patchelf來修改你程序的rpath:

# 修改rpath
patchelf --set-rpath "$ORIGIN/lib" --force-rpath your_app
# 查看rpath
patchelf --print-rpath your_app

注意:patchelf修改文件後再strip會導致文件損壞.

所以應該先用strip刪除符號表縮小二進位文件,然後再用patchelf設置rpath.

題外話,Android上既沒有glibc庫,也沒有庫鏈接器ld-linux.so.3.

如果你要把Debian ARM(如樹莓派Raspbian)上的軟體放到Android上跑,你一樣可以打包程序依賴的共享庫,讓程序也能跑在Android上,比如PHP:

alias php="/data/local/tmp/web/lib/ld-linux-armhf.so.3
--library-path /data/local/tmp/web/lib
/data/local/tmp/web/php"

也就是你把庫鏈接器ld-linux-armhf.so.3和PHP依賴的庫都放到/data/local/tmp/web/lib里,然後設置個別名,就能在Android的adb shell里運行樹莓派的PHP了.

當然,你也可以用patchelf設置PHP的interpreter和rpath,效果差不多:

interpreter 對應 ld-linux.so
rpath 對應 --library-path
patchelf --set-interpreter "/data/local/tmp/web/lib/ld-linux-armhf.so.3" php
patchelf --set-rpath "$ORIGIN/deps" --force-rpath php
其中 --set-interpreter 也可以使用相對路徑,但不支持$ORIGIN.


5.9應該是最新版本了,有兩種方法(在qt官網有的前提下)一種是去官網下載Linux版本的.run包,在終端執行./xxx.run。還有一種方法就是去官網下載相關版本的源碼壓縮包,解壓後 去源碼目錄下執行./configure -help 查看要配置的選項 然後在ubuntu上編譯,編譯完成後配置環境變數,可以去參考一下嵌入式ARM qt移植。


需要把整個程序包都打好再部署到別的機器上。通過apt-get可能下不到你想要的版本的庫。


放到同一個目錄下,設置好LD_LIBRARY_PATH不能用嗎


推薦閱讀:

Linux上沒有真正的非同步,為什麼伺服器還是用Linux的多?
RHCE证书的含金量怎么样,这个证好不好考,考出来以后做关于Linux的哪方面工作,或者在公司能够做什么
利用一年的時間,利用空餘的每天兩個小時,怎麼可以熟練掌握,python,mysql,伺服器,Linux?
要想完全放棄 Windows 使用 Linux 需要多少勇氣?
Linux 中鍵粘貼和Ctrl+V粘貼的區別是什麼?

TAG:Linux | Ubuntu | QtC開發框架 | Linux開發 | Ubuntu入門 |