如何制作Linux Qt应用的二进制发行版

时间:2022-11-14 04:08:06

I am developing cross-platform Qt application. It is freeware though not open-source. Therefore I want to distribute it as a compiled binary.

我正在开发跨平台Qt应用程序。它是免费的,但不是开源的。因此,我想把它作为编译好的二进制文件分发。

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. The first produces huge executable and also require static versions of many libraries which Qt depends on, i.e. I'll have to rebuild all of them from scratches. The second method is based on reconfiguring dynamic linker right before the application startup and seems a bit tricky to me.

Qt部署指南建议两种方法:静态链接和使用共享库。第一个生成了巨大的可执行文件,并且还需要Qt所依赖的许多库的静态版本,也就是说,我必须从头开始重新构建所有库。第二种方法基于在应用程序启动之前重新配置动态链接器,对我来说有点棘手。

Can anyone share his/her experience in distributing Qt applications under Linux? What method should I use? What problems may I confront with? Are there any other methods to get this job done?

有人能分享他/她在Linux下发布Qt应用程序的经验吗?我应该使用什么方法?我可以面对什么问题?还有其他方法可以完成这项工作吗?

8 个解决方案

#1


12  

You can also distribute Qt shared libraries on Linux. 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. This is probably the simplest solution for you. You can always change this in a wrapper script for your executable.

您还可以在Linux上分发Qt共享库。然后,让您的软件加载这些文件,而不是系统默认的文件。可以使用LD_LIBRARY_PATH环境变量覆盖共享库。这可能是最简单的解决方案。您总是可以在可执行文件的包装器脚本中更改它。

Alternatively, just specify the minimum library version that your users need to have installed on the system.

另外,只需指定用户需要在系统上安装的最小库版本。

#2


15  

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. To use this on my QMake file, I add this line in the .pro file:

例如,我将我的库存储在二进制文件的旁边,或者是在二进制文件旁边的“mylib”目录中。要在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.

我可以用本地库来运行二进制文件,重写任何系统库,并且不需要启动脚本。

#3


4  

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. 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应用也不例外。您当然可以静态地使用Qt进行构建,您不应该像krbyrd在其响应中指出的那样去构建大量的附加依赖项。

#4


3  

sybreon's answer is exactly what I have done. 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. 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). After you have them all, run the binary with LD_LIBRARY_PATH set to it's previous value plus $LDD.

为每个目录设置一个已交付的Qt库。编写一个shell脚本,让它在可执行文件上运行ldd,并为这些库中的每个库添加“not found”,将相应的目录添加到一个列表(我们称之为$ 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.

最后一个评论是关于“我将不得不从头开始重新构建它们”。不,你不必这么做。如果您有这些库的开发包,您应该有一个文件,您可以针对这些文件进行静态链接。

#5


3  

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.

    打开你的源代码。

#6


1  

The probably easiest way to create a Qt application package on Linux is probably linuxdeployqt. It collects all required files and lets you build an AppImage which runs on most Linux distributions.

在Linux上创建Qt应用程序包的最简单方法可能是linuxdeployqt。它收集所有必需的文件,并允许您构建运行在大多数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版本上构建应用程序,以便您的AppImage可以在AppImageHub上列出。

#7


0  

You can look into QtCreator folder and use it as an example. It has qt.conf and qtcreator.sh files in QtCreator/bin.

您可以查看QtCreator文件夹并将其用作示例。它有qt.conf和qtcreator。sh QtCreator / bin文件。

lib/qtcreator is the folder with all needed Qt *.so libraries. Relative path is set inside qtcreator.sh, which should be renamed to you-app-name.sh

lib/qtcreator是包含所有需要的Qt *的文件夹。所以库。相对路径设置在qtcreator中。sh,应该重命名为you-app-name.sh

imports,plugins,qml are inside bin directory. Path to them is set in qt.conf file. This is needed for QML applications deployment.

导入、插件、qml都在bin目录中。它们的路径在qt.conf文件中设置。这是QML应用程序部署所需的。

#8


-1  

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)
  • 打包所有东西并进行部署(这里需要做一些调整,但是对不起,我还没有尝试)

#1


12  

You can also distribute Qt shared libraries on Linux. 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. This is probably the simplest solution for you. You can always change this in a wrapper script for your executable.

您还可以在Linux上分发Qt共享库。然后,让您的软件加载这些文件,而不是系统默认的文件。可以使用LD_LIBRARY_PATH环境变量覆盖共享库。这可能是最简单的解决方案。您总是可以在可执行文件的包装器脚本中更改它。

Alternatively, just specify the minimum library version that your users need to have installed on the system.

另外,只需指定用户需要在系统上安装的最小库版本。

#2


15  

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. To use this on my QMake file, I add this line in the .pro file:

例如,我将我的库存储在二进制文件的旁边,或者是在二进制文件旁边的“mylib”目录中。要在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.

我可以用本地库来运行二进制文件,重写任何系统库,并且不需要启动脚本。

#3


4  

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. 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应用也不例外。您当然可以静态地使用Qt进行构建,您不应该像krbyrd在其响应中指出的那样去构建大量的附加依赖项。

#4


3  

sybreon's answer is exactly what I have done. 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. 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). After you have them all, run the binary with LD_LIBRARY_PATH set to it's previous value plus $LDD.

为每个目录设置一个已交付的Qt库。编写一个shell脚本,让它在可执行文件上运行ldd,并为这些库中的每个库添加“not found”,将相应的目录添加到一个列表(我们称之为$ 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.

最后一个评论是关于“我将不得不从头开始重新构建它们”。不,你不必这么做。如果您有这些库的开发包,您应该有一个文件,您可以针对这些文件进行静态链接。

#5


3  

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.

    打开你的源代码。

#6


1  

The probably easiest way to create a Qt application package on Linux is probably linuxdeployqt. It collects all required files and lets you build an AppImage which runs on most Linux distributions.

在Linux上创建Qt应用程序包的最简单方法可能是linuxdeployqt。它收集所有必需的文件,并允许您构建运行在大多数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版本上构建应用程序,以便您的AppImage可以在AppImageHub上列出。

#7


0  

You can look into QtCreator folder and use it as an example. It has qt.conf and qtcreator.sh files in QtCreator/bin.

您可以查看QtCreator文件夹并将其用作示例。它有qt.conf和qtcreator。sh QtCreator / bin文件。

lib/qtcreator is the folder with all needed Qt *.so libraries. Relative path is set inside qtcreator.sh, which should be renamed to you-app-name.sh

lib/qtcreator是包含所有需要的Qt *的文件夹。所以库。相对路径设置在qtcreator中。sh,应该重命名为you-app-name.sh

imports,plugins,qml are inside bin directory. Path to them is set in qt.conf file. This is needed for QML applications deployment.

导入、插件、qml都在bin目录中。它们的路径在qt.conf文件中设置。这是QML应用程序部署所需的。

#8


-1  

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)
  • 打包所有东西并进行部署(这里需要做一些调整,但是对不起,我还没有尝试)