ocraの動作と、エラーの原因を考えてみる

ocraはRubyスクリプトをexeするソフトだ。
Rubyインタプリタと、使うRubyのソース、ライブラリをまとめてexeの中に取り込み、実行時にはテンポラリのディレクトリにそれを展開して動かす。
動作原理は(たぶん)こんな感じ。


(a-1)使うスクリプトと拡張ライブラリを検索
(a-2)それらとRubyインタプリタをまとめて、必要なら圧縮
(a-3)stub.exeもしくはstubw.exeの後ろにくっつけて出力
(b-1)exeを実行すると、stub.exeもしくはstubw.exeの後ろにくっついているファイルをテンポラリディレクトリに展開
(b-2)テンポラリ内のスクリプトを、テンポラリ内のRubyインタプリタで実行


テンポラリの名前に日本語を含まないようにしてDXRubyスターターキットのdevelopment.exeを実行すると、テンポラリにseb??.tmpのような名前のディレクトリが作成されて、その中にbinとlibとsrcができる。
終了すると消えるから、実行中にそれをコピーして置く。
binにはインタプリタのexeとコアdll、libにはエンコードまわりの拡張ライブラリとdxruby.soとrubygems.rb、srcにはdevelopment.rbが展開される。
exeに組み込まれているのはdevelopment.rbだから、このインタプリタでこれを実行しているわけだ。


テンポラリ内のインタプリタは何もいじられていないし、development.rbも細工されたものではない。
そのまま入っている感じだ。
元のdevelopment.exeと同じディレクトリにあるmain.rbが、パス指定なしで読み込みできるわけだから、カレントディレクトリは移動せず、起動時にフルパスでインタプリタとdevelopment.rbを指定しているのかもしれない。
先日のエラーの原因はそのあたりにありそうだ。


コピーした先のディレクトリ名を「あ」って日本語名に変更して、インタプリタを起動してみよう。

D:\tmp>あ\bin\ruby.exe
:3:in `require': incompatible character encodings: Windows-31J
and ASCII-8BIT (Encoding::CompatibilityError)
from :3:in `block in '
from :1:in `each'
from :1:in `'

D:\tmp>

同じエラーになった。
rubyw.exeを動かしてもエラー出力が無いから動いたかどうかわからない。
main.rbとcharactor.pngをテンポラリのディレクトリにコピーしてきて、main.rbを呼び出してみても、やっぱり動かない。
これらのファイルを「あ」の下にコピーしてから実行してみる。

D:\tmp\あ>bin\ruby.exe main.rb
:3:in `require': incompatible character encodings: Windows-31J
and ASCII-8BIT (Encoding::CompatibilityError)
from :3:in `block in '
from :1:in `each'
from :1:in `'

D:\tmp\あ>bin\rubyw.exe main.rb

D:\tmp\あ>

ログではわからないが、rubyw.exeのほうは動いた。
ちなみに環境変数tmpはd:\tmpに設定しているので日本語名は入っていない。


この結果から推測できることは、
ruby.exeとrubyw.exeで動きが違う
ruby.exeはインタプリタ絶対パスに日本語が入ってるだけでNGっぽい
・rubyw.exeは読み込むファイルの相対パスに日本語が入っているとNGっぽい


んじゃあ、ってことで、arton氏のサイトからRuby1.9.1を落としてきてインストールするときにディレクトリを日本語混じりにしたら、インストール中にエラーが出て完了しない。
日本語を含めないとちゃんとインストールできた。
もひとつ実験ということで、インストール済みのRuby1.9.1のbinディレクトリを日本語名に変えてみたところ、これは正常に実行できる。
あれ?


んー。
再現性と現象を確定できたと思ったのにな。

(2009/07/02追記)Ruby1.9.2開発バージョンで修正されたことを確認。