There’s an excellent article by Don “dons” Stewart called The lambda revolution which explains how to build a Haskell library in way that it is easy to download, compile, install, test, distribute, etc. I believe all those qualities are essential for successfully software. The next logicall step is to make OS-specific packages of it and since today I’ve had a short talk with Ian “Iglo” Lynagh, maintainer of many Haskell packages on Debian, who dissipated all my doubts about how to build a deb package of a Haskell library. Armed with that knowledge I am going to turn Don’s dlist into a beautiful deb package for Debian, Kubuntu or any other deb based operating system and tell you how.

We start downloading this new package and extracting it:

$ wget http://www.cse.unsw.edu.au/~dons/dlist/dlist-0.1.tar.gz
$ tar xvfz dlist-0.1.tar.gz
dlist-0.1
dlist-0.1/Data
dlist-0.1/Data/DList.hs
dlist-0.1/dlist.cabal
dlist-0.1/Setup.lhs
dlist-0.1/tests
dlist-0.1/tests/Parallel.hs
dlist-0.1/tests/Properties.hs
dlist-0.1/LICENSE
dlist-0.1/README

All the files we are going to create for packaging go in the “debian” directory inside dlist-0.1:

$ cd dlist-0.1/
~/dlist-0.1$ mkdir debian
~/dlist-0.1$ cd debian

We are going to take the files from another Haskell package to use them as templates. There are some Debian tools that generate a huge set of files inside the debian dir for making a package, but they are not targeted to Haskell and since you’d have to make so many changes that it’ll be easier to start from another Haskell package. Pick almost any from package from Haskell Unsafe, I’ve picked haskell-hunit:

~/dlist-0.1/debian$ wget http://haskell-unsafe.alioth.debian.org/.../haskell-hunit_1.1-1.diff.gz

It is a diff we have to apply after uncompressing it:

~/dlist-0.1/debian$ gunzip haskell-hunit_1.1-1.diff.gz
~/dlist-0.1/debian$ patch < haskell-hunit_1.1-1.diff
patching file copyright
patching file compat
patching file control
patching file rules
patching file changelog
patching file control.in
patching file libghc6-hunit-dev.prerm
patching file libghc6-hunit-dev.postinst
patching file libghc6-hunit-dev.prerm.in
patching file libghc6-hunit-dev.postinst.in

Some of those files are automatically generated (this is very different to normal Debian packages), so, we delete them:

~/dlist-0.1/debian$ rm control libghc6-hunit-dev.postinst libghc6-hunit-dev.prerm

And we can also remove the diff now:

~/dlist-0.1/debian$ rm haskell-hunit_1.1-1.diff

Now it is time to edit the files and customize them accordingly. Let’s start with changelog. The format of this file is very precise, one extra or missing space in some places and you’ll get an error. The result now looks like:

dlist (0.1-1) unstable; urgency=low

* Initial release.

-- José Pablo "Pupeno" Fernández

Mon, 11 Dec 2006 12:08:04 -0300

From that file the system will get the version of the package: 0.1-1. The first part, 0.1 is the mainstream release. The second part, -1, is the Debian release. It is there so you can correct a packaging mistake and release a new package, 0.1-2. The next file is control.in:

Source: dlist
Section: devel
Priority: optional
Maintainer: José Pablo "Pupeno" Fernández
Standards-Version: 3.7.2
Build-Depends: debhelper (>= 4), haddock (>= 0.6), $ghc6_lib_bdeps,
haskell-utils (>= 1.5), libghc6-base-dev, libghc6-base-prof
Package: libghc6-dlist-dev
Provides: libghc6-dlist-prof
Architecture: any
Depends: $ghc6_lib_deps, ${shlibs:Depends}, ${misc:Depends},
libghc6-base-dev, libghc6-base-prof
Description: A Haskell list type supporting O(1) append and snoc operations.
dlist provides Data.DList, a list type supporting O(1) append and snoc operations.

Build-Depends and Depends should be on one line, they were broken just to fit in the screen here. Description has two parts. The one in the first line is the short description. The rest, indented by spaces, is the long description. If the long description has more than one paragraph, each paragraph should be separated by an indented line containing a dot, like this:

this is the first paragraph.
.
this is the second paragraph.

The first line with nothing in it finishes the description. Now the copyright. This file contains some general information about who created the deb and who created the software itself:

This package was debianised by José Pablo "Pupeno" Fernández
on Mon, 11 Dec 2006.
It was downloaded from:
http://www.cse.unsw.edu.au/~dons/dlist/dlist-0.1.tar.gz
The homepage for the module is:
http://www.cse.unsw.edu.au/~dons/dlist.html
Copyright (c) 2006, Don Stewart
Licensed under the BSD3 license. A copy can be found at:
/usr/share/common-licenses/BSD

We now rename some files:

~/dlist-0.1/debian$ mv libghc6-hunit-dev.postinst.in libghc6-dlist-dev.postinst.in
~/dlist-0.1/debian$ mv libghc6-hunit-dev.prerm.in libghc6-dlist-dev.prerm.in

And that’s all. We don’t have to change anything in those last two files. In file rules we only have to replace Setup.hs for Setup.lhs, but that obviously depends on wether the package comes with a Setup.hs or a Setup.lhs. We now have to run some commands to get our beloved .deb file:

~/dlist-0.1/debian$ chmod +x rules

Generate the real control and other files:

~/dlist-0.1/debian$ cd ..
~/dlist-0.1$ debian/rules update-generated-files
update-haskell-control
ghc5 varfile not found
nhc98 varfile not found
hugs varfile not found
sed "s/@PACKAGE@/`dh_listpackages`/g"
debian/`dh_listpackages`.prerm.in
> debian/`dh_listpackages`.prerm
sed "s/@PACKAGE@/`dh_listpackages`/g"
debian/`dh_listpackages`.postinst.in
> debian/`dh_listpackages`.postinst

And to build the package:

$ dpkg-buildpackage -rfakeroot

That generates a lot of output, and in the end:

dpkg-deb: building package `libghc6-dlist-dev' in `../libghc6-dlist-dev_0.1-1_i386.deb'.

We can now try installing it:

$ sudo dpkg -i libghc6-dlist-dev_0.1-1_i386.deb
Password:
Selecting previously deselected package libghc6-dlist-dev.
(Reading database ... 137227 files and directories currently installed.)
Unpacking libghc6-dlist-dev (from .../libghc6-dlist-dev_0.1-1_i386.deb) ...
Setting up libghc6-dlist-dev (0.1-1) ...
Reading package info from stdin ... done.
Saving old package config file... done.
Writing new package config file... done.

Let’s check what was installed:

$ dpkg -L libghc6-dlist-dev
/.
/usr
/usr/bin
/usr/lib
/usr/lib/libghc6-dlist-dev
/usr/lib/libghc6-dlist-dev/unregister.sh
/usr/lib/libghc6-dlist-dev/register.sh
/usr/lib/dlist-0.1
/usr/lib/dlist-0.1/ghc-6.6
/usr/lib/dlist-0.1/ghc-6.6/Data
/usr/lib/dlist-0.1/ghc-6.6/Data/DList.p_hi
/usr/lib/dlist-0.1/ghc-6.6/Data/DList.hi
/usr/lib/dlist-0.1/ghc-6.6/libHSdlist-0.1.a
/usr/lib/dlist-0.1/ghc-6.6/HSdlist-0.1.o
/usr/lib/dlist-0.1/ghc-6.6/libHSdlist-0.1_p.a
/usr/lib/dlist-0.1/ghc-6.6/include
/usr/share
/usr/share/doc
/usr/share/doc/libghc6-dlist-dev
/usr/share/doc/libghc6-dlist-dev/copyright
/usr/share/doc/libghc6-dlist-dev/changelog.Debian.gz

Very nice. That’s it. The only missing step is letting the people at Debian Haskell know about it so it may be included in Debian. When people approach a new language they often want to do something with it. When that something is half done in a library, they are more likely to use the language. When that library has a simple and sane build system they are more likely to be able to use the library. When the library is sane and simple, it is more likely to be pre-packaged for different operating systems. When getting a library is such a matter of running a familiar command that is safe and simple, with easy removal and tracking of file, people feel safer and indeed is safer. So, if you follow Don’s advice when making your library you are helping improve the Haskell comunity. I’ve tried many languages and the ultimate test is how easy or hard is getting the libraries in place and working (and wether the libraries exist or not). I see a great potential here in Haskell.

You may also like:

If you want to work with me or hire me? Contact me

You can follow me or connect with me:

Or get new content delivered directly to your inbox.

Join 5,047 other subscribers

I wrote a book:

Stack of copies of How to Hire and Manage Remote Teams

How to Hire and Manage Remote Teams, where I distill all the techniques I’ve been using to build and manage distributed teams for the past 10 years.

I write about:

announcement blogging book book review book reviews books building Sano Business C# Clojure ClojureScript Common Lisp database Debian Esperanto Git ham radio history idea Java Kubuntu Lisp management Non-Fiction OpenID programming Python Radio Society of Great Britain Rails rant re-frame release Ruby Ruby on Rails Sano science science fiction security self-help Star Trek technology Ubuntu web Windows WordPress

I’ve been writing for a while:

Mastodon