如何在符合 LGPL 的 Linux 上部署 Qt5 应用程序? [关闭]
Posted
技术标签:
【中文标题】如何在符合 LGPL 的 Linux 上部署 Qt5 应用程序? [关闭]【英文标题】:How to deploy Qt5 application on Linux in compliance with LGPL? [closed] 【发布时间】:2014-08-06 16:04:21 【问题描述】:最近,我成功地将我的 Qt4 应用程序迁移到了 Qt5。事实上,应用程序使用来自 qt-opensource-linux-x64-5.3.1 发行版的预构建二进制 Qt5 库在开发机器上构建和运行。
因为我的应用需要符合 LGPL 2.1 许可,所以到 Qt5 的链接必须是动态的。 (所以我不能**不能**静态链接到 Qt!)
我的问题是部署此应用程序。我只是想不出一个包含所有可共享库的包,它可以在现有的 Linux 发行版上运行。
我可以容忍用户需要自己从 qt-opensource-linux-x64-5.3.1 二进制文件安装 Qt5 的要求。事实上,这将确保更严格地遵守 LGPL 2.1。所以,我可以假设兼容的 Qt5 库已安装并在主机上可用(虽然我不知道是否可以假设 Qt 安装的特定目录)
但是,我不清楚如何打包我的应用程序以在主机上运行。任何帮助将不胜感激!
【问题讨论】:
你不能只创建一个 .tar.gz 包含你的应用程序、Qt 库(动态链接到)、所有需要的 Qt 插件,并使用一个小脚本来设置LD_LIBRARY_PATH
哪个启动您的应用程序? (或使用ORIGIN
。)这就是documentation 中描述的内容。
这正是我正在做的,除了我使用 Install Jammer 来打包二进制文件、库和 shell 脚本以启动应用程序。问题是它在 Ubuntu 12.04 上运行,但在其他 Linux 上存在分段错误,例如 Slackware :-(
这在Qt手册中都有解释:qt-project.org/doc/qt-5/linux-deployment.html
谢谢 MrEricSir。这是指向相同 Qt 文档的第二条评论,我已经找到并基于我的第一次部署尝试(针对 Ubuntu 12.04)。对于应用程序可执行文件和平台插件 libqxcb.so,我煞费苦心地复制了 ldd 指示的所有依赖项。这很乏味,显然不适用于其他 Linux。另一方面,Qt5 本身的二进制发行版可以正常工作,因为 QtCreator 可以正确启动。我的问题是如何在已经存在的 Qt5 安装上复制这个,也许是“搭载”。
我投票决定将此问题作为离题结束,因为它是关于许可或法律问题,而不是编程或软件开发。 See here 了解详情,help center 了解更多信息。
【参考方案1】:
我认为其他有类似问题的人会对我最终做的事情感兴趣。因此,我用最简单的标准预构建二进制 Qt5 共享库的动态链接进行了更多实验。事实证明,我可以想出一个适用于以下 Linux 发行版的发行版:CentOS 7 64 位、Ubuntu 12.04 64 位和 Slackware 14.1 64 位和 KDE 桌面。诀窍是不包含ldd
命令显示的所有依赖项。相反,我的二进制发行版仅包含以下文件:
+-platforms/
| +-libqxcb.so
+-libicudata.so.52
+-libicui18n.so.52
+-libicuuc.so.52
+-libQt5Core.so.5
+-libQt5DBus.so.5
+-libQt5Gui.so.5
+-libQt5PrintSupport.so.5
+-libQt5Widgets.so.5
+-qm
+-qm.sh
其中,qm
是应用程序可执行文件,qm.sh
是用于启动应用程序的 bash 脚本。脚本如下:
#!/bin/sh
dirname=`dirname $0`
tmp="$dirname#?"
if [ "$dirname%$tmp" != "/" ]; then
dirname=$PWD/$dirname
fi
LD_LIBRARY_PATH=$dirname
export LD_LIBRARY_PATH
$dirname/qm "$@"
应用程序 (qm
) 没有任何插件,仅使用基本的 Qt 小部件库。
我或许应该补充一点,我使用的是二进制 qt-opensource-linux-x64-5.3.1 发行版:
http://download.qt-project.org/official_releases/qt/5.3/5.3.1/qt-opensource-linux-x64-5.3.1.run.mirrorlist
我希望这会有所帮助。
【讨论】:
【参考方案2】:伊纳尔
LGPL 的一个常见误解是它需要动态链接。它没有。它只需要获得代码的一方能够重新链接它与 LGPL 的库,他们能够从 您使用并提供的源重建构建应用程序附带的 Qt。
根据定义,动态链接会解决这个问题,因为每次在应用程序启动时都会执行链接(预链接只是一个缓存),并且库的源代码是可用的(在分发包中)。
因此,您只需将应用程序拆分为两个项目:
包含所有代码的静态库项目 (.a)。这是闭源部分。
将静态库与 Qt 库、C++ 运行时等链接的应用程序可执行文件。此时,Qt 库是静态链接还是动态链接并不重要。
要符合 LGPL,您的用户必须能够根据 LGPL 条款获得执行第 2 步所需的所有文件(在最简单的情况下只是一个 .pro 文件!),以及静态库 ( .a) 从第 1 步开始。
事实上,第 2 步可以很容易地提供一种特定于平台的方式来将您的项目与本地安装的 Qt 链接起来。例如,如果您的目标是 RedHat 系统,您可以使用以下脚本:
#! /bin/bash
# MiroProject.sh
yum install qt5-devel
qmake MiroProject
make install
假设静态库与MiroProject.pro
和dummy.cpp
位于同一位置,项目文件可能如下所示。
# MiroProject.pro
template = app
LIBS += -L. -lMiroProject
SOURCES += dummy.cpp
您需要在静态库中引用至少一个符号才能将其链接。这也避免了a different problem peculiar to MSVC。例如:
// dummy.cpp
int main(int argc, char ** argv);
void dummy__reference()
main(0, 0);
一个最小包需要四个文件:MiroProject.sh
- 上面的脚本,MiroProject.a
来自步骤 #1,dummy.cpp
和 MiroProject.pro
。当然,您必须提供用于构建 MiroProject.a
的 Qt 库的源代码。
理想情况下,您的包应该包含整个 shebang:Qt 源代码、您的闭源代码 .a
或 .lib
、开源包装器以及构建它们的脚本。
伊纳尔
【讨论】:
非常感谢,库巴。这种方法似乎很有趣。您能否指出以这种方式部署的任何现有应用程序?或者,是否有可能为更简单的 Qt 示例应用程序之一创建这样的部署?我认为这对于所有像我这样的可怜人来说都是非常有用的参考。 @Miro 这很简单。只需将模板类型从app
更改为staticlib
。这通常是从您的项目中生成 .a
(unix) 或 .lib
(Windows) 静态库所需的全部内容。
是的,我知道您食谱中的第 1 步相对简单。毕竟,这是我理解的代码。但我不清楚下一步。我知道我必须在 Linux-64 上静态重新构建 Qt(你会推荐哪个发行版?)。然后我需要创建另一个将所有这些静态链接在一起的项目(“MiroProject.pro”)。我可以在这里用一只手。
静态编译 Qt 需要您遵循 Qt 提供的说明,只需将 -static
选项传递给 configure
。我已经修改了上面的示例以使其完整。当运行qmake
在您的机器上 时,请确保从静态 Qt 安装运行 qmake。这负责设置其他所有内容,您无需调整 PATH
环境变量或类似的东西。
再次感谢您,库巴。现在步骤变得更加清晰了。我需要从静态构建 Qt5 开始。接下来,我需要针对静态 Qt5 库将我的闭源应用程序代码构建为静态库 (.a)。接下来,我需要使用 MiroProject.pro 将它们静态链接在一起(感谢 dummy_reference 技巧)。所有这些都应该生成一个易于安装的独立可执行文件。最后,我需要准备一个包含 Qt5 源代码、所有构建脚本以及我的闭源静态库的 LGPL 合规工具包,以便任何人都可以重复静态链接步骤。以上是关于如何在符合 LGPL 的 Linux 上部署 Qt5 应用程序? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
如何在Qt C++中解析JSON数据并使之被QML应用 / 蓝讯