Building a Debian package out of a Rubygems' .gem file

This post is sort of a status update on ongoing work in Debian's Ruby packaging infrastructure, i.e. the tools used to package Ruby libraries and applications (not the Ruby interpreters themselves) for Debian. We have recently added two new utilities to ruby-pkg-tools:

  • gem2tgz, a tool to convert .gem files into source tarball suitable for being used as a Debian upstream tarball. This is needed because unfortunately several useful Ruby libraries and applications are only officially released in the .gem format.

  • a ruby buildsystem for debhelper, which will automatically build standards-compliant Debian Ruby packages.

To follow the steps in this post, you'll need to build ruby-pkg-tools from the pkg-ruby-extras team subversion repository (e.g., you need ruby-pkg-tools 0.18, which is not in the archive yet). You can also browse the source.

First you have to download a .gem file. Let's took fast_gettext as an example. Enter a temporary directory and download the latest version of the .gem:

$ wget http://rubygems.org/downloads/fast_gettext-0.5.10.gem

Now we need to convert that .gem file into a source tarball to be used by the Debian package:

$ gem2tgz fast_gettext-0.5.10.gem libfast-gettext-ruby-0.5.10.tar.gz

Then uncompress the source tarball, and change to the extracted source directory:

$ tar xzf libfast-gettext-ruby-0.5.10.tar.gz$ cd libfast-gettext-ruby-0.5.10/

Inside the source directory, you need the generate the Debian package files. For now, you'll use good old dh_make:

$ dh_make -f ../libfast-gettext-ruby-0.5.10.tar.gz --single

Then we have an almost "ready" Debian package. It still misses several documentation issues that need manual checking, but for the sake of the example in this post it is good enough already.

I normally remove all the example files dh_make generates for us:

$ rm -f debian/*.ex debian/*.EX

The next step is to change debian/rules so that it will use our custom Debhelper build system. It's just a matter of adding an extra argument for the dh call. The final rules file must look like this:

#!/usr/bin/make -f

%:        dh --buildsystem=ruby $@

Now we build the package. I normally use debuild for that.

$ debuild

After the build lintian will complain a lot, because our package has lots of unchanged dh_make boilerplate, but as fas as this post is concerned, the point is that the package will install the code correctly.

You can check the contents of the package with debc, to make sure everything will be where it should. Our custom debhelper buildsystem is installing Ruby libraries to /usr/lib/ruby/vendor_ruby, so it will available to all Ruby versions installed.

Now that the package is built, you can install and test it:

$ sudo dpkg -i ../libfast-gettext-ruby_0.5.10-1_i386.deb[...]
$ irb -rfast_gettext>> FastGettext.add_text_domain 'mutt', :path => '/usr/share/locale'; 1
=> 1
>> FastGettext.text_domain = 'mutt'
=> "mutt"
>> FastGettext.locale = 'pt_BR'
=> "pt_BR"
>> include FastGettext::Translation
=> Object>> _('Delete')=> "Remover"

I tried the above with both irb (currently Ruby 1.8's irb) and irb1.9.1 (Ruby 1.9.2's irb), and it worked fine.

This custom buildsystem still misses proper handling for some special cases:

  • C extensions. They must be installed under /usr/lib/ruby/vendor_ruby/${RUBY_VERSION}/${ARCH}/

  • Libraries that are specific to a single Ruby version. This is the case for example of libraries that got included in Ruby 1.9.x itself but are still useful for Ruby 1.8, or even C extensions that do not compile under Ruby 1.9.x. Those libraries must be installed under /usr/lib/ruby/vendor_ruby/${RUBY_VERSION}/ for pure-Ruby libraries and /usr/lib/ruby/vendor_ruby/${RUBY_VERSION}/${ARCH}/ for C extensions.

  • Applications. Normally an application should use a single and well-known Ruby version, e.g. either Ruby 1.8 or Ruby 1.9.2. So that no matter which is the default Ruby version (the one started when ruby is invoked), the application will work the same.

Next steps include providing a dh-make-ruby tool that will convert the extracted tarball into a proper Ruby Debian package. This tool will eliminate the need for all the manual steps listed above after the gem2tgz invocation and before the package build (debuild).

dh-make-ruby will use the Rubygems metadata that gem2tgz puts inside the generated tarball to automatically fill important files in the package, such as debian/control and debian/copyright. It will also generate a debian/rules that is ready to go for most packages. Hopefull the generated source package will also as lintian-clean as possible.

There is an existing implementation of dh-make-ruby out there, which will be surely taken into account when building our own.

There is also lots of documentation that needs to be written/updated, and all help we get will be appreciated.