[last updated:2005/03/30] [since:2003/11/09]
もともとは「Ruby 1.8.0をPlan9で動かす」という題名でしたが、 Ruby 1.8.1にも対応したので、変更しました。
Plan9の Additional Software を見ると、PerlとかPythonとかはあるのに、 Rubyはありません。 ということで、RubyをPlan9でコンパイルしてみることにしました。 Plan9のAPE環境でコンパイル出来るようにすることを目指しました。
成果物を以下に置いておきます。 使用条件は、もとのRubyと同じということで(手抜き)。 このアーカイブのソースコードは、他のプラットフォームではコンパイルできない (かもしれない)形に改変されています。 単にmakeしてmake testを通しただけなので、バグが残っているかもしれません。
cpu% CFLAGS='-D_BSD_EXTENSION -D_LIMITS_EXTENSION' cpu% ./configure --prefix'='$home --bindir'='$home/bin/$objtype --libdir'='$home/lib --build'='i386
Ruby 1.8.1では、--with-default-kcode=utf8を指定すると、make testで失敗する ようです。
基本的には、1.8.0と同じ改変がなされていますが、幾つか異なる部分もあるため、 以下に変更をリストアップします。
浮動小数点型の取扱いに対応。 ruby_init関数に、
setfcr(FPRNR|FPPEXT);
を追加。 ruby_init関数の前に、
#define _PLAN9_SOURCE 1 #include <lib9.h> #include <float.h>
を追加。
以下の定義を追加。
#define READ_DATA_PENDING(fp) ((fp)->wp - (fp)->rp > 0) #define READ_DATA_PENDING_COUNT(fp) ((fp)->wp - (fp)->rp) #define READ_DATA_PENDING_PTR(fp) ((fp)->rp)
fchownがないので、chownを使う。
chown(fn, st.st_uid, st.st_gid);
を使う。
NUM2LLの定義を、
#define NUM2LL(x) rb_num2ll((VALUE)x)
にする。
uid_tとgid_tのサイズの問題に対応。
#include "config.h"
の直後で、
#undef uid_t #undef gid_t
する。
Plan9のisInfを用いて作成する。
#include <stdio.h> int isinf(double n) { return isInf(n, 1) || isInf(n, -1); }
Plan9のisNaNを用いて作成する。
#include <stdio.h> int isnan(double n) { return isNaN(n); }
Plan9ではdlopenなどが無い。
option nodynamic
の行頭の#を外す。
以下のライブラリを有効にする。
他は、環境の違いのためコンパイル不可。
以下の型を追加。(ここでは#defineを使っておく)
#define u_char unsigned char #define u_short unsigned short #define u_long unsigned long
manはインストールしないでおく。
Dir.glob("*.[1-9]") do |mdoc| ... end
の部分を、=begin ... =end でコメントにする。
以下に、行なった改変についてのメモを記載しておきます。
Plan9でコンパイルするには、_BSD_EXTENSIONと_LIMITS_EXTENSIONの#defineが必要。
echo > confdefs.h
している近辺に、
cat >> confdefs.h <<_ACEOF #define _BSD_EXTENSION 1 #define _LIMITS_EXTENSION 1 _ACEOF
を追加する。
→これではまずいようなので(bigdecimalコンパイルで発覚)、 configureのときに
CFLAGS='-D_BSD_EXTENSION -D_LIMITS_EXTENSION'
を環境変数として設定しておく。
オプションとして、最低でも
--build=i386
が必要。
NUM2LLの定義を、
#define NUM2LL(x) rb_num2ll((VALUE)x)
にする。
Plan9ではdlopenなどが無い。
option nodynamic
の行頭の#を外す。
Plan9のisInfを用いて作成する。
#include <stdio.h> int isinf(double n) { return isInf(n, 1) || isInf(n, -1); }
gc.cについて、GCの実行を殺してみる。
まだ、「0/0!=NaN」およびreadでのIOErrorの問題がある。
Plan9の8c(386コンパイラ)には、NaNの取扱に関するバグがあるような気配である。
readの問題は調査中。io.cのremain_sizeでこけている。st.st_sizeやtellの 結果がおかしいようである。
stat構造体について、本来のsizeof(struct stat)は32であるが、 #include "ruby.h"をすると(-L. -lruby-staticも必要)、 sizeof(struct stat)が36になってしまう。
あとは、Marshalについてnot okがある。(浮動小数点数に誤差が出る)
save_mantissaの処理を簡単なプログラムで確かめていくと、
d = modf(ldexp(d, MANT_BITS),&n); m = (unsigned long)n;
にて、mが0x80000000になってしまっている。(本当は、0xce560000)
以上でmake testは通った。
以下の型を追加。(ここでは#defineを使っておく)
#define u_char unsigned char #define u_short unsigned short #define u_long unsigned long
manはインストールしないでおく。
Dir.glob("*.[1-9]") do |mdoc| ... end
の部分を、=begin ... =end でコメントにする。
--prefix=$home --bindir=$home/bin/$objtype --libdir=$home/lib --with-default-kcode=utf8 --build=i386
以下の定義を追加。
#define READ_DATA_PENDING(fp) ((fp)->wp - (fp)->rp > 0) #define READ_DATA_PENDING_COUNT(fp) ((fp)->wp - (fp)->rp) #define READ_DATA_PENDING_PTR(fp) ((fp)->rp)