Thursday, January 16, 2014

Making Debian Packages the Quick and Dirty Way

I love Debian. Which is like saying "I love New York". So let me be more specific. I don't actually care for Debian docs (great example of more is less). Or the overtly zealous worship of the Debian Ideals (IceWeasel, seriously?). Or the Debian irc channel ("go away, read the docs, leave us alone"). 

But I do really like the Debian package management system. Building an (embedded) product based on a Debian system, means you can make your own software modular, and installed/upgraded using Debian packages. When working with other developers, this means that you can use a local repository to synchronize your work. Which is a lot better than "hey, let me Skype you my modified version of /etc/network/interfaces." So much better to put that in a package that can be loaded by everyone, and when you update it, everyone can grab the updates.

But making Debian packages is... involved. There are guidelines, and makefiles, and multiple tools, etc. But if you just want a simple binary package owned and managed just by you, that just puts files in places and runs scripts, there are easier ways.

A Debian package is just an ar package of three files: debian-binary, control.tar.gz, and data.tar.gz. debian-binary is a fixed file. Package metadata goes in control.tar.gz and your new files go in data.tar.gz. So let's walk through making a package that does something simple (and pretty much pointless, but hey, it's an example). Our simpledebpackage will add a newSingleFile to the file system and then make a simple edit to it. To make sure I'm not using a bunch of Debian specific tooling, I'm actually going to do it from the command line in OSX.
$ cd ~
$ mkdir simpledebpackage # our working directory, can be named whatever you want
$ cd simpledebpackage/
Now let's create the canned debian-binary file:
$ echo "2.0" > debian-binary
Let's do the new file next:
$ mkdir ROOT # this represents the root of the file system when installing
$ cd ROOT # you can name it whatever you want
$ mkdir -p usr/local # the path where newSingleFile will go on the target system
$ echo "What is the Answer?" > usr/local/newSingleFile # create a simple newSingleFile
$ tar -cvzf ../data.tar.gz * # archive all the files you want to add to the data.tar.gz file
$ cd ..
That was easy. Now for the package metadata:
$ mkdir DEBIAN # directory put all of our meta files
$ cd DEBIAN #again, the name isn't important
Use your favorite editor (mine is vim) to add a file named control (this name is important):
$ cat control
Package: simpledebpackage
Version: 1.0.0
Architecture: all
Maintainer: me@somewhere.mail
Description: The simplest package that possibly could
The control file defines the package metadata. Those are the 5 required fields. You can add more. The manual describes all of the fields in section 5.3.

Now build a simple shell script named postinst (this name is important too):
$ cat postinst
#!/bin/sh
echo "Duh: 42" >> /usr/local/newSingleFile
postinst is an example of a maintainer script. There are others like postrm, preinst, etc. What they are and when they fire is shown in graphical glory over at the Debian Wiki.

Now we ball these up similar to how we did the data.tar.gz one:
$ tar -cvzf ../control.tar.gz *
a control
a postinst
$ cd ..
The only thing that remains to be done is to ball the 3 files up in an archive file:
$ ar r simpledebpackage_1.0.0.deb debian-binary control.tar.gz data.tar.gz
One word of warning. Debian parses fields from filenames based on the underscore character. So, don't use it in your package name. Also, capital letters will cause warnings as well.

To test your package just run

        $dpkg -i simpledebpackage_1.0.0.deb

No comments:

Post a Comment