Simples .deb
Sun, Jan 1, 2017Suppose we want to build the simplest Debian package we can, just so we can understand the minimal set of tools and ingredients we need - no more.
If you’ve managed to choke down other spurious convenience food analogies in related posts on this site, well done! I hope this one proves palatable - with fewer anchovies at least.
We think we pretty much get Debian package management and distribution. At least we do on a workaday basis; apt-get
, dpkg
, aptitude
and all their chums. But let’s say we want to build our own software into a Debian package. There’s nothing remotely “official” about our approach here by the way - we simply want to hot-wire, and joy-ride, the Debian Pizza Delivery Scooter of Mirth.
We’ll create a package called margherita
, putting into it a “useful” tool called mozzarella
. And then we’ll distribute it direct to our mouth when we’re done.
First, let’s examine the tree of the source code we actually need.
# tree margherita
margherita
|-- DEBIAN
| `-- control
`-- usr
`-- bin
`-- mozzarella
Simples!
There’s not much there when you boil it down. This may come as a surprise to some - it may even upset others!
The first thing is the root directory that contains everything. Its name is the same as the name of the package.
The second thing is that there’s a DEBIAN/control
file in there. This is the only clever bit really. We’ll come back to this.
The third, and final, thing is everything else that isn’t the DEBIAN
directory. These are the files that will be installed under /
. In our case it’s some application software - an imagined command line tool called mozzarella
. Note the directory structure though. The structure mirrors how it will look when installed under /
. So in this case we’ll get a /usr/bin/mozzarella
in our path when we install the package.
For our mozzarella
, some kind of smokin’ app like the following might be in order.
cat << EOF > margherita/usr/bin/mozzarella
#!/bin/sh
echo Stringy cheese!
EOF
chmod +x margherita/usr/bin/mozzarella
OK, so what’s in the control
file?
Package: margherita
Version: 1.0.0
Maintainer: Art Crawford <art@a4pizza.com>
Description: Sample package to illustrate deb build process
Prints out a test message.
Architecture: all
The tags and formatting are important - they’re specified. Don’t be leaving any out or you’ll get ominous portents of doom from the spectral developers of Linux past. They’re important meta-data for the Debian packaging tool as we’ll see in a minute. There is a lot more that could go in there though, were our packaging needs to become more complex.
Right now, pretty much the simplest way to build our package is to use the tool called dpkg
. For simplicity, we’ll run it from the directory just above the package’s root.
# dpkg --build margherita targetdir
…which, by the way, has the exact same effect as doing this:
# dpkg-deb --build margherita targetdir
[A quick shufti at the man-page for both dpkg
and dpkg-deb
reveals their symbiosis.]
The --build
option takes a single argument - the root source directory (margherita/
). The second positional argument is an existing target directory into which the archive is built (targetdir/
in our example). [If the second argument is something that doesn’t exist, it is used, instead, as the name of the package file that’s created.]
Here is what happens when we actually do it.
# mkdir targetdir
# dpkg-deb --build margherita targetdir
dpkg-deb: building package `margherita' in `targetdir/margherita_1.0.0_all.deb'.
dpkg
has the -c
option for listing the contents.
# dpkg -c targetdir/margherita_1.0.0_all.deb
drwxr-xr-x root/root 0 2017-01-01 07:07 ./
drwxr-xr-x root/root 0 2017-01-01 07:07 ./usr/
drwxr-xr-x root/root 0 2017-01-01 07:08 ./usr/bin/
-rwxr-xr-x root/root 33 2017-01-01 07:08 ./usr/bin/mozzarella
You may be interested to see what’s actually inside the generated binary .deb
file. At its lowest level, the Debian package file is actually an ar
format archive. So if you want to look inside it you can use the ar
tool like so.
# ar t targetdir/margherita_1.0.0_all.deb
debian-binary
control.tar.gz
data.tar.xz
You could also extract these files using ar x
and examine each one (only if you’re not busy). debian-binary
is just a text file containing the Debian file format version. And control.tar.gz
is our tarred, compressed control file - and any other stuff that was in the DEBIAN/
directory would have gone in here too. data.tar.gz
is a tar-ball of the actual files that will be installed.
All that remains is to chew the crust. As rogue Debianeers we want to see if our DIY, budget package behaves as we might expect it to.
Can we install it?
# dpkg -i targetdir/margherita_1.0.0_all.deb
Selecting previously unselected package margherita.
(Reading database ... 24742 files and directories currently installed.)
Preparing to unpack .../margherita_1.0.0_all.deb ...
Unpacking margherita (1.0.0) ...
Setting up margherita (1.0.0) ...
Yes we can.
Can we use it?
# mozzarella
Stringy cheese!
Yes we can.
Can we remove it?
# dpkg -r margherita
(Reading database ... 24743 files and directories currently installed.)
Removing margherita (1.0.0) ...
Yes we can.
‘Nuff said! We’ve stripped down the essence of a Debian package to see how to easily create one and use it.
With a bit of imagination you can easily see how a whole wealth of development tools and workflows can be built around this simple base. Unsurprisingly, exactly this sort of ecosystem exists. How Debian distributions are put together depends on it. For those contributing to that story a much deeper understanding of the shop-floor workings is needed.
Nevertheless, the main point remains. If you’re just trying to get your teeth into a slice, trying to comprehend the whole pizza factory may leave you hungry for a while. A lot of what’s out there may be totally unnecessary to you if you’re simply trying to piggy-back the process to distribute your own software.