irpackとかいうのを作ってひそかにリリースしました。
IronRubyでスクリプトをexeにまとめるやつです。言ってしまえばIronRuby版Exerb。
rubygems.orgに置いてあるのでgemで入ります…が、IronRubyで動かさないといけないのでIronRubyのgemで入れましょう。バッチファイルはigem.batとかなってたはず。
あとはまとめたいスクリプトを指定するとまとまります。
まとめ込むスクリプトは当然IronRubyで動くやつじゃないとだめですよ。
irpack main.rb
これでmain.exeが出来るんだっけかな?でもこの方法はやばい問題があるので非推奨(後述)。
irpack -d matome -o dekita.exe matome/main.rb
こうするとmatomeディレクトリの中身を全部exeに放り込みます。で、matome/main.rbから実行してくれます。出力ファイルはdekita.exe。
完全に失敗したんですけど、まとめこむディレクトリ指定を省略にしちゃうと指定したrbファイルのあるディレクトリをまとめようとするのね。なのでマイドキュメント直下のtest.rbとかをまとめてみよーとかやると大変なことになります。-dは必ず指定しましょう。今度直す。
ああ、あと、標準ライブラリとかのまとめこみは勝手にやらないので、手動でコピってからまとめてあげてください。これもそのうちなんとかしたい。
.NET3.5版のIronRubyでirpackをすると.NET3.5で動くexeが、.NET4版でやると.NET4で動くexeが出来上がります。 .NET3.5で動くやつはmono 2.6.7でも動くのを確認済み。もちろんmonoで作ったexeも.NETで動くよ。
他のオプションとしては、コンソールを出さないGUIアプリを作れる-w、まとめこんだファイルを圧縮して実行ファイルを小さくする--compress、IronRubyのランタイムを埋め込まない--no-stdlibなんかがあります。
そうそう、アイコンを指定するオプションは無いんだけど、まとめこむディレクトリ内に.icoファイルを入れておくと勝手にそれを使うよ。複数あったらどれになるかは知らね。
圧縮機能は所詮zipなのであとでzipで固めるならやる意味ないと思う。実行時の展開遅くなるし。
ランタイムは埋め込まない方が実はおすすめで、exeと同じディレクトリにIronRuby関係のdll置いてngenでAOTコンパイルしてあげてください。インストールしないから自動的にngenするタイミングがないとかngenってなんですかって人は気にせず埋め込んじゃってください。
中身どうなってるかは、ソースを頑張ってgithubに上げたのでそっち参照。rbファイルほぼ1つで出来てます。中身半分C#じゃねーかって?うるさいだまれ。
動きとしては、中身zipなパッケージという機能が.NETにあるんでそれにファイルぶち込んでexeのリソースとしてくっつける。exeはパッケージ開いて中からIronRubyのdllなんぞを拾ってロード、IronRubyのAPI*1は仮想ファイルシステムみたいなのを実装できるようになってるので、パッケージ内からもファイル読めるようにしてあげた。というだけ。
簡単ですね。これだけなのでrbファイル1つでできちゃう。 .NETのいいところはランタイムにC#コンパイラが内蔵ってこと。さっくりとdllとかexeが生成できる。変な癖があるけど。monoを見なかったことにすればC++もランタイムにコンパイルできちゃうよ!
今後改良されたらいい点としては、exerbのexyみたいなレシピファイルを使うようにするのと、mkexyみたいに必要なファイルを列挙する機能が欲しいなぁ。あとIronRubyのdllだけじゃなくてdllは全部埋め込まないようにもなるとngenで嬉しい。
あと.NET4版で.NET3.5用のバイナリ作れる機能もあったらちょっといいな。.NET3.5版のIronRubyランタイムをどこから拾ってくるのかだけが問題なんだが。
*1 というかDLR