This post is a short introduction to building *.deb packages using dh_make & dpkg_buildpackage tools.
Let us assume that we want to make a Debian package for a simple library. We are going to create two *.deb files, due to the fact that in Debian-based operating systems, libraries are usually distributed in one of the two forms:
- dev package – containing both library binaries and header files for programmers. Used mainly by the developers.
- standard package – storing only the library binaries
Having that in mind, we should start our work from downloading necessary utilities:
apt-get install dpkg-dev dh-make debhelper devscripts pbuilder fakeroot
Next step is to set a proper name for the directory containing the source code of the library.
It should have the following pattern: _-_ ( ex. mylib-0.1.0 )
Inside that directory we execute a command generating files describing the content of the package:
where “l” stands for library
We can notice that a new directory “debian” was created. It contains several files, the most important are described below:
- changelog – Changelog for the package from which a number of the latest version is taken
- control – File containing package description and its dependencies
- rules – Script responsible for generating package (similar to make)
- mylib1.install – List of directories containing files which should be copied to the package (normal package)
- mylib-dev.install – Similar as mylib1.install but related to development package
Just to make it look better, let’s rename all “mylib1*” files into “mylib*” and then delete unnecessary *.EX and *.ex files. (these files are used in more complex packages, for example involving rc.init script modifications)
Exemplary content of the mentioned files is presented below:
debian/changelog
mylib (0.1.0-1) unstable; urgency=low
* Initial release
-- TG <myemail@x.com> Fri, 05 Sep 2008 17:40:45
debian/control
Source: mylib
Priority: extra
Maintainer: TG <myemail@x.com>
Build-Depends: debhelper (>= 5)
Standards-Version: 3.7.2
Section: libs
Package: mylib-dev
Section: libdevel
Architecture: any
Depends: mylib (= ${Source-Version})
Description: myITcorner.com Sample Library (dev)
Development files.
Package: mylib
Section: libs
Architecture: any
Depends: libglib2.0-0 (>= 2.6), openssl (>= 0.9)
Description: myITcorner.com Sample Library.
Binary package
mylib.install
Copy all the libraries from usr/local/lib
mylib.install
Copy all the libraries (also dev files) and C headers
usr/local/include/*
usr/local/lib/lib*.a
usr/local/lib/lib*.so
usr/local/lib/pkgconfig/*
usr/local/lib/*.la
usr/local/lib/pkgconfig/*
debian/rules
Content of debian/rules script is more complex and in most of the situations we can base our package on the file generated by dh_make utility. However, some minor modifications presented below should be introduced:
...
#Configure and compile library from the
#source code and install it into temporary location
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install
# the package into debian/tmp
$(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
dh_installchangelogs ChangeLog
dh_installdocs
dh_installexamples
dh_install --sourcedir debian/tmp
It’s worth mentioning that a structure of the above file is similar to Makefile script. There are some tasks and their dependencies. For example in install task a library is compiled and then installed into debian/tmp directory. Later in binary-arch, a Debian package is generated from the compiled data taken from debian/tmp directory.
Building the package
Package description and configuration files are ready. So how to make a *.deb files? For that purpose we can use the following command:
dpkg-buildpackage -us -uc -rfakeroot
But let’s make it simpler. Why not to add an entry in a Makefile, just to have everything in one place?
Assuming that we are using Autotools, here is the most interesting part of Makefile.am.
Makefile.am
pkg-deb: dist
- rm -rf $(TMP_DIR)
mkdir -p $(TMP_DIR)
mv $(PACKAGE)-$(VERSION).tar.gz $(TMP_DIR)/
tar --directory $(TMP_DIR)/ \
-xf $(TMP_DIR)/$(PACKAGE)-$(VERSION).tar.gz
cd $(TMP_DIR)/$(PACKAGE)-$(VERSION)/; \
./configure; \
dpkg-buildpackage -us -uc -rfakeroot; \
mv ../*.deb $(PWD)/pkg/
rm -rf $(TMP_DIR);
In such a way a new task pkg-deb was defined. It executes another task called dist, which makes a tarball of the library source code. Later dpkg-buildpackage is called and just to clean everything up, some files are either removed or renamed.
It is important not to forget about including debian directory in the tarball generated with dist task. It can be done by adding the following line somewhere at the top of the Makefile.am:
EXTRA_DIST = <some_pkg_config_file.pc; other_files> debian
By the way TMP_DIR stores a location of the directory for the library installation files. In my case I assumed that
Now it’s enough to invoke:
Debian packages should be created inside pkg directory.
References:
Debian New Maintainers’ Guide
Andy Balaam’s Blog