SyntaxHighlighter

2012年11月4日日曜日

ocra による Ruby の EXE 化

ocra による Ruby の EXE 化

近頃はずっと仕事が忙しく、mruby を見たり遊んだりもまったくできないので、業務で使わせていただいている ocra について、主に社内用にメモしておきます。

JsMruby やその他のリクエストに対応できていなくてごめんなさい。

以前にも書きましたが、Ruby 1.8 のときに愛用させていただいていた Exerb は、現在主流の Ruby 1.9 には対応していないようです。
そのため、現在は Ruby 1.9 に対応している ocra を使わせていただいています。
今回はその ocra についてのメモです。
もっと詳細は、 GitHub の ocra のページを参照してください。

Ruby の EXE 化

ocra では、Ruby のスクリプトを Ruby 本体やライブラリとともに、一つの EXE にまとめてくれます。
実行する際は、できた EXE ファイルを、実行したい PC に置くだけで実行することができます。

EXE 化する際には、一度 ocra がそのスクリプトを実行し、スクリプトファイル中で require などで読み込まれたファイルやライブラリを、圧縮して一つのファイルにまとめてくれます。

逆に実行時には、スクリプトファイルや Ruby 本体やライブラリを Temp ディレクトリに展開してから実行されます。

ちなみに、Exerb では require を専用のものに置き換え、ファイルが require されたときに、EXE ファイル本体内に格納されているスクリプトファイルを実行するようになっています。

ocra で定義される定数や環境変数

ocra のように、コンパイル時に一度スクリプトを実行してみるようなものでは、以下の三つの状態をスクリプト内で区別したいときがよくあると思います。

  1. 通常の Ruby で実行されている
  2. ocra でコンパイルされている間に、 require をチェックするために実行されている
  3. ocra で EXE 化された後に、その EXE ファイル経由で実行されている

ocra では、この条件を簡単に見切るために以下の定数や環境変数を参照できます。

定数 Ocra
ocra でコンパイル中のみ定義されています。 EXE ファイル実行中は定義されていません。
そのため、例えば以下のように書けば、コンパイル中のみコードを実行させることができます。
環境変数 OCRA_EXECUTABLE
ocra によって生成された EXE ファイルを実行しているときのみ、実行中の EXE ファイルのフルパスが "\" 区切りで設定されます。
そのため、例えば以下のように書けば、 EXE ファイル実行中のみコードを実行することができます。

各環境での動作

ここでは以下のようなスクリプトを実行し、それらの値やカレントディレクトリなどの環境をまとめておきます。

通常の実行時

このスクリプトを C:/work/test/test.rb として c:/work/test で実行すると、以下のようになります。

EXE 化する時

ocra で EXE 化する場合、ocra によってスクリプトが実行され、その際に require で読み込まれたファイルやライブラリがチェックされます。
この require されるファイルチェックの場合には、以下のようになります。

このように、EXE 化する時には Ocra という定数が定義されます。
通常のスクリプトは、EXE 化する際には本処理を実行したくないことが多いので、たいていは以下のように書くことになると思います。

EXE 実行時

できた test.exe を実行すると、以下のようになります。

このように、EXE 実行時には OCRA_EXECUTABLE という環境変数が、 EXE ファイルのフルパスとして定義されます。

また、上で書いたように ocra はスクリプトファイルなどを Temp ディレクトリに展開した状態で実行しますが、 __FILE__$0 を見ると、確かに Temp ディレクトリの中に展開されていることが分かります。

EXE ファイルへの他のファイルの同梱

ocra は require で読み込んだファイルを自動で検出して EXE ファイルに含めてくれますが、明示的にスクリプトファイルやその他のファイルを含めることもできます。

やり方は簡単で、 EXE を作るときに ocra.bat に渡す引数に加えてやればよいだけです。

こうすると、 EXE 実行時には、 7za.exesample.rb と同じディレクトリに展開されます。
つまり、 sample.rb 内であれば File.dirname(__FILE__) + "/7za.exe" でパスを得ることができるので、別の EXE を同梱して Ruby スクリプト実行時に参照することも可能です。

0 件のコメント:

コメントを投稿