Qt应用程序部署—X11平台

DerryZhang/2010-4-10 译自:http://doc.trolltech.com/4.5/deployment-x11.html 

转载请注明http://blog.csdn.net/derryzhang/archive/2010/04/10/5469978.aspx

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

    由于Unix操作系统(包括商业版Unix、发行版Linux等等)应用范围不断增加,在Unix上部署应用程序显得十分复杂。在开始之前,我们需知道在一种Unix平台上编译成功的程序不一定能在其他Unix操作系统上正常运行。例如,除非你使用跨编译器机制,否则在lrix上编译的程序就无法部署在AIX上。

内容:

l  静态链接

n  静态构建Qt

n  把应用程序连接到Qt的静态版本

l  共享库

n  构建Qt为共享库

n  把应用程序连接到共享库的Qt

n  创建应用程序包

l  应用程序依赖

n  附加

n  Qt插件

本文将讨论以下话题:在应用程序发布的时候应该包含哪些文件,并且确保程序运行的时候能够找到它们。将结合Plug&Paint程序(在Qt示例程序目录下)的部署来演示这些过程。

静态链接

       Unix上静态链接通常是最安全最简单的方式,因为它使你免于部署Qt库的烦恼,确保他们部署在目标系统的默认的库查找路径。

静态构建Qt

       使用该方法必须从安装Qt库的静态版本开始:

       

 指定prefix选项以免覆盖了已有的Qt安装。上述示例仅构建Qt库,例如示例程序及Qt设计器将不会被构建。当make完成后,就可以在/path/to/Qt/lib目录看到Qt库。

       当链接应用程序到Qt静态库的时候,需要注意可能需要在project文件中的LIBS添加额外的库。参见应用程序依赖一节获取更多信息。

把应用程序链接到Qt的静态版本

       一旦Qt静态构建,接下来就需要重新生成makefile,重新构建程序。首先必须进入到包含应用程序的目录:

        

       现在运行qmake为应用程序创建新的makefile文件,然后执行干净的构建来创建静态链接的可执行程序:

       

       也许你想链接发布版的库文件,这就需要在调用qmake的时候进行指定。需要注意的是必须设置刚才构建的静态Qt所在的路径。

       为了检验应用程序是不是真的静态链接到了Qt,可以执行ldd工具(在大多Unix系统上都可用):

      

       核实一下在上面的输出中没有Qt的库。

       现在如果所有编译和链接都无错误,我们应该能够得到可用于部署的plugandpaint文件。检验程序可以震的独立运行的一种简便方法就是把它拷贝到一台不包含Qt或者没有安装过任何Qt应用程序的机器上,然后运行看看是否正常。

       值得注意的是如果你的应用程序依赖于编译器相关的库,这些库同时也要和应用程序一起发布。参见应用程序依赖一节获取更多信息。

       Plug&Paint示例程序是由若干个组件构成的:核心程序(Plug&Paint),基本工具(Basic Tools)以及附加过滤器(Extra Filters)插件。由于无法通过静态链接方式部署插件,当前的可执行程序尚未完成。应用程序虽然可以运行,但是由于插件丢失功能将无法使用。部署基于插件的应用程序我们需要使用共享库的方式。

共享库

       使用共享库方式部署Plug&Paint程序面临着两个挑战:在目标系统上Qt运行时库必须和可执行程序正确的发布,插件必须在正确的位置上安装,以便于让应用程序可以找到它们。

构建Qt为共享库

       假设你已经以共享库方式安装了Qt,而共享库安装时Qt的默认安装方式,它们被安装在目录/path/to/Qt上。关于如何构建Qt,参见Qt文档的“安装”部分内容。

把应用程序连接到共享库的Qt

       在确保Qt以共享库方式构建后,我们就可以着手构建Plug&Paint程序了。首先需要到应用程序所在目录:

         

      现在执行qmake来创建新的makefile,然后执行一个干净的构建创建动态链接可执行程序:

       

       这将会构建主程序,下面的指令将构建插件:

        

       如果编译连接无误,我们会得到一个plugandpaint可执行文件以及libpnp_basictools.solibpnp_extrafilters.so插件文件。

创建应用程序包

       Unix上尚无标准的安装包管理工具,所以下面展示的是一种通用的解决方案。可以查看目标系统的联机文档来查看如何创建安装包。

       部署应用程序的时候,我们必须确保拷贝了相关的Qt库(要和你应用程序所使用的Qt模块一致)以及可执行文件到相同的目录下。需注意的是如果应用程序依赖于编译器相关的库,这些库也必须和应用程序一起分发。参见应用程序依赖一节获取更多信息。

       对于插件我们将简要叙述,但关于共享库的主题是必须确保动态链接程序能够找到Qt库。如果不明确告知,动态链接程序不会查找到应用程序所依赖的库路径。有几种方法来解决这个问题:

l  可以将Qt库安装到某个系统库目录下(例如:在多数操作系统上的/usr/lib目录)。

l  当链接程序的时候传递预定义的路径给-rpath命令行选项。这将会告诉动态链接程序在启动你的应用程序时查找这个目录。

l  可以为应用程序写一个启动shell脚本,在这个脚本里修改动态链接配置(例如把你的应用程序目录添加到LD_LIBRARY_PATH环境变量。注意:如果应用程序将会以“运行时设置用户ID”方式运行,并且拥有者为root用户,那么某些平台将会忽略LD_LIBRARY_PATH。在这种情况下不宜使用LD_LIBRARY_PATH方法)。

       第一种方法的缺点是用户必须具备超级用户权限。第二种方法的不足在于用户有可能不具备安装程序到预定目录的权限。其他情况是,用户可能不具备将程序安装到home目录的选择。我们建议使用第三种方法,因为它最灵活。例如下面的plugandpaint.sh脚本:

          

     通过运行该脚本而不是直接运行可执行程序,就能保证动态链接程序能够找到Qt库。需注意的是如果需要运行其他应用程序的话,只需要重命名一下脚本就行了。

       当查找插件的时候,应用程序将会在当前目录下的插件子目录查找。既可以手动拷贝插件到plugins目录,也可以在插件工程文件中设置DESTDIR选项:

       DESTDIR = /path/to/Qt/plugandpaint/plugins

       包含了Plug&Paint程序所需要的Qt库、所有插件的存档文件将包括:

组件

文件名

可执行程序

plugandpaint

执行脚本

plugandpaint.sh

基本工具插件

plugins/libpnp_basictools.so

附加过滤器插件

plugins/libpnp_extrafilters.so

Qt核心模块

libQtCore.so.4

Qt GUI模块

libQtGui.so.4

       在多数操作系统下,共享库的扩展名是.so,但要注意的是在HP-UX上例外,它是.sl

       需要注意的是如果应用程序依赖于编译器相关的其他库,这些库也必须和程序一起分发。参见应用程序依赖一节获取更多信息。

       为了验证程序现在可以成功部署,你可以解压缩这个归档包到一个没有安装Qt以及编译器的机器上,尝试运行一下,例如运行plugandpaint.sh脚本。

       将插件放入plugins子目录的替代方法是在应用程序启动的时候,使用QApplication::addLibraryPath()QApplication::setLibraryPaths()方法来添加一个自定义的查找路径:

      

应用程序依赖

附加库

       执行ldd命令(大多数Unix系统都可用)来查看应用程序依赖哪些库:

       ldd ./application

       这就会把程序依赖的共享库都列出来。根据配置,这些库必须和程序同步分发。特别是标准C++库,如果你的应用程序使用了与系统编译器二进制不匹配的编译器,那么它也必须一起分发。如果可能的话,最安全的方法就是以静态的方式链接这些库。

       也许你想与标准的X11库进行动态链接,但是某些程序会尝试使用dlopen()方法来打开其他共享库,那么一旦调用失败,X11库可能会导致应用程序崩溃。

       同样值得一提的是,Qt会查找某些X11扩展,例如XineramaXrandr,可能把它们都放了进来,包括它们所链接的所有库。如果你不能保证某些扩展确实存在,最安全的方法就是在配置Qt到时候禁用该功能(例如/configure -no-xrandr)。

       FontConfigFreeType是其它经常不可用或者经常二进制不匹配的例子。听起来也许很怪,一些软件厂商通过在非常陈旧的机器上编译他们的软件已经获得成功,并且很小心的不去升级运行在其中的任何软件。

       当把程序链接到Qt静态库的时候,你必须显式的连接上述所有依赖库。通过在project文件中添加LIBS选项来实现。

Qt插件

       可能你的程序也会依赖某个或者多个Qt插件,例如JPEG图片格式插件,或者SQL驱动插件。一定要确保你程序里用到的插件也一同分发,并且要注意每一种类型的插件都应该部署到应用程序所在目录的指定子目录下(如:imageformatssqldrivers目录)。

注意:如果需部署一个使用了QtWebKit来展现万维网的HTML页面的程序,那么就需要包含所有文本编码插件以便于支持足够多的HTML编码。

       Qt插件的查找路径(同样也有一些其它路径)在QtCore库里是写死的,第一个写死的插件查找路径是:/path/to/Qt/plugins。就像上面提到的那样,使用预定的路径会有一些不足,因此你需要评估几种替代方案来确保Qt插件能被正常找到:

l  使用qt.conf。由于它提供了极大的灵活性,我们推荐用这种方法。

l  使用QApplication::addLibraryPath()QApplication::setLibraryPaths()

l  使用第三方安装包打包工具或者目标系统的安装包管理工具来改变QtCore里写死的路径。

如何创建Qt插件这篇文章展示了构建和部署Qt插件程序的相关注意事项。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值