notes-computer-makingDebianPackages

I just made a few Debian packages for WikiGateway. I found that it is simpler than it seems. So I thought I'd write a little guide to the essentials of making Debian packages. Note that I don't really know much about it myself, so this is a case of "the blind leading the blind".

This document assumes that you already know a fair bit about Debian and GNU/Linux administration.

How to unpack a Debian package

mkdir tmpdir_to_unpack_in
cp ../the_package.deb .
dpkg -e the_package.deb DEBIAN 
dpkg -x the_package.deb .

(replace "tmpdir_to_unpack_in" with whatever you want; replace "the_package" with the filename of the .deb)

dpkg -e unpacks the "control files". dpkg -x unpacks the normal files.

The structure of a Debian package

There's two parts; the "control files", also known as "the stuff in the DEBIAN/ subdirectory", and the normal files.

The normal files are laid out in a little fake filetree in order to indicate where they should go.

The control files at a minimum must contain a file called "control", which has a special format (see below).

Example: the normal files

Here's the contents of python-wikigateway_0.001981-1_all.deb:

$ dpkg -x python-wikigateway_0.001981-1_all.deb .
$ ls
python-wikigateway_0.001981-1_all.deb  usr
$ find .
.
./python-wikigateway_0.001981-1_all.deb
./usr
./usr/bin
./usr/sbin
./usr/lib
./usr/lib/python2.3
./usr/lib/python2.3/site-packages
./usr/lib/python2.3/site-packages/WikiGateway
./usr/lib/python2.3/site-packages/WikiGateway/Errors.py
./usr/lib/python2.3/site-packages/WikiGateway/_HighLevelFunctions.py
./usr/lib/python2.3/site-packages/WikiGateway/_WikiGatewayBase.py
.... (a bunch of stuff omitted) ....
./usr/share
./usr/share/doc
./usr/share/doc/python-wikigateway
./usr/share/doc/python-wikigateway/README.txt
./usr/share/doc/python-wikigateway/ARCHITECTURE.txt
./usr/share/doc/python-wikigateway/PKG-INFO
./usr/share/doc/python-wikigateway/WIKI_TYPES.txt
./usr/share/doc/python-wikigateway/copyright
./usr/share/doc/python-wikigateway/changelog.Debian.gz

Example: the control file

$ dpkg -e python-wikigateway_0.001981-1_all.deb DEBIAN
$ cat DEBIAN/control
Package: python-wikigateway
Version: 0.001981-1
Section: python
Priority: extra
Architecture: all
Depends: python, python-egenix-mxdatetime, python-feedparser, python-mechanize
Installed-Size: 492
Maintainer: Bayle Shanks <bshanks2_debian@yahoo.com>
Source: wikigateway
Description: library for interacting with remote wikis
 Wiki::Gateway presents a unified API for interfacing with a variety of
 different wiki engines. It allows you to read, to write, to get
 RecentChanges, and to get a list of all pages on the target wiki.
 .
 Right now, WikiGateway supports (i.e. knows how to talk to) the following
 wiki engines:
 - MoinMoin
 - UseMod
 - OddMuse
 - Mediawiki
 - PhpWiki
 - any wiki providing WikiXmlRpcInterface

Notes:

How to make a debian package

Well, just going off what's above, you could make one now; just make a filetree describing which file goes where, make a control file, then use "dpkg -b" to create a .deb from a directory.

How to make a debian package the hard way

The Debian New Maintainers' Guide has some more complicated suggestions. There are all these helper tools that make it easier if you are doing complicated stuff (like running preinstall scripts) or if you are maintaining a package over time. If you use these, there will be a bunch more special files and a couple more steps. The idea is that the extra complexity is worth it for the efficiency gains.

By the way, if you're making a Perl package, see dh-make-perl. It can package a CPAN module for you automatically!

What do I gain in exchange for this complexity?

The procedure given in the New Maintainers' Guide is tailored to someone (a New Maintainer) who downloads something from "upstream" (i.e. from some other person who wrote the program) and then creates a Debian package for it. Creating the Debian package may include making some changes (for instance, changing which directories it uses; changing configuration defaults; etc) to the software being packaged. Later on, new upstream releases will come along, and the New Maintainer will want to update the corresponding Debian package.

The procedure given in the New Maintainers' Guide is more complex, but will make it easy to redo whatever changes you made to the upstream software as each new release comes out. It will also do things "the right way", i.e. keep a "changelog" that records each successive version of the package.

If you aren't planning on bothering to maintain the package as time goes on "the right way" (i.e. maybe you just want to recreate the package from scratch for each new release), and if you don't need to change the package in the process of making a .deb out of it, then you don't need to do all that. If you are planning on maintaining a package in the official Debian distribution, however, you'll have to do things "the right way".

Using "debhelper" quick & dirty

First, get a .tar.gz of the upstream distribution for the package that you want to make.

Next, create a directory named the Debian name of the package you are going to make, plus a dash, plus the version (e.g. mkdir python-wikigateway-0.00198).

Now,

cd python-wikigateway-0.00198
dh_make -e your.maintainer@address -f ../upstreamDistribFilename.tar.gz

This unpacks the .tar.gz into this directory, creates a "debian" subdirectory with a bunch of files in it, and creates some files in the directory above this one that will help you keep track of different versions of this package.

Wow, now there's a bunch of confusing files. Which ones are important?

First of all, forget about the files which were created above this directory (".changes" and all that). These may be useful later when you download a new upstream version, and they may be useful for providing a "source package" in Debian, but THEY AREN'T USED AT ALL IN CREATING THE FIRST BINARY VERSION OF YOUR DEBIAN PACKAGE.

Second, inside the "debian" subdirectory; here are the only files that are important:

Actually, I'm not even sure if "changelog", "dirs", "compat", "copyright", and "files" are necessary.

All of the *.ex and *.EX files are just examples. You can delete them all.

SOMETHING.docs is not necessary but you may as well use it if you want to include docs. Its format is simple; it's just a text file where each line is the path to a file that you want to put in the documention directory (path is relative to the one directory above the "debian" directory).

"control" was described above. That leaves "rules".

"rules" looks scary. It's just a makefile (does that make it less scary or more :) ). Feel free to fiddle with it to get it to work. Its default contents (i.e. what dh_make puts in it) is designed to be helpful for packages that need to be compiled, and which use Makefiles. But feel free to mess with it.

The objective of most of "rules" is to create a filetree image in the subdirectory debian/YOUR_PACKAGE_NAME. That's all -- it's just a helper to help you create that subdirectory. So feel free to mess with it in any way that helps you achieve that goal.

There is one other thing "rules" does. After it creates that filetree image, you get to the "binary-common" target inside "rules", which as you see called a bunch of dh_* commands. These are what actually build the .deb.

You'll invoke "rules" via the command "dpkg-buildpackage", and I think "dpkg-buildpackage" ultimately invokes "rules" with "make binary".

When you are ready to build (or try to build) the package, just do

     dpkg-buildpackage -us -uc -b -rfakeroot

the "-us -uc" says "don't cryptographically sign the package". "-b" says "binary only; don't build the 'source' package". "-rfakeroot" says "pretend you're root so that the software will install itself in the fake filetree as if you were the root user in a real filetree".

If you're making an architecture-independent package...

If you're making a package that doesn't need to be compiled (say, a Python script)/that doesn't have a makefile, you have to change some things.

Some hints:

If you're making a multiple binary package...

This means you have one "source" distribution that will yield multiple different Debian packages. For instance, the "wikigateway" project that I work on includes a Perl module and a Python module and a commmand-line tool. I package these as three separate .deb packages (with some dependencies between them).

The first thing I tried was making three separate directories (python-wikigateway-0.00198, libwiki-gateway-perl-0.00198, wikiclient-0.00198), running dh_make in each of them, then fixing the contents of the "debian" directory until they all worked. Turned out there was an easier way. You can just make ONE directory (in my case, "wikigateway-0.00198", and then fix things up so that that one directory is used to build 3 separate .deb packages.

It's pretty simple to do so, although I couldn't find good documentation on it. Put 3 different entries into the "debian/control" file, separated by one blank line.

Now massage "rules" as follows:

Example excerpt from the wikigateway "rules" file:

install-indep: install-python-wikigateway install-libwiki-gateway-perl install-wikiclient


install-python-wikigateway:
	dh_testdir -ppython-wikigateway
	dh_testroot -ppython-wikigateway
	dh_clean -k -i -ppython-wikigateway
	dh_clean -k -ppython-wikigateway
	dh_installdirs -i -ppython-wikigateway

	cd libraries/pythonModule; python setup.py install --prefix $(CURDIR)/debian/python-wikigateway/usr

	dh_install -i -ppython-wikigateway

install-libwiki-gateway-perl:
	dh_testdir  -plibwiki-gateway-perl
	dh_testroot  -plibwiki-gateway-perl
	dh_clean -k  -plibwiki-gateway-perl

	cd libraries/perlModule; $(MAKE) install DESTDIR=$(CURDIR)/debian/libwiki-gateway-perl PREFIX=/usr
	# As this is a architecture independent package, we are not supposed to install
	# stuff to /usr/lib. MakeMaker creates the dirs, we delete them from the deb:
	rmdir --ignore-fail-on-non-empty --parents $(CURDIR)/debian/libwiki-gateway-perl/usr/lib/perl5



install-wikiclient:
	mkdir -p $(CURDIR)/debian/wikiclient/usr/bin/
	cp apps/wikiclient $(CURDIR)/debian/wikiclient/usr/bin/

binary-common:
	dh_testdir
	dh_testroot
	dh_installchangelogs 
	dh_installdocs
	dh_installexamples
#	dh_installmenu
#	dh_installdebconf	
#	dh_installlogrotate	
#	dh_installemacsen
#	dh_installpam
#	dh_installmime
#	dh_installinit
#	dh_installcron
#	dh_installinfo
	dh_installman
	dh_link
	dh_strip
	dh_compress 
	dh_fixperms
#	dh_perl
#	dh_python
	dh_makeshlibs
	dh_installdeb
	dh_shlibdeps
	dh_gencontrol
	dh_md5sums
	dh_builddeb