Quickstart to Hacking Rubinius

rubinius

Thu Jun 12 01:38:00 -0700 2008

I recently tried my hand at hacking on Rubinius. Here’s a rough description of what I did - following this same pattern should let any skilled Ruby developer be contributing patches in no time.

First:

git clone git://git.rubini.us/code rubinius
cd rubinius
rake spec:update
rake build

This will take a while to finish. Once it’s built, you can run Ruby scripts by using shotgun/rubinius [filename], instead of ruby [filename]. You can also run it with no arguments to get an interactive shell (i.e., irb). Put this alias into your bashrc:

alias rbx=/home/adam/rubinius/shotgun/rubinius

…and then you can run rbx instead of ruby from anywhere.

Install gems:

rbx gem install [gemname]

I kicked things off by running the specs on my own open source Ruby libraries, once I had installed the rspec and other dependency gems. RestClient passed fine, so I moved on to rush, which is much more complex. Running individual specs, e.g.:

rbx rush/spec/dir_spec.rb

…I soon found some that broke. Since I know these specs pass normally, this served as my launchpoint for how I could improve Rubinius.

Rubinius was throwing an exception in popen, which was only partially implemented. But before trying to fix it, the first step was to write a spec. Rubinius uses mspec, which an RSpec-style specing library. I ran the popen spec like this:

bin/mspec spec/ruby/1.8/core/io/popen_spec.rb

This runs it on Rubinius. To run it on MRI (aka Ruby 1.8), use:

bin/mspec -t ruby spec/ruby/1.8/core/io/popen_spec.rb

Write the spec to pass on MRI first. Then check to see if it passes on Rubinius. If not, you’ll need to tag it as failing. Here's my first committed spec, and notice that the second file is popen_tags.txt, which marks the read/write pipe as failing.

All specs should pass on MRI at all times. But it’s entirely reasonable to write a spec that passes MRI and fails on Rubinius - this makes evident a missing feature in Rubinius.

Once I had the spec which passed on MRI but failed on Rubinius, I could now turn my attention to making the spec pass. The code I tinkered with was in kernel/core/io.rb. It relies on a primitive create_pipe (via IO.pipe), which is actually a very simple C function that can be found in shotgun/lib/primitives.rb.

In the process of working on the main issue you will most likely discover small ones. Take the opportunity to write a spec, and fix Rubinius. But if you can only do one or the other (write the spec, or fix a failing spec), that’s great too. This two-phase process (expose the problem, then fix it) works extremely well for mapping out the complex problem space of writing a language VM, particularly in trying to track an implementation that has no formal specification.

One thing that triped me up was that you must run rake to rebuild after any code change - even if all the code you changed was Ruby. I’m not used to having a compile step on an interpreted language, but once I got into the habit it was easy to remember.

For submitting the patch, put it into a pastie and post it on Lighthouse. Most developer communication happens in the IRC channel, so you may want to start by posting your pastie there and soliciting feedback.

I was really impressed by the receiptiveness of the Rubinius developers to new hackers. Even while critiquing my patches on IRC, they took every opportunity to let me know how much they appreciated my contribution. From what I’ve seen, these guys are setting a new bar on making a low barier of entry for people to jump in and contribute. I hope to see other open source projects follow their good example.

Further reading: