3. Obtaining Your pbuilder Build Environment

Before you can begin backporting packages, you first must setup an appropriate environment for doing so. We'll walk through bootstraping an initial image for pbuilder, the pbuilder configuration, and the hook shell scripts that glue the process together. I'll be using sudo, though not strictly necessary, to execute pbuilder with root privileges extensively, so you may wish to quickly familiarize yourself with it first.

3.1. Obtaining pbuilder

For the purposes of this discussion, it's assumed you'll be using pbuilder >= 0.148. The version that is available in Debian Sarge should work, but you miss out on some options like --save-after-login which can be useful when you must modify the built image interactively, though you generally won't need to.

If you want to simply use the version in Sarge, the usual magic will suffice.


# apt-get update
# apt-get install pbuilder fakeroot sudo devscripts apt-utils

If you'd like the version from Debian Backports, you will need to add a new sources entry to /etc/apt/sources.list and configure /etc/apt/preferences correctly. If you haven't done this before, now is a good time to learn, as backporting with pbuilder will require you to use /etc/apt/preferences fairly extensively.


# cat >> /etc/apt/preferences
Package: *
Pin: release a=sarge-backports
Pin-Priority: 700

Package: *
Pin: release a=stable
Pin-Priority: 600
^D
# echo "deb http://www.backports.org/debian/ sarge-backports main" >> \
  /etc/apt/sources.list
# apt-get update
# apt-get install -t sarge-backports pbuilder
# apt-get install fakeroot sudo devscripts apt-utils

The configuration above allows you to pull software and dependencies from the helpful backporting archive, Debian Backports, which targets backports at the current Debian Stable.

3.2. Modifying your pbuilder Configuration

Before firing up pbuilder, you must first point an editor at /etc/pbuilder/pbuilderrc and make a few changes.

First, change the target MIRRORSITE to something that suites your region.


MIRRORSITE=http://http.us.debian.org/debian

Thereafter, you will want to point DISTRIBUTION at your target of choice as demonstrated below. If you intend to backport packages to the current Debian Stable, as you likely will, then set it accordingly. While you can follow a meta release, be it Stable or Testing, it's best to target a specific release name so your configuration doesn't break mysteriously when a new Debian release occurs.


DISTRIBUTION=sarge

Next, you will want to define a directory, HOOKDIR, for shell scripts that hook into the build process. pbuilder will execute these scripts based on the first three characters of the filename, described later, at different stages of the build process. You must define this as it will be relied upon later for magic to happen. I suggest /etc/pbuilder/hook.d.


HOOKDIR=/etc/pbuilder/hook.d

And, create it.


# mkdir /etc/pbuilder/hook.d

Now, let's specify an important bind mount to the BINDMOUNTS. pbuilder will mount the specified path, in this instance, the path to successfully backported packages, to its respective location within the chroot environment pbuilder operates within.


BINDMOUNTS=/var/cache/pbuilder/result

You can specify additional paths to bind mount, separated by a space, though you should not need to bind mount anything else for successful backporting.


BINDMOUNTS="/var/cache/pbuilder/result /home /usr/src"

Finally, you will need to configure your PATH. While not strictly necessary, I suggest you add /usr/local/sbin and /usr/local/bin to your path, so you can easily integrate distcc, but more on that later.


export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin"

3.3. Bootstrapping your pbuilder Image

At last, the real excitement begins. It's time to bootstrap your pbuilder image. The process is not unlike installing Debian, except there's no installer, hardware configuration, or questions. Instead, the base system is pulled down and initialized for the distribution of your choice. By default, it will be saved in the tarball named by BASETGZ, which you can change either in /etc/pbuilder/pbuilderrc or on the commandline. The default is fine if you only need a image of a single Debian distribution.

To get started, just execute the following. cdebootstrap does the heavy lifting. Or if you're using the older version of pbuilder from Sarge itself, debootstrap.


$ sudo pbuilder create --distribution sarge
W: /.pbuilderrc does not exist
Distribution is sarge.
Building the build environment
 -> running cdebootstrap
/usr/bin/cdebootstrap
...
 -> debootstrap finished
 -> copying local configuration
  -> Installing apt-lines
Refreshing the base.tgz
...
 -> creating base tarball [/var/cache/pbuilder/base.tgz]
 -> cleaning the build env
    -> removing directory /var/cache/pbuilder/build//12775 and its subdirectories

Once that's complete, you should have a shiny new image of the Debian distribution of your choice, Sarge in this instance.


$ ls -lh /var/cache/pbuilder/base.tgz
-rw-r--r--  1 root root 95M Apr 15 03:48 /var/cache/pbuilder/base.tgz

3.4. Feeding your build Environment

If you've never actually tried to backport a package, a brief explanation of the process is necessary or the benefit of feeding your environment will not be immediately apparent.

When backporting any package, you will usually be greeted by a wall of unmet dependencies attempting to block your efforts. These dependencies represent a package's build requirements as determined by the package maintainer, which closely track the upstream author's library dependencies for the package in question. Often, some of the required dependencies will be missing on your target Debian distribution.

In a classical backporting endeavor, you'd execute dpkg-buildpackage to build each dependency as you discover it, install it on your build system, then attempt to build the package that is your ultimate goal. The process repeats until the package goal is achieved or the backporter retires from the field.

When using pbuilder for the process outlined above, it becomes somewhat less painful. Your build environment is self healing. Further, you can use pbuilder hooks, shell scripts that are called at various points in the build process, to ensure that any required build dependencies that you have backported are automatically found and installed. In particular, the following script utilizes an apt-get package pool of your backported packages from pbuilder's own build result directory. As you backport with pbuilder, it feeds itself!

Creating a package pool is fairly straight forward. You must ensure HOOKDIR points to the correct location and that any script you would like to be run is marked executable. The first three characters are significant. The letter D indicates the hook script will be run after your image has been unpackaged and before any attempt to satisfy build dependencies occurs. Hook scripts are executed in ascending numerical order. The letter F performs a similar function for when a login shell into the pbuilder environment is invoked directly.


# mkdir /etc/pbuilder/hook.d
# touch /etc/pbuilder/hook.d/D01apt-ftparchive
# chmod 755 /etc/pbuilder/hook.d/D01apt-ftparchive
# ln /etc/pbuilder/hook.d/D01apt-ftparchive /etc/pbuilder/hook.d/F01apt-ftparchive
# cat >> /etc/pbuilder/hook.d/D01apt-ftparchive

#!/bin/sh

# We want this to be up to date for _every_ run for magic to happen!

( cd /var/cache/pbuilder/result ;
  apt-ftparchive packages . > /var/cache/pbuilder/result/Packages
)

cat<<EOF >/var/cache/pbuilder/result/Release
Archive: stable
Component: main
Origin: pbuilder
Label: pbuilder
Architecture: i386
EOF

cat<<EOF >/etc/apt/sources.list
deb file:///var/cache/pbuilder/result ./
deb http://http.us.debian.org/debian/ sarge main contrib non-free
deb http://www.backports.org/debian/ sarge-backports main
EOF

cat<<EOF >/etc/apt/preferences
Package: *
Pin: release o=pbuilder
Pin-Priority: 701

Package: *
Pin: release a=sarge
Pin-Priority: 600

Package: *
Pin: release a=sarge-backports
Pin-Priority: 700
EOF

apt-get update
^D

Above, the D01apt-ftparchive hook will ensure that your pbuilder image has access to each successful build result. It's important to note the usage of preferences for apt-get above, which pins each successive release to ensure that the latest version of any required dependency is installed. You may wish to adjust that or exclude Debian Backports, depending on your objective. The choice is yours.

Finally, remember that /var/cache/pbuilder/result will be a growing pool of backported packages. If you experience strange results during pbuilder dependency resolution, you may find a previously backported package is the cause. Once you've completed a given backport task, remember to remove packages from /var/cache/pbuilder/result where applicable.