14
9

More than 1 year has passed since last update.

Neri を使って Ruby スクリプトを実行ファイル(.exe)に変換して配布する

Posted at

Ruby で書かれたスクリプトを Ruby の入っていない Windows 環境に向けて配布するツールとしては、OCRA という gem が有名です。

しかし OCRA にはいくつかの欠点1があったため、Neri という gem を作成しました。このたび ver 1.0 を公開し、今までより多くの Ruby スクリプトを実行ファイルに変換できるようになったので、Neri を使って Ruby スクリプトを実行ファイルに変換するチュートリアルを書いてみたいと思います。

Neri の目的

Neri は、ちょっとした CUI スクリプトや、あるいは DXRubyGosu を用いたゲーム、LibUI(あるいはそのラッパーである Glimmer DSL for LibUI)を用いた GUI プログラムなどを実行ファイルに変換し、Ruby の無い Windows 環境でも容易に動作させられるようにすることが目的です。

多くのライブラリを用いた大規模で複雑なプログラム(例えば Rails)を実行ファイル化することには向かないので、ご了承ください。

実行環境

Neri が動作するのは、Ruby Installer を用いてインストールされた Ruby 環境だけです。Windows 以外の環境(含 WSL)では動作しません。

また、.exe ファイルを作成するには Devkit 付きの Ruby Installer が必要です。ただし .bat ファイルを作成する機能もあり、それを使うのであれば Devkit は必ずしも必要ではありません。

この記事は「DXRuby で作ったゲームを .exe 化する」という状況を例にして書いていきます。Ruby Installer with Devkit および DXRuby はインストール済みなものとします。Neri は以下のように gem コマンドからインストールしてください。

gem install neri

DXRuby は、この記事を書いている 2022年01月09日現在、Ruby 最新版である 3.1 には対応していません。(2.5~3.0 に対応。) また、64bit(x64) 版 Ruby では不安定な動作も多いので、32bit(x86) 版を使用することをオススメします。 (※ なお、Neri は Ruby のバージョンや 32/64bit に関係なく動作します。) なお、最近の多くの環境では DXRuby を使用するには d3dx9_40.dll が必要になります。その導入方法については下記リンク先を御覧ください。(d3dx9_40.dll は、インストールしている Ruby のフォルダの中の bin フォルダにコピーすることをオススメします。)

サンプルプログラム

⭐ ほしあつめ - GitHub

以下のようなファイル構成になっています。

  • image フォルダ:画像ファイルの入ったフォルダ
  • src フォルダ:メイン以外のスクリプトの入ったフォルダ
  • data フォルダ:その他のファイルの入ったフォルダ
  • star.ico:実行ファイルのアイコン
  • ほしあつめ.rb:メインの実行スクリプト

neri1.png

Neri を用いて実行ファイルを作成する

まず最初に一度、

ridk enable

として開発環境にパスを通しておく必要があります。

基本

neri ほしあつめ.rb

基本は上のように、neri コマンドに続けて実行スクリプトを指定するだけです。

するとまずは一度スクリプトが実行されゲームが起動するので、× をクリックして終了してしまいましょう。

neri2.png

これで実行ファイル ほしあつめ.exe と、実行に必要なファイルを収めた system フォルダが作成されます。実際に .exe ファイルを実行して、ゲームが動作することを確かめてください。

neri3.png

アイコンを設定する

neri --icon star.ico ほしあつめ.rb

と、--icon オプションを使用することで .exe ファイルにアイコンを設定することができます。

neri4.png

実行に必要なファイルをデータファイルにまとめる

ソースコード (.rb) をまとめる

今のままでは、配布するにあたっては

  • data フォルダ
  • image フォルダ
  • src フォルダ
  • system フォルダ
  • ほしあつめ.exe

をすべてまとめて配布する必要があります。実際にはここにさらに Readme とかも追加することになるでしょう。ちょっとゴチャゴチャしている感がありますね。

また、ソースコードが(ほしあつめ.rbsrc フォルダ内のものも)そのままになってしまっているため、Ruby がちょっと分かる人であれば簡単に書き換えて改造することができてしまいます。

そこで、Neri にはそうしたファイルをデータファイルにまとめる機能があるので、それを使って配布するファイルを減らし、簡単には改造できないようにすることができます。

neri --icon star.ico ほしあつめ.rb src

2こうすると、system フォルダ内に ほしあつめ.dat というファイルが作成されます。src 内のファイル(および ほしあつめ.rb)はこのデータファイルに入っているのですが、require 等でそのまま読み込めるようになっています。つまりファイルを隠蔽したにもかかわらず、ソースコードを書き換える必要なくそのまま動作させることができます。

画像・音声ファイルをまとめる (DXRuby 使用時)

さらに画像(あるいは音声)ファイルについても、DXRuby を使っている場合はソースコードを書き換えることなしに、ファイルをデータファイルに入れてしまうことができます。つまり

neri --icon star.ico ほしあつめ.rb src image

とすれば srcimage フォルダ内のファイルがデータファイルに入るので、配布に必要なものは以下だけになります。

  • data フォルダ
  • system フォルダ
  • ほしあつめ.exe

それ以外のファイルをまとめる

まだ data フォルダが残っているので、これもまとめてしまいたいところです。しかし残念ながらソースコードや画像ファイル以外のファイルは、そのまま

neri --icon star.ico ほしあつめ.rb src image data

のようにしてデータファイルに追加しただけでは、うまく動作しません。

上のコマンドで作成した .exe ファイルを実行してみてもゲーム画面はおろかエラーメッセージも何も表示されないので、このままでは原因がわかりにくいですね。そうした場合には --bat オプションを使って .exe ではなく .bat を作ると、エラーメッセージが表示されるようになるので原因がわかりやすくなるでしょう。

neri --bat --icon star.ico ほしあつめ.rb src image data

作成された ほしあつめ.bat を実行すると、ほしあつめ.rb:27:in 'read': No such file or directory @ rb_sysopen - data/secret.txt (Errno::ENOENT) とのエラーで、data/secret.txt を読み込めていないことがわかります。こうした場合はソースコードにも手を入れる必要があります。

ほしあつめ.rb に、まずは一番上に

ほしあつめ.rb
require "neri"

を追加しましょう。こうするとデータファイル内のデータを扱うためのメソッドが使えるようになります。

そして、25行目の

ほしあつめ.rb
SECRET_MESSAGE = File.read("data/secret.txt", encoding: "utf-8")

を、以下のように変更します。

ほしあつめ.rb
SECRET_MESSAGE = Neri.file_read("data/secret.txt", "utf-8")

Neri.file_read は、データファイルがあるときにはそちらから、無ければ実際のファイルからデータを読み込みます。そのため普通に Ruby から実行した際にも、Neri で作った .exe ファイルを実行した際にも、同じ様にデータを読み込むことができます。

この上で

neri --icon star.ico ほしあつめ.rb src image data

data フォルダ内のファイルもデータファイルに入れておけば、配布に必要なものは

  • system フォルダ
  • ほしあつめ.exe

の 2 つだけになりました。非常にすっきりしましたね。

データファイルを暗号化する

しかし、今のままでは問題があります。data/secret.txt は、10 点以上の点を取った人だけに見せたい秘密のメッセージです。しかし無理やりデータファイルを開いてみると、この秘密のメッセージがそのまま保存されてしまっていることがわかります。

neri5.png

それが気になるのであれば、--encryption-key オプションを使って暗号化しましょう。3

neri --encryption-key tekitounakey --icon star.ico ほしあつめ.rb src image data

こうすればデータファイルを開いても、何が書いてあるのかわからなくなります。

neri6.png

出力先を別フォルダにする

デフォルトでは Neri はカレントフォルダに実行ファイル等を作成しますが、--output-dir オプションを使って別のフォルダ内に作成するようにしてみましょう。

neri --output-dir ../starcollector --encryption-key tekitounakey --icon star.ico ほしあつめ.rb src image data

設定ファイルを作る

先程のような長いコマンドを何度も入力するのは大変です。そこで neri.config というファイルを作っておくと、そこから設定を読み込んでくれます。

neri.config
--output-dir ../starcollector
--encryption-key tekitounakey
--icon star.ico
ほしあつめ.rb
src
image
data

こうしておけば、

neri

だけで実行ファイルを作ってくれます。

一部の設定だけを neri.config に書いておき、残りの設定を Neri 実行時に指定することもできます。

いちいち × をクリックして終了しなくても済むようにする

今の状態では、実行ファイルを作成するたびにいちいちゲームが起動してしまい、そのたびに × をクリックして終了する必要があります。

実行ファイル作成時には module NeriBuild が定義されているので、これの有無をチェックし 有るなら早期に4終了させてしまえば、いちいち × をクリックする必要がなくなります。

ほしあつめ.rbの6行目に追加
exit if defined? NeriBuild

LibUI を使ったスクリプトを .exe 化する

GUI ライブラリ LibUI を使ったスクリプトも問題なく .exe 化できることを確かめています。LibUI の Usage にある以下のサンプル(※ ただし 1 行目を追加)を Neri で .exe 化できることを確かめてみてください。

libui_example.rb
require 'rbconfig'
require 'libui'

UI = LibUI

UI.init

main_window = UI.new_window('hello world', 200, 100, 1)

button = UI.new_button('Button')

UI.button_on_clicked(button) do
  UI.msg_box(main_window, 'Information', 'You clicked the button')
end

UI.window_on_closing(main_window) do
  puts 'Bye Bye'
  UI.control_destroy(main_window)
  UI.quit
  0
end

UI.window_set_child(main_window, button)
UI.control_show(main_window)

UI.main
UI.quit

neri7.png

1 行目の require 'rbconfig' が無いと、スクリプトを実行した際は問題なく動作しますが、Neri で作った .exe ファイルを実行しようとするとうまくいきません。 Neri はデフォルトでは軽量化のために Rubygems を取り除いてしまうのですが、Rubygems が RbConfig を require しており、そして現行バージョン(0.0.13)の LibUI は RbConfig を(require 無しで)使用しているためです。 今後のバージョンでは、この点が改善され require 'rbconfig' が不要になるかもしれません。

最後に

この Neri は実は 3 年ほど完全に放置してしまっていたプロジェクトだったのですが、GitHub でプルリクを送ってくださった方がいて、それで 3 年ぶりにやる気を出して正式版の公開にまでこぎつけることができました。この場を借りて御礼申し上げます。


  1. 作成当時は OCRA には「日本語ユーザー名の環境では実行できない」という欠点があったのですが、現在は解消されたようです。ただ、x64 版の Ruby を使っていると libssp-0.dll や libgmp-10.dll がデフォルトでは同梱されずエラーになることがあるようで、その場合 

    ocra foo.rb --dll ruby_builtin_dlls\libssp-0.dll --dll ruby_builtin_dlls\libgmp-10.dll
    

    のように明示的に dll を追加する必要があります。(以下参照)

    Neri はその点を(力技ですが)対処しているので、x64 環境でも問題なく実行ファイルを作成できます。

  2. 実行するスクリプトは、(オプションをのぞいて)一番最初に書く必要があります。つまり 

    neri --icon star.ico src ほしあつめ.rb
    

    と順番を変えるとエラーになります。オプションは後ろに書いても大丈夫なので

    neri ほしあつめ.rb src --icon star.ico
    

    でも大丈夫です。

  3. 暗号化と言っても簡易的なものなので、つよつよエンジニアの手にかかれば解読可能です。重要なデータの暗号化には使わないでください。 

  4. 一通りライブラリのロードが終わってからにする必要があります。 

14
9
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
9