Satish BysanyArchiveAbout

Building a .deb package

Starting off, wishing you all a Happy New Year 5020 (gatakali 5019)!

This is a tutorial-for-the-impatient about building .deb packages, meant for installing locally (e.g. your own computer). There are many third-party helpers like checkinstall or fpm, but we’re going to use the same tools used by Debian package maintainers. If you want your deb to be included in the official Debian archive, it needs to be more rigorous and thorough. For a local install, we can be a little flexible. Familiarity with these will help you become a Debian Developer some day :)

As an example, we’re going to consider GNU Stow. It’s a neat Perl tool to keep your home directory clean and under a version control system. A couple of years ago, Debian sid had version 2.2.0 but upstream had released 2.2.2 already, so we’re going to package it.

tl;dr:

    debmake --revision 0~local1 --invoke debuild

Debianization

First step is to “debianize” the upstream sources. We’re going to use debmake (dh_make is similar but older one, but works too. And not to be confused with deb-make which is deprecated and removed from Debian).

wget https://ftp.gnu.org/gnu/stow/stow-2.2.2.tar.gz
tar xf stow-2.2.2.tar.gz
cd stow-2.2.2/

debmake works especially well if the upstream is a well-behaved source, such as GNU software. As a trial run:

./configure
make

If there are errors in either of the above steps, you likely have some packages missing. Just apt-get install them as needed. Luckily, Stow doesn’t need anything more than a recent Perl installation. Run make clean before you go on. We need a few environment variables, which I hope are self-explanatory:

export DEBFULLNAME="Anamika Asok"
export DEBEMAIL="asok@example.com"

You might want to quickly read man debmake to familiarize with the overall options. We’re going to need these:

-j, --judge
   run dpkg-depcheck to judge build dependencies and identify file paths.
-b --binaryspec "binarypackage[:type],..."
   type "perl" implies a Perl script package
-r, --revision "rev"
   set the Debian package revision.

Using -j generates a stow.build-dep.log which lists all the build-time dependencies needed to compile the package. You can just apt-get install them, if needed. Switch -b takes values like perl, python, bin, lib, etc. which adjusts certain Debian packaging variables. If you leave it out, debmake will usually make a pretty good guess.

Debian Revision

Choosing the correct Debian revision (-r) is very important. Most likely, Debian would release an official stow-2.2.2 later and we want to upgrade to it instead of keeping our local install. Revision number helps in this smooth upgrade path. There are strict rules about versioning, but I’ll try to summarize.

Most Debian packages are of the form X.Y.Z-N where everything before the hyphen is the upsteam_version and after hyphen is the debian_revision. In our case X.Y.Z = 2.2.2. The Debian revision number N is usually single digit, incremented by the package maintainer, starting from 1. We want our revision number to lower than official Debian’s, so N = 0 is good. We can compare whether two versions are less than (lt) or greater than (gt), thus:

╭── dpkg --compare-versions 2.2.2-0 lt 2.2.2-1 && echo true
╰─▷ true

If the revision number is omitted (usually for Debian’s infrastructure packages like build-essential or debianutils), it’s taken as zero. X.Y.Z is same as X.Y.Z-0. This collides with our choice of N = 0 above. Oops! We want something which sorts “less than zero”. And that is tilda (~). Think of ~ as a minus sign, like a negative number.

╭── dpkg --compare-versions 2.2.2-0~ lt 2.2.2 && echo true
╰─▷ true

If there’s a minus sign, there’s gotta be a plus sign (+):

╭── dpkg --compare-versions 2.2.2 lt 2.2.2-0+ && echo true
╰─▷ true

In short, 2.2.2-0~ < 2.2.2-0 (=2.2.2) < 2.2.2-0+.

If we ourselves are building stow-2.2.2 many times, let’s call our successive packages as local1, local2, etc.

In short, since we want our package to have as low version number as possible, a good choice would be:

--revision 0~local1

Usually “~yourname” is used for a backport and “+yourname” for a recompile.

“recompile” (e.g. binary NMU), means a package was recompiled without changing the source. This often occurs when one of the libraries a package depends on has changed, and it needs to be recompiled against the newer library. The debian_revision normally will be +b1 (+b2 etc).

“backport” means a “recompile” but from higher Debian release to a lower Debian release (e.g. sid -> testing or testing -> stable).

Invoking debmake

This is easy:

debmake --judge --revision 0~local1 -b":perl"

The output lines starting with I: are info, W: are warnings and E: are errors. This generates a directory called debian/. This process is hence “debianization”.

tree debian/
├── changelog
├── compat
├── control
├── copyright
├── patches
│   └── series
├── README.Debian
├── rules
:
:...

debian/rules is a separate topic in itself. In essence, it’s a just a Makefile which fulfils certain make targets (like build, clean, install etc.). See maint-guide for more.

Editing control and changelog

Edit debian/control. Change Section: manual, Priority: extra, and add a suitable description.

:
...
Section: manual
Priority: extra
Homepage:  https://www.gnu.org/software/stow/
...
Description: software package installation manager
 GNU Stow is a tool for managing the installation of multiple
 software packages in the same run-time directory tree.
 .
 The approach used by Stow is to install each package into its
 own tree, then use symbolic links to make it appear as though
 the files are installed in the common tree. 

Debian package priorities are sorted as required > important > standard > optional > extra.

Add a new changelog entry in debian/changelog. Keep it as UNRELEASED since we’re not going to publish it in testing or unstable.

stow (2.2.2-0~local1) UNRELEASED; urgency=low

  * Initial release. Built from pristine upstream sources.

 -- Anamika Asok <asok@example.com>  Thu, 21 Jan 2016 22:30:17 +0200

You can manipulate changelog entries with dch -i.

Building the package

No need of -uc -us since UNRELEASED. nocheck will skip running make test or make check.

DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage

This generates:

../stow_2.2.2-0~local1_all.deb
../stow_2.2.2-0~local1_amd64.changes
../stow_2.2.2-0~local1.dsc

Info about the package (note uppercase -I):

dpkg -I ../stow_2.2.2-0~local1_all.deb

You can list the contents of the deb:

dpkg -c ../stow_2.2.2-0~local1_all.deb

And, install it, finally (lowercase -i, phew!):

sudo dpkg -i ../stow_2.2.2-0~local1_all.deb

You can remove the package with dpkg -D or apt-get purge stow.

Going further (optional)

Use -i (--invoke) to build the package right after debianization (but without editing debian/changelog etc.)

debmake --judge --revision 0~local1 -b":perl" -i dpkg-buildpackage

You can sign *.dsc and *.changes files using your PGP key (4096-bit RSA recommended, as of today).

export DEBSIGN_KEYID=1234ABCD
debsign ../stow_2.2.2-0~local1.dsc
debsign ../stow_2.2.2-0~local1_amd64.changes

debsign picks the correct signing key from GPG keyring based on the “Maintainer” line in debian/control, even if DEBSIGN_KEYID is defined. Anyways, you can force a different key with -k ABCD1234.

Lintian is a tool to check the .deb for conformance to Debian policy.

lintian -EviI ../stow_2.2.2-0~local1_all.deb

Simplified, debuild runs dpkg-buildpackage + linitian in a clean way by sanitizing environment variables, etc. Highly prefereable than just running dpkg-buildpackage.