Mac下發布Qt應用程序


Qt編寫的應用發布到用戶手里,同時也要把Qt庫一起打包給用戶。方法有很多。

1. 簡單又麻煩的辦法,靜態編譯Qt

簡單是因為靜態編譯的Qt庫會隨着應用一起發布,麻煩是我們必須自己編譯靜態的Qt。而且,很多情況下我們不僅是要使用Qt,還有很多其它的庫,如果每一個都靜態編譯,我們的執行文件就太巨大了。所以簡單的應用,靜態編譯可能是好的,但是,比較大的項目,這種方法就不推薦了。

2. 好又不麻煩的辦法,使用Frameworks

Mac中的GUI應用必須以Bundle的形式運行,所謂Bundle,是一個以".app"結尾命名的文件夾,系統自動識別它為一個應用包,應用所有的東西(執行文件、鏈接的動態庫、資源文件等等)都在里面了,打開應用直接"open myApp.app"就可以了,安裝的時候直接把Bundle拖到Finder里就行了。卸載的時候直接把Bundle刪除就行了。多讓人省心。

Bundle的結構如下圖:(從Qt文檔里借來的)

我們如果要隨着我們的應用一起發布Qt庫,比較合理的就是把所有需要的Qt庫都復制到Frameworks目錄中。

使用otool可以查看一個應用都鏈接了哪些動態庫

$ otool -L myApp.app/Contents/MacOS/myApp 
myApp.app/Contents/MacOS/myApp:
    libqxmpp.0.dylib (compatibility version 0.7.0, current version 0.7.4)
    /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
    QtWebKit.framework/Versions/4/QtWebKit (compatibility version 4.9.0, current version 4.9.3)
    QtXml.framework/Versions/4/QtXml (compatibility version 4.8.0, current version 4.8.3)
    QtCore.framework/Versions/4/QtCore (compatibility version 4.8.0, current version 4.8.3)
    QtGui.framework/Versions/4/QtGui (compatibility version 4.8.0, current version 4.8.3)
    QtNetwork.framework/Versions/4/QtNetwork (compatibility version 4.8.0, current version 4.8.3)
    /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0)
    /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1669.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

我們用了QtWebKit、QtXml、QtCore、QtGui、QtNetwork,然后挨個Copy吧。

$ cp -R /path/to/Qt/lib/QtCore.framework  myApp.app/Contents/Frameworks
......
......

真的悲慘到到自己手工去復制?當然不是,我們都是懶人啊,Qt自身帶了一個macdepolyqt的神器,一切就變得簡單了。

$ macdeployqt myApp.app
  ERROR: no file at "/usr/lib/libqxmpp.0.dylib" 

qxmpp是我們用的一個三方庫,並不在/usr/lib下,找不到並不奇怪,怎么才能讓macdeployqt找到這個三方庫呢?

Mac下是用DYLD_LIBRARY_PATH來尋找動態庫的,類似於Linux下的LD_LIBRARY_PATH。otool -L輸出的信息,其實是保存在編譯好的可執行文件里的。libqxmpp.0.dylib沒有指定絕對路徑,系統會到DYLD_LIBRARY_PATH中去尋找它,macdepolyqt並不理會DYLD_LIBRARY_PATH,所以,我們只好將libqxmpp.0.dylib這一條修改成它的絕對路徑,讓macdeployqt可以找到它。

install_name_tool -change "libqxmpp.0.dylib" "/opt/library/qxmpp/lib/libqxmpp.0.dylib" myApp.app/Contents/MacOS/myApp

如此以后就沒問題了

$ macdeployqt fytclient.app

$ otool -L myApp.app/Contents/MacOS/myApp 
myApp.app/Contents/MacOS/myApp:
    @executable_path/../Frameworks/libqxmpp.0.dylib (compatibility version 0.7.0, current version 0.7.4)
    /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
    @executable_path/../Frameworks/QtWebKit.framework/Versions/4/QtWebKit (compatibility version 4.9.0, current version 4.9.3)
    @executable_path/../Frameworks/QtXml.framework/Versions/4/QtXml (compatibility version 4.8.0, current version 4.8.3)
    @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore (compatibility version 4.8.0, current version 4.8.3)
    @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui (compatibility version 4.8.0, current version 4.8.3)
    @executable_path/../Frameworks/QtNetwork.framework/Versions/4/QtNetwork (compatibility version 4.8.0, current version 4.8.3)
    /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0)
    /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1669.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

這時候再看otool的結果,qxmpp以及Qt的動態庫都指向了Bundle里Frameworks目錄下了。@executable_path顧名思義就是應用的執行目錄,也就是myApp.app/Contents/MacOS

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM