This is a way to create a "universal" .deb package suitable for installing on Debian, Ubuntu and similar distributions such as Linux Mint; and on any machine architecture (64-bit, 32-bit, even Raspberry Pi).
The package actually installs the source files under /usr/src/ and performs the compilation and installation of the actual binary in the post-installation phase. The package manager will make sure all dependencies are installed before running the post-install script. As long as all dependencies are correctly specified (remember, if you need libfoo to run something, you will also need libfoo-dev to build it) then the overall effect will be exactly the same as if they had installed a pre-compiled binary package; but you only have to .deb-ify it once, and you won't be expecting random strangers to install unknown binaries on their systems.
We are going to create a package called "wibble", which will contain this simple program:
#include <stdio.h>
int main() {
printf("Wibble\n");
return 0;
};
All it does is display "Wibble", but the same principles obviously are applicable to anything more ambitious.
Building It
Our package is going to be called "wibble", version 1.0-0 and it will be suitable for all architectures. So the canonical package name would be wibble_1.0-0_all. Make a folder to contain the files that will go into the package, and a skeleton folder structure beneath this:
$ mkdir wibble_1.0-0_all
$ cd wibble_1.0-0_all
$ mkdir usr
$ mkdir usr/share
$ mkdir usr/share/doc
$ mkdir usr/share/doc/wibble
$ mkdir usr/src
$ mkdir usr/src/wibble
$ mkdir DEBIAN
Everything but the DEBIAN folder will be unpacked under the root directory. The DEBIAN folder contains a control file, and some scripts which will be run by the package manager at various stages of the installation and removal processes.
usr/share/doc/wibble/COPYING
NO RIGHTS RESERVED. THIS CODE IS DEDICATED TO THE PUBLIC DOMAIN.YOU MAY USE IT, ABUSE IT, ENJOY IT, DESTROY IT, STUDY IT, SHARE IT AND
ADAPT IT WITHOUT RESTRICTION.
usr/share/doc/wibble/README.jm
This package is not quite as simple as it looks.(/usr/share/doc/wibble/ is where a package's information files conventionally reside -- READMEs, changelogs and so forth, perhaps even an "examples" subfolder.)
usr/src/wibble/wibble.c
#include <stdio.h>int main() {
printf("Wibble\n");
return 0;
};
DEBIAN/control
Package: wibbleVersion: 1.0-1
Section: base
Priority: optional
Architecture: all
Depends: build-essential
Maintainer: Julie Montoya <bluerizlagirl@gmail.com>
Description: Wibble demo
A simple demo that does not do very much, except prove it is possible
to do what it does.
This file tells the package manager about the package. Note the Depends: line. Use this to specify any dependencies (and don't forget the -dev packages, since you are going to be building stuff). The package build-essential is actually a metapackage; that is to say, it does not contain any files of its own except a documentation folder, but crucially it depends on a bunch of other packages, so you can force them all to install in one fell swoop. Note also that continuation lines of the description begin with a space.
This is all well and good, but all this will do is unpack the source "tree" (here, just one little file) into a folder under /usr/src/ . We still need to build the code. Fortunately, the Debian package format allows for us to do some finishing-off after the installation is completed, and again just before removal commences, by means of scripts which, if they exist within the package, will automatically be run at certain stages.
DEBIAN/postinst
#!/bin/sh############################## POSTINST script ##############################
# By the time this runs, dpkg will already have unpacked the Source Code
# under /usr/src/ -- this is where we build and install it.
#
# This may be as simple as ./configure && make install but probably isn't
OLD_FOLDER=$(pwd)
cd /usr/src/wibble/
gcc -owibble wibble.c
install -c wibble /usr/bin/
cd $OLD_FOLDER
exit
This script runs after all the files that make up the package have been installed to their proper locations, and all dependencies have been installed. So now we just have to build our Source Code, and install the binary we have just created to its intended location.
DEBIAN/prerm
#!/bin/sh################################ PRERM script ################################
# We need to remove any files we created during installation that were
# not on the manifest, so folders to be removed are empty.
#
# NB, this includes the actual executables we installed!
# This may be as simple as make uninstall && make clean but probably isn't
if [ -e /usr/src/wibble/wibble ]
then
rm -f /usr/src/wibble/wibble
fi
if [ -e /usr/bin/wibble ]
then
rm -f /usr/bin/wibble
fi
exit
This is a script that runs before the files installed during installation are removed. The package manager will only remove files that were on the
original manifest, and will complain if a folder it wants to remove is
not empty (as might be the case if some sort of upgrade had been done
outside of dpkg). So this is where we can remove the files we created (not
forgetting the actual binary!)
With a real package with a Makefile, you probably will be able to run make uninstall to remove the binaries and make clean to get rid of all extraneous files.
Set permissions on the scripts:
$ chmod 775 DEBIAN/prerm DEBIAN/postinst
And build the package:
$ dpkg-deb -b wibble_1.0-0_all
If all goes well, you will end up with a .deb package! You can inspect this with various GUI and command-line tools and see the individual files inside it, if you like.
Testing It
You can test the package by just running the DEBIAN/postinst script. The final installation will fail for want of write permission, but if it gets that far then the build was successful.The next test will be to install it with dpkg:
$ sudo dpkg -i wibble_1.0-0_all.deb
Now remove it, to make sure that works too:
$ sudo dpkg -r wibble
But what you have not tested yet is the dependencies. To do this properly, you will need a pristine system with only a bare minimum of packages installed -- probably the second-best way to get one, if you can't just fire up a brand new virtual machine ;) , is just to boot up a live Ubuntu system from a USB drive. This should let you install packages from an Internet repository using apt-get. Or if you have a spare Raspberry Pi, you can even burn a fresh SD card image and use that (which will also prove it really is packaged for all architectures).
If it works, well done! Otherwise, make a note of any dependencies you missed, and add them to the DEBIAN/control file. Your test environment need not be reinstalled from scratch, as long as you are sure you did not remove anything from the list of dependencies (though if the test environment is just your main laptop booted from USB, that can't really be helped).
Note it's also entirely possible to install a package with no files at all except DEBIAN/control . You might think that is not much use, but you can specify a whole bunch of packages in Depends: which will be installed automatically. You can use this to install the same software packages (possibly even from a local repository) on a bunch of machines together.
No comments:
Post a Comment