〜2003年2月中旬〜
mswin32とmingw32のrbconfig.rbを見比べるとprefix関係に違いはない。 win32/Makefile.subをよく見ると
!if !defined(prefix) prefix = /usr !endif !if !defined(DESTDIR) DESTDIR = $(prefix) !endif
となっていた。これっていいのかなあ。 なんか/usr/usrになりそうな気がしないでもないんだけど。
それはそれとしてmingw32も
% make prefix=c:/mingw
とでもしとけばいいわけだ。でも
curses.o(.text+0x7a4):curses.c: undefined reference to `resizeterm' curses.o(.text+0x1a5a):curses.c: undefined reference to `wresize'
となってしまう。ext/curses/mkmf.logを見るとしっかり-L/libが残ってた。 checkはCygwinのほうを見てしまったわけか。 mswin32のほうも確認してみると-libpath:/libがあった。 つまりtry_fooもprefix対応が必要だ。
instruby.rbとext/extmk.rbに--prefixオプションを追加すればよさそう。 あとはCONFIG['prefix']を書き換えて、lib/mkmf.rbのxsystem, xpopenでやってる
Config.expand(command)
を
command = Config.expand(command.dup, CONFIG.dup)
とすればいい感じではある。 これでいちいちconfigureし直さなくてもmakeの引数でprefixを変更できる(たぶん)。 が、dupだらけになってきたので、そろそろ引数を書き換えないConfig.expandが欲しいね。 たぶんlib/mkmf.rbの中だけだからここで定義しようかな。
御要望にお応えして、Cygwinだけパッケージ化してみる。
OpenSSL 0.9.6hのMinGW版バイナリを探すのが面倒で、 ソースから作る。Configureを見るとMingw32という文字列が見えるので、
% ./Configure Mingw32
と実行するとMakefile.sslができた。CCを書き換えて、 include pathの足りないとこを足せば一応ライブラリはできる。 apps, test, toolsは要らないので作らなくてもいい。
あとは
% make install INSTALL_PREFIX=$HOME/openssl-0.9.6h
としてlibとincludeを内容を/usr/local/mingwへコピーすれば使える。
NDBM互換インタフェースが追加されたので、Rubyでも簡単に試せそうだ。 でもこの互換APIでは、データサイズが8KBに制限されるとこが惜しい。
vim6で=を使うといけるけど、いけないのもある。 たとえば =G とすれば一気にshiftwidthでindentされる。 が、たいていはうまくいかないのでVでクラスとか選んでちまちま変換したりする。
CONFIG['libdir']が書き換わってしまうのは、 Config.expandは再帰的に自分を呼び出しているけどそのときはdupしてないからだった。 やはり書き換えないversionが必要になることがわかった。 しかもlib/mkmf.rbの中では結局のところ全部書き換えたらまずいものばかりだ。 というわけで作る。
ところでrbconfig.rbにはCONFIGとMAKEFILE_CONFIGがある。 CONFIGはすべて展開された形で、 MAKEFILE_CONFIGはその名のとおりmakeが認識できる変数を参照するような形のままになっている。 Makefileが展開された形で作られたら、prefix=と指定しても意味がないからだ。 rbconfig.rbの見た目ではCONFIGとMAKEFILE_CONFIGは逆のような感じだが、 歴史的事情により現在のような構成になっている。
こうすれば引数の中身を書き換えることはない。
def expand(val, config = CONFIG) config = config.dup val.gsub(/\$\$|\$\(([^()]+)\)|\$\{([^{}]+)\}/) do |var| if !(v = $1 || $2) '$' elsif key = config[v] config[v] = false config[v] = expand(key, config) else var end end end
でも"$(srcdir)"ってのがあったのだ。 ほんと奥が深い。ここはせっかくだからFile.dirname($0)を使おう。
起きたら15:00だった。
NDBM互換APIにデータサイズの制限がなくなり、Cygwin対応も入った。 でも、DLL対応はしてないので、必ず静的にリンクされる。
ふだんはbinary mountしか使わないけど、 text mountのテストをしたいときはどこかのディレクトリだけをtext mountするといい。
% mkdir ~/text % mount -u -t $(cygpath -w ~/text) ~/text % cd ~/text % echo foo > foo % od -c foo 0000000 f o o \r \n 0000005
Rubyは今日から常にbinmodeになったのでこうなる。
% ruby -e 'open("foo", "w").print "foo\n"' % od -c foo 0000000 f o o \n 0000004
_fmodeの件はextern int _fmode;という宣言からして、 DLLの中では無意味だということに気づくべきであった。 最初は_fmodeにこだわって
#include <windows.h> #include <sys/cygwin.h> ... extern __declspec(dllimport) struct per_process __cygwin_user_data; #define user_data (&__cygwin_user_data) #define __fmode (*(user_data->fmode_ptr)) ... __fmode &= ~O_TEXT; __fmode |= O_BINARY;
などと考えていたが、 これはstruct per_processの構造が変わるとバイナリ互換の問題があるから使いたくない。
とりあえずprefix対応は今週中にまとめよう。
例のCPPの定義は互換性を考えて残すべきかなあ。 %sがわかりにくいからやめてしまったわけだけど。 どうせなら1.6もいじってしまいたい気もしないでもない。
PragProgRubyがインストールされてる状態でMinGWのコンパイラを使い拡張ライブラリを作りたいというわけ? mkmf.rbはRUBY_PLATFORMとrbconfig.rbに従っていろいろ場合分けされるので、 これらを書き換えてやる必要がある。たとえばRUBY_PLATFORMは
class Object remove_const :RUBY_PLATFORM RUBY_PLATFORM = 'i386-mingw32' end
とすればmkmf.rbは騙せる。 $LOAD_LIBRARYを書き換えればmingw32用のrbconfig.rbをロードできるし
$LOAD_LIBRARY.gsub!(/mswin32/, "mingw32")
以上のようなことをするfake.rbをsite_rubyにでもおいて、 c:/Ruby/lib/1.6/i386-mingw32/rbconfig.rbを用意すれば
% ruby -rfake extconf.rb
と実行できるはずだ。
あ、そういうパッケージを作ればいいわけか。
CygwinでもちゃんとDLLとインポートライブラリを作るようになった。 ってどう考えてもこの日記を読んでいるとしか思えない。 ちゃんとメールで報告しとくべきだったか。
更新。
なんか嘘ばかり書いてるなあ。そもそも$LOAD_LIBRARYじゃないし。 配列だから
$LOAD_PATH.each do |x| x.gsub!(/mswin32/, "mingw32") end
という感じだ。
残りはrbconfig.rbだけど、 そのままi386-mingw32のをコピーするのも芸がないので、
require 'i586-mswin32/rbconfig'
として差分だけ書き換えるのはどうだろう? これなら1.6/1.8のどちらにも対応できそうだ。