〜2002年5月中旬〜
missing.hを加えるということはMakefile.inにも依存関係を書かないといけない。 ruby.hでincludeしてるのでruby.hを探してそこに追加すればいいんだが、 チェックする意味で
% touch config.h % gcc -I. -MM *.c >depend
してみた。やはりutil.hとか抜けがあった。
commitは明日だな。
あ、これ途中で切れてますね。 元々 切れ目がわかりにくいのが災いしたか。
#if 0 main #endif
がないとPerlで実行されない。 ま、Rubyの本だからいいのかもしれないが、 そうすると謎のblock_given?は何ということになる。
というわけで"#----------"を区切りにしよう。 ついでに日本語は削除、 無意味な先頭のsemi-colonも削除、 昔のメールアドレスの入ったのは@ruby-lang.orgにしようと思ったら ruby-langは非常に困ったことになるねえ。 ま、いいや。適当に作っとこ。
で jarh.rb を実行してみると、 Regexp::quoteの仕様が変わっていることに気づいた。
% ruby-1.6.7 -e 'p Regexp::quote("J A")' "J\\ A" % ruby-1.6.6 -e 'p Regexp::quote("J A")' "J A"
空白もquoteされるようになった。 jarh.rb も対応しとこう。
1.7.2では
`new': identifier Just another Ruby hacker, needs to be constant (NameError)
となる。空白や記号はやっぱだめだよね。
print Struct.new('Just_another_Ruby_hacker').to_s.split(':')[2].tr('_',' '),','
とするか。
結局
% for i in *.c~lex.c;do gcc -I. -MM -MT "$i:r.@OBJEXT@" $i>>depend ;done
としてみた。 -MMは長い行は\で継続になるんだけど、後で.oを.@OBJEXT@へ置換するとそれが乱れる。 というわけで個々にgccで処理。 *.c~lex.cはlex.c以外の*.cという意味。setopt EXTENDED_GLOBが必要。 こうすると
parse.@OBJEXT@: parse.y ...
から
parse.@OBJEXT@: parse.c ...
になるけど、build directoryを別にしてもsrcdirにparse.cがあれば、 わざわざCWDにparse.cを作らなくなるから、 このほうがいいんじゃないかな。
あ、win32/Makefile.subを忘れてた。 とても面倒なことになってるね。
@OBJEXT@とobjと違う $(srcdir)/がprefixされてる
うーむ。それと
parse.obj: {$(srcdir)}parse.c ...
だけ{}を使っているのも気になる。 これってVPATHみたいな感じでCWDにあればそっちが優先されるとかそういう意味? というか区切りがないのはいいのだろうか? Borlandのmakeを使ってみるとそんな感じだ。優先されるのはsrcdirのほうだけど。
ext/dl/dl.cには
return fp ? rb_dlptr_new(fp, sizeof(FILE), 0) : Qnil;
という記述がある。一方diet libcの<stdio.h>は
typedef struct __stdio_file FILE;
でstruct __stdio_fileは公開されてない。この場合
FILE *fp;
のようにポインタとして常に扱ってメンバ変数へアクセスしなければ問題ない。 でも
sizeof(FILE)
は無理だ。てゆかこれは一体何のため?
更新。
また新たなXML parserができた模様。 そんなに作りたくなるものなのかな。
以前のうささんの日記にNMAKEのリファレンスマニュアルへのURLがあったことを思い出した。 googleで見つけた。{}の件に関しては これ だ。
{directory[;directory...]}dependent
ということか。nmakeはちゃんとCWDを先に見るようだ。 Borland makeでは
foo.obj: {.;$(srcdir)}foo.c ...
とすればCWDが優先されてVPATHと同じこともできるわけだ。
vpath={.;$(srcdir);$(srcdir)\missing} foo.obj: $(vpath)foo.c ...
というのはどうだろう?
直接@OBJEXT@を使うのではなく
OBJEXT = @OBJEXT@
として
foo.$(OBJEXT): foo.c ...
とすればwin32/Makefile.subへの対応は楽になるか? いやどうせ$(srcdir)/とかつけなきゃいけないから変わらないな。
UNIX USERの6月号に
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
というのが載ってた。これはいいかもって、 man zshcompsysすれば書いてあった。こっちはちょっと違っていて
zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}'
となっている。 なるほど。 UNIX USERのほうはわざわざ大文字で始めたんだから大文字だけでいいじゃん的な発想なんだろう。 ところで''は何?
結局使い捨てのフィルタを作った。
% gcc -I. -MM array.c |ruby depend.rb vpath = {$(srcdir);$(srcdir)/missing} OBJEXT = obj array.$(OBJEXT): $(vpath)array.c $(vpath)ruby.h $(vpath)config.h \ $(vpath)defines.h $(vpath)intern.h $(vpath)missing.h $(vpath)util.h \ $(vpath)st.h
てな感じになる。 が、使ってないmsvcrt版のbuild環境を変更してもいいもんだろうか? 個人的にはbuild treeは別に用意して、新たな実験は
% cp $srcdir/foo.c . % vi foo.c % make
という感じでするので、CWDのファイルが対象じゃないのは使いにくそう。 大きなお世話的な話だが。
大きなお世話ついでに。
{$(srcdir)/missing}.c.obj: $(CC) $(CFLAGS) -I. -I$(<D) $(CPPFLAGS) -c -Tc$(<:\=/) {$(srcdir)/win32}.c.obj: $(CC) $(CFLAGS) -I. -I$(<D) $(CPPFLAGS) -c -Tc$(<:\=/) {$(srcdir)}.c.obj: $(CC) $(CFLAGS) -I. -I$(<D) $(CPPFLAGS) -c -Tc$(<:\=/) .c.obj: $(CC) $(CFLAGS) -I. $(CPPFLAGS) -c -Tc$(<:\=/)
は
{$(srcdir);$(srcdir)/win32;$(srcdir)/missing}.c.obj: $(CC) $(CFLAGS) -I. -I$(<D) $(CPPFLAGS) -c -Tc$(<:\=/)
だけでいいのではないだろうか? と思ったらNMAKEでは推論規則の検索パスは1つしか指定できないと 書いてあった 。一方Borland makeのほうはsemi-colonで区切って複数指定できる。 うーむ。うまくいかないもんだ。
あ、最後の推論規則でCWDのファイルが有効になるのか?
失敗してcygwin1.dllをリンクしちゃったようだ。
% i686-pc-cygwin-objdump -p setup.exe |grep 'DLL Name: cygwin' DLL Name: cygwin1.dll
-mno-cygwinをつけ忘れたのか?
gdb-20020411-1をインストールすれば
% RUBY_TCL_DLL=cygtcl83.dll RUBY_TK_DLL=cygtk83.dll ruby -rtk -e0
てな感じで使えるけど、これは簡単じゃないよねえ。
%.: all #{print "Just another Ruby hacker,"} @: . + %; all: @ruby Makefile;
とりあえず
rexmlparser.rbからrequire 'uconv'を外して ::を__へ変換して
1.4.4.1-1としてrepackした。
ソースがいつのまにかパッケージとして含まれるようになってるようだ。 CVSのlocationも/cvs/src/winsup/cinstallから/cvs/cygwin-apps/setupへ変更されてる。
あれ?Date fieldはJSTに変換しないのかな。 ruby-talk MLがJSTに変換されるほうが変なのかもしれないけど、 どこかのtimezoneで揃ってたほうがわかりやすい。
それはですね、 こういう事情 があったりします。 setup.iniのほうはi386-cygwinを1に変更してます。
GNU doschkって最近見かけないけど
% tar tfz soap4r-1_4_4_1.tar.gz |doschk |grep invalid soap4r-1_4_4_1/test/interop/clientSOAP::Lite.rb - invalid character `:' soap4r-1_4_4_1/test/interop/clientSOAP::Lite.rb - invalid character `:'
と例のファイル1つだけのようです > なひさん。
で、どのくらい違うかというと
./miniruby sample/test.rb 137.17s user 9.15s system 99% cpu 2:27.73 total ./miniruby sample/test2.rb 27.05s user 1.36s system 92% cpu 30.574 total
と約5倍なのだ。
C,C++しか使わないのでcoreとg++だけ取ってくる。
% tar xfvz gcc-core-3.1.tar.gz % tar xfvz gcc-g++-3.1.tar.gz % mkdir gcc-3.1/linux; cd gcc-3.1/linux % ../configure --enable-languages=c,c++ --with-system-zlib \ --enable-sjlj-exceptions --enable-threads % make bootstrap
conifugreのオプションはgcc -vで前回指定したものが使えるので楽だ。
更新。
考えてみるとevalに変更したらsystemじゃないよね。
multibyte対応が入ってるようだ。
12. Multi-byte character support has been added, courtesy of IBM Japan.
ChangeLogを見るとIsamu Hasegawaという人なのでgrep 2.5と同じ人だ。
bccwin32へのForwarding DLLを作ってみよう。 ってちょうど一年前の日記にもForwarding DLLについて 書いている じゃん。 bcc32はすべてのsymbolに_がprefixされてるので、 Forwarding DLLの中でその変換もしよう。それにはdef fileの中で
Init_Array=bccwin32_ruby17._Init_Array
とすればいい。あ、これはdllwrapを使うのを前提にしてる。 Borlandのツールの中にはimplibやlibdefがあるが、 def fileからForwarding DLLを作るものはないようだ。
実際はbcc32でmakeするとできるbccwin32_ruby17.defを元に
% ruby -lpe '$_ = $_[1..-1] + "=bccwin32_ruby17." + $_ if $. != 1' \ bccwin32_ruby17.def >tmp.def % dllwrap -mno-cygwin --target=mingw32 --def=tmp.def \ -o mingw32-ruby17 .dll
という感じで作る。CWDにbcc32で作った
ruby.exe, bccwin32_ruby17.dll
とmingw32で作った
etc.so
を用意して早速試す。
% ./ruby -r./etc -e0 0: 127: The specified procedure could not be found. \ - _Init_etc (LoadError) ./etc.so
_Init_etcが見つからないというエラーになる。 ruby-win32 MLで言ってたアンダースコア対応とは実はこれも含まれる。
dln.cをいじる前にすこし実験をしてみよう。 拡張ライブラリfooのrequireはfoo.soをloadしてInit_fooを呼べばいい。 ということはRuby/DLやWin32APIを使っても同じことが可能だ。
require 'Win32API' module Xrequire def self.require x Win32API.new(x + '.so', 'Init_' + File.basename(x), [], 'V').call end end Xrequire.require('./etc') p Etc.getlogin
これを実行してみよう。
% ./ruby -v req.rb ruby 1.7.2 (2002-05-12) [i686-bccwin32] "watanabe"
見事に成功。 つまりbcc32で作ったruby本体からmingw32で作ったetc.soをrequireできたわけだ。
一昨日Ruby/LibGladeのwindows版を作ってくれという英語のメールが来た。 GUI関係は嫌いというか興味はないんだが、移植は好きなのだ。
まずはlinux上で試す。 libglade は libxml , zlibが必要なのでlibxml, libgaldeの順番でインストール。 使ったのは最新と思われる
libxml-1.8.17 libglade-0.17
の2つ。zlibは例の騒ぎで1.14を入れたばかり。
Ruby/LibGladeはRAAに登録されてる。 普通にruby extconf.rbしてmakeするとコンパイルエラーになる。 どうもインストールされる位置が以前とは違うようだ。 --with-gladeで指定すればいいのだが、 extconf.rbの中でgtk-configの代わりにlibglade-configを使うようにしてみた。 これでok。sample/test.rbも動いた。
元々WIN32対応されてるので比較的簡単にmakeできる。 ただその対応はメンテされてないらしく ちょっとした変更 が必要。あとは
% PATH=/usr/local/mingw/bin:$PATH \ NM=i686-pc-cygwin-nm \ LIBS=-lwsock32 \ CFLAGS=-Os CC='i686-pc-cygwin-gcc -mno-cygwin' \ ./configure --target=i386-mingw32 --host=i686-pc-cygwin \ --build=i586-pc-linux-gnu --prefix=/usr/local/mingw % make
でいける。/usr/local/mingw/binにはwin32用の gtk-config が置いてある。glib, gtk, gdkなどのヘッダやライブラリは、 /usr/local/mingwでそのままzip fileを展開して置いてあるだけ。
makefile.mingwというファイルがあるから簡単のように思えるが、その中に
TOP = .. include $(TOP)/win32build/make.mingw
とあり困る。glibのwin32対応にもそんなファイルがあった気もするが、 面倒なのでconfigureすることにした。 こっちも一ヶ所 変更 がある。 あとは
% PATH=/usr/local/mingw/bin:$PATH \ CFLAGS=-Os CC='i686-pc-cygwin-gcc -mno-cygwin' \ ./configure --target=i386-mingw32 --host=i686-pc-cygwin --build=i586-pc-linux-gnu --prefix=/usr/local/mingw % make
でok。
% mkdir mingw; cd mingw % PATH=/usr/local/mingw/bin:$PATH i386-mingw32-ruby ../extconf.rb % make undefined referenceがいっぱい
む。extconf.rbの
system('echo LDFLAGS+=`libglade-config --libs` >> Makefile')
がまずい。ここはLIBSじゃないと。てゆか+=自体本来ならかなりまずいだろう。 とりあえずそれは置いといてもう一度やりなおすと、
undefined reference to `get_value_from_gobject'
だけ残った。なんでしょね、これは? どこにあるかわからんので、
% find /usr/local -name '*.so*' |xargs nm -o |grep get_value_from_gobject
してみた。
/usr/local/lib/ruby/site_ruby/1.6/i386-linux/gtk.so:\ 0001d9b0 T get_value_from_gobject
ということだ。ぐはぁ、gtk.soか。これはやっかいだな。 今のmkfm.rbだと対応してないんだよね。 Windowsではgtk.soのimport libraryを用意しなきゃいけないし、 それなりにexportしてあげないといけない。
またとりあえずだがRuby/GTKのほうのMakefileをいじって、
--def=gtk.defを削除して --output-lib=libruby-gtk.dll.aを追加して
import libraryも作ってみた。 できあがったlibruby-gtk.dll.aをRuby/LibGladeのMakefileの中で指定してやっとできた。 sample/test.rbも無事に動いたんできっと大丈夫なんだろう。
今回は関数だったのでうまくいったが、 変数だとEXTERNだけでは対処できないので非常に困ったことになる。 たとえばRuby/GNOMEとか。 ってこれがWin32で作れるかどうかは別の問題ではあるが。
Emacsにはviperのようなvi modeがあるが、 これはvimのemacs modeだそうだ。 viperのinsert modeでたまにC-fだのC-eだの使ってるし、 vimのほうでもたまに間違えたりするのでいいかもしれない。 おお、C-x 2もC-x oもできるね。
timelocalだと
% perl -MTime::Local -e 'timelocal(0, 0, 0, 32, 3, 2002)' Day '32' out of range 1..31 at -e line 1
のように0や32以上を指定したらdieしてしまいます。 つまりeval{}して$@の値を見る必要があります。
というわけで--export-allしたRuby/GTKをrepack。
というわけでできたのだ。 libxmlとzlibとlibglade自体はstaticにlinkされてるので、 Ruby/GTKが動く環境なら動くはず。 メールも出しとくか。
それはwin32ole.libが
C:\borland\bcc55\lib\psdk\win32ole.lib
にあるから(C:はインストールしたドライブレターに読み換えるべし)。 解決するにはmkmf.rbでpsdk\をprefixした名前も試すとかあると思うけど、 bcc32.cfgとilink32.cfgに
-LC:\borland\bcc55\lib\psdk
を追加するのが一番いいと思います。Rubyだけの問題じゃない気がするし。 てゆか、BCC32のインストールマニュアルに書いといて欲しいなあ。