In my day job, we have need to interface with an Oracle database, from ruby. There’s a gem for that: ruby-oci8. The problem, since OS X Lion came out, is that installing the gem with it’s native extensions (i.e. compiled C code) fails. Why? Because the native extensions cannot be built using the default 64-bit architecture.
The solution? Build it for a 32-bit architecture! Unfortunately, that is a little easier said than done. So, last week I set out to see what it would take to actually move to Lion. Turns out, it wasn’t that bad.
Our particular situation is that we have a number of Ruby developers (who have to interact with Oracle, even for testing) running OS X Snow Leopard, because they joined the company before Lion came out. I am one of those developers (although my primary focus is iOS development). We could all stay on Snow Leopard indefinitely, but the real problem is for any new developers who may join our ranks: They’ll be getting MacBook’s with Lion (or newer!). (Did I mention we’re an all Mac shop? ) So being able to interface with Oracle from Lion using Ruby is coming whether we like it or not.
Since most of us here will be upgrading from Snow Leopard, I used Carbon Copy Cloner to clone my system onto a spare MacBook Pro we had in the office. That took about 90 minutes but your experience will be determined by how much data you have on your disk.
The cloned machine booted just fine, and I upgraded it to Lion without incident. Then I set about getting ruby installed and building the driver.
Since we have many Rails projects, we use rvm, and you should too. I followed these steps to build ruby and the driver. You will need a C compiler, so either install Xcode via the Mac App Store (it’s free) or for just the compilers, you can find them on github.
You’ll need to wipe away rvm and all installed Rubies and Gemsets and start from scratch. It’s just easier this way and you can be sure of where you’re starting:
Close your terminal window and open a new one because rvm likes to mess with your shell. Opening a new terminal ensures you have a “good” environment to re-install rvm:
bash -s stable <<(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
Close your terminal window again and open a new one for the same reasons as before.
Now you can install ruby:
rvm install ruby-1.9.2-p290 -n i386 --with-arch=i386
Ta da! No patching required, and the resulting ruby binary is a 32-bit binary. (There is a lot of accumulated internet chatter about this problem. Other solutions require setting environment variables and patching ruby sources. While all of that still seems to work if you go that route, the simpler one-liner above also works. And for me, simple wins.)
Important Note: As of this writing, ruby 1.9.3-p125 will not build on OS X Lion, either as a 32-bit or 64-bit binary.
For projects using the ruby-oci8 gem, update existing .rvmrc files, or create new ones to use ruby-1.9.2-p290-i386. For example:
% echo "rvm use ruby-1.9.2-p290-i386@myproject" > .rvmrc
With this ruby, you can run “bundle install” (if you’re using bundler) or “gem install ruby-oci8” and the ruby-oci8 gem should build. (It should go without saying that to build ruby-oci8 you must have Oracle client developer tools already installed, which are available from Oracle.)
It is further worth noting that by using a 32-bit Ruby, if you are doing anything with dates, you will now be constrained by the so-called Y2038 problem, which is that the furthest date in the future that can be represented in 32 bits is 01/19/2038 03:14:07 UTC. Shouldn’t be an issue for a while, but we had some tests that started failing because they used dates way out beyond 2038.