Create  Edit  FrontPage  Index  Search  Changes  History  RSS  Login

tips_rubyscript2exe

Creating an executable with rubyscript2exe

rubyscript2exe is a a tool that transforms your Ruby script into a standalone compressed executable file. It's not a compiler: it does not convert Ruby code to byte code. It only creates one executable that embeds everything needed to run your script: the Ruby interpreter, your program and your program's dependencies. In the end, you get a single executable that is ready to use on any computer! It can be used for Windows, Linux and Mac OS X (Darwin). The main interest of this tool is for distributing your application or for demonstration purpose.

This page will describe how you can use this tool with ruby-gnome2!

rubyscript2exe on Windows

The working environement

First, you need to have a workable ruby-gtk2 environment, such as:

The first thing to do is of course to get your program working with this environment, i.e. without rubyscript2exe.

We generally use setup.rb for the installation process of a ruby program. The tree structure of your program must be like that:

  • bin/yourapp.rb (main program)
  • data/yourapp/ (shared data directory)
  • data/locale/ (*.mo files if you use gettext)
  • lib/yourapp/ (files required by the main program)

In this latter directory, a nice idea is to define a hook script called pre-setup.rb with:

File.open('config.rb', 'w') do |file|
file.print <<EOS

  module Config
    MAIN_DATA_DIR = '#{config('data-dir')}'
    DATA_DIR = '#{config('data-dir')}/yourapp'
    LIB_DIR = '#{config('rb-dir')}'
  end

EOS
end

Thank to this hook script, you'll get a file called config.rb which defines the constant Config::DATA_DIR (by default, c:\ruby\share\yourapp\) and that your main program will be able to require. You'll want to use this constant everytime you need a file in the shared data directory. This trick will be useful further in this documentation.

With the One-Click installer, the installation of your app will result as follow:

  • c:\ruby\bin\yourapp.rb
  • c:\ruby\share\yourapp\
  • c:\ruby\share\locale\
  • c:\ruby\lib\ruby\site_ruby\1.8\yourapp\

After having installed GTK+ for Windows, you get a c:\GTK\ directory which contains:

  • c:\GTK\bin\ (GTK dlls and executables, the latter are not strictly necessary for us)
  • c:\GTK\lib\ (some additional dlls which are resolved by the GTK dlls)
  • c:\GTK\etc\(configurations files needed by dlls, they define where the dlls above are located)
  • c:\GTK\share\ (shared files among which i18n files)

Using rubyscript2exe

Now that the environment is set and our program works correctly, we're going to see how to generate an executable with rubyscript2exe. We will work in the c:\ruby\bin\ directory. Let's copy rubyscript2exe.rb to it.

The ruby dependencies (pure ruby and extensions) are resolved recursively and embedded in the executable automatically. You don't have to worry about that.

But the extensions' dependencies (for us, GTK) are not resolved automatically. You have to copy each dll to where rubyscript2exe will be executed. So copy all dlls from c:\GTK\bin\ to c:\ruby\bin. All except three: libgtk-win32, libgdk_pixbuf, libpango.

Here is the reason. When you execute the program created by rubyscript2exe, rubyscript2exe simply unzips it in a temporary directory and the three dlls mentionned above won't find the files they need: files which are in c:\GTK\lib\, c:\GTK\etc\ and c:\GTK\share(because paths are relative). The solution is to provide them separetely. This way, the paths to those external files will be resolved.

Copy c:\GTK\lib\, c:\GTK\etc\ and c:\GTK\share to c:\ruby.

Now we can run rubyscript2exe. Here's the scenario:

  • cd c:\ruby\bin
  • ruby rubyscript2exe.rb yourapp.rb
  • rubyscript2exe resolves the ruby dependencies, they are embedded in the executable
  • rubyscript2exe embeds every dll in the current directory, i.e. c:\ruby\bin
  • rubyscript2exe needs libgtk-win32, libgdk_pixbuf, libpango but does not find them so it feches them in c:\GTK\bin (because this directory has been set in the load path by the GTK+ for Windows installer)
  • your app starts correctly
  • once you've closed your app, rubyscript2exe compress everything and generates the executable.

In the end, you need to ship to your user a directory with:

  • yourapp.exe (which embeds the ruby interpreter, ruby dependencies and the GTK dlls except three)
  • the three dlls libgtk-win32, libgdk_pixbuf, libpango
  • the three directories etc/, lib/ and share/

A zip file with all that should be arround 5MB. You can also use <NSIS|URL:http://nsis.sourceforge.net> to create an installer which will install those files.

See the rubyscript2exe website to know how to prevent the DOS prompt from being popped up and how to change the executable's icon.

Sorry for all this "ballet" with directories. Let me know if you know a cleaner way.

Dealing with external files

With traditional install, the data files are placed in an absolute path, e.g. c:\ruby\share\yourapp.

With rubyscript2exe, path to external files have to be relative to the .exe file. So let's replace our DATA_DIR constant from our config file by:

DATA_DIR = "#{Dir.pwd}/share/data/yourapp"

This way, the program works wherever the archive is unzipped.

You need to copy the share/ directory holding data/ in c:\ruby\bin before running rubyscript2exe.

Starting time and reducing size

As it was said before, rubyscript2exe needs to unzip every embedded component in a temporary directory everytime yourapp.exe is started. It may take up to 3 our 4 seconds which can be boring. If you don't mind if the GTK dlls are visible (which is the case if you create a NSIS installer), don't put them in the c:\ruby\bin dir when you execute rubyscript2exe. rubyscript2exe won't embed them,will have less components to unzip on the fly and your program will start more quicly.

The main advantage of providing the GTK dlls with your app is that it will work out of the box. But without them, your executable will weight about 1.5M only. You can also reduce the size by removing the GTK locale (share/locale/) [about 3M]. To reduce the size a bit more, you may try to determine more precisely which GTK dlls your program requires or not.

rubyscript2exe on Windows, solution 2

Another solution is to copy all the needed files inside the temporary directory created by rubyscript2exe, each time the application starts. You put all the needed GTK files and folders in a subfolder of your source code, and copy those files in the rubyscript2exe directory at startup. That way, you don't have to touch your ruby installation or make it possible to run your ruby program from any folder.

Let's create a "run_dep" folder under the folder where you have the source code of your application. In that folder, copy the etc/, lib/ and share/ from your GTK installation. The GTK installation is in c:\gtk or C:\Program Files\Common Files\GTK\2.0. You can safely remove the "doc" and "gtk-doc" subfolders of the "share", to save some space. In share\locale, you can remove the locales you don't need if you want, to save more space (locales take ~20Mb). You can remove all the contents of the share\locale folder if you want, the english/US is always shipped. For me, I could also remove *.lib in lib (10Mb), and lib\locale (15Mb).

Then, add the following lines at the start of your main .rb file:

require 'rubyscript2exe'
require 'fileutils'
require 'pathname'

p0 = Pathname.new(RUBYSCRIPT2EXE.appdir)
root_runtime = p0.parent.to_s
begin
   FileUtils.cp_r('run_dep/.', root_runtime)
rescue
end

Those lines copy all the files & folders inside the "run_dep" folder to the folder where rubyscript2exe will extract your application. The begin/rescue is needed because that fails when you run your application the first time in rubyscript2exe, to create the .exe.

Regenerate your application, and run the exe.. it should work now!

In the end, to ship my application I need 6Mb exe and 1.26Mb "run_dep", plus the glade files. And it seems no GTK installation is needed on the target computer!

Note: that method will not work if the developer's computer has another GTK installed than the gladewin32 GTK or the GTK from ruby-gtk2. If the developer installed the GTK that comes with gimp for windows for instance, it will not work, because that version of GTK will be used in the EXE, and that version does not work well for ruby-gtk2. In that case, the best is for the developer to either temporarily rename the folder containing that special GTK or even uninstall it, and use the gladewin32 version, which works fine with GIMP (and GAIM) on windows, and allows creating EXEs for ruby-gtk2 programs. For the user running the EXE you'll create, it doesn't matter which version of GTK they have, or even if they have GTK at all, it will work thanks to the version from your EXE.

Changelog

2007-02-21 Emmanuel Touzery
Describe problem if the GTK from GIMP-WIN32 is installed on the computer
2007-02-05 Emmanuel Touzery
Describe alternative solution
2006-01-09 Mathieu Blondel
Using rubyscript2exe and Dealing with external files
2005-12-27 Mathieu Blondel
Initial release
Last modified:2011/06/11 10:24:59
Keyword(s):
References:[tips]