![]() |
|
Requirements: build-essential, automake, gnupg, lintian, fakeroot and pbuilder. |
In this example we will be using the GNU hello
program as our example. You can download the source tarball from
ftp.gnu.org.
For the purposes of this example, we will be using the
~/hello/
directory.
mkdir ~/hello cd ~/hello wget http://ftp.gnu.org/gnu/hello/hello-2.1.1.tar.gz
We will also compare our package to one that is already
packaged in the Ubuntu repository. For now, we will place
it in the ubuntu
directory so we can look at
it later. To get the source
package, make sure you have a "deb-src" line in your
/etc/apt/sources.list
file for the Main
repository. Then, simply execute:
mkdir ubuntu cd ubuntu apt-get source hello cd ..
![]() |
|
Unlike most apt-get commands, you do not need to have root privileges to get the source package, because it is downloaded to the current directory. In fact, it is recommended that you only use apt-get source as a regular user, because then you can edit files in the source package without needing root privileges. |
What the apt-get source command does is:
Download the source package. A source package commonly contains a .dsc file describing the package and giving md5sums for the source package, an .orig.tar.gz file containing the source code from the author(s), and a .diff.gz file containing patches applied against the source code with the packaging information.
Untar the .orig.tar.gz file into the current directory.
Apply the gunzipped .diff.gz to the unpacked source directory.
If you manually download the source package (.dsc, .orig.tar.gz, and .diff.gz files), you can unpack them in the same way apt-get source does by using dpkg-source as follows:
dpkg-source -x *.dsc
The first thing you will need to do is make a copy of the
original (sometimes called "upstream") tarball in the following
format:
<packagename>_<version>.orig.tar.gz
.
This step does two things. First, it creates two copies of the source
code. If you accidentally change or delete the working copy you can
use the one you downloaded. Second, it is considered poor
packaging practice to change the original source tarball unless
absolutely necessary. See the section called “Common Mistakes” for
reasons.
cp hello-2.1.1.tar.gz hello_2.1.1.orig.tar.gz tar -xzvf hello_2.1.1.orig.tar.gz
![]() |
|
The underscore, "_", between the package name (hello) and the version (2.1.1), as opposed to a hyphen, "-", is very important. Your source package will incorrectly be built as a Debian native package. |
We now have a hello-2.1.1
directory
containing the source files. Now we need to create the customary
debian directory where all the
packaging information is stored, allowing us to separate the
packaging files from the application source files.
mkdir hello-2.1.1/debian cd hello-2.1.1/debian/
We now need to create the essential files for any Ubuntu
source package: changelog
,
control
, copyright
, and
rules
. These are the files needed to create
the binary packages (.deb files) from the original (upstream)
source code. Let us look at each one in turn.
The changelog
file is, as its name
implies, a listing of the changes made in each version. It
has a specific format that gives the package name, version,
distribution, changes, and who made the changes
at a given time. If you have a GPG key, make sure to use the same name
and email address in changelog
as you
have in your key. The following is a template
changelog
:
package (version) distribution; urgency=urgency * change details more change details * even more change details -- maintainer name <email address>[two spaces] date
The format (especially of the date) is important. The date should be in RFC822 format, which can be obtained from the 822-date program.
Here is a sample changelog
file for
hello:
hello (2.1.1-1) dapper; urgency=low * New upstream release with lots of bug fixes. -- Captain Packager <[email protected]> Wed, 5 Apr 2006 22:38:49 -0700
Notice that the version has a -1 appended to it, or what is called the Debian revision, which is used so that the packaging can be updated (to fix bugs for example) with new uploads within the same source release version.
![]() |
|
Ubuntu and Debian have slightly different package versioning
schemes to avoid conflicting packages with the same
source version. If a Debian package has been changed in Ubuntu,
it has ubuntuX (where
X is the Ubuntu revision number)
appended to the end of the Debian version. So if the
Debian hello package was
changed by Ubuntu, the version string would be
|
Now look at the changelog
for the
Ubuntu source package that we downloaded earlier:
less ../../ubuntu/hello-2.1.1/debian/changelog
Notice that in this case the distribution is unstable (a Debian branch), because the Debian package has not been changed by Ubuntu. Remember to set the distribution to your target distribution release.
At this point create a changelog
file
in the debian
directory where you should
still be.
The control file contains the information that the package manager (such as apt-get, synaptic, and aptitude) uses, build-time dependencies, maintainer information, and much more.
For the Ubuntu hello package, the control file looks something like:
Source: hello Section: devel Priority: optional Maintainer: Captain Packager <[email protected]> Standards-Version: 3.6.1 Package: hello Architecture: any Depends: ${shlibs:Depends} Description: The classic greeting, and a good example The GNU hello program produces a familiar, friendly greeting. It allows non-programmers to use a classic computer science tool which would otherwise be unavailable to them. . Seriously, though: this is an example of how to do a Debian package. It is the Debian version of the GNU Project's `hello world' program (which is itself an example for the GNU Project).
Create control
using the
information above (making sure to provide your information for
the Maintainer field).
The first paragraph gives information about the source package. Let us go through each line:
Source: This is the name of the source package, in this case, hello.
Section: The apt repositories are split up into sections for ease of browsing and categorization of software. In this case, hello belongs in the devel section.
Priority: This sets the importance of the package to users. It should be one of the following:
Required - packages that are essential for the system to work properly. If they are removed it is highly likely that your system will break in an unrecoverable way.
Important - minimal set of packages for a usable system. Removing these packages will not produce an unrecoverable breakage of your system, but they are generally considered important tools without which any Linux installation would be incomplete. Note: This does not include things like Emacs or even the X Window System.
Standard - Somewhat self explanatory.
Optional - in essence this category is for non-required packages, or the bulk of packages. However, these packages should not conflict with each other.
Extra - packages that may conflict with packages in one of the above categories. Also used for specialized packages that would only be useful to people who already know the purpose of the package.
Maintainer: The package maintainer with email address.
Standards-Version: The version of the Debian Policy to which the package adheres (in this case, version 3.6.1). An easy way to find the current version is apt-cache show debian-policy | grep Version.
Build-Depends: One of the
most important fields and often the source of bugs, this line
lists the binary packages (with versions if necessary)
that need to be installed in order to create the binary package(s)
from the source package. Packages that are essential are
required by build-essential and do not need to be
included in the Build-Depends line. In the case of
hello, all the needed packages are a
part of build-essential, so a Build-Depends line is not
needed. The list of build-essential packages can be found at
/usr/share/doc/build-essential/list
.
The second paragraph is for the binary package that will be built from the source. If multiple binary packages are built from the source package, there should be one section for each one. Again, let us go through each line:
Package: The name for the binary package. Many times for simple programs (such as hello), the source and binary packages' names are identical.
Architecture: The architectures for which the binary package(s) will be built. Examples are:
all - The source
is not architecture-dependent. Programs that use Python
or other interpreted languages would use this. The
resulting binary package would end with
_all.deb
.
any - The source
is architecture-dependent and should
compile on all the supported architectures. There will be
a .deb file for each architecture (
_i386.deb
for
instance)
A subset of architectures (i386, amd64, ppc, etc.) can be listed to indicate that the source is architecture-dependent and does not work for all architectures supported by Ubuntu.
Depends: The list of
packages that the binary package depends on for functionality. For
hello, we see
${shlibs:Depends}
, which is a variable that
substitutes in the needed shared libraries. See the
dpkg-source
man page for more
information.
Recommends: Used for packages that are highly recommended and usually are installed with the package. Some package managers, most notably aptitude, automatically install Recommended packages.
Suggests: Used for packages that are similar or useful when this package is installed.
Conflicts: Used for packages that will conflict with this package. Both cannot be installed at the same time. If one is being installed, the other will be removed.
Description: Both short and long descriptions are used by package managers. The format is:
Description: <single line synopsis> <extended description over several lines>
Note that there is one space at the beginning of each line in the long description. More information on how to make a good description can be found at http://people.debian.org/~walters/descriptions.html.
This file gives the copyright information. Generally, copyright information
is found in the COPYING
file in the program's source
directory. This file should include such information as the names of the
author and the packager, the URL from which the source came, a
Copyright line with the year and copyright holder, and the text of the
copyright itself. An example template would be:
This package was debianized by {Your Name} <your email address> {Date} It was downloaded from: {URL of webpage} Upstream Author(s): {Name(s) and email address(es) of author(s)} Copyright: Copyright (C) {Year(s)} by {Author(s)} {Email address(es)} License:
As one can imagine, hello is
released under the GPL license. In this case it is easiest to
just copy the copyright
file from the
Ubuntu package:
cp ../../ubuntu/hello-2.1.1/debian/copyright .
You must include the complete copyright unless it is is GPL, LGPL, BSD, or
Artistic License, in which case you can refer to the corresponding file in the
/usr/share/common-licenses/
directory.
Notice that the Ubuntu package's
copyright
includes a license statement for
the manual. It is important that all the
files in the source be covered by a license statement.
The rules
file is an executable
Makefile that has rules for building the binary package from
the source packages. For hello, it
will be easier to use the rules
from the Ubuntu package:
#!/usr/bin/make -f # Sample debian/rules file - for GNU Hello. # Copyright 1994,1995 by Ian Jackson. # I hereby give you perpetual unlimited permission to copy, # modify and relicense this file, provided that you do not remove # my name from the file itself. (I assert my moral right of # paternity under the Copyright, Designs and Patents Act 1988.) # This file may have to be extensively modified package = hello docdir = debian/tmp/usr/share/doc/$(package) CC = gcc CFLAGS = -g -Wall INSTALL_PROGRAM = install ifeq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) CFLAGS += -O2 endif ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) INSTALL_PROGRAM += -s endif build: $(checkdir) ./configure --prefix=/usr $(MAKE) CC="$(CC)" CFLAGS="$(CFLAGS)" touch build clean: $(checkdir) rm -f build -$(MAKE) -i distclean rm -rf *~ debian/tmp debian/*~ debian/files* debian/substvars binary-indep: checkroot build $(checkdir) # There are no architecture-independent files to be uploaded # generated by this package. If there were any they would be # made here. binary-arch: checkroot build $(checkdir) rm -rf debian/tmp install -d debian/tmp/DEBIAN $(docdir) install -m 755 debian/postinst debian/prerm debian/tmp/DEBIAN $(MAKE) INSTALL_PROGRAM="$(INSTALL_PROGRAM)" \ prefix=$$(pwd)/debian/tmp/usr install cd debian/tmp && mv usr/info usr/man usr/share cp -a NEWS debian/copyright $(docdir) cp -a debian/changelog $(docdir)/changelog.Debian cp -a ChangeLog $(docdir)/changelog cd $(docdir) && gzip -9 changelog changelog.Debian gzip -r9 debian/tmp/usr/share/man gzip -9 debian/tmp/usr/share/info/* dpkg-shlibdeps debian/tmp/usr/bin/hello dpkg-gencontrol -isp chown -R root:root debian/tmp chmod -R u+w,go=rX debian/tmp dpkg --build debian/tmp .. define checkdir test -f src/$(package).c -a -f debian/rules endef binary: binary-indep binary-arch checkroot: $(checkdir) test $$(id -u) = 0 .PHONY: binary binary-arch binary-indep clean checkroot
Let us go through this file in some detail. One of the first parts you will see is the declaration of some variables:
package = hello docdir = debian/tmp/usr/share/doc/$(package) CC = gcc CFLAGS = -g -Wall INSTALL_PROGRAM = install ifeq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) CFLAGS += -O2 endif ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) INSTALL_PROGRAM += -s endif
This section sets the CFLAGS for the compiler and also handles the
noopt
and nostrip
DEB_BUILD_OPTIONS for debugging.
Next is the build
rule:
build: $(checkdir) ./configure --prefix=/usr $(MAKE) CC="$(CC)" CFLAGS="$(CFLAGS)" touch build
This rule runs ./configure with the proper prefix,
runs make, and creates a build
file that is a timestamp of the
build to prevent erroneous multiple compilations.
The next rule is clean
, which runs make -i distclean
and removes the files that are made during the package building.
clean: $(checkdir) rm -f build -$(MAKE) -i distclean rm -rf *~ debian/tmp debian/*~ debian/files* debian/substvars
Next we see an empty binary-indep
rule, because there are no
architecture-independent files created in this package.
There are, however, many architecture-dependent files, so binary-arch
is
used:
binary-arch: checkroot build $(checkdir) rm -rf debian/tmp install -d debian/tmp/DEBIAN $(docdir) install -m 755 debian/postinst debian/prerm debian/tmp/DEBIAN $(MAKE) INSTALL_PROGRAM="$(INSTALL_PROGRAM)" \ prefix=$$(pwd)/debian/tmp/usr install cd debian/tmp && mv usr/info usr/man usr/share cp -a NEWS debian/copyright $(docdir) cp -a debian/changelog $(docdir)/changelog.Debian cp -a ChangeLog $(docdir)/changelog cd $(docdir) && gzip -9 changelog changelog.Debian gzip -r9 debian/tmp/usr/share/man gzip -9 debian/tmp/usr/share/info/* dpkg-shlibdeps debian/tmp/usr/bin/hello dpkg-gencontrol -isp chown -R root:root debian/tmp chmod -R u+w,go=rX debian/tmp dpkg --build debian/tmp ..
First, notice that this rule calls the
checkroot
rule to make sure the package is built as root and calls the
build
rule to compile the source. Then the debian/tmp/DEBIAN
and
debian/tmp/usr/share/doc/hello
files are created, and the postinst
and the prerm>
scripts are installed to debian/tmp/DEBIAN
. Then
make install is run with a prefix that installs to the
debian/tmp/usr
directory. Afterward the documentation files (NEWS, ChangeLog, and the debian
changelog) are gzipped and installed. dpkg-shlibdeps is invoked to find the shared
library dependencies of the hello executable, and it stores the list in the
debian/substvars
file for the ${shlibs:Depends} variable in
control
. Then dpkg-gencontrol is run to create a control file for
the binary package, and it makes the substitutions created by dpkg-shlibdeps. Finally, after
the permissions of the debian/tmp
have been set, dpkg --build is run
to build the binary .deb package and place it in the parent directory.
The postinst
and
prerm
files are examples of maintainer
scripts. They are shell scripts that are executed after
installation and before removal, respectively, of the package. In the case of
the Ubuntu hello package, they
are used to install (and remove) the info file. Go ahead and
copy them into the current debian
directory.
cp ../../ubuntu/hello-2.1.1/debian/postinst . cp ../../ubuntu/hello-2.1.1/debian/prerm .
Now that we have gone through the files in the
debian
directory for
hello in detail, we can build the
source (and binary) packages. First let us move into the
root of the extracted source:
cd ..
Now we build the source package using dpkg-buildpackage:
dpkg-buildpackage -S -rfakeroot
The -S flag tells
dpkg-buildpackage to build a source
package, and the -r flag tells it to use
fakeroot to allow us to have fake
root privileges when making the package.
dpkg-buildpackage will take the
.orig.tar.gz
file and produce a
.diff.gz
(the difference between
the original tarball from the author and the directory we
have created, debian/
and its contents)
and a .dsc
file that has the
description and md5sums for the source package. The
.dsc
and
*_source.changes
(used for uploading the
source package) files are signed using your GPG key. If you do not
have a GPG key, add the -us -uc flags to the invocation of
dpkg-buildpackage. Your package
will build but it cannot be uploaded until it is
signed.
In addition to the source package, we can also build the binary package with pbuilder:
sudo pbuilder build ../*.dsc
Using pbuilder to build the
binary packages is very important. It ensures that the build
dependencies are correct, because
pbuilder provides only a minimal
environment, so all the build-time dependencies are
determined by the control
file.
We can check the source package for common mistakes using lintian:
cd .. lintian -i *.dsc