古いRubyをビルドする

動機

現時点でRubyの最新版は2.4, サポートされているのは2.2までで、2.1以前はメンテナンス対象外である。そのような古いバージョンを動かすのは決してよいことではない。

しかし実のところ、現在でも多くのWindowsマシンで、Ruby1.8.1とRuby1.9.2p0が動作している。具体的には、RPGツクールXP, RPGツクールVXというソフトウェアで作られたゲームはRuby1.8.1の処理系とともに配布されており、RPGツクールVX Aceというソフトウェアで作られたゲームはRuby1.9.2p0の処理系とともに配布されている。既に多くのゲームが世に送り出されているのみならず、これらのいずれのツールも、未だにそれぞれ根強い人気があり、今でも多くの名作が作られている。「ふりーむ」というサイトで「RPGツクール XP」と検索した結果からも、その人気を伺い知ることができる。

そういった事情から筆者はRuby1.8.1とRuby1.9.2p0に強い興味があり、ビルドを試みたところ、いくつかの問題があった。

前提

とりあえず、Ubuntu 16.04 x86_64でのビルドを想定している。アーキテクチャを拡大すれば、より多くの問題が顕在化するかもしれない。

Ruby1.9.2p0の問題

Ruby1.9.2p0を現代の環境でビルドすると、以下の問題があった。

  • 継続・コルーチン処理が最適化で壊れる
  • bisonでコンパイルエラーになる

継続・コルーチン処理が最適化で壊れる

Fiberやcall/ccの処理はスタックのコピーによって実現されているが、コンパイラによってはspレジスタの最適化によりこの処理が壊れてしまい、処理系がサイレントに死ぬことがある。これはr34278をbackportすることで解決できた。

bisonでコンパイルエラーになる

pure-parser周りの仕様変更により新しめのbisonでコンパイルできない。これはr42282をbackportすることで解決できた。

Ruby1.8.1の問題

Ruby1.8.1を現代の環境でビルドすると、以下の問題があった。

  • group_memberの衝突
  • bisonとの組み合わせでGCが壊れる
  • autoconf2.6x系列でビルドできない

group_memberの衝突

file.cで定義されているgroup_memberと、Cライブラリのgroup_memberが衝突する。これはgroup_memberrb_group_memberにリネームすることで解決できた。歴史的にはこの変更はr13240r26682の組み合わせといえる。

bisonとの組み合わせでGCが壊れる

ある程度新しいbisonはLRのセマンティックバリューのスタックをヒープで管理することがあるが、この場合Ruby1.8.1だとヒープ上のセマンティックバリューのマーク漏れが発生する。ノードのnd_fileが汚染された結果、次のGCのタイミングでGCのフリーノードの直前のRVALUEの最後の1バイトが破壊され、その1バイトがノードからのポインタになっていた場合に領域外参照でサイレントに死ぬ。これはr9355, r9405, r9416, r9382, r9639をbackportすることで解決できた。

autoconf2.6x系列でビルドできない

いくつかの複合的な問題からautoconf2.6系列でビルドできない。これはr10189の一部、r10392r11594をbackportして、srcdirの解釈を正しくするよう少し改造を加えることで解決できた。

成果物

現時点での成果物をqnighy/ruby-1.9.2p0qnighy/ruby-1.8.1に置いてある。