超簡単に Ruby プログラムを exe にする新しい方式 (構想)

exerb は 1.9 に対応してないし、いろいろオーバースペックだと思う。ocra はテンポラリフォルダに展開して実行するのがダサすぎて論外。(参考)
ということで、すごくシンプルに Ruby プログラムを exe 化する方式を考えてみました。

デモ

# t.rb
puts "test!"

これを exe にしたい。こうします。

C:\Ruby>copy /B ruby.exe+t.rb t.exe
ruby.exe
t.rb
        1 個のファイルをコピーしました。

実行する。

C:\Ruby>t
test!

動いた!
つまり、インタプリタスクリプトをファイル結合するだけで exe にできてしまいます。

実装

Rubyパッチをあててビルドする必要があります。やってることは自己解凍書庫と同じ感じです。

  1. ruby.exe のファイルサイズをバイナリリソースとして ruby.exe 自身に持たせておく。
  2. ruby.exe は起動時に、ファイルサイズが大きくなってるかチェックする。なっていなかったら通常の ruby.exe として動作する。
  3. 大きくなってたら、自分自身をファイルとして開いて増分まで seek してスクリプトとして実行する。

このサイトが参考になりました。
ちなみにパッチは Ubuntu でクロスコンパイルしか試したことがないので、mswin とかではビルドできない予感がすごくします。

制限

  • 複数ファイルの埋め込みには対応してません。
  • 拡張ライブラリの埋め込みもできません。
  • プリコンパイルや圧縮や難読化は自分でやってください。
  • アイコンとかバージョン情報変えたい人は Resource Hacker とか使えばいいと思います。ただし RUBY_PAYLOAD_OFFSET に 32bit リトルエンディアンで ruby.exe のファイルサイズを更新してください。

今後の展望

Ruby 側ではこのくらいシンプルなプリミティブ機能だけを提供して、複数ファイル対応とかの作り込みは gem でやるといいと思うんですよね。coverage.so と simplecov のような関係がいい。
これ、ruby 本体にコミットできるかなあ。無理か。

おまけ: Ubuntu で mingw32 版 ruby をクロスコンパイルする方法

$ apt-get install mingw32
$ ./configure --build=x86_64-unknown-linux-gnu --host=i586-mingw32msvc
$ make

これだけで ruby.exe や rubyw.exe ができた。思ったより簡単だなあ。
ただし msvcrt-ruby200.dll がセットであることに注意。嫌なら configure に --disable-shared を渡せばいい。