为 Linux 分发二进制应用程序的最佳方法是什么?
我刚刚将应用程序从 Windows 移植到 Linux 中。
我必须创建应用程序的安装程序。
该应用程序不是开源=>我应该分发应用程序的二进制文件(可执行文件、几个 .so 文件、帮助文件和图像)。
我找到了几种方法来做到这一点:
- RPM 和 DEB 软件包;
- .sh 文件中的安装程序;
- 自动打包。
我不喜欢第一种方法(RPM 和 DEB 软件包),因为我不想为不同的 Linux 发行版维护不同的软件包。
为 Linux 分发二进制应用程序的最佳方式是什么?
I just finished porting an application from Windows into Linux.
I have to create an installer of the application.
The application is not open source => I should distribute the application's binaries (executable file, couple .so files, help files and images).
I found several methods to do it:
- RPM and DEB packages;
- installer in .sh files;
- Autopackage.
I don't like first method (RPM and DEB packages) because I don't want to mantain different packages for different Linux distros.
What is the best way to distribute a binary application for Linux?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
在商业产品中经历过几次这种情况后,我认为最好的答案是为每个支持的平台使用本机安装程序。其他任何事情都会给最终用户带来不愉快的体验,并且实际上您必须在您想要支持的每个平台上进行测试,因此为每个平台维护软件包并不是一个重大负担。您可以创建一个可以在每个平台上“正常工作”的二进制文件的想法,包括一些您从未听说过的平台,但实际上并没有那么好。
我的建议是,您首先选择一两个平台进行支持(我的建议是 Red Hat 和 Ubuntu),然后让用户需求驱动其他安装包的创建。也许让人们知道您愿意支持其他平台,只需支付适当的费用即可覆盖您在该平台上进行打包和测试的时间和精力。如果事实证明某个平台非常不同,您可能需要为持续支持收取更多费用。
哦,对于这样的场景,我怎么强调虚拟机的价值都不过分。您需要为您支持的每个平台构建虚拟机,并且可能为每个平台构建多个虚拟机,以便轻松测试不同的配置。
Having been through this a couple of times with commercial products, I think the very best answer is to use the native installer for each supported platform. Anything else produces an unpleasant experience for the end-user, and in practice you have to test on every platform you want to support anyway, so it's not really a significant burden to maintain packages for each. The idea that you can create a binary that can "just work" on every platform out there, including some you've never even heard of, just really doesn't work all that well.
My recommendation is that you pick a platform or two to support initially (Red Hat and Ubuntu would be my suggestions) and then let user demand drive the creation of additional installation packages. Perhaps make it known that you're willing to support additional platforms, for a modest fee that covers your time and effort in packaging and testing on that platform. If a platform proves to be very different, you may need to charge more for ongoing support.
Oh, and I cannot overemphasize the value of virtual machines for scenarios like this. You need to build VMs for each platform you support, and perhaps multiple VMs per platform to make it easy to test different configurations.
有很多很好的答案(包括我的:))这里。尽管这更多的是关于二进制兼容性(您确实需要担心)。
对于安装程序,我会推荐 autopackage(我们成功地用它发布了我们软件的多个版本),他们已经完成了“installer.sh”部分以及更多(例如桌面集成)。
您必须小心并测试您的升级方案和内容,具体取决于您的包结构的复杂程度,但总体而言非常简洁。我在 1.2.6 中修复了一些依赖处理的错误,所以应该没问题。
更新:原始问题已删除,因此在此处重新发布完整答案,忽略所有对 autopackage 的引用,该引用已合并到 Listaller,不确定相关部分是否幸存。
对于可能在发行版中可用的标准库(例如 crypto++、pthreads 等),动态链接并告诉用户从其发行版存储库获取它们。或者如果可行的话静态链接。
对于必须控制其版本的奇怪库(例如,如果您想在敌人侏儒的领土上部署 Qt4 应用程序),请自行编译它们并安装到只有您的应用程序知道的私有位置。
切勿将私有库安装到标准位置,除非您可以确保不会干扰您支持的所有发行版的软件包系统。 (而且他们也不能干扰你)。
使用 rpath 而不是 LD_LIBRARY_PATH,并为所有相互引用的二进制文件和所有 dll 正确设置它。您可以将二进制文件上的 rpath 设置为“$ORIGIN;$ORIGIN/../lib;/opt/my/private/libs”,并让链接器在任何标准路径之前搜索这些位置。 (我认为必须设置一些链接器标志才能使 origin 工作)。确保在你的库上也设置了rpath:例如QtGui需要QtCore,如果用户碰巧安装了不同版本的标准包,你绝对不希望它被拾取(exe -> ../lib/QtGui.so (4.4.3) -> /usr/local/lib/QtCore.so (4.4.2)——肯定会早死。
如果使用任何 rpath 进行编译,则可以稍后使用 chrpath 进行更改,从而可以在后处理或安装脚本中调整安装位置。
保持二进制兼容性。 GLIB_C 对于您的用户来说几乎是静态的,因此您应该链接到一些足够旧的版本。 2.3 是一个安全的选择。您可以使用 APBuild——一个 gcc 包装器,它强制执行 GLIB_C 版本并执行一些其他二进制兼容性技巧,因此您不必在非常旧的发行版上编译所有应用程序。
如果您静态链接到任何内容,通常也必须使用 APBuild 重新构建,否则它必然会拖动更新的 GLIB_C 符号。您私下安装的所有 .so 自然也必须用它来构建。有时您必须修补第三方库才能使用旧符号。 (我必须修补 ruby 以返回真正的权限而不是有效的权限,因为旧的 GLIB_C 中没有这样的函数。仍然不确定我是否破坏了任何东西:))。
要与桌面环境集成(文件关联、mime 类型、图标、开始菜单条目等),请使用 xdg-utils。但要注意,就像 Linux 上的所有东西一样,它们并不喜欢文件名中的空格:)。确保在每个目标发行版上测试这些东西——xdg 实现充满了错误和怪癖。
对于实际安装,您可以提供各种本机软件包(rpm、deb 等),或者推出您自己的安装程序,或者找到适用于所有发行版的安装程序,绕过本机软件包管理器。为此,我们成功地使用了 Autopackage(与制作 APbuild 的人相同)。
There were a lot of good answers (mine included :)) here. Although that is more about binary compatibility (which you do need to worry about).
For installer I would recommend autopackage (we successfully released several versions of our software with it), they did the "installer.sh" part already and more (desktop integration for example).
You have to be careful and test your upgrade scenarios and stuff, depending on how complex you package structure is, but it is pretty neat overall. I fixed few bugs with dependency handling in 1.2.6, so it should be fine.
UPDATE: The original question was deleted, so reposting full answer here, ignore all references to autopackage, that was merged into Listaller, not sure if relevant parts survived.
For standard libraries (like crypto++, pthreads, etc) that are likely to be available in a distribution -- link dynamically and tell users to get them from their distro repository. Or link statically if it is feasible.
For weird libraries that you must control version of (if you want to deploy Qt4 app on territory of enemy gnomes for example), compile them yourself and install into a private spot only your app knows about.
Never install private libs into standard places unless you can be sure to not interfere with package systems of all distros you support. (and that they can't interfere with you either).
Use rpath instead of LD_LIBRARY_PATH, and set it properly for all you binaries and all dlls that reference each other. You can set rpath on you binary to "$ORIGIN;$ORIGIN/../lib;/opt/my/private/libs" and have linker search those places before any standard paths. (have to setsome linker flag for origin to work I think). Make sure to set rpath on your libs too: for example QtGui needs QtCore, and if user happens to install standard package with different version, you absolutely don't want it picked up (exe -> ../lib/QtGui.so (4.4.3) -> /usr/local/lib/QtCore.so (4.4.2) -- a sure way to die early).
If you compile with any rpath, you can change it later with chrpath, thus making it possible to tweak install location as part of post processing or install script.
Maintain binary compatibility. GLIB_C is pretty much static for your users, so you should link against some sufficiently old version. 2.3 is a safe bet. You can use APBuild -- a gcc wrapper that enforces GLIB_C version and does few other binary compatibility tricks, so you don't have to compile all you apps on a really old distro.
If you link to anything statically, it generally will have to be rebuilt with APBuild too, otherwise it is bound to drag newer GLIB_C symbols. All .so's you install privately will naturally have to be built with it too. Sometimes you have to patch third party libs to use older symbols. (I had to patch ruby to return real permissions instead of effective ones, since there is no such functions in older GLIB_C. Still not sure if I broke anything :)).
For integration with desktop environments (file associations, mime-types, icons, start menu entries, etc) use xdg-utils. Beware though, like everything on linux they don't really like spaces in filenames :). Make sure to test those things on each target distro -- xdg implementations are riddled with bugs and quirks.
For actual install you can either provide variety of native packages (rpm, deb and a few more), or roll out your own installer, or find installer that works on all distros bypassing native package managers. We successfully used Autopackage (same people who made APbuild) for that.
可以在 Debian 上安装 RPM,在 RHEL 上安装 APT。
如果您要静态链接该程序,或者仅动态链接将在包中分发的库,那么如何分发它并不重要。最简单的方法是 tar.gz ,这样就可以了。
OTOH 如果它与系统库动态链接,特别是如果它依赖于将与客户端的其他应用程序共享的动态库,那么您需要执行 RPM、APT 或两者都执行。
It's possible to install an RPM on Debian and an APT on RHEL.
If you are going to statically link this program, or dynamically link only with libraries that you will be distributing in the package, then it doesn't much matter how you distribute it. The simplest way is tar.gz and that would work.
OTOH if it is dynamically linked with system libraries, and particularly if it has dependencies on dynamic libraries that will be shared with the client's other applications, then you kind of need to do either RPM, APT, or both.
您可能想尝试 InstallBuilder。它是跨平台的(可以在 Windows、Linux、Mac OS X、Solaris 和几乎任何其他 Unix 平台上运行)。 Intel、Motorola、GitHub、MySQL、Nokia/Trolltech 和许多其他公司都在使用它,因此你会成为一个很好的伙伴:) 除了二进制安装程序之外,它还可以创建跨发行版的 RPM 和 DEB 包。
InstallBuilder 是商业性的,但我们为开源程序提供免费许可证,并为 mISV 或独立开发人员提供非常优惠的折扣,请给我们留言。
You may want to try out InstallBuilder. It is crossplatform (runs on Windows, Linux, Mac OS X, Solaris and nearly any other Unix platform out there). It is used by Intel, Motorola, GitHub, MySQL, Nokia/Trolltech and many other companies so you will be in good company :) In addition to binary installers, it can also create cross-distro RPMs and DEB packages.
InstallBuilder is commercial, but we offer free licenses for open source programs and very significant discounts for mISVs or solo-developers, just drop us a line.
使用二进制文件创建一个 .tar.bz2 存档,然后为其发布一个 feed,如下所示:
使用您的 GPG 密钥对其进行签名。您可以使用 0install.net 上的工具来计算摘要并以正确的格式为您添加 GPG 签名。
然后,将其放在您网站的 uri 属性中的地址上。大多数 Linux 发行版(例如 Ubuntu、Fedora、Debian、Gentoo、ArchLinux 等)上的任何用户都可以安装并运行您的程序:
他们的系统还将定期检查更新。不同的桌面环境有不同的 GUI,但命令行在任何地方都可以使用。
另请参阅一些现有提要以获取灵感。
Create a .tar.bz2 archive with the binary, then publish a feed for it, like this:
Sign it with your GPG key. You can use the tools on 0install.net to calculate the digest and add the GPG signature for you in the correct format.
Then, put it on your web-site at the address in the uri attribute. Any user on most Linux distributions (e.g. Ubuntu, Fedora, Debian, Gentoo, ArchLinux, etc) can then install and run your program with:
Their system will also check for updates periodically. There are various GUIs for the different desktop environments, but the command-line will work everywhere.
Also look at some of the existing feeds for inspiration.
今天,我还会看看 Snapcraft 和 Flatpak 受到一些流行发行版的欢迎。我探索了其他选项,这最终最适合我。尤其是 Flatpak 还帮助我了解了要遵循的标准 Linux 桌面约定。
Today, I would also look at Snapcraft and Flatpak which are embraced by some popular distributions. I explored other options and it is what ended up working best for me. Flatpak in particular also helped me learn about standard Linux desktop conventions to follow.
我告诉你另一种可能性,尽管我不知道它的状态:Loki 安装程序。 Loki 是一家为 Linux 进行视频游戏移植的公司。它于 2002 年停止运行,但安装程序仍然可用。
InstallShield 也适用于 Linux。但不知道状态。
尽管很多人建议您使用 tar.gz,但请不要这样做。我假设您希望为用户提供愉快的安装过程体验。 tar.gz 是您可以做的最低级别、低质量、低可用性的选择之一。正如你所知,它在任何地方都适用,因为它基本上什么也不做。
freedesktop.org 和 LSB 的人非常清楚把东西放在哪里。您需要的是一个友好的程序来做到这一点。 Autopackage 恕我直言,它有这些数字(我喜欢它),但尽管它已经很老了,我还没有看到任何一个程序作为自动软件包分发。
仔细评估它,但不要仅仅因为它不受欢迎而错过成为支持它的动力的一部分的机会。如果它适合您,也适合您的用户,那么其他一切都不重要。
I tell you an additional possibility, although I am not aware of its status: the Loki installer. Loki was a company doing videogames porting for Linux. It went down in 2002, but the installer is available.
InstallShield is also available for linux. No idea on the status though.
Although many people are proposing you to go with tar.gz, please don't. I assume you want to provide a pleasant experience for the installation procedure to your users. A tar.gz is one of the most low level, low quality, low usability choices you can do. It works everywhere because it does basically nothing, as you know.
The guys at freedesktop.org and the LSB are quite clear on where to put stuff. What you need is a friendly program to do that. Autopackage imho has the numbers (I love it), but despite its age, I haven't seen a single program out there distributed as an autopackage.
Evaluate it carefully, but don't skip the chance of being part of the momentum in favour of it, just because it's not popular. If it works for you, and it works for your users, everything else does not matter.
没有最好的方法(普遍来说)。
tar.gz 二进制文件,应该可以工作。
There is no best way (universally speaking).
tar.gz the binaries, that should work.
您可能还想查看 AppImage (https://appimage.org/)。这个概念是它生成一个二进制文件,用户下载该文件,设置可执行文件并直接运行;无需安装,无需安装依赖项(因为应用程序映像通常包含除 glibc 等基本内容之外的所有依赖项)。这带来了非常好的用户体验!
一些缺点:
You may also want to look at AppImage (https://appimage.org/). The concept is that it produces a single binary file that the user downloads, sets executable, and runs directly; no installation necessary, no dependencies to install (since the app image typically includes all the dependencies except basic stuff like glibc). This makes for a really great user experience!
Some downsides:
我也在工作中研究过这个问题,我不得不承认确实没有“最好的方法”。如果您的应用程序作为源代码分发,那么我会使用打包在 tar.gz 中的 make/configure 方法。这在 Linux 世界中似乎相当普遍。
了解要做什么的一个好方法是查看更大的组织并了解他们如何分发二进制文件。
I've also looked into this at work and I'd have to agree there really isn't a "best way". If your application is being distributed as source then I'd go with the make/configure methods packaged up in a tar.gz. That seems fairly universal in the Linux world.
A good way to get an idea of what to do is to look at larger organziation and see how they distribute their binaries.