Goal

Create a backported Ruby 1.9.3p484 Ubuntu package. For the purposes of this post, we will assume that you are OK with not creating a signed package (required if uploading to launchpad). If you wish to upload to launchpad (for example to share your backport with the world), it may be useful for you to check out this site after reading through this guide.

Motivation

At my day job, I had to upgrade Ruby on very old production boxes that were running Oneiric AMD64. Upgrading the OS was a chore that would be happening later but we needed to start using the latest Ruby as soon as possible.

Unfortunately, there is no Ruby 1.9.3p484 Debian package readily available for Oneiric, not even as a backport.

Basic requirements

  • A reasonable Ubuntu environment. Use Vagrant (and its dependencies, such as Virtualbox) if you are on OSX
  • Basic *Nix knowledge (command line editors and various tools)

Overview

The idea is to use tools readily available on Ubuntu and Debian to create a backported package. These include backportpackage and pbuilder among others.

Without going into too much detail, backportpackage helps us “prep” (e.g. generating .dsc files with conventional names for backported packages) our existing target package on to be backported. pbuilder is a tool that sets up a clean chroot environment (via debootstrap) to build Debian packages. See the man page for backportpackage and the pbuilder howto page for more information.

Normally, backportpackage and pbuilder are very straightforward to use when backporting packages that do not have many dependencies. However, when porting the Ruby 1.9.3p484 package from Trusty to Oneiric, quite a bit of “massaging” needed to be done, mostly because of the significant time difference between the two Ubuntu releases.

Procedure

  1. Have a reasonable Ubuntu environment ready. It doesn’t matter which version you are currently on because we will be using the aforementioned tools to download, prep and build packages. It may be a good idea to run $ sudo apt-get update
  2. $ sudo apt-get install ubuntu-dev-tools to install Ubuntu dev tools on your host machine. This will install
  3. If you are using a version of Ubuntu newer than Precise, you may be able to skip this step. $ wget http://ubuntu.wikimedia.org/ubuntu//pool/universe/u/ubuntu-dev-tools/ubuntu-dev-tools_0.143_all.deb && sudo dpkg -i ubuntu-dev-tools_0.143_all.deb This installs a newer version of backportpackages that allows us to not sign our packages
  4. $ mkdir -p ~/backport_workdir/ruby191 && cd ~/backport_workdir/ruby191 to create and go to our working directory
  5. $ backportpackage --dont-sign -s trusty -d oneiric -w . ruby1.9.1 to download the newest (at time or writing) Ruby 1.9.3p484 package and create the prepped .dsc files for backporting.
  6. Important Open up ruby1.9.1_1.9.3.484-1ubuntu2~ubuntu11.10.1.dsc with your preferred editor and remove the versioning constraints on debhelper and cdbs in the Build-Depends line. Theoretically you could backport dependencies as well and put them in a local apt-get repo, but these particular packages are nasty in that they have many further dependencies and since in this case, the default versions that come with Oneiric are fine, we can safely remove these constraints.
  7. $ sudo apt-get install pbuilder to install pbuilder 8. Create a ~/.pbuilderrc file with the following contents. This is a preference file for pbuilder and the following configuration will allow us to easily toggle between different distributions of Ubuntu and architectures when using it to build packages. Credit to tolaris.com
pbuilderrc (pbuilderrc) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
: ${DIST:=$(lsb_release --short --codename)}
: ${ARCH:=$(dpkg --print-architecture)}
NAME="$DIST-$ARCH"
DISTRIBUTION="$DIST"
DEBOOTSTRAPOPTS=("--arch" "$ARCH" "${DEBOOTSTRAPOPTS[@]}")
BASETGZ="`dirname $BASETGZ`/$NAME-base.tgz"
BUILDRESULT="/var/cache/pbuilder/$NAME/result/"
APTCACHE="/var/cache/pbuilder/$NAME/aptcache/"
# Don't rebuild source files (.diff.gz, .dsc), or list them in .changes
# See Ubuntu bug 118181
DEBBUILDOPTS="-b -d"

case "$DIST" in
    oneiric|trusty|lucid|karmic|jaunty|intrepid|hardy|dapper) # ubuntu specific
        MIRRORSITE="http://archive.ubuntu.com/ubuntu/"
        COMPONENTS="main restricted universe multiverse"
        ;;
    sid|squeeze|lenny|etch) # debian specific
        MIRRORSITE="http://mirrors.kernel.org/debian/"
        COMPONENTS="main contrib non-free"
        ;;
    *)
        echo "Unknown distribution: $DIST"
        exit 1
        ;;
esac

HOOKDIR=$HOME/.pbuilder-hooks

The only additions I’ve made are to add the -d flag, which is required for us to ignore dependency discrepancies (in this case, our debhelper and cdbs dependencies are not at the version specified by the official package) and to update the list of Ubuntu distro names. 9. $ sudo DIST=oneiric ARCH=amd64 pbuilder create to create an Oneiric AMD64 chroot environment to build our backport on. 10. $ sudo DIST=oneiric ARCH=amd64 pbuilder login --save-after-login to login to our chroot environment. The --save-after-login flag tells pbuilder to save the environment after we exit. 11. In chroot environment $ apt-get update && apt-get install tcl8.5-dev tk8.5-dev to install tcl/tk dev packages. Next, symlink the .so files to where the Ruby 1.9.3p484 package for Trusty expects them to be by doing: $ ln -s /usr/lib/libtk8.5.so /usr/lib/x86_64-linux-gnu/libtk8.5.so && ln -s /usr/lib/libtcl8.5.so /usr/lib/x86_64-linux-gnu/libtcl8.5.so. Next, exit the chroot environment by hitting Control-D or $ exit. Normally, pbuilder will take care of downloading build-dependencies for you, but in this case, the problem is that the Ruby 1.9.3p484 package for Trusty assumes taht libtcl and libtk .so files are located in places where they are not installed by default on our target distro. 12. $ sudo DIST=oneiric ARCH=amd64 pbuilder build ruby1.9.1_1.9.3.484-1ubuntu2~ubuntu11.10.1.dsc to instruct pbuilder to build your package. Go grab a coffee, walk your dog, etc. because this may take a while. If you are running in a VM (e.g. in Vagrant), be sure you’ve allocated enough memory (I recommend at least 2GB) so that the build tests for Ruby will pass. 13. When pbuilder is done, look in /var/cache/pbuilder/oneiric-amd64/result/ for your packages

Conclusion

There are a few places where I needed to get my hands dirty and look at package source code to understand where and why things were failing. Hopefully this guide helps you to backport not only Ruby, but any Ubuntu/Debian package between different releases !

If you have problems and questions, please leave a comment :)

Comments