Reflecting on Linux packages and how they are built

I was tasked to build a .deb package recently (the software package for Debian-alike systems such as Debian and Ubuntu). As I was inexperienced in the matter, I frequently consulted the documentation. Unfortunately, the more I worked on building the .deb package, the more I saw how slapdash the documentation and the build-tools are.

My packaging experience up to this point has only been with RPM’s and Slackware packages. Both of these have particular shortcomings, but make up for it in simplicity.

RPM’s are built with a single .spec file which contains all the information for the build process. The .spec file format takes a little bit of reading the documentation (about 1-2 hours), but simply looking at an example .spec file can give you a general idea of how to build one. If specific files need to go to specific places, it’s not a big deal.

Slackware packages are a little simpler in construction compared to an RPM, as they are built with shell scripts. This is handy as you don’t need to learn any funky syntax to get going, although one of the problems with the scripts are the lack of dependency control. I’ve only had a problem with this a couple of times, but as long as the configure script inside the project’s tarball does a half-decent job of flagging missing dependencies, it shouldn’t be too bad.

.deb files are a different beast altogether. Now I know that Debian has several command-line tools to make some of these things easier, but I still find the process overly brittle. Inside of the project directory you need to make a debian folder, and inside of that folder are several files.

  • control - This file is primarily for package information, such that programs such as apt and dpkg can read the metadata. I can understand requiring certain fields, but requiring the order they’re supposed to be in without having the build tools giving meaningful errors just seems a bit boneheaded.
  • rules - This is the real meat of the package, and possibly the most complicated part. This file is a standard makefile, with several required targets. If you have a simple configure; make; make install type of installation, they even have a simple way of doing it that’s only a couple of lines. However, if your package deviates from this in any way, you need to write the whole thing yourself. Looking through several Debian and Ubuntu packages, a lot of the projects use a pre-written template and comment out the unnecessary debhelper programs that are used for each target.
  • *packagename*.dirs - This file is used by one of the debhelper programs to make the temporary directory structure for the packaging process.
  • copyright - This file is self-explanatory. I still find it a bit off-putting that this a required file, but it’s just enough to touch the file.
  • compat - This defines the debhelper compatibility mode. Seems like there should be a better place for that information in either control or rules.
  • changelog - Here’s the one that really pisses me off. Again, I can understand it being a required file, but requiring a specific format that you can only really get right by using dch -i is not cool.

Now where the confusion sets in is whether to then use dpkg-buildpackage, dpkg-deb --build, or even call a target in the rules file directly. Choice is fine for browsers and mail clients, but here’s a situation where the ambiguity just leads to confusion. These three choices all build in slightly different ways, and one of them may work while the other ways do not.

With the wealth of .deb packages on the net, it makes me wonder whether there’s an insanely dedicated small group of packagers for Debian, or a lot of people who tried to package one project and gave up after it. From the amount of wailing in the forums and the lack of coherency in documentation, I’m tempted to think the latter.