代码:
嗨,大家好,我一直在尽自己的绵薄之力为社区搬砖,这一次我来说说我熟悉的 Windows 上的 Ruby,以及我带给大家的 rbenv for Windows
.
我最开始学习 Ruby 的时候,就是在 Windows 上,然而很多人说在 Windows 上使用 Ruby 就是浪费时间。其实到我学的那段时间,这种情形已经不那么明显了。因为 社区在发展,用爱发电的人们在前进。人们并没有因为困难,就直接放弃对 Windows 平台的支持,而是一朝一夕的不断改进。
RubyInstaller 从 2009 年开始开发,到 2017 年左右切换到 RubyInstaller2 (下文我们直接称 RubyInstaller 来指代 RubyInstaller2). 后者以 @larskanis 为主要开发人员,成为了 Windows 上安装 Ruby 的事实标准。该项目 5 年多几乎只有他一人在做实际的维护工作,仅有少数的爱好者在一起帮忙解决问题。我对这位来自德国的工程师,Ruby 爱好者,感到敬佩。除了琐碎的用户不清楚的内部维护细节之外,最明显的一个改进是:
曾经我们在 Windows 上安装 Rails
的时候,很容易就卡在 gem install sqlite3
,然而这个还不是令人无语的网络问题,而是一个编译选项问题。当时的网上的帖子都不管用,对于刚学习 Ruby 的人更是一头雾水。我当时花了好几天才找到解决方案,心里也默默的来了句 "真是浪费时间。。。" . 然而你现在再使用 RubyInstaller,你会发现这一步已经被自动化解决了,即 SQLite3 其实会被 pacman
(对,这个就是 Arch Linux 社区中最骄傲的软件 — 包管理工具) 自动安装,这在 macOS 和 Linux 上的同学都没有这样的特殊待遇。
国内现在安装 Ruby 就只有一个问题,那就是网络。不过,在 2021 年 2 月,我们在上海交通大学镜像站的帮助下创建了 https://rubyinstaller.cn/ (代码在Gitee 这) ,这个迟来的站点也许已经服务了不少新手老手了吧。
作为 Ruby 爱好者,你的电脑上一定少不了 rbenv
或 rvm
,以供你在不同 Ruby 版本中做各种有趣的语言功能实验。然而 rbenv 的安装也会让人遇到烦人的网络问题,对此,我又创建了 rbenv-cn 来完全的解决它(感谢 uzxmx 对 ruby-build 的补丁,不知道您是否在社区里),而不是部分解决它(有些前辈把解决方案代码放在 Github 上,却不在意用户是否能拉下来 Github 的代码)
由于与 rbenv 的不解之缘,我了解了一部分 rbenv 的工作原理,不过也就是知道个大概,噢,用 Bash 实现的代码,真的有人在它能正常工作的时候费心思去阅读它吗?
在 Linux 上待久了,回到 Windows 上工作,觉得最缺的就是它了,于是我想尝试在 Windows 上使用它。我尝试直接在 MSYS2
中使用 rbenv
,经过一番小小的修改,很可惜还是工作不了。然后我突然发现,RubyInstaller 自带的工具 ridk
其实已经实现了 ridk use
来管理多版本。嗯,不错,不过它是以 Ruby 实现的,因此有非常多的缺点,比如,你对 Ruby 版本的切换只能在本次生效。另外,你得自己手动安装很多个版本,对于不了解 RubyInstaller 内部工作的人来说,将会很头疼,比如要不要安装 MSYS2
? 需不需要更新?安装在哪个目录?为什么它的官网给了那么多可下载的链接?(这就是为什么我在 https://rubyinstaller.cn/ 中的下载区域只提供了几个链接的原因,其他那些让高级用户自己去存档里找吧)
我决定实现一个 rbenv
,然而我还是太自信了,我之前的了解 rbenv
原理其实就是读了几篇已有的文章,再加上写 rbenv-cn
的时候与之打交道了一部分而已,其实你随便问一个问题,我就支支吾吾了,比如 rehash
到底是啥?生成 Bash 脚本?生成 Bash 脚本用来干嘛?不知道。
于是我决定耐下心来,研究清楚 rbenv 在 Windows 上的可能性。我搞清楚了大部分 RubyInstaller 的工作原理(这次是真的绝大部分了,毕竟也没有人写它的文章,无从参考)。这个时候我自己就有一套实现 rbenv 的方案了。而且,我一上来想到的就和 rbenv
的实现不同,是利用 Windows 文件系统的 junction
来处理(然而,最后我还是另外实现了 shims)。至于语言,当然是用 Windows 上的原生语言 PowerShell
写,使用 PowerShell
开发的舒适度远远远超过于令人发指,令人气愤的 Zsh
, Bash
. 刚才我们提到的 rbenv 网络问题,我记得在看它的 issues 时,有人就提到了用 Bash 实现太混乱,不好修改代码的问题。
尽管 PowerShell
也有非常多脚本语言存在的弊端,不过代码的清晰度,可维护性,都非常地高了,运行速度也非常快,所以你最终会发现我实现的 shims 仅有 8ms ~ 20ms 的延迟,这个已经可以达到 rbenv
的效果了。
实现效果如何?使用 rbenv install head
来直接体验正在开发的 Ruby-dev 吧!
国内用户优先考虑,我直接将镜像内置了。也就是说,以后几乎不需要再去 https://rubyinstalelr.org 或者 https://rubyinstaller.cn 了。完全用命令行来下来安装管理多 Ruby 吧。
<2023-04-12> 更新:在这里我只提供国内用户使用的方式(通过 Gitee)
# 自定义你想安装到的位置,最好不要有空格,因为没有测试过
$env:RBENV_ROOT = "C:\Ruby-on-Windows"
$s = (iwr -useb "https://gitee.com/RubyMetric/rbenv-for-windows/raw/main/tool/install.ps1")
icm -sc ([scriptblock]::Create($s.Content)) -arg "install", "cn"
然后在你的 $profile
里添加
# rbenv for Windows
$env:RBENV_ROOT = "C:\Ruby-on-Windows"
# 这个变量一定要放在 init 之前
$env:RBENV_USE_MIRROR = "CN" # For Chinese users
& "$env:RBENV_ROOT\rbenv\bin\rbenv.ps1" init
rbenv
更快,因为直接使用 RubyInstaller2
经过测试打包好的二进制,意味着所有人使用经过测试的统一版本,也不需要编译,非常节省时间。scoop
代码,整个框架非常清晰。想了解 rbenv
原理,不如直接来看本项目是怎么实现的。