Introduction to the Common Debian Build System

Debian

Colin Walters

Debian

Copyright 2003 Colin Walters. Permission is granted to copy, distribute and/or modify this document under the terms of the GPL.

2003-09-29

Revision History
Revision 2
Revision 12003-09-29
First DocBook/XML version.

Table of Contents

Versioning note
buildcore.mk: A framework
Introduction to classes
debhelper.mk: A rule fragment
A full example
Class inheritance
Customization
Adding extra code
makefile.mk and Single vs. Multi Binary packages
A simple patch system
dpatch patch system
DBS (tarball-inside-a-tarball) build system
Common build problems
Build fails to to missing include files or something

In a single sentence: CDBS is a framework based on Makefile inheritance for building Debian packages.

It is essentially a set of Makefile fragments which you may include into your debian/rules. Each makefile fragment can have effects in different parts of your build process.

The original motivating factor for CDBS was originally that more and more programs today are created using GNU configure scripts and GNU automake, and as such they are all very similar to configure and build. I realized that a lot of duplicated code in everyone's debian/rules could be factored out. But CDBS isn't only useful for packages which use the GNU autotools. It is a flexible core upon which you can create your own custom build systems.

Versioning note

CDBS might change incompatibly in the future, and to allow for this, all the rules and classes are in a verison-specific subdirectory. That's the reason for the 1 in /usr/share/cbds/1. For right now though, during the initial development of cdbs, when few packages are using it, I might break compatibility in small ways. You will be warned if this happens.

buildcore.mk: A framework

Every CDBS-using debian/rules should eventually include /usr/share/cdbs/1/rules/buildcore.mk (it might be included automatically via dependencies, as we will see later). This Makefile fragment sets up all of the core default Makefile structure and variables, but doesn't actually do anything on its own.

You can use the buildcore.mk rules to hook in your own build system to actually implement each stage of compiling, installing, and building .debs if you wish.

Introduction to classes

However, cdbs also provides classes which contain makefile rules and variables implementing some or all of these steps. Classes tend to be declarative; they say your program has particular properties. Suppose for instance that your package uses a regular Makefile to compile, and has the normal make and make install targets. In that case, you can say:

include /usr/share/cdbs/1/class/makefile.mk

And you get all the code to run make automagically. This basically works by adding code to the common-build-arch, common-build-indep, common-install-arch, and common-install-indep targets inside buildcore.mk. It might be instructive to look at makefile.mk now.

debhelper.mk: A rule fragment

The next important piece of the puzzle is to actually build .debs from the now compiled software. You could implement this step yourself if you wished, but most people will want to take advantage of Debhelper to do it mostly automatically. To do this, simply add another line like:

include /usr/share/cdbs/1/rules/debhelper.mk

Note that if you use debhelper.mk, you must add a Build-Depends on debhelper (>= 4.1.0). This is the minimum version; it is recommended to use at least 4.1.46 to get some additional Debhelper features.

A full example

With just the two lines above, you should have a reasonable first cut at a fully functional build system! To recap, your debian/rules should now look like:

#!/usr/bin/make -f
include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/class/makefile.mk

And that's all! Note that makefile.mk and debhelper.mk both include buildcore.mk, so you don't need to include it explicitly.

Incidentally, you should usually include debhelper.mk first, before other rules. This will turn on optional Debhelper-using parts of other rules, if any, which is usually what you want.

Class inheritance

Now, let's look at some common situations. Say that your package uses GNU autoconf and automake. In that case, you can use the provided autotools class. One thing to note is that the autotools class actually builds upon the makefile class. This autotools class will take care of details such as updating the config.{sub,guess} files, running ./configure with the standard arguments, etc. So now our debian/rules looks like:

#!/usr/bin/make -f
include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/class/autotools.mk

Customization

However, suppose you need to pass --disable-frobnication to ./configure. How do you do this? Well, it couldn't be easier. The autotools.mk file includes a number of variables which you can override, like this:

#!/usr/bin/make -f
include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/class/autotools.mk
DEB_CONFIGURE_EXTRA_FLAGS := --disable-frobnication

Note that the variable is set after the rule fragment is included. This is necessary for it to have any effect. There are a few exceptions to this; but generally variables should be set after rule fragments are included.

Now, let's suppose your package is a little bit strange (e.g. Perl); perhaps it has a ./Configure script which isn't made by autoconf; this script might instead expect the user to interactively configure the program . In that case, you can just implement the common-configure rule, by adding something like the following to your debian/rules:

common-configure::
	./Configure --blah --blargh < debian/answers

Note that if you do this, you can't include autotools.mk, since then you'll get two implementations of common-configure, which is sure to fail. It would be nice to be able to partially override rule fragments; this is a tricky problem, but I hope to address it.

Adding extra code

Suppose that your package generates extra cruft as a side effect of the build process that's not taken care of by the upstream clean rule, and ends up bloating your diff. To handle this (until upstream fixes it), you can simply add stuff to the clean rule as follows:

clean::
	rm -f foo/blah.o po/.intltool-merge-cache

Almost all of the current rules are double colon rules (See the GNU Make manual). This means you can simply add to them without overriding the default.

You can also add dependencies to the rules. For example, suppose you have a multi-binary package which builds both a program and a shared library, and the program depends on the shared library. To tell CDBS to build the shared library before the program, just do something like:

binary/program:: binary/libfoo

However, this must come before you include buildcore.mk. This is due to the way make works.

And speaking of multi-binary packages:

makefile.mk and Single vs. Multi Binary packages

If you have a single binary package, the default common-install implementation in makefile.mk tries to use the upstream Makefile to install everything into debian/packagename, so it will all appear in the binary package. If you're using debhelper.mk, to remove files, move them around, just override the binary-post-install/<packagename> target

binary-post-install/mypackage:
	mv debian/mypackage/usr/sbin/myprogram \
	  debian/mypackage/usr/bin/myprogram
	rm debian/mypackage/usr/share/doc/mypackage/INSTALL

If you have a multi-binary package, makefile.mk (by default) uses the upstream Makefile to install everything in debian/tmp. After this, the recommended method is to use debhelper.mk (which uses dh_install) to copy these files into the appropriate package. To do this, just create packagename.install files; see the dh_install man page.

A simple patch system

Suppose you'd like to keep separated patches, instead of having them all in your .diff.gz. cdbs lets you hook in arbitrary patch systems, but (as with the rest of cdbs), it has its own default implementation, called simple-patchsys.mk. To use it, just add:

include /usr/share/cdbs/1/rules/simple-patchsys.mk

to your debian/rules. Now, you can drop patch files into the debian/patches directory, and they will be automatically applied and unapplied. Note that currently patches must end in .patch.

dpatch patch system

Like the simple patch system detailed previously, the dpatch patch system allows you to seperate your changes to the upstream tarball into multiple seperate patches instead of a monolithic diff.gz. This is a wrapper to the dpatch tools contained in the dpatch Debian package, and it's named dpatch.mk. To use it, add:

include /usr/share/cdbs/1/rules/dpatch.mk

to your debian/rules. If you use autotools.mk, be sure to include dpatch.mk after autotools.mk. Additionally, remember to add dpatch to your Build-Depends.

Finally, for a more complete treatment of dpatch files, their format, and their application, please read the documentation included in the dpatch package. Notably, /usr/share/doc/dpatch/README.gz and the dpatch(1) manpage.

DBS (tarball-inside-a-tarball) build system

Some Debian developers may be familiar with DBS, where you include a tarball of the source inside the Debian source package itself. This has some advantages, and some disadvantages. If you'd like to use this, just include tarball.mk, and specify DEB_TAR_SRCDIR. Note that it must be first in the list of included rules.

Common build problems

Build fails to to missing include files or something

Often this is caused by the fact that cdbs passes CFLAGS along with the make invocation. A sane build system allows this - CFLAGS are for the user to customize. Setting CFLAGS shouldn't override other internal flags used in the package like -I. However if fixing the upstream source is too difficult, you may do this:

DEB_MAKE_INVOKE := $(DEB_MAKE_ENVVARS) \
	make -C $(DEB_BUILDDIR)

That will avoid passing CFLAGS. But note this breaks the automatic implementation of DEB_BUILD_OPTIONS.