因项目需要,可能有不同版本的qt程序要运行到同一台机器上,本次实验是qt4.8.5和qt5.3.1开发的程序同时运行在同一台机器上,此机器可以不按照qt的任何版本,当然,两个版本开发的qt与机器的位数必须一样,例如都是32位或者64位。

    两个版本的qt的程序我都采用动态编译(静态编译方法请度娘),所以需要把运行程序所需的动态库放到程序可以链接的地方,程序可以链接的动态库路径参见:linux动态库搜索路径。此处直接贴出结论:动态库的搜索路径搜索的先后顺序是:

  1.编译目标代码时指定的动态库搜索路径;

  2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;

  3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;

  4.默认的动态库搜索路径/lib;

  5.默认的动态库搜索路径/usr/lib。

    考虑到一台机器要运行多个不同版本的qt,而且不能要求机器一定会安装了某个版本的qt,所以不同qt版本的程序所需的动态库最好是放在编译目标代码指定的动态库路径,做到路径独立,因为如果把动态库放在/lib和/usr/lib的话,那么其他版本的qt程序也会到这个地方搜索动态库,可能出现冲突。故此,我这里qt4.8.5和qt5.3.1的程序都在编译时指定动态库路径为工程所在目录下面的lib。


一、对于qt4.8.5具体操作如下:

       1)修改工程文件(.pro文件),加上一行LIBS += -L./lib,注意,-L后面不能有空格,要紧跟你指定的动态库路径(可以自由指定),然后保存文件。

       2)在终端去到你工程所在目录,执行命令qmake xxx.pro,其中xxx.pro是你的工程文件,命令执行完毕后生成Makefile,用vi或者其他工具打开Makefile,然后搜索LIBS,可以看到,我们这里的LIBS已经加上了你刚才在.pro文件里面配置的./lib,具体如图(图中的-L./lib)所示:

        3)执行make得到可执行文件xxx。

     测试方法:通过ldd命令查看xxx依赖的动态库指向哪里,命令如下:

ldd untitled | grep -i qt, #这里的untitled为刚才make出来的可执行文件

命令执行结果为:

libQtGui.so.4 => /usr/local/Trolltech/Qt-4.8.5/lib/libQtGui.so.4 (0x00007f289a88e000)
libQtCore.so.4 => /usr/local/Trolltech/Qt-4.8.5/lib/libQtCore.so.4 (0x00007f289a3a0000),

可见此时编译出来的可执行文件的动态库是指向/usr/local/Trolltech/Qt-4.8.5/lib/,这个路径为qt的安装路径,个人猜测是你用qtCreator编写qt程序时就已经默认加上这个动态库搜索路径的,这是qtCreator已经配置了这个路径,具体见qtCreator的Tools-->Options-->Build & Run-->Kits-->Qt Version.

首先我们把这些依赖的库拷贝到我们的可执行文件的同级目录的lib下,首先用终端去到我们的qt工程所在目录,执行命令如下:

mkdir lib    #创建lib目录,目录名必须要与我们在pro文件新增的LIBS += -L后面指定的目录名称一致

cp /usr/local/Trolltech/Qt-4.8.5/lib/libQtGui.so.4 ./lib  #把依赖的库拷贝到lib里面

cp /usr/local/Trolltech/Qt-4.8.5/lib/libQtCore.so.4 ./lib

我们通过屏蔽当前可执行文件指向的动态库路径模拟一个没有安装qt的机器,执行命令如下:

cd /usr/local/Trolltech/Qt-4.8.5;mv lib lib-bak,

这样把lib改名后,我们重新执行了ldd untitled | grep -i qt,命令的结果如下:

libQtGui.so.4 => ./lib/libQtGui.so.4 (0x00007f89a6631000)
libQtCore.so.4 => ./lib/libQtCore.so.4 (0x00007f89a6142000),

可见此时的可执行文件可以自动把动态库路径指向我们编译时执行的./lib,运行可执行文件正常。

     最终,我们发布文件时,要把lib拷贝到可执行文件的当前目录,同时把所需的库拷贝到lib里面,把可执行文件和lib一起发布即可。


二、对于qt5.3.1:

       这里我采用与qt4.8.5一样的方法,在工程文件所在目录创建lib目录,然后在.pro文件加上LIBS += ./lib,然后重新qmake xxx.pro,然后make,然后ldd xxx | grep -i qt,然后,命令执行结果的所有so文件拷贝到工程文件所在目录的lib里面,然后屏蔽掉ldd xxx | grep -i qt命令执行结果的qt安装路径里面对应的lib,即把这个对应的lib改个名字,然后运行我们的make出来的可执行程序,然后提示错误,error while loading shared libraries: libQt5Widgets.so.5: cannot open shared object file: No such file or directory,然后我用ldd查看动态库链接情况,ldd version531 | grep -i qt,(version531为make出来的可执行程序),结果如下:

    libQt5Widgets.so.5 => not found
    libQt5Gui.so.5 => not found
    libQt5Core.so.5 => not found
但是我查看工程目录所在目录的lib,里面是有这几个文件的,不过是一个软连接,但是这个软连接所链接的文件我也已经拷贝在lib里面的,不知道为什么还是提示找不到,没办法,我只有通过环境变量LD_LIBRARY_PATH指定动态库搜索路径到lib了,执行如下命令:

    export LD_LIBRARY_PATH=./lib

此时,再次运行可执行文件,然后又出错,提示如下:
    This application failed to start because it could not find or load the Qt platform plugin "xcb".
Reinstalling the application may fix this problem.
Aborted

这个错误,我在网上搜索了下,这个错误的原因是qt5的新特性导致的,最终的解决办法在工程目录创建platforms目录,然后把安装qt5的目录的lib所在目录的同一级目录的plugins/platforms里面的libqxcb.so拷贝到刚才新建的platforms目录,重新运行可执行文件,可以正常运行,此时我把LD_LIBRARY_PATH环境变量置为空也正常了。