February 22, 2007

Make your own packages for Debian-based systems

Author: Joe 'Zonker' Brockmeier

For the uninitiated, creating Debian packages is a mysterious process that looks much harder than it really is. To make it a little less mysterious, let's take a look at two methods of building Debian packages: using standard Debian packaging tools and the CheckInstall utility.

I've used the tools described in this article to create packages on Debian and Ubuntu systems, but they should be suitable for other Debian-derived distros, such as MEPIS, Xandros, Linspire, and Freespire. In the interest of simplicity, I'm going to use the phrase "Debian package" throughout the article, even though the tools and techniques should apply across the board.

Also note that I'm not going to get into the packaging policies for each distro. If you're interested in contributing packages to one or more distros that use the Debian package system, you can find policy information on the distros' Web sites.

What's all this about Policy?

Debian, Ubuntu, and other distributions have rules about how packages should be put together to be included in the distribution. Debian Policy covers everything from the name and structure of the package to the acceptable licenses for packages. If you check out the Debian Policy docs, it probably seems like a lot of red tape to deal with just to get a package into the repository -- until you realize that the policy is necessary to coordinate the efforts of hundreds (if not thousands) of independent developers.

In addition to Debian's Policy docs, if you are interested in creating Ubuntu packages, see the UbuntuDevelopment page on the Ubuntu wiki. As far as I know, Linspire/Freespire, Xandros, and MEPIS don't have as large developer communities as Debian and Ubuntu, and don't have public guides for package policy.

The easy way

The easiest way to create a Debian package is to use the CheckInstall utility. We've covered it in the past, but I'll run through the steps here briefly. First, install the CheckInstall package:

apt-get install checkinstall

Then, compile the source to your program as you normally would using ./configure and make, but skip the make install step.

Instead, in the source directory, run checkinstall and follow the prompts. That's all there is to it. CheckInstall will create and install the package on your system. If you want to remove the package, it's as easy as using dpkg -r packagename.deb. If you want to install the package on multiple systems, just copy it over and run dpkg -i packagename.deb and you're good.

The right way

CheckInstall is great for quick-and-dirty package generation if all you're worried about is having an easier way to manage applications you're installing from source. However, CheckInstall packages don't pass the sniff test when you are trying to create packages that comply with distro policies.

If you want to create packages that are suitable for distribution, then you'll need to use the native tools to create packages. Don't worry, it's not nearly as painful as you might think.

The first thing you're going to want to do is install a few packages with the utilities you'll need to build packages:

apt-get install build-essential dh-make devscripts fakeroot

The build-essential package is a meta-package that brings in any non-essential system packages that are usually required for building packages, such as GNU Make, the GNU Compiler Collection, and patch. The dh-make package includes tools to convert a standard source tarball into an archive formatted according to Debian policy. As the name implies, the debscripts package includes scripts for developers making Debian packages. The fakeroot package allows you to build packages as a regular user.

You may also want to install a few additional packages, depending on whether you're going to be integrating patches, and if you plan to submit packages to the Debian project. Odds are you have the patch utilities installed anyway, but if not grab the following packages:

apt-get install patch diff patchutils

Debian also offers automated policy checking applications called Lintian and Linda, which examine a Debian package to see if it complies with Debian policy. I think Linda is more user-friendly when describing potential errors in a package, so I'd recommend starting with it:

apt-get install linda

Getting examples

Before you start making packages, you might want to see how other packages are constructed. It's often easier to learn something by looking at examples, and in this case it's simplicity itself to check out the construction of official packages. You probably won't even need to download a package, because you should have a store of packages already, under /var/cache/apt.

To see what's in a given package, just copy it to a work directory and run ar -x packagename.deb. This will give you three files: control.tar.gz, data.tar.gz, and a text file named debian-binary. The debian-binary file contains the version of the Debian file format -- it should just contain one line that reads 2.0.

The control.tar.gz archive contains the package's control file, scripts that are run at various stages of the installation or removal process, and a text file containing the MD5 sums of files in the package's archive. The data.tar.gz, as you might expect, contains the actual files that will be installed.

You can also use Linda to check packages to see if the official Debian packages contain any errors against policy:

linda packagename.deb

Here's some of the output I get when running Linda against a package of quadkonsole that was generated by CheckInstall:


E: quadkonsole; Description starts with package name.
E: quadkonsole; Package is in section checkinstall, which is unknown.
E: quadkonsole; Package does not contain a copyright file.
W: quadkonsole; File /usr/share/doc/quadkonsole/COPYING is considered to be an extra license file.

Lines preceded by E are errors, and lines preceded by W are warnings. See the linda man page for the full scoop.

Making a package

Now for the part you've all been waiting for. To start with, you're going to need a work directory and the source of the software you want to package. Let's say you're working with version 1.0 of a package called rabidbunny. You should have a directory called rabidbunny-1.0, and under that directory, the source of the package you're going to work with.

Once you have that all together, cd to the rabidbunny-1.0 directory and run the dh_make script:

dh_make -e user@domain.com -s -n

After you run this, you'll see a prompt from the script like so:


Maintainer name : Your Name
Email-Address   : user@domain.com
Date            : Tue, 14 Feb 2007 11:26:03 -0700
Package Name    : rabidbunny
Version         : 1.0
License         : blank
Type of Package : Single
Hit <enter> to confirm:

The -e option passes your email address to the dh_make script. The -s option tells dh_make that you're going to make a single binary package, and the -n tells the script that you're going to create a native Debian package. You may need to change these options for some projects, but for the sake of this article we'll assume that you're creating a simple package.

If everything looks good, go ahead and hit Enter. The dh_make script will create a directory named debian in your source directory. You're going to need to edit some of the files under the debian directory before building the package. The order isn't really important but we'll start with the changelog file with information about this version of the package:

rabidbunny (1.0-1) unstable; urgency=low

  *Initial package

  -- Your Name <user@domain.com> Tue, 14 Feb 2007 11:26:03 -0700

If you want to look over changelog examples, look at any package under /usr/share/doc/ for a changelog.Debian.gz file.

You also need to edit the copyright file, which should be self-explanatory. Next, you're going to edit the control file under the debian directory. This file provides information on the package's dependencies, the maintainer contact info, description of the package, the priority level of the package, and other information about the package. See the Debian Policy Manual for more on this file.

You may need to edit the rules file. If your project has a straightforward configure file, it probably won't be necessary. If it is, be sure to read the Debian manual for more information.

You'll also notice that the debian directory includes a number of .ex files, which provide examples of files you might need. Depending on the type of package you're creating, you can remove many of these files safely. For instance, if your application is not a daemon, you don't really need the init.d.ex file. If you have a manpage written already, you can safely remove manpage.1.ex. If you don't have a manpage, you can edit this file as a template for the man page.

Once you have manpages created, you'll need to create a file called manpages that lists the man pages for the package. For instance, if you have two man pages for rabidbunny, like rabidbunny.1 and rabidbunnyrc.1 under the debian directory, you'd want to have two lines in the manpages file:

debian/rabidbunny.1
debian/rabidbunnyrc.1

Once you've finished tweaking all the files under the debian directory, it's time for the moment of truth. To build the package, run the debuild utility:

debuild --linda -us -uc

This will compile the source and then create a Debian package. The -us -uc options tell debuild not to sign the package -- if you do have a GPG key, you'll want to skip those. The --linda option tells debuild to use Linda to check the package rather than Lintian. Skip that option if you'd prefer to use Lintian.

After compiling the package, you may see a number of warnings or errors from Linda (or Lintian). Depending on the severity of the errors, you may have to make some changes and then re-run debuild.

If you don't see any fatal errors you can move up one directory and find the newly created Debian package. Install it using dpkg for a final test:

dpkg -i rabidbunny_1.0.0_i386.deb

And now you're done. If you aren't getting massive errors from Linda, then you should be able use this package to distribute to other users and even for inclusion in Debian, Ubuntu, or any other Debian-derived distro. Happy packaging.