How To Install Ruby Extensions Like openssl With rbenv
Today we are going to look at installing Ruby extensions when they do not get built as part of Ruby itself.
rbenv, for example, can install ruby which lacks openssl module which is then useless for any practical work as rubygems use HTTPS, as the following example demonstrates:
% rbenv install 1.9.3-p448 Downloading yaml-0.1.4.tar.gz... -> http://dqw8nmjcqpjn7.cloudfront.net/36c852831d02cf90508c29852361d01b Installing yaml-0.1.4... Installed yaml-0.1.4 to /home/me/.rbenv/versions/1.9.3-p448 Downloading ruby-1.9.3-p448.tar.gz... -> http://dqw8nmjcqpjn7.cloudfront.net/a893cff26bcf351b8975ebf2a63b1023 Installing ruby-1.9.3-p448... Installed ruby-1.9.3-p448 to /home/me/.rbenv/versions/1.9.3-p448
Ruby installed! Let's try using it:
% bundle install Could not load OpenSSL. You must recompile Ruby with OpenSSL support or change the sources in your Gemfile from 'https' to 'http'. Instructions for compiling with OpenSSL using RVM are available at rvm.io/packages/openssl.
Uh-oh. My ruby is useless for my project.
One way of fixing this situation is to follow the instructions at rvm.io/packages/openssl which more or less say "give rvm a root shell and let it take care of everything, you don't need to know the details". This though is a non-starter for those of us with systems background. Instead we are going to install the needed extensions manually.
Installing ruby extensions
The first thing we need to know is that ruby installation is performed
in two parts. The first part builds and installs the ruby interpreter
itself, the second part builds and installs extensions that are
included with the interpreter. Without some extensions (like
stringio) most programs won't run. Other extensions (like
are required by some programs but ignored by others.
Still other extensions (
win32ole) are so obscure that you may have
never heard of them, and they may well not exist on your machine.
Ruby-the-interpreter can be installed without many of the extensions it
ships with, which explains how rbenv reports installation success yet
produces a ruby installation that is useless for a particular application.
The second thing we need to know is that ruby extensions can be installed
at any time into an existing ruby installation. There is no requirement that
the interpreter and extensions are built together. This means to install
openssl extension we just need to build that one extension,
not rebuild the entire ruby installation.
Now, for how to actually do it. First, we need to obtain the ruby source code. rbenv deleted it after "successful" installation, but told us where the source came from: http://dqw8nmjcqpjn7.cloudfront.net/a893cff26bcf351b8975ebf2a63b1023 above. Therefore:
% wget http://dqw8nmjcqpjn7.cloudfront.net/a893cff26bcf351b8975ebf2a63b1023 ... 2014-01-27 22:14:01 (6.34 MB/s) - a893cff26bcf351b8975ebf2a63b1023 saved [12559260/12559260]
This is really a tarball, which we can unpack:
% tar xf a893cff26bcf351b8975ebf2a63b1023
If your tar is smart, it should detect gzip and bzip2 compressed
tarballs. If it does not, try
xfj in place of
Now we have a
ruby-1.9.3-p448 directory with ruby source in it.
Navigate to the extension we are trying to install:
% cd ruby-1.9.3-p448/ext/openssl
If you have not done so already, activate the ruby you want to install the extension to which should be the same version:
% rbenv shell 1.9.3-p448
Now configure the extension:
% ruby extconf.rb
You will get a bunch of output. If all goes well, you'll see something like this at the end:
=== Checking done. === creating extconf.h creating Makefile Done.
Chances are, all does not go well, as otherwise openssl would have been installed automatically. If so you might see an error like this:
=== Checking for required stuff... === checking for openssl/ssl.h... no === Checking for required stuff failed. === Makefile wasn't created. Fix the errors above.
This system is missing openssl headers.
Resolve the issue if any, patch the source if necessary, then rerun
ruby extconf.rb. Repeat until it succeeds.
Once the extension is configured you can build it:
And once it's built, you can install it:
% make install
Go back to your application and see if it now works!
This recipe works for readline and any other extension shipped with ruby.