Tuesday, September 18, 2007

Compiling Your Ruby App with RubyScript2Exe

I've mentioned RubyScript2Exe previously. This tool allows you to 'compile' a script/application into a portable executable file (EXE) that you can easily provide to your users without requiring them to install Ruby and the required libraries. RubyScript2Exe traces and gathers all the necessary files, including the Ruby interpreter, and 'compiles' them into a single EXE file. You can easily embed images and icon files, and DLLs such as SQLite.

I put the word 'compile' in quotes above because RubyScript2Exe does not transform your code as a C compiler or .Net compiler would. Rather, it collects all the files necessary to run your application and bundles them into a single EXE file. When the user runs that EXE file, that bundle is quickly extracted to a temporary file and your Ruby code is executed.

Installing RubyScript2Exe is as easy as falling off a log, thanks to RubyGems. Just get to a command prompt and enter:


gem install rubyscript2exe

Include the following require statement at the top of your script:

require 'rubyscript2exe'

Whenever possible, include all your require statements at the top of your script. This ensures that RubyScript2Exe successfully traces and includes all the necessary files your application will need.

If you are compiling a non-console script and therefore want to use the rubyw.exe interpreter, rather than the ruby.exe interpreter, include the following module variable near the top of your script:

RUBYSCRIPT2EXE.rubyw = true

When I use the NetBeans Ruby IDE, which defaults a new project's main script name to "main.rb", I include the above code to avoid renaming the script with a ".rbw" extension or providing command-line parameters to the RubyScript2Exe compiler. More on that later.

A Ruby Forum reader and RubyScript2Exe user recently mentioned "I want to be able to wrap the icon file along with the rest of the application." You can embed additional files such as icons or DLLs in the executable like this:

RUBYSCRIPT2EXE.bin = ["my_icon.ico", "sqlite3.dll"]

When you run your compiled executable, RubyScript2Exe extracts all the files from your executable into a temporary directory. But sometimes you need to know the location of the folder the executable was originally run from. Just call the RUBYSCRIPT2EXE.exedir method:

APPLICATION_PATH = RUBYSCRIPT2EXE.exedir

Enough preparation! Let's compile our application. Go to a command prompt and enter:

rubyscript2exe my_script.rb

...or...

rubyscript2exe my_script.rbw

If your script has a filename extension of .rb, RubyScript2Exe will include the ruby.exe interpreter and a console window. If your script has a filename extension of .rbw, RubyScript2Exe will include the rubyw.exe interpreter and your app will therefore not have a console window; this is the same as if you had included RUBYSCRIPT2EXE.rubyw = true in your code.

The size of your compiled executable can vary widely depending on what files are needed to be included. A simple console app may be 1mb in size, a wxRuby 0.6 GUI app may be 3-4mb, and a wxRuby 2 GUI app may be 6-8mb in size. Part of this size is due to a known 'bug' that may cause some files (the 8mb wxRuby2.so file, for example) to be included twice. This affects the size of the EXE file but not the performance.

There you have it. But this post just scratches the surface. RubyScript2Exe's creator, Erik Veenstra, has done a great job maintaining and documenting this tool, and you should take a few minutes and read the docs here.

Questions? Comments? Suggestions?

Post a comment here or send me an email.

Thanks for stopping by!

Digg my article

9 comments:

Anonymous said...

Thanks for the simple example on Windows. This'll come in handy for me later.

For windows it becomes so important to make things "one click".

I guess the next step would be to also wrap this in some kind of simple installer script to store it in the right place and add the appropriate menu/desktop icons.

David Mullet said...

Thanks, Sy!

"I guess the next step would be to also wrap this in some kind of simple installer script..."

Sounds like a good suggestion for my next article.

David

Anonymous said...

Hey,

Just thought I'd drop in and mention "exerb" for a second. It's under development now, but I think it has somewhat of a superior run-time process. I've also found it quite useful in the way one can tie it to build scripts. I've actually used it in a few places to build rudimentary installers for other software.

Cheers,

raggi

Emmanuel said...

Mmmm maybe it's just me, but i think the word "compiling" may be misleading for a lot of people.

Maybe the word "Packaging", or even "Collecting" would be more accurate.

David Mullet said...

@emmanuel-

I use the word 'compile' because that is likely the word that comes to mind for most potential users of RubyScript2Exe. They want to create a portable executable file, so they assume they need a 'compiler'.

But you make an important point, and I have clarified this in the article.

@raggi-

I haven't used exerb in quite some time, but will check it out. RubyScript2Exe always works well for me (and my users), so I have not been motivated to investigate other options.

David

Sean said...

I have a question... if I were to use rubyscript2exe to 'compile' everything on say... XP, would I then be able to run that program on Windows 98 or 95? (Does it end up as a universal executable?)

David Mullet said...

@Sean-

Good question! As long as your Ruby code is Win95/98 compatible, then I believe that your executable would be as well. I have 'compiled' on Win XP and executed on Windows Vista, but have not executed on an earlier system. Unless your code leverages libs and methods specific to later Windows versions, I think you'll be alright.

Please let me know if you find otherwise.

David

Unknown said...

hi
I don't understand what about the path of .rb program
and how to do perform the command
"rubyscript2exe my_script.rbw"

Anonymous said...

Congrats on the side, it has helped me numerous times and taught me lots of things..One question in regards to rubyScript2exe..IF I have an excel file working along with Ruby how I 'bundle' that into the installation so in the end you preserve directory structure and include that excel file in the bundle?

Any help is greatly appreciated..

Thanks in advance,

Pantelis