JRubyで作ったスクリプトをwindowsユーザに提供する方法

良いスクリプトができたとき、その感動を他の人にも共有したくなる時があります。
ですが、Rubyスクリプトを他の人に実行してもらう時困ったことが起こります。
それは、Rubyを実行する環境が、他の人のデスクトップで整っていないことです。
これは致命的です。
まぁWindows用のCRubyをインストールしてもらえばいいんですが、頑固な人もいてなかなか受け入れてくれなかったり。。
で、思いついたのがJRubyです。Javaランタイムなら大抵の場合(うちでは)入っているようです。
よし!JRubyで提供だ。

JRubyで提供する方法(+バッチファイル)

sample.rbというスクリプトを実行する環境を用意してみます。

まずは、JRubyを用意します。
JRubyのパッケージはいろいろ揃っているようです。exeとかzipとか
その中で.jarを選択します。
http://jruby.org/download
jruby-complete-1.7.0.preview1.jar

このパッケージは万能でRuby標準付属ライブラリはrequireで読み込むことができます。
たとえば'fileutil'とか'pp'とか'erb'とか

次にwindowsで実行するためのバッチファイルの作成です。
以下のように作ってみました。ファイル名はrun.batにします。

@echo off
cd /d %~dp0
java -jar jruby-complete.jar sample.rb %1 %2 %3

準備okです。
ファイル構成は、

./sample_app
  |-- run.bat
  |-- jruby-complete.jar
  `-- sample.rb

実行は、run.batをダブルクリックするだけです。

gemのライブラリを使っているスクリプトを配布する場合(+バッチファイル)

gem installを使ってインストールしたライブラリを使っているスクリプトを提供する場合は、gem installパッケージも一緒に配布する必要があります。
ですが、そのままgem以下を提供するとファイルがいっぱいあるので好まれないかもしれません。
そこで提供したいgemライブラリをjarに固めてしまいます。
方法は以下のとおりです。

mkdir gemjar
# gem installで同封したいパッケージを落とす
java -jar jruby-complete.jar -S gem install -i ./gemjar rmagick --no-rdoc --no-ri

#jarに固める
jar cf jruby-extensions.jar -C gemjar .
rm -rf gemjar

あとは、バッチファイルの作成です。
バッチファイルの中で今回作成したjruby-exteinsions.jarをライブラリとして読み込むようにします。

@echo off
cd /d %~dp0
java -jar jruby-complete.jar -I./ -rjruby-extensions.jar sample.rb %1 %2 %3

ファイル構成は、こんなかんじになります。

./sample_app
  |-- run.bat
  |-- jruby-complete.jar
  |-- jruby-extensions.jar    <=追加したgemライブラリ
  `-- sample.rb

これで動くはず。
これならば、比較的受け入れられやすいのではないでしょうか。

rawrでexeを作る方法

それでもexeじゃなきゃダメと言われてしまえば、しようがない最後の方法。
どうやらrawrというライブラリを使うことでexeが作成できてしまうようです。

とりあえずライブラリ化したいスクリプトをmain.rbという名前で用意しておきます。

rawrインストール

まずは準備です。

% jruby -S gem install rawr --source http://gems.neurogami.com

このときバージョンは1.6.3でした。そのままgem installすると1.4.5でした。

で1点問題があって、このツールではftoolsという古いライブラリを使っているようなのですが最新のJRuby(1.7.preview)ではもうすでに削除されていて実行しようとすると次のメッセージでErrorとなります。

rake aborted!
no such file to load -- ftools

(See full trace by running task with --trace)

でしようがないのでライブラリをいじることにします。(ftools→fileutils)
JRubyのインストール先、
C:\xxx\jruby-1.7.0.preview1\lib\ruby\gems\shared\gems\rawr-1.4.5\lib\zip\zip.rb
を開きます。
修正箇所は2箇所

zip.rb2行目あたりの
require 'ftools'

require 'fileutils'

zip.rb1570行目あたり
File.move(tmpFilename, name)

FileUtils.move(tmpFilename, name)

これで準備OK。

パッケージ作成の準備
% mkdir sample            <= 適当なディレクトリを作成
% cd sample
% jruby -S rawr install

すると、sampleディレクトリ以下に必要なファイルが自動生成されます。

./sample
  |-- lib
  |-- src
  |-- build_confiuration.rb
  `-- Rakefile

rawr-1.4.5では、jruby-complete.jarというJRuby本体も必要に応じてダウンロードしてくれるようです。lib/java/jruby-complete.jarに勝手に置かれます。

次にbuild_configuration.rbをいじります。とりあえず必要最小限で、

c.project_name = "sample"
c.output_dir = "package"
c.main_ruby_file = "main"
c.target_jvm_version = 1.7

で、最後にexe化したいスクリプト(main.rb)を./sample/srcに置きます。

パッケージ作成

jar化なら次を実行してみます。

% jruby -S rake rawr:jar
% java -jar package/jar/sample.jar

おぉ!実行できた。

exe化なら次を実行します。

% jruby -S rawr:bundle:exe

すると、sample/package/windows/sample.exe が生成されます。
実行して起動できれば、達成です。

まとめ

少し手間はかかりますが他の人に使ってもらいたいアプリを提供するならばこちらもいろいろ使ってもらうための工夫は必要だと思います。exe化までやれば文句ないでしょう。
とりあえず、満足です。