OS X QT App redistributable bundle 部署教程

来源:互联网 发布:免费的算账软件 编辑:程序博客网 时间:2024/05/21 20:29

大家做 OS X App开发的时候, 应该注意到Apple简洁的应用程序分发方式 - App bundle, 作者摸索后发现QT官方的文档不是很简洁, 照着教程做容易走弯路,  在这里分享一个比较简单的制作方法:

1) QT项目, 动态库编译为dylib, 可执行程序编译为app bundle输出.

2) 拷贝编译出来的动态库到/usr/lib下

3) 使用QT的macdeployqt工具生成可重分发包, 它会帮你将动态链接的QT framework打进App bundle里.

4) 不建议使用 otool/install_name_tool 自己写库依赖. 希望能自己写成功的同学批评指正.

详细讲一下Apple App bundle: App bundle简而言之就是一个目录树结构:

MyApp.app ----- Contents ------- Frameworks                         

                                               ------- MacOs -------- MyApp

                                               ------- Resources

                                               ------- Plugins

                                               ------- Info.plist

Frameworks 目录一般保存 .framework打包形式的动态库, 可以是项目编译出来的, 也可以第三方的库. MacOs保存可执行文件, Resouces下保存资源. 制作完毕的App bundle, 发布后要求可以放在用户的任何目录执行. 

Framework ----- Apple 对程序库独特的打包方式, 目录结构类似于App bundle,  支持单个或多个程序库伞状嵌套, 支持程序库的多版本配置. 具体有兴趣的同学可移步:

https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/OSX_Technology_Overview/SystemFrameworks/SystemFrameworks.html

Framework/App Bundle的制作,  在Apple的X Code工具下制作比较容易,请搜索相关教程. 在QT中制作步骤如下:

QT 项目输出 framework, app bundle的pro设置:

config -= lib_bundle

config += app_bundle

拷贝项目编译输出的dylib到usr/lib下:

sudo cp -R -f mydylib.dylib usr/lib

配置Qt frameworks,  改变引用:

macdeployqt myapp.app -verbose=1

点击下app, 应该能工作了. 虽然看起来很简单, 但也走过一些弯路, 有不少心得, 分享一下吧. 刚开始, 我认为参考Qt  官方的部署文档, 以及install_name_tool教程:

http://qt-project.org/doc/qt-5.0/qtdoc/deployment-mac.html

http://bbs.csdn.net/topics/350155746

应该很容易就能搞定, 到最后发现使用otool, install_name_tool直接修改每个库和程序的引用就行, 但是结果不太好,原因如下:

1) 程序库之间的引用比较复杂, 自己写配置极其容易出错.

2) 即使写对了install_name_tool,  QT中深层次依赖仍然没有搞定, 会出一些奇怪的问题, 以及crash, 自己写需要对程序库之间的依赖关系非常熟悉.

展开讲一下, 比如说我的项目有5个动态库, 1个可执行文件, 使用了QtCore, QtGui两个framework,  假设库分别为a,b,c,d,e,  可执行程序为MyApp. b依赖a, c依赖a,b, d依赖a, b, c,  e依赖c, d, MyApp依赖a,b, c,d, e. 那么咱们用otool 逐个检查每个库或可执行文件, 以f为例:

otool -L MyApp.app/Contents/MacOs/MyApp

你会发现MyApp对a, b, c, d, e, QtCore, QtGui都有依赖. 这个时候, 按照Qt部署教程的做法, 先把QtCore, QtGui 两个framework,拷贝到MyApp/Frameworks下( OS X 10.9 在

/Library/Frameworks/)  下, 并建立一个Library目录保存dylib. 然后逐条用install_name_tool修改MyApp的依赖:

install_name_tool -change a.dylib @loader_path/../Library/a..dylib MyApp/Contents/MacOS/MyApp

...
install_name_tool -change e.dylib @loader_path/../Library/e..dylib MyApp/Contents/MacOS/MyApp 

修改完了项目的动态库, 再修改Qt的模块引用:

install_name_tool -change QtGui.framework/Versions/4/QtGui @loader_path/../Frameworks/QtGui.framework/Versions/4/QtGui MyApp/Contents/MacOS/MyApp
install_name_tool -change QtCore.framework/Versions/4/QtCore @loader_path/../Frameworks/QtCore.framework/Versions/4/QtCore MyApp/Contents/MacOS/MyApp

别忘了QtGui自己依赖QtCore, 继续修改:

install_name_tool -change QtCore.framework/Versions/4/QtCore @loader_path/../Frameworks/QtCore.framework/Versions/4/QtCore MyApp.app/Contents/Frameworks/QtGui.framework/Versions/4/QtGui

搞定了MyApp, 再继续修改a, b, c, d, e吧.

最后当你觉得松了一口气,点击运行的时候,程序crash掉了. 这里有个调试的办法, 就是用终端运行MyApp/Contents/MacOS/MyApp, 看看有何抱怨. 我碰到过一个qt_menu.nib不能加载的问题, 拷贝这个东西到MyApp/Resouces下,问题解决.

最后,能运行了, 但是似乎程序图标不见了. 看看终端, 抱怨QPixmap is null. 为什么图标不能显示? Google一下有的同学在嵌入式开发里也碰到同样的问题,最后他发现libjpg没有烧到板子上去. 猛然警觉, 是不是QtGui引用的图片库没打包成功?这么做太琐碎,太容易错了, 去弄清楚每个第三方库的依赖, 对客户程序员的要求太高了点吧,是不是路走错了?

继续看看Qt 官方的配置文档, 发现Qt提供了一个macdeployqt工具专门来干这个事情. 使用之,非常简单,可以制作dmg, 所有问题解决.看看打好的包里的framework, 活活有8个framework被打包进来: QtGui, QtCore, QtDelarative, QtNetwork, QtScript, QtSql, QtSvg, QtXmlPatterns. 

感想: 苹果非常强势地推进自家的X Code, LLDB, OS X 10.9, 似乎完全不考虑QT的感受,  QT失去Nokia的支持后似乎对OS X支持得一般, 也许在苹果后面追赶擦屁股的感觉并不太好. 不过在OS X上用QT的程序员应该大大的有, 希望大家多多交流,.



原创粉丝点击