rbenv first impressions
Background: I maintain a scenario that I test against multiple versions of Rails and multiple versions of Ruby. I primarily develop on Ubuntu, but I bought a new Mac Mini because some of my readers were having installation problems on Snow Lion and my previous mac min can’t install Snow Lion.
Armed with my new Mac Mini, I set off to to repeat my testing of various versions of Rails and Ruby. Whereas I have been using, and happy with, RVM on Ubuntu for dealing with Ruby versions; I decided to try rbenv/ruby-build. What I started with was a new machine, a full installation of XCode, the Command Line utilities, and Homebrew.
Keeping my build recipies up to date involves rvm get stable
for rvm, and brew update
followed by brew upgrade ruby-build' if `brew outdated`.include? 'ruby-build'
for rbenv.
Changing to the latest version of 1.9.3 using rvm is accomplished with rvm use 1.9.3
. If the latest version isn’t installed, this will fail, and rvm install 1.9.3
will do the dirty deed. For rbenv, one needs to first get a list of versions using rbenv install --list
, select ones starting with 1.9.3, sort the list numerically by the last digits of the string, and select the largest result.
Building the latest 2.1.0 can be done with rvm install ruby-trunk-nxxx
where the -n
is optional but useful for tracking multiple “latest” versions. I use the subversion revision number for xxx.
Building the latest 2.1.0 is where this all goes downhill with rbenv on Mac OS X 1.8.3. There is a recipe for 2.1.0-dev. It automatically downloads and builds openssl to workaround a problem if it detects has_broken_mac_openssl
. I like that in a ruby build tool.
Unfortunately, building Ruby 2.1.0 doesn’t work with Apple’s provided version of autoconf, nor does ruby-build automatically know where homebrew puts its version of autoconf. Adding /usr/local/opt/autoconf/bin
explicitly to the PATH allows me to build exactly one version of 2.1.0-dev. Fortunately, I can rename that directory to add a -rxxx
. Unfortunately, the shims have hardcoded paths in the shebang lines. Fortunately, a symbolic link compensates for that. This does mean that in the infrequent event that I want to go back to a prior build of 2.1.0 I need to remember to update the symbolic link too, but I can live with that.
Determining when the previously build “latest” 2.1.0 is no longer current is a matter of finding out where the git checkout of the ruby repository was done to. For rvm, this is $rvm_path/repos/ruby
. For rbenv, the default is to throw this away, but this default can be overridden using the --keep
option, in which case it is saved to $RBENV_ROOT/sources/2.1.0-dev/ruby-2.1.0-dev
. If a git pull
in those directories comes up with Already up-to-date.
, you are golden. If not, time to rebuild.
Rebuilding with rvm will make use of what I already have. Rebuilding with rbenv will fail unless I first erase the $RBENV_ROOT/sources
directory, after which point it will do a full download of both openssl and a full (albeit shallow) git clone of ruby.
Just when I think I am done, I find out that what works using foreground login sessions via ssh doesn’t work via background sessions like cron or Apache CGI. Symptoms are that ruby-build downloads and builds openssl, downloads and builds ruby, then complains with:
The Ruby openssl extension was not compiled. Missing the OpenSSL lib?
. This took a while to isolate building Ruby 2.1.0 takes a while even with modern hardware. Ultimately, I determine that the build only succeeds if /usr/sbin
is in my PATH
. This makes no sense at all to me, but it works. Moving on...
At this point, I have everything working, but it certainly isn’t pretty. Time to refactor.
One way to approach this is to move all of this logic to a rbenv plugin. rbenv whatis is a step in this direction.
A better approach would be to first see which parts of this I could either motivate to get fixed in rbenv itself, perhaps even contributing code myself. The first step is to start a dialog with the developers, but alas I can find no IRC channel or mailing list. I see that others have resorted to using the issue tracker for this, but that doesn’t seem quite appropriate for this grab bag of small issues and WIBNIs I have at this point.
A prioritized wish list to start with:
- If a source is already downloaded or cloned, use it.
- Allow me to provide an additional revision number when building 2.1.0-dev. Either that or automatically do this for me.
- If homebrew has installed a later version of autoconf, use it in preference to the Apple provided version.
- Figure out what is needed in
/usr/sbin
and either avoid it or make sure that it is found.
It is indeed possible that I overlooked something and/or one or more of these are user errors on my part. If so, pointers would be welcome.
Whatever is not done, I can put into a rbenv get
or equivalent command which does whatever is necessary under the covers to switch to the specified version, including build it if necessary.