结论:
似乎找到了 2 个实例;Linux 通过系统包管理即可。
原文:
大家好,我是 Mark24。
设想一下,如果你在用 Ruby 开发一个 GUI 应用,或者是 游戏。如何把产物可以送到你用户的手中。尽可能的轻松跑起来?
我目前感兴趣的是游戏应用。所以后面都是建立在游戏跑在终端的角度考虑。
虽然我们在讨论 Ruby,但是对于所有动态脚本语言的思路是通用的。
解决打包动态语言的问题。最后一公里,如何送到用户手中。
比如 Go、Rust、Crystal 的构建产物。
结论:
Go、Rust、Crystal …… 他们依然是在有限条件下运行。只不过这种条件实际上特别宽泛,好像他们的产物可以在各种系统下运行。
实际上 MacOS、Linux、Windows 的底层都是不鼓励静态链接。并且一些关键的包,也不提供静态链接需要的库。
这是为了体积考虑,也是为了安全更新考虑。
这些能够相对来说把自己打成静态链接的语言,实际上都做了大量的工作,自己实现了底层需要的部分。
动态语言无法直接把代码打包成这样。这条路是违背原理的。
这个思路是 MRuby。
MRuby 是一个轻量级的 Ruby 为嵌入式设计。它可以交叉编译成不同的架构。被设计的尽可能的少依赖,多拓展。
一定程度上,MRuby 就像是 Go。
可以用 MRuby 来构建应用、游戏。MRuby 也有 SDL 的绑定
这里有篇演讲,Dragon Ruby 的游戏引擎设计者,如何使用 MRuby 来构建一个应用。
Dragon Ruby 从 IDE 到 游戏产物全部是静态二进制。
但是具体的原理不详。依然不知道 Dragon Ruby 是如何做到的。
Taylor 是个个人开源框架,试图挑战 Dragon Ruby。
Taylor 的思路也是经典思路,容器中构建一个可以被静态的环境,绕过系统 (MacOS 不允许静态链接系统 lib)。
这些代码可能很难理解,在于他们究竟如何在发挥具体作用。
Taylor 正在重大重构中,但是目前的版本,是完全可以工作的!
这个思路需要一个 可以移动执行的 Ruby 解释器。
如果拥有了 Portable Ruby,那么 软件包 = (Portable Ruby + 项目代码)。
这条路相对可行。
还是前面的问题,Ruby 没有像 Go 等实现了全部的底层依赖的静态库。所以 编译!= portable。
Portable 的重点就是,尽可能的不依赖。如果实在无法避开的依赖,比如 Linux 中的 glibc(系统底层),需要使用较低版本来编译。 因为 glibc 永远是高版本兼容低版本,所以这样尽可能的获得兼容性。
Crystal、Go …… 他们一样。也只能工作在有限的 glibc 中。
Crystal 给出了平台很好体现了这一点:Crystal Platform Support。
用户不需要安装 Ruby,但是需要安装 Ruby 需要的底层库。来获得动态链接库。
这个思路获得了成功。
3)使用 Mac 的 App 壳应用
可以获得一个 Mac 的应用。
前面说了,如果可以创造出 静态的包。Ruby 也可以像 Go、Java 一样。这里参考这样一个项目,尝试在容器中模拟一个这样的环境。尽可能把所需的依赖全部集成起来,产出 portable ruby
不过这个产物我没怎么跑起来。但是这个是经典思路,是完全可行的。
app code + (Portable Ruby + lib) = software
用户安装 Ruby 运行游戏。由于前面无法实现彻底的静态打包,即使是安装依赖库,整个过程是差不多的。用户依然要安装。
如果这样避不开。推荐常见的处理办法 —— 前置的安装器(Installer)。解决环境依赖问题。
在 Windows 上 Ruby 是需要 安装包来安装。整个过程就像这样。
这一点,在 Windows 上也成功实现了:
构建过程和 Sample Project: ruby-windows-example
Crystal 的语法和 Ruby 非常相似,也有 游戏库、GUI 的绑定。
可以做到类似的事情。这一点就像 C++
但是缺点是 Crystal 目前还在建设中。
Crystal 对 MacOS ARM、Windows 的支持还不足。
现在无法当作一个成熟方案。
Java 其实采用了类似的思路,自己实现了底层。所以 Java 自身可以打包成静态的二进制。
我们可以把打包工作建立在 Java 的基础上。
这个实践方向是 Glimmer
Glimmer DSL for SWT 能够在 JRuby 之上将 Ruby 应用程序打包到原生安装程序(如 Mac DMG/PKG/APP、Windows MSI/EXE 和 Linux RPM/DEB)中,使开发者能够给最终用户(非程序员)一个单一的文件来运行,以安装所有需要的内容,比如 JRuby(可以运行任何 Ruby 代码)、它的 JVM 依赖项,以及正在安装的应用程序:
Glimmer DSL for LibUI,它直接在 Ruby 上运行而不是 JRuby,也有一个关于打包 Ruby 应用程序的部分,你可能想要查看(它提到了 Windows 和 Mac 的打包解决方案):
以下是使用 Glimmer DSL for SWT 打包的应用程序示例,这些应用程序由最终用户安装,没有问题:
这些都是作者发来的例子。尝试跑了几个,没有成功。 还需要研究研究。
如何把 Ruby 带到终端,其实一直不停的有人研究。项目生生死死。这里列举一些,供参考。
1)容器打包,静态链接 portable ruby 思路:
2)临时文件系统思路:
3)JRuby 思路:
4)Portable Ruby 思路:
5)只打包应用脚本,指定系统 Ruby
6)静态语言
使用 Crystal,Ruby 语法的 Go like 语言开发应用
7)使用 Zig
这是一个问号,Zig 作为一个新语言可以作为 C 的环境,而且自己实现了所有的静态库。
不知道 Zig 作为 CRuby 的编译器会如何?但是 Zig 目前依然在发展中。
8)使用容器
容器技术是任何语言的一个打包工具。
对于开发者友好,但是终端用户还是有门槛的。
不适合游戏应用。
9)Gem
如果都能接受用户总归要自己安装 Ruby 的设定。
把游戏、应用,封装成 gem,可以自动处理依赖、版本问题。
10)切换 Ruby 的实现:CRuby 无法实现静态打包
补充:
补充资料: