Adding Ruby Enterprise Edition to multiruby versions

Like many other Rails developers, the most part of my Rails applications run on production with Apache, mod_rails and Ruby Enterprise Edition. In fact, this environment has proved to be one of the most successful under many aspects.

Ruby Enterprise Edition is a server-oriented friendly branch of Ruby which includes various enhancements. Although it should share more or less the same Ruby 1.8.6 behavior and be 100% compatible, you should never rely on assumptions when debugging your application.

Debugging an application running on Ruby Enterprise Edition can be a little tricky unless you don't install Ruby Enterprise Edition on your local machine. However, this means you should either replace your favorite Ruby version or create a kind of switch to choose the Ruby interpreter you might want to use for that specific development session.

Taking this problem to an other level, many programmers started to have the same need as soon as they wanted to test their application against Ruby 1.8.x and Ruby 1.9. Fortunately, the solution already exists and it's called multiruby.

Multiruby is an awesome tool crafted by Ryan Davis that enables you to run the same ruby code across multiple versions of ruby all at once. Off course, you can also run your application, debug your script or run your test against multiple ruby versions.

So, the next obvious step is to add Ruby Enterprise Edition to the list of multiruby versions. In this way you'll be able to use Ruby EE on your local machine or execute the same piece of code with other Ruby interpreters.

Note. This tutorials assumes you are running a Unix based operating system like Linux or Mac OS X. This is my configuration:

  • Mac OS X 10.5 Leopard
  • ZenTest 4.1.1
  • Ruby 1.8.6 (2008-08-11 patchlevel 287) [universal-darwin9.0]

Installing multiruby

If you haven't heard about multiruby yet, you should probably start reading this excellent post by Dr Nic.

In short, follow these steps.

To install multiruby, first install the ZenTest GEM. It should add multiruby and multiruby_setup binaries as well.

$ sudo gem install ZenTest

Successfully installed ZenTest-4.1.1
1 gem installed
Installing ri documentation for ZenTest-4.1.1...
Installing RDoc documentation for ZenTest-4.1.1...

$ which multiruby
/usr/bin/multiruby

$ which multiruby_setup
/usr/bin/multiruby_setup

Download, build and install the default multiruby Ruby versions. Simply type the following command to have multiruby do the job for you.

multiruby_setup the_usual

Please note that this step might take a while. Be patient while your computer downloads the .tgz archives and performs the necessary operations.

At the end of the story, multiruby should probably have installed 3 Ruby versions: Ruby 1.8.6, Ruby 1.8.7 and Ruby 1.9.1.

Run a simple command, for example multiruby -e "p 1+1", just to make sure everything works as expected. You should end up with something like this.

$ multiruby -e "p 1+1"

VERSION = 1.8.6-p369
CMD     = ~/.multiruby/install/1.8.6-p369/bin/ruby -e p 1+1

2

RESULT = 0

VERSION = 1.8.7-p173
CMD     = ~/.multiruby/install/1.8.7-p173/bin/ruby -e p 1+1

2

RESULT = 0

VERSION = 1.9.1-p129
CMD     = ~/.multiruby/install/1.9.1-p129/bin/ruby -e p 1+1

2

RESULT = 0

TOTAL RESULT = 0 failures out of 3

Passed: 1.9.1-p129, 1.8.6-p369, 1.8.7-p173
Failed:

Great, it works! If you want to learn more about multiruby you should probably start reading multiruby and multiruby_setup documentation.

Installing Ruby Enterprise Edition

As you probably already noticed, you can add more Ruby versions using the multiruby_setup command. Unfortunately, you can't actually use it to install Ruby Enterprise Edition because this version comes with a custom installer.

If you want to learn more about the problem, be sure to read the following section. Otherwise, simply skip to the Downloading Ruby Enterprise Edition section and you'll find the steps to install Ruby EE without additional fuss.

Under the hood of multiruby

One of my biggest complain about multiruby is probably the lack of a good documentation. You can find many blog post and tutorial, but no comprehensive documentation neither about multiruby nor multiruby_setup.

What do you usually do when no documentation is available? Simple enough, you open the library and read the code!

I found the way multiruby detects ruby versions to be a bit obscure unless you are used to it. The are 4 subfolders in the .multiruby folder: tmp, build, versions and install.

All Ruby versions are located in the install subfolder and, if you store a new Ruby installation directly in this folder, it will be listed by the multiruby_setup list command. However, it turns out that if you try to run a command with multiruby, the version is simply ignored unless a corresponding .tar package exists in the versions folder.

And this is only a part of the story. The package in versions must be called ruby-CUSTOM_VERSION.tgz while the folder in install must be named exactly CUSTOM_VERSION. At least, this worked for me.

Be careful. Whenever you try to run a command with multiruby, it first compares the package in versions with the installed Ruby versions and if it founds a package without a corresponding folder in install, first it runs the installation process.

This is the reason why you should remove all Ruby Enterprise Edition installation files before running the very first script with multiruby.

Downloading Ruby Enterprise Edition

Download Ruby Enterprise Edition from Phusion website and move the package to the multiruby versions folder, usually located under your home directory at .multiruby/versions. Notice the . before the folder name: it's a hidden folder, you might need to change your system settings to view it.

$ wget http://www.rubyenterpriseedition.com/ruby-enterprise-1.8.6-20090610.tar.gz
$ mv ruby-enterprise-1.8.6-20090610.tar.gz ~/.multiruby/versions

Move the package to the multiruby version folder and decompress it.

$ cd ~/.multiruby/versions
$ tar -xzvf ruby-enterprise-1.8.6-20090610.tar.gz

Running Ruby Enterprise Edition Installer

As I told you before, Ruby EE comes with its own installer. Run the script and answer the questions as follows.

$ ./ruby-enterprise-1.8.6-20090610/installer

Welcome to the Ruby Enterprise Edition installer
This installer will help you install Ruby Enterprise Edition 1.8.6-20090610.
Don't worry, none of your system files will be touched if you don't want them
to, so there is no risk that things will screw up.

You can expect this from the installation process:

  1\. Ruby Enterprise Edition will be compiled and optimized for speed for this
     system.
  2\. Ruby on Rails will be installed for Ruby Enterprise Edition.
  3\. You will learn how to tell Phusion Passenger to use Ruby Enterprise
     Edition instead of regular Ruby.

Press Enter to continue, or Ctrl-C to abort.

Checking for required software...

 * C compiler... found at /usr/bin/gcc
 * C++ compiler... found at /usr/bin/g++
 * Zlib development headers... found
 * OpenSSL development headers... found
 * GNU Readline development headers... found
--------------------------------------------

The installer first checks your environment for required softwares. If a requirement is miss, the installation is aborted and you should install that library before running the installer again.

Once you have all dependencies installed, the installer asks for the target directory. This is the most important step of the entire tutorial: be sure to follow these instructions carefully.

The target folder must be called exactly as the ruby enterprise archive name, except for the ruby prefix that you must ignore. It should also points to the .multiruby/install folder.

Here's the example for the package ruby-enterprise-1.8.6-20090610.tar.gz I've just downloaded before.

Target directory

Where would you like to install Ruby Enterprise Edition to?
(All Ruby Enterprise Edition files will be put inside that directory.)

[/opt/ruby-enterprise-1.8.6-20090610] : /Users/weppos/.multiruby/install/enterprise-1.8.6-20090610
--------------------------------------------

As you can see, I specified the full qualified path instead of using the ~ shortcut for the home directory: ~/.multiruby/install/enterprise-1.8.6-20090610.

Ok, you're almost done. Now Ruby Enterprise Edition is going to be compiled and installed. As the installer notifies you, it's going to take a while. Relax and take a coffee.

Compiling and optimizing the memory allocator for Ruby Enterprise Edition
In the mean time, feel free to grab a cup of coffee.

./configure --prefix=/Users/weppos/.multiruby/install/enterprise-1.8.6-20090610 --disable-dependency-tracking
...

Compilation Errors/Warnings

The installer doesn't only install Ruby Enterprise Edition, but it also tries to install some common GEMs and libraries. Depending on your system configuration, you might be unable to get some of them.

For instance, Ruby Enterprise Edition hasn't been able to install MySQL and PostgreSQL adapters on my computer due to the lack of some required libraries.

Installing mysql...
/Users/weppos/.multiruby/install/enterprise-1.8.6-20090610/bin/ruby /Users/weppos/.multiruby/install/enterprise-1.8.6-20090610/bin/gem install -r --no-rdoc --no-ri --no-update-sources --backtrace mysql
Building native extensions.  This could take a while...
ERROR:  Error installing mysql:
        ERROR: Failed to build gem native extension.

/Users/weppos/.multiruby/install/enterprise-1.8.6-20090610/bin/ruby extconf.rb
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... no
checking for mysql_query() in -lmysqlclient... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Installing postgres...
/Users/weppos/.multiruby/install/enterprise-1.8.6-20090610/bin/ruby /Users/weppos/.multiruby/install/enterprise-1.8.6-20090610/bin/gem install -r --no-rdoc --no-ri --no-update-sources --backtrace postgres
Building native extensions.  This could take a while...
ERROR:  Error installing postgres:
        ERROR: Failed to build gem native extension.

/Users/weppos/.multiruby/install/enterprise-1.8.6-20090610/bin/ruby extconf.rb
extconf.rb:73: command not found: pg_config --bindir

If this happens, don't worry. Unless this is an unrecoverable error, the installer will simply skip them and you'll be able to take care of these issues later, if you really need to.

If everything goes well, at the end of the installation you should probably see a message like

--------------------------------------------
Ruby Enterprise Edition is successfully installed!
If want to use Phusion Passenger (http://www.modrails.com) in combination
with Ruby Enterprise Edition, then you must reinstall Phusion Passenger against
Ruby Enterprise Edition, as follows:

  /Users/weppos/.multiruby/install/enterprise-1.8.6-20090610/bin/passenger-install-apache2-module

Make sure you don't forget to paste the Apache configuration directives that
the installer gives you.

If you ever want to uninstall Ruby Enterprise Edition, simply remove this
directory:

  /Users/weppos/.multiruby/install/enterprise-1.8.6-20090610

If you have any questions, feel free to visit our website:

  http://www.rubyenterpriseedition.com

Enjoy Ruby Enterprise Edition, a product of Phusion (www.phusion.nl) :-)

Removing Installation Files

Before running any multiruby command, you need to remove the installation files. Remove the Ruby Enterprise Edition folder but don't remove the .tar package. multiruby needs it in order to work properly.

$ rm -rf ~/.multiruby/versions/ruby-enterprise-1.8.6-20090610

Checking multiruby installation

At this point, multiruby should correctly display Ruby EE in the known version list.

$ multiruby_setup list

Known versions:
  1.8.6-p369
  1.8.7-p173
  1.9.1-p129
  enterprise-1.8.6-20090610

Run a simple test command with multiruby. It should be executed across all ruby versions, including Ruby EE.

$ multiruby -e 'p 1+1'

VERSION = 1.8.6-p369
CMD     = ~/.multiruby/install/1.8.6-p369/bin/ruby -e p 1+1

2

RESULT = 0

VERSION = 1.8.7-p173
CMD     = ~/.multiruby/install/1.8.7-p173/bin/ruby -e p 1+1

2

RESULT = 0

VERSION = 1.9.1-p129
CMD     = ~/.multiruby/install/1.9.1-p129/bin/ruby -e p 1+1

2

RESULT = 0

VERSION = enterprise-1.8.6-20090610
CMD     = ~/.multiruby/install/enterprise-1.8.6-20090610/bin/ruby -e p 1+1

2

RESULT = 0

TOTAL RESULT = 0 failures out of 4

Passed: 1.9.1-p129, enterprise-1.8.6-20090610, 1.8.6-p369, 1.8.7-p173
Failed:

Looking for other Ruby versions?

This tutorial is largely inspired by Nate Murray's blog post about Adding MacRuby to multiruby. Checkout his tutorial to install MacRuby and don't forget to read Rob Seaman's blog post if you want to install JRuby.

Is this the right way to accomplish this?

If you dig into the multiruby source code, you probably notice that it provides built-in support for many different Ruby implementations. You might be wondering if this tutorial follows the right way to install Ruby EE.

As I told you at the beginning of this post, Ruby EE differs from the other Ruby versions because it comes with its own installer. You should use it to ensure the installation process ends successfully.

In order to add Ruby EE built-in support to multiruby, you should probably hack the Ruby EE installer and pass it the required parameters such as the target path. I must confess I didn't have so much time to check how to do this and I found the default installation to be the most fast and easiest way.

Because multiruby is always looking for maintainers for others Ruby implementation, I don't exclude to create a patch in the future. Off course, if you have a better solution, feel free to share it here and send a patch to the ZenTest project.