This is a DRAFT

This page was taken from the Ubuntu Wiki and is being edited here. If the changes are satisfactory, they will be put on the original page Also note that this tutorial is written in first person. However, this guide involves the work of more than one person and I doesn't refer to one person in particular.

Credits and License

pochu(Emilio Pozuelo Monfort) and Stani co-hosted the Python Apps Packaging IRC session (during "Ubuntu Open Week 2008") that the original guide was based on.

Michael Gliwinski wrote the original guide based on the Emilio's and Stani's IRC session.

Creative Commons License

This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License

CDBS and debhelper

There are two popular packaging tools that will help you build your Debian package, CDBS and debhelper. Packaging using one of these tools is significantly different from packing with the other. This tutorial will guide you through packing using both these tools separately.

In the first part, we will package a software project called Terminator using CDBS. The second part uses debhelper7 to package python-markdown. Both these tools make packaging projects that use distutils easy. However, the people at debian-python seems to lean a bit towards debhelper. #REVIEWERS: Check neutrality and validity of this statement. This is possibly because debhelper's simple case is "absurdly simple" (as the author of debhelper put it) and the more complicated cases are easier to understand and work with. It is also easy to install files without distutils when using debhelper.

Before we begin

Here's what we need to begin packaging our software:

If you are packaging using cdbs, then you will have to install the cdbs package as well.

Some of the tools introduced below will look for two environment variables to guess your name and email address to put in the package metadata, let's set them up here:

  export DEBFULLNAME="Your Name"
  export DEBEMAIL="Your.Email@address.here"

you should also add these to your .bashrc or other shell startup script if you want them to be set up automatically.

To begin we will need to make a folder inside which we will work, where the packaging and building will take place. You can adjust the directory below to your liking.

  $ mkdir ~/python-packaging 
  $ cd ~/python-packaging

The CDBS way

As mentioned earlier, this tutorial will introduce you to the CDBS method of packaging python applications by an example of a software called Terminator. Terminator is a terminal emulator written in python that can split several terminals in the same window.

The source tarball

You need the source tarball, as distributed by the upstream author. It is best to choose the source in tar.gz (or tar.bz2) format (in case the author distributes the package in various formats), as then we won't need to modify the source format for packaging. For terminator do:

  $ wget http://launchpad.net/terminator/trunk/0.14/+download/terminator_0.14.tar.gz

to get the source.

Let's unpack the tarball and enter the resulting directory to work on it:

  $ tar -xf terminator_0.14.tar.gz
  $ cd terminator-0.14/
  $ ls -lt

A quick look at the contents of the package and the INSTALL file reveals this software is using distutils, just what we need, let's start the packaging :)

Applying the template

We are going to use dh_make, which will create a template from which we will work on. Run:

  $ dh_make -c gpl -s -b -f ../terminator_0.14.tar.gz

which means: -c gpl tells it that the package is licensed under the GPL license, -s tells it that we just want one binary package. One source package can be split into many binary packages. This is very useful when a package has huge documentation (so you build a -doc package too), or many images (so you build a -common package), or it's a library. We just need one, which will contain everything, -b tells it to use CDBS, Common Debian Build System, which will make our packaging simple, so we can concentrate on the Python specific things. -f ../terminator_0.14.tar.gz tells it that we are using the ../terminator_0.14.tar.gz file as our source.

You should see something like:

Maintainer name : Your Name
Email-Address   : Your.Email@address.here
Date            : Wed, 24 Feb 2010 19:53:51 +0530
Package Name    : terminator
Version         : 0.14
License         : gpl3
Using dpatch    : no
Using quilt     : no
Type of Package : cdbs
Hit <enter> to confirm: 
Currently there is no top level Makefile.  This may require additional tuning.
Done.  Please edit the files in the debian/ subdirectory now.  You should also
check that the terminator Makefiles install into $DESTDIR and not in / .

Press enter. Before we look at what has happened inside the terminator-0.14/ directory, let's see what has happened to the directory above it:

  $ cd ../
  $ ls -l

You'll notice that there is a file here that we haven't created: terminator_0.14.orig.tar.gz. Packaging programs, in addition to binary package, also generates a source package which consists of three files: ${PKGNAME}_${VER}.orig.tar.gz (the original upstream tarball), ${PKGNAME}_${VER}-${PKGVER}.diff.gz (a diff file for the debian/ directory) and ${PKGNAME}_${VER}-${PKGVER}.dsc (a signed summary of the source package). Because we told dh_make where our upstream source tarball was, it renamed it appropriately (${PKGNAME}_${VER}.orig.tar.gz). We could very well have renamed it ourself and not passed the -f option, we chose to be lazy!

The debian/ directory

Let's enter the newly created debian/ directory.

  $ cd terminator-0.14/debian/

The many files inside debian/

A quick listing of the debian/ directory shows the template files. There's many files we don't want for this example (all the *.ex ones), so let's get rid of them. These files are useful examples, as you can guess you have templates for init scripts, man pages, Debian menu files, maintainer scripts, watch files, etc. (If you wanted to use any of the example files just rename it to remove the .ex suffix and adjust contents to your needs). You should find the Debian New Maintainers' Guide helpful here.

In normal situations you may want to use a manpage if the application doesn't have it's own, as it is required by the Debian Policy and your package has a greater chance of getting through the review process if it complies.

Terminator contains (and installs within setup.py itself) it's own .desktop file. This is the file that installs a menu item for the package (required only for applications, not modules). Often, the upstream tarball will not contain a .desktop file (since not all programs are designed only for Linux) and we will need to write this by ourselves. It is important to emphasize here that we should not touch anything from the upstream source (except for special cases, which haven't been documented very well as yet). All packaging work takes place ONLY inside the debian/ directory.

changelog
compat
control
copyright
cron.d.ex
dirs
docs
emacsen-install.ex
emacsen-remove.ex
emacsen-startup.ex
init.d.ex
init.d.lsb.ex
manpage.1.ex
manpage.sgml.ex
manpage.xml.ex
menu.ex
postinst.ex
postrm.ex
preinst.ex
prerm.ex
README.Debian
rules
terminator-default.ex
terminator.doc-base.EX
watch.ex

  $ rm *ex *EX

Let's finish with the other files. As we don't need to document anything in README.Debian, let's remove it. We don't need the dirs file, as distutils and python-support/central will take care of making the necessary directories.

  $ rm README.Debian dirs

Package information - debian/control

Ok, now let's start filling the template. first we will edit the control file, so open it in your preferred editor. As you can see, the file is separated in two sections. The first one is always the source package info, and the others (in our case it's just one) are the binary packages. For the source package, we need to change the Section (misc is a good one, the list is here), the Priority should be optional (it's extra for -dev, -dbg packages, and maybe a few others).

If you're packaging a Python module, section should be python, but not for applications.

For packages that enter Debian, the Standards-Version should be the latest. Since we would normally not be using the latest dh_make, the value in this field might be lower than it should. The changes in policy are summarized in a checklist and the full policy is also available. (Note: when updating Standards-Version, we should always check that we are still compliant to the new Policy). This may seem complicated at first. You should ask #debian-python or #debian-mentors if you have any question about this.

The Architecture should be all (for Python packages), as our code is architecture-independent, so we don't need to compile it for every architecture (i386, amd64, powerpc, sparc...). This is true always for Python code, but it's different when we are packaging Python bindings written in C for example. For the reference all means architecture independent, any means should be compiled on any available architecture.

In the section for the binary package, we need to put a short and long description. The first line of the field is the short description and the next lines are the long description. For the long description, every line should start with an space, and if you want to put a white line, it should be an space and a dot, " .".

Python specific details

Now let's get to the Python specific bits. Look at the Build-Depends and Depends. The Build-Depends are the packages we need to build our package, and the Depends are the packages we need to run it. Let's look at the Depends first. We need to add here all the modules our application uses. Our job is made simple, since the INSTALL file lists the dependencies (python, python-vte and python-gnome2). If this information was not provided, we would need to perform a grep and search for all the lines with "import" in them:

  $ grep -B 3 -A 3 import ../terminator

There we have our list of imported modules. Some of them are standard to Python (i.e. shipped with Python itself, so depending on Python will be enough to cover them), but others aren't. Let's list them all. Also, most of them are required, but if you look at 'import gnome', if it's not installed it will just import the webbrowser module, which is a standard Python module. We will need to depend on modules which aren't shipped with Python so that our package can actually work.

For the Depends field we will need to find package names. To do that you may need to do some research, although 'apt-cache search $module | grep python' may help. So we have gobject, which is in python-gobject, gtk and pango which are in python-gtk2, gconf which is in python-gconf, and vte which is in python-vte. A quick look at 'apt-cache depends python-gnome2 | grep python-' shows us that all these dependencies are met by python-gnome2. (How did we decide to look up python-gnome2, you ask? The INSTALL file ;) )

So let's add python-gnome2, python-vte to Depends. We can also remove ${shlibs:Depends} which isn't useful for pure Python packages. We also depend on python so we insert ${python:Depends} as a dependency. This doesn't look like a real package name. Since we are going to use python-support or python-central (we'll come to that later), this will be interpreted appropriately. The DebianPython Policy has more on this.

Build-Depends

Looking at the python policy, specifically at the section on build dependencies we can see that we need to build depend on python, and python-support (or the python-central alternative). You can choose either, but debian-python seems to lean towards python-support so we will go with python-support. (Change it to python-central if you want to use pycentral).

Let's also look at what python-support actually does. The Debian Python Policy has a section on packaging tools. We can see that both python-support and python-central integrate with debhelper, therefore we Build-Depend on debhelper as well.

Let's add the following lines to the source section (i.e. the first section) of the control file:

Build-Depends: cdbs (>= 0.4.49), debhelper (>= 7), python (>= 2.4), python-support

(If you are using python-central, just replace python-support with python-central). You can also change the version of python depending on the software you are packaging.

Whichever packaging tool we use will need to know which python version we are building on. So we add a XS-Python-Version field also:

XS-Python-Version: >= 2.4

Note here that you need to build depend on the same version of python that you use in XS-Python-Version.

That leaves the our control file looking roughly like this (note that the standards version field needs to be the latest, but you have to make sure your package follows the latest policy before doing that):

Source: terminator
Section: misc
Priority: optional
Maintainer: Your Name <Your.Email@address.here>
Build-Depends: cdbs (>= 0.4.49), debhelper (>= 7), python (>= 2.4), python-support
XS-Python-Version: >= 2.4
Standards-Version: 3.8.4
Homepage: https://launchpad.net/terminator

Package: terminator
Architecture: any
Depends: ${misc:Depends}, python-gnome2, python-vte, ${python:Depends}
Description: Multiple GNOME terminals in one window
 Terminator is a little project to produce an efficient way of filling a large 
 area of screen space with terminals.
 .
 The user can have multiple terminals in one window and use keybindings to 
 switch between them.  See the manpage for details.

Please don't blindly copy this file. If you write it yourself, you will find it much easier to write a control file the next time.

Building instructions - debian/rules

The debian/rules file is a makefile that actually builds the package. CDBS uses the setup.py from the upstream source to build our package, which reduces our job here to almost nothing. setup.py is usally a script that uses distutils to distribute the python project. It's a system to distribute Python applications and modules: see. Our example application - terminator - uses it so we don't need to worry about that now.

We need to set the DEB_PYTHON_SYSTEM environment variable in the rules makefile. As we have chosen python-support, that would look like DEB_PYTHON_SYSTEM=pysupport before the includes. (You would replace this with pycentral if you used python-central).

And finally let's add the distutils magic, removing the makefile one (as the package doesn't have a Makefile but a distutils script). So let's change include /usr/share/cdbs/1/class/makefile.mk with include /usr/share/cdbs/1/class/python-distutils.mk

We should be done now :-) This is roughly how your file should look like:

#!/usr/bin/make -f

DEB_PYTHON_SYSTEM=pysupport

include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/class/python-distutils.mk

# Add here any variable or target overrides you need.

Changes information - debian/changelog

Before we begin editing this file (and if you already have, close your editor), I'm going to introduce you to a tool that helps you edit this file: dch. This script uses the environment variables (name and email) mentioned in the initial section of this tutorial, so make sure you have them set up. This tools automatically makes some changes before you begin editing to make editing it simpler. For now we only want to edit the changelog, so we pass the -e flag. In other cases, we might like to add a new changelog entry (for a new Debian revision or a new upstream release). There are many options that you can pass to do such things, so you should look up man dch.

  $ dch -e

And let's put a bug number there in Closes (for this example we don't have one, so let's invent it). If the package is only for Ubuntu, the bug should be a Launchpad bug and we should change Closes with LP. For Ubuntu also change unstable with intrepid and 0.14-1 with 0.14-0ubuntu1. (These can also be done by passing flags to dch, which is better because it reduces the chance of your making a mistake).

Remember that if you package it for Debian, then it will hit both Debian and Ubuntu, and probably other Debian derivatives. If you intend to submit your package to Debian (and have it reach a wider audience) then you should put your ITP (Intend To Package) bug number like this: "Initial release (Closes: #123456)".

As a reminder, version number format is: ${UPSTREAM_VER}-${DEBIAN_PKG_RELEASE}(ubuntu${UBUNTU_PKG_RELEASE})?. If the package is not in Debian, you should leave DEBIAN_PKG_RELEASE as 0.

We have almost finished this! We only need to put the right info in debian/copyright. This is very important for real packaging. Without a perfect debian/copyright file listing all the necessary info, the package should not be distributed and will certainly be rejected at the first step if you submit it to Debian or Ubuntu. To write good debian/copyright files, these two mails from a couple of Debian Developers are very useful: this, and this. You can also read the section on the copyright file on Debian New Maintainers' Guide.

Ready to build

So let's now build the package and install it! Enter the source root directory (i.e. if you're still in debian/ then do cd ..), be prepared to be flooded with all sorts of text and do:

  $ debuild -us -uc

That will build the source and binary package. The -us -uc options are not to sign the source and changes files (we would need to sign them to upload them to Ubuntu/Debian/your PPA, but we'll skip that in this tutorial, if you are interested in PPAs, there was a session about it, logs are available here).

If everything has gone fine you will feel bombarded with command line output that will end with something like this:

dpkg-deb: building package `terminator' in `../terminator_0.14-1_i386.deb'.
 dpkg-genchanges  >../terminator_0.14-1_i386.changes
dpkg-genchanges: including full source code in upload
dpkg-buildpackage: full upload (original source is included)
Now running lintian...
W: terminator source: newer-standards-version 3.8.4 (current is 3.8.3)
W: terminator: manpage-has-errors-from-man usr/share/man/man5/terminator_config.5.gz 185: warning [p 4, 5.2i]: cannot adjust line
Finished running lintian.

Lintian complains a little. We will ignore this for now, but will have to (have to) fix these errors if we are to get the package into Debian. (The first error is because my lintian is outdated).

We can now install the package. The debi command (from the devscripts package too) will install it if we have just built it from the package directory, so we can do:

$ sudo debi

This should end with something like:

Setting up terminator (0.14-1) ...

Processing triggers for desktop-file-utils ...
Processing triggers for hicolor-icon-theme ...
Processing triggers for man-db ...
Processing triggers for python-support ...

So we got it!! Now you can start terminator with the following command:

$ terminator

And there is a terminator menu entry in the Accesories menu (that's in GNOME). So we are done :-)

The debhelper way

python-markdown, is Markdown written in Python. If you've used the perl or PHP implementations, you'll know that Markdown quite a neat syntax for plain text formatiing (and should consider using it the next time you need something to format your plain text).

Source tarball

Let's get straight to downloading the original tarball. At the moment the latest version of python-markdown is 2.0.3, and there's a .tar.gz available so let's wget that:

  $ wget http://pypi.python.org/packages/source/M/Markdown/Markdown-2.0.3.tar.gz
  $ tar -xf Markdown-2.0.3.tar.gz
  $ cd Markdown-2.0.3/

Applying the template

Let's try to use dh_make and apply the template to our package:

  $ dh_make

And now we have our first encounter with Debian Policy: the package name is "not in a valid format". Let's fix it:

  $ cd ../
  $ mv Markdown-2.0.3 markdown-2.0.3
  $ cd markdown-2.0.3/

Since that fixes it, we can now get to applying the dh_make template on our package:

  $ dh_make -c bsd -s -f ../Markdown-2.0.3.tar.gz

And we get:

Maintainer name : Your Name
Email-Address   : Your.Email@address.here 
Date            : Mon, 01 Mar 2010 20:09:18 +0530
Package Name    : markdown
Version         : 2.0.3
License         : bsd
Using dpatch    : no
Using quilt     : no
Type of Package : Single
Hit <enter> to confirm: 

Let's take a look at what we've told dh_make and what it has done. dh_make helps us create a debian package out of the source code. It applies a template inteligently, leaving us with very little work to do. -c bsd tells it that the package is licensed under the BSD license (always check to see which license the project is distributed under, in this case we need to look in doc/), -s tells it that we just want one binary package. One source package can be split into many binary packages. This is very useful when a package has huge documentation (so you build a -doc package too), or many images (so you build a -common package), or it's a library. We just need one, which will contain everything, -f ../Markdown-2.0.3.tar.gz tells it that we are using the ../Markdown-2.0.3.tar.gz file as our source.

A Debian source package consists of three files: ${PKGNAME}_${VER}.orig.tar.gz (the original upstream tarball), ${PKGNAME}_${VER}-${PKGVER}.diff.gz (a diff file for the debian/ directory) and ${PKGNAME}_${VER}-${PKGVER}.dsc (a signed summary of the source package)

Look at what passing the -f has done:

  $ cd ../
  $ ls -l

Because we told dh_make where our upstream source tarball was, it copied it appropriately (there is now a markdown_2.0.3.orig.tar.gz file). We could very well have renamed it ourself and not passed the -f option, we chose to be lazy!

Let's now jump straight into packaging!

The debian/ directory

The many files inside debian/

  $ cd markdown-2.0.3/debian/
  $ ls -l

That is a lot of files! Don't worry, most of them will be gone in a minute. :)

changelog
compat
control
copyright
cron.d.ex
dirs
docs
emacsen-install.ex
emacsen-remove.ex
emacsen-startup.ex
init.d.ex
init.d.lsb.ex
manpage.1.ex
manpage.sgml.ex
manpage.xml.ex
markdown.default.ex
markdown.doc-base.EX
menu.ex
postinst.ex
postrm.ex
preinst.ex
prerm.ex
README.Debian
rules
watch.ex

There're many files we don't want for this example (all the *.ex ones), so let's get rid of them. These files are useful examples, as you can guess you have templates for init scripts, man pages, Debian menu files, maintainer scripts, watch files, etc. (If you wanted to use any of the example files just rename it to remove the .ex suffix and adjust contents to your needs). You should find the Debian New Maintainers' Guide helpful here.

In normal situations you may want to use a manpage if the application doesn't have it's own, as it is required by the Debian Policy and your package has a greater chance of getting through the review process if it complies. Markdown doesn't have one in the upstream source tarball and if we were going to submit this to Debian, we'd have to write.

Before we touch anything here, it should be emphasized that we are not supposed to touch anything, anything, outside the debian/ directory. The source code should remain originial, except for special cases, which haven't been documented very well as yet.

So, as promised we're going to delete a lot of files from this directory. If you plan to distribute your package, you should look up the functions of each of these files.

  $ rm *ex *EX
  $ rm dirs docs README.Debian
  $ ls -l

We now have a managable number of files:

changelog
compat
control
copyright
rules

Package information - debian/control

The control files contains all the information about the package - name, maintainer, dependencies, etc. That means that this section is all about filling in information. Use your favourite editor and open the control file. You'll notice immidiately that the file has two sections. The first section is for the source package (information required to build the package) and the second for the binary package (information about the binary package that will be used by the users' package manager). In our case we are building only one binary package. If there were more binaries, then we would make one section for each binary package.

Although the name could (and should) have been python-markdown, we'll leave it as it is for now (as that would mean renaming the directory). Since we are packaging a python module, the section should be python. A full list of sections is available in the Debian Policy. The Priority should usually be optional.

Let's leave the Build-Dependencies in the source package information as it is and come back to it at the end.

Since we're going to follow the latest Debian Policy, we'll use the latest version number for the Standards-Version field. Whenever we "bump" the Standards-Version to the latest version, we should ensure that we're following the latest policy by reading the upgrading checklist. Also note that since you're not neccessarily using the latest dh_make (especially if you are using Ubuntu), you might have to change this to the latest manually. The policy is at version 3.8.4 at the time of writing this. You should check this when you're building a package for Debian.

The upstream Homepage is http://www.freewisdom.org/projects/python-markdown, so we can now fill that field as well.

Let's move on to the binary package information (remember, we'll come back for the build-dependencies later).

Since we are building a Pure Python module, the Architecture should be all. If the package had Python bindings in C, for example, we would need to use any.

We should also add a short and long description of the package. Each line of the long description starts with a space. An empty line is a space and a dot: " .". There're a lot of "best practices" about package descriptions. The Developers' Reference will give you a good idea of what sort of description is expected when you submit a package to Debian.

Package Dependencies

Let's look at what the package currently depends on: ${shlibs:Depends}, ${misc:Depends}. We can remove ${shlibs:Depends}, since we don't need it. ${misc:Depends} is debhelper magic. debhelper keeps track of all the dh commands (don't worry, we'll come that soon) that we use and ensures that our package depends any other package that is required to run the command we do.

We're also going to use a tool called python-support (we'll see how soon), or it's alternative - python-central. These tools automatically expand some values for us, so we can simply add ${python:Depends} as a depedency. We also need to look for other dependencies. Normally we would run grep -r "import" .. if we didn't know what we depended on. The INSTALL file saves us the trouble and us that python-markdown depends on ?ElementTree. A little bit of looking up tells us that ?ElementTree is already in python by default, which leaves us with only Python to depend on.

Build-Dependencies

We've got just one part of the the control file remaining: Build Dependencies. Build-Dependencies are the packages that are required to build the package. When we write the control file, we most probably already have the dependencies. However, packages are usually built in chroots, and only the build dependencies are installed. So we need to make sure that we don't add too much, but we also need to make sure that our package builds. As you can see, we already depend on debhelper. As I mentioned earlier, we're using python-support to help build the package, so we need to build-depend on python-support also. If you are using python-central, you can build depend on that instead of python-support.

Needless to say, we need to depend on python also. However, it is important that we know which versions of python we can use to build and run our project. For most projects >=2.4 should do fine. Our Build-Depends field now looks like:

Build-Depends: debhelper (>= 7), python-support, python (>=2.4)

Our control file now looks like this:

Source: markdown
Section: python
Priority: optional
Maintainer: Your Name <Your.Email@address.here>
Build-Depends: debhelper (>= 7), python-support, python (>=2.4)
Standards-Version: 3.8.4
Homepage: http://www.freewisdom.org/projects/python-markdown

Package: markdown
Architecture: all
Depends: ${misc:Depends}, ${python:Depends}
Description: text-to-HTML conversion library/tool
 Markdown is a text-to-HTML conversion tool for web writers. Markdown 
 allows you to write using an easy-to-read, easy-to-write plain text 
 format, then convert it to structurally valid XHTML (or HTML).
 .
 This is a Python implementation of John Gruber's Markdown. The current
 version of python-markdown implements all Markdown syntax features and 
 fully passes Markdown Test Suite 1.0. It also supports footnotes and 
 attributes. 

We can our move on to pyversions.

Python versions information - debian/pyversions

Like I mentioned earlier, pysupport manages our python dependencies, so we need to tell pysupport which python versions the package can use. We create a pyversions file for that. This file contains only one line, here're some examples: 2.4- for 2.4 and above -2.5 for 2.5 and below 2.5 for 2.5 only Since we've said >=2.4 in the build depends field we'll use 2.4- in our pyversions file. Ensure that the versions you've put in Build-Depends should match the versions in pyversions.

  $ echo "2.4-" > pyversions

Building instructions (simple) - debian/rules

debhelper makes writing a rules file very easy. It just allows us to hand over all the complicated work to debhelper. Here's what a simple rules file (a.k.a cdbs killer) looks like:

#!/usr/bin/make -f
%:
        dh $@

Make sure that you use a tab and not spaces to indent (general rule for the rules file ;) ) This is like auto-pilot. All the targets go to % and dh handles them all. (e.g. a clean target would run dh clean, an install would run dh install). We can override anything we want to, but we'll come to that only much later.

Changes information - debian/changelog

Before we begin editing this file (and if you already have, close your editor), I'm going to introduce you to a tool that helps you edit this file: dch. This script uses the environment variables (name and email) mentioned in the initial section of this tutorial, so make sure you have them set up. This tools automatically makes some changes before you begin editing to make editing it simpler. For now we only want to edit the changelog, so we pass the -e flag. In other cases, we might like to add a new changelog entry (for a new Debian revision or a new upstream release). There are many options that you can pass to do such things, so you should look up man dch.

  $ dch -e

And let's put a bug number there in Closes (for this example we don't have one, so let's invent it). If the package is only for Ubuntu, the bug should be a Launchpad bug and we should change Closes with LP. For Ubuntu also change unstable with intrepid and 0.14-1 with 0.14-0ubuntu1. (These can also be done by passing flags to dch, which is better because it reduces the chance of your making a mistake).

Remember that if you package it for Debian, then it will hit both Debian and Ubuntu, and probably other Debian derivatives. If you intend to submit your package to Debian (and have it reach a wider audience) then you should put your ITP (Intend To Package) bug number like this: "Initial release (Closes: #123456)".

As a reminder, version number format is: ${UPSTREAM_VER}-${DEBIAN_PKG_RELEASE}(ubuntu${UBUNTU_PKG_RELEASE})?. If the package is not in Debian, you should leave DEBIAN_PKG_RELEASE as 0.

We have almost finished this! We only need to put the right info in debian/copyright. This is very important for real packaging. Without a perfect debian/copyright file listing all the necessary info, the package should not be distributed and will certainly be rejected at the first step if you submit it to Debian or Ubuntu. To write good debian/copyright files, these two mails from a couple of Debian Developers are very useful: this, and this. You can also read the section on the copyright file on Debian New Maintainers' Guide.

Ready to build

So let's now build the package and install it! Enter the source root directory (i.e. if you're still in debian/ then do cd ..), be prepared to be flooded with all sorts of text and do:

  $ debuild -us -uc

That will build the source and binary package. The -us -uc options are not to sign the source and changes files (we would need to sign them to upload them to Ubuntu/Debian/your PPA, but we'll skip that in this tutorial, if you are interested in PPAs, there was a session about it, logs are available here).

If everything has gone fine you will feel bombarded with command line output that will end with something like this:

dpkg-deb: building package `markdown' in `../markdown_2.0.3-1_all.deb'.
 dpkg-genchanges  >../markdown_2.0.3-1_i386.changes
dpkg-genchanges: including full source code in upload
dpkg-buildpackage: full upload (original source is included)
Now running lintian...
W: markdown source: newer-standards-version 3.8.4 (current is 3.8.3)
W: markdown: binary-without-manpage usr/bin/markdown
W: markdown: unusual-interpreter ./usr/share/pyshared/markdown/extensions/def_list.py #!Python
W: markdown: unusual-interpreter ./usr/share/pyshared/markdown/extensions/tables.py #!Python
Finished running lintian.

Lintian complains. Some of these are upstream issues, one we would need to fix if we were submitting to Debian (we'd have to write a manpage ourselves and use markdown.manpages to have it installed). We will ignore this for now.

We can now install the package. The debi command (from the devscripts package too) will install it if we have just built it from the package directory, so we can do:

$ sudo debi

A sophisticated rules files

debhelper allows us to customize our package beyond the simple distutils installation. In fact, it is very easy to build a package without a distutils (setup.py) script at all!

In this section, we will look at simple rules examples. Before that, a quick recap at what rules does and what we've put in it. At the moment, our rules file looks somethink like this:

#!/usr/bin/make -f
%:
        dh $@

(Remember to check that your editor is not expanding tabs into spaces)

This, like I said before, is like an auto-pilot mode. dh does everything by itself. If you look at this like a makefile, we are making all targets point to the relavant dh command. If we want to override a target, we create a new target, override_dh_foobar, where foobar is the target we're trying to override.

Let's take, for example, a case where we want to install only three files, but for some reason, don't want to use distutils to get the files installed. The first thing we need to do is to make sure that dh doesn't try to use an auto mode and run setup.py (in case we have one, it will generally run it). For this we add the following lines to rules:

override_dh_auto_build:

override_dh_auto_install:

Now, debhelper will simply skip the steps where it does an auto build and install. However, it will still call dh_install, which we want. There are two ways to use dh_install. Although I will explain this particular example here, you should know that you can always get a huge amount of information from the manpages. Let's take a look at the dh_install manpage:

  $ man dh_install

and we get:

...
       dh_install [-Xitem] [--autodest] [--sourcedir=dir] [debhelper options]
       [file [...] dest]
...
       dh_install is a debhelper program that handles installing files into
       package build directories. There are many dh_install* commands that
       handle installing specific types of files such as documentation,
       examples, man pages, and so on, and they should be used when possible
       as they often have extra intelligence for those particular tasks.
       dh_install, then, is useful for installing everything else, for which
       no particular intelligence is needed. It is a replacement for the old
       dh_movefiles command.

       Files named debian/package.install list the files to install into each
       package and the directory they should be installed to. The format is a
       set of lines, where each line lists a file or files to install, and at
       the end of the line tells the directory it should be installed in. The
       name of the files (or directories) to install should be given relative
       to the current directory, while the installation directory is given
       relative to the package build directory. You may use wildcards in the
       names of the files to install (in v3 mode and above).
...

This means that there are two ways of installing files. The first is to override dh_install in our rules file and run something like dh_install foobar /path/to/target/dir/ for each file we want to install:

override_dh_install:
        dh_install foobar /usr/bin/
        dh_install libfoo/* /usr/share/pyshared/libfoo/
# etc ...

There is, however, a simpler method. The second paragraph of the manpage tells us that we can use a debian/package.install file. It also gives us the syntax for the file. A foobar.install file doing what the above example did would would like this:

foobar          /usr/bin/
libfoo/*        /usr/share/pyshared/libfoo/

Obviously, this allows us to do a lot more things than we were able to do before. Say we don't like foobar being called foobar in the /usr/bin/ directory. (In the case of markdown, the perl markdown was prefered over the python one, so /usr/bin/markdown had to be renamed to /usr/bin/markdown_py). Change the relevant part of the rules file. This is not the actual rules file for markdown. It is just an example of what the markdown rules file might look like if it used debian/markdown.install to install all its files.

override_dh_install:
        dh_install
        mv debian/markdown/usr/bin/markdown debian/markdown/usr/bin/markdown_py

As you can see, we can continue to complicate our rules file till all the required files are properly installed. Let us take a look at how we can learn more about the various other dh_commands. Remember what we first read about in the dh_install manpage:

There are many dh_install* commands that handle installing specific types of files...

A manpage is better installed by dh_installman than by dh_install. Reading the dh_installman manpage would help you find an efficient way of installing manpages.

Here's a great example where not reading the manual will get you in trouble. If you saw that a dh_installmanpages command exists and decided to use it without reading the manual, you would never know that it was deprecated in favor of dh_installman. You may also never realize that dh_installman allows you to list manpages in debian/package.manpages instead of having you type commands into the rules file. Remember that reading the documentation will always help.

There's a lot that you can do here. Listing out specific examples would be pointless. If you don't know what commands are available to you, you can see them all by reading the manpage for debhelper or by using the auto-complete feature of your terminal (if you haven't heard of that, then it's about time you look it up ;) .

Here's what the final rules file for python-markdown looks like:

#!/usr/bin/make -f
# -*- mode: makefile; coding: utf-8 -*-

%:
        dh $@

override_dh_installchangelogs:
        dh_installchangelogs docs/CHANGE_LOG

override_dh_auto_clean:
        dh_auto_clean
        find -name '*.pyo' -exec rm -f {} \;

override_dh_auto_install:
        dh_auto_install
        mv debian/python-markdown/usr/bin/markdown debian/python-markdown/usr/bin/markdown_py

.PHONY: override_dh_auto_clean override_dh_installchangelogs override_dh_auto_install

Checking for basic mistakes

When you submit a package to Debian or Ubuntu, it is always important that you check for basic errors. This has been documented in the New Maintainers' Guide, but the basics are summarized here:

Lintian

lintian is a tool that checks for errors. When you run debuild, the package is automatically checked with lintian (as you would already have seen). To make sure that you're checking agaist the latest standards and policies, you can run lintian from an updated sid chroot.

pbuildier

pbuilder builds your packages in a clean room environent. When you build a package, you may use a package to build the package that is installed on your computer but you may not have included it in Build-Depends. pbuilder creates a chroot and installs only the packages you've listed in Build-Depends. This means that if your package builds successfully on pbuilder, it is unlikely to have FTBFS (Fails To Build From Source) problems. Try to use the latest version of pbuilder. If you run into any trouble, #debian-mentors would be a good place to ask for help (since you are, hopefully, going to submit your package to Debian).

Q&A

Edited and deviates from the original guide

In the original guide, this section was related to the IRC session. This section has also been editted and the answers to these questions are not necessarily those of the original author. These will also change often as the rest of the guide changes.

When creating multiple binary packages from one source package (e.g. Python module + GTK program), what should the section of the source package be?

Python applications are all but if we package something made with C or something similar the only way is to *test*? how?

When and why is it worth to build native python program?

Are there specific things to do for a package which only works with one version of Python (eg 2.5 and not before)? and the same question for a package not Python version dependant.

I'm getting an error: /usr/share/cdbs/1/class/python-distutils.mk:69: *** unsupported Python system: pycentral (select either pysupport or pycentral). Stop.

How do I combine 'multiple binary' with 'cdbs' in dh_make? It seems the one or the other.

How should I deal with real Python version specific files like new encodings having to be put in /usr/lib/python2.5/encodings/ ? should I put them at the right place by hand (using "install -c ...") or is there some more automatic way not requiring to know the exact location?

How does packaging from scratch differ, i mean if i have no tar.gz file do i just tar up my existing project and work from there? does the layout of the source files matter in anyway?

What do I need to remove to rebuild the package again?

What is a really good example of a simple, beautifully packaged and written and documented python package (to use for a template)?

What is a source package and why would I need one?

Quick note about PAPT

PAPT, or Python Applications Packaging Team, is a Debian team which has many Python applications. There's also many Ubuntu developers and contributors packaging their applications there, as then they will hit both Debian and Ubuntu. I maintain all my Python applications there, and I have never had any problem in getting them into Ubuntu. (General procedures of getting a package into Debian will apply).

See Debian page and Ubuntu page for more info. On IRC, there's #ubuntu-motu here on Freenode and #debian-python on OFTC where you can ask for help with packaging (the latter only for Python packaging obviously :) More general questions on getting a package into Debian can be asked on #debian-mentors (OFTC).