古い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_member
をrb_group_member
にリネームすることで解決できた。歴史的にはこの変更はr13240とr26682の組み合わせといえる。
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の一部、r10392、r11594をbackportして、srcdir
の解釈を正しくするよう少し改造を加えることで解決できた。
成果物
現時点での成果物をqnighy/ruby-1.9.2p0とqnighy/ruby-1.8.1に置いてある。