简体   繁体   English

如何为Linux的Qt应用程序进行二进制分发

[英]How to make binary distribution of Qt application for Linux

I am developing cross-platform Qt application. 我正在开发跨平台的Qt应用程序。 It is freeware though not open-source. 虽然不是开源的,但它是免费软件。 Therefore I want to distribute it as a compiled binary. 因此,我想将其作为编译二进制文件分发。

On windows there is no problem, I pack my compiled exe along with MinGW's and Qt's DLLs and everything goes great. 在Windows上没有问题,我将我编译的exe与MinGW和Qt的DLL打包在一起,一切都很顺利。

But on Linux there is a problem because the user may have shared libraries in his/her system very different from mine. 但是在Linux上存在一个问题,因为用户可能在他/她的系统中拥有与我的完全不同的共享库。

Qt deployment guide suggests two methods: static linking and using shared libraries. Qt部署指南提出了两种方法:静态链接和使用共享库。 The first produces huge executable and also require static versions of many libraries which Qt depends on, ie I'll have to rebuild all of them from scratches. 第一个产生巨大的可执行文件,并且还需要Qt所依赖的许多库的静态版本,即我必须从划痕重建所有这些库。 The second method is based on reconfiguring dynamic linker right before the application startup and seems a bit tricky to me. 第二种方法是基于在应用程序启动之前重新配置动态链接器,对我来说似乎有点棘手。

Can anyone share his/her experience in distributing Qt applications under Linux? 任何人都可以分享他/她在Linux下分发Qt应用程序的经验吗? What method should I use? 我应该使用什么方法? What problems may I confront with? 我可能遇到什么问题? Are there any other methods to get this job done? 有没有其他方法来完成这项工作?

Shared libraries is the way to go, but you can avoid using LD_LIBRARY_PATH (which involves running the application using a launcher shell script, etc) building your binary with the -rpath compiler flag, pointing to there you store your libraries. 共享库是可行的方法,但您可以避免使用LD_LIBRARY_PATH (它涉及使用启动程序shell脚本运行应用程序等)使用-rpath编译器标志构建二进制文件,指向存储库的存储库。

For example, I store my libraries either next to my binary or in a directory called "mylib" next to my binary. 例如,我将库存储在二进制文件旁边或我二进制文件旁边名为“mylib”的目录中。 To use this on my QMake file, I add this line in the .pro file: 要在我的QMake文件中使用它,我在.pro文件中添加以下行:

QMAKE_LFLAGS += -Wl,-rpath,\\$\$ORIGIN/lib/:\\$\$ORIGIN/../mylib/

And I can run my binaries with my local libraries overriding any system library, and with no need for a launcher script. 我可以使用我的本地库来运行我的二进制文件,覆盖任何系统库,而不需要启动器脚本。

You can also distribute Qt shared libraries on Linux. 您还可以在Linux上分发Qt共享库。 Then, get your software to load those instead of the system default ones. 然后,让您的软件加载那些而不是系统默认的软件。 Shared libraries can be over-ridden using the LD_LIBRARY_PATH environment variable. 可以使用LD_LIBRARY_PATH环境变量覆盖共享库。 This is probably the simplest solution for you. 这可能是最简单的解决方案。 You can always change this in a wrapper script for your executable. 您始终可以在可执行文件的包装脚本中更改此设置。

Alternatively, just specify the minimum library version that your users need to have installed on the system. 或者,只需指定用户需要在系统上安装的最低库版本。

When we distribute Qt apps on Linux (or really any apps that use shared libraries) we ship a directory tree which contains the actual executable and associated wrapper script at the top with sub-directories containing the shared libraries and any other necessary resources that you don't want to link in. 当我们在Linux(或任何使用共享库的应用程序)上分发Qt应用程序时,我们提供了一个目录树,其中包含顶部的实际可执行文件和相关的包装器脚本,其中包含共享库的子目录以及您所需的任何其他必要资源我想链接进去。

The advantage of doing this is that you can have the wrapper script setup everything you need for running the application without having to worry about having the user set environment variables, install to a specific location, etc. If done correctly, this also allows you to not have to worry about from where you are calling the application because it can always find the resources. 这样做的好处是,您可以让包装器脚本设置运行应用程序所需的一切,而无需担心用户设置环境变量,安装到特定位置等。如果正确完成,这也允许您不必担心从哪里调用应用程序,因为它始终可以找到资源。

We actually take this tree structure even further by placing all the executable and shared libraries in platform/architecture sub-directories so that the wrapper script can determine the local architecture and call the appropriate executable for that platform and set the environment variables to find the appropriate shared libraries. 我们实际上通过将所有可执行文件和共享库放在平台/体系结构子目录中来进一步采用这种树结构,以便包装器脚本可以确定本地体系结构并为该平台调用适当的可执行文件并设置环境变量以找到适当的共享库。 We found this setup to be particularly helpful when distributing for multiple different linux versions that share a common file system. 我们发现这种设置在分发共享公共文件系统的多个不同Linux版本时特别有用。

All this being said, we do still prefer to build statically when possible, Qt apps are no exception. 说到这一切,我们仍然倾向于在可能的情况下静态构建,Qt应用程序也不例外。 You can definitely build with Qt statically and you shouldn't have to go build a lot of additional dependencies as krbyrd noted in his response. 你绝对可以静态地用Qt构建,你不应该像krbyrd在他的回复中所说的那样构建很多额外的依赖。

Not an answer as such (sybreon covered that), but please note that you are not allowed to distribute your binary if it is statically linked against Qt, unless you have bought a commercial license, otherwise your entire binary falls under the GPL (or you're in violation of Qt's license.) 这不是一个答案(sybreon涵盖了这一点),但请注意,如果你的二进制文件与Qt静态链接,你不能分发你的二进制文件,除非你已经购买了商业许可证,否则你的整个二进制文件属于GPL(或者你'违反了Qt的执照。)

If you have a commercial license, never mind. 如果您有商业许可证,请不要介意。

If you don't have a commercial license, you have two options: 如果您没有商业许可证,您有两种选择:

  1. Link dynamically against Qt v4.5.0 or newer (the LGPL versions - you may not use the previous versions except in open source apps), or 动态链接Qt v4.5.0或更新版本(LGPL版本 - 除开源应用程序外,您可能不使用以前的版本),或者

  2. Open your source code. 打开源代码。

sybreon's answer is exactly what I have done. sybreon的答案正是我所做的。 You can either always add your libraries to LD_LIBRARY_PATH or you can do something a bit more fancy: 您可以随时将库添加到LD_LIBRARY_PATH ,也可以做一些更有趣的事情:

Setup your shipped Qt libraries one per directory. 每个目录设置一个装运的Qt库。 Write a shell script, have it run ldd on the executable and grep for 'not found', for each of those libraries, add the appropriate directory to a list (let's call it $LDD). 编写一个shell脚本,让它在可执行文件上运行ldd ,并为'not found'运行grep,对于每个库,将相应的目录添加到列表中(让我们称之为$ LDD)。 After you have them all, run the binary with LD_LIBRARY_PATH set to it's previous value plus $LDD. 完成所有操作后,运行二进制文件,并将LD_LIBRARY_PATH设置为之前的值加上$ LDD。

Finally a comment about "I'll have to rebuild all of them from scratches". 最后评论“我将不得不从划痕重建所有这些”。 No, you won't have to. 不,你不必。 If you have the dev packages for those libraries, you should have .a files, you can statically link against these. 如果你有这些库的开发包,你应该有.a文件,你可以静态链接这些。

The probably easiest way to create a Qt application package on Linux is probably linuxdeployqt . 在Linux上创建Qt应用程序包的最简单方法可能是linuxdeployqt It collects all required files and lets you build an AppImage which runs on most Linux distributions. 它收集所有必需的文件,并允许您构建在大多数Linux发行版上运行的AppImage

Make sure you build the application on the oldest still-supported Ubuntu LTS release so your AppImage can be listed on AppImageHub . 确保在最旧的仍然支持的Ubuntu LTS版本上构建应用程序,以便可以在AppImageHub上列出您的AppImage

You can look into QtCreator folder and use it as an example. 您可以查看QtCreator文件夹并将其用作示例。 It has qt.conf and qtcreator.sh files in QtCreator/bin . 它在QtCreator / bin中qt.confqtcreator.sh文件。

lib/qtcreator is the folder with all needed Qt *.so libraries. lib / qtcreator是包含所有所需Qt * .so库的文件夹。 Relative path is set inside qtcreator.sh, which should be renamed to you-app-name.sh 相对路径在qtcreator.sh中设置,应该重命名为you-app-name.sh

imports , plugins , qml are inside bin directory. importpluginsqml都在bin目录下。 Path to them is set in qt.conf file. 它们的路径在qt.conf文件中设置。 This is needed for QML applications deployment. 这是QML应用程序部署所必需的。

This article has information on the topic. 本文包含有关该主题的信息。 I will try it myself: http://labs.trolltech.com/blogs/2009/06/02/deploying-a-browser-on-gnulinux/ 我会自己尝试一下: http//labs.trolltech.com/blogs/2009/06/02/deploying-a-browser-on-gnulinux/

In a few words: 简而言之:

  • Configure Qt with -platform linux-lsb-g++ 使用-platform linux-lsb-g ++配置Qt
  • Linking should be done with –lsb-use-default-linker 应使用-lsb-use-default-linker进行链接
  • Package everything and deploy (will need a few tweaks here but I haven't yet tried it sorry) 打包所有内容并部署(这里需要一些调整,但我还没有尝试过对不起)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM