2011-11-22

ROOT package for debian

ROOT Debian packaging is often late or broken. Users are trying their best themselves. I've decided to join and remake ROOT Debian packaging from scratch.
Debian ROOT packaging system is published on github.
Currently it builds only two packages: libroot and libroot-dev which contain whole ROOT installation. xrootd is not included due to the bug in it's build system. Many more components and plugins are not built to keep dependencies at minimum. Fine grained packaging and useful dependency tags are subject for further improvement.
Debian wiki page watches the progress of main official and unofficial ROOT repositories.

2011-11-09

How to build a DKMS Debian package

Dynamic Kernel Module Support is a very simple concept allowing to always keep your kernel and modules up to date. DKMS builds module source on each change of active kernel. All you need is to install source files and register them with one-line command. On the other hand packaging system of Linux distributions makes those tasks even easier managing versioning, conflicts resolution and automated registration. Suppose you have "mydriver" kernel module. Following is annotated process of packaging for it step by step.
sudo apt-get install debhelper
debhelper is a set of perl scripts for automated Debian packaging. It helps creating a minimal debian package example in your source tree:
dh_make --single --packagename mydriver-1.2 --native --copyright gpl2
  • --single - creates a single deb package template
  • --native - tells dh_make to consider current directory as the root of source tree
  • --copyright - should be gpl2 (defaults to gpl3) to be compatible with current Linux kernel license
  • --packagename - should take argument of form mydriver-version
dh_make will create a subfolder debian with a bunch of template files. Fortunately most of them are optional and can be deleted:
rm debian/*.ex debian/*.EX debian/README* install
This leaves following files and directories: changelog compat control copyright README rules source substvars
  • changelog, copyright, README files are to be (optionally) fixed with your name and comments
  • compat and source are file and directory controlling Debian helper behaviour and are to be left as they are
  • control file contains your package metainformation. If you are sure that your driver will compile and work on any architecture change Architecture: field to "all".
  • substrvars contains variable values that are used in control file. It can be ignored.
The most important rules file should look like:
#!/usr/bin/make -f

VERSION=$(shell dpkg-parsechangelog |grep ^Version:|cut -d ' ' -f 2)

%:
 dh $@ --with dkms

override_dh_install:
 dh_install Makefile mydriver.c usr/src/mydriver-$(VERSION)/

override_dh_dkms:
 dh_dkms -V $(VERSION)
Rules file does almost everything related to Debian packaging. Follows the explanation of its content.
  • VERSION of your package is determined by changelog and Debian policies require changelog to always be up to date. dpkg-parsechangelog parses debian/changelog and outputs information as key: value pairs, one per line. We are selecting "Version" key with grep and obtain its value with cut.
  • % target redirects every unknown target to dh perl program provided by debhelper. dh implements all required targets for debian standard rules Makefile, but it can't guess everything and provide "override" mechanism to configure every aspect of packaging, if rules define override_dh_* target it replaces default action that dh usually does.
  • override_dh_install installs our sources to the required target location. Actually dh has default dh_install step, which may do this for you (using debian/install configuration file), but it is limited to constant path only, which renders it unusable for dkms installation (requiring module version to be present in target folder name).
  • override_dh_dkms it needed for the very same purpose - to avoid updating packet version inside you DKMS configuration file (see below).
Finally create debian/mydriver.dkms file with the following content:
PACKAGE_VERSION="#MODULE_VERSION#"
PACKAGE_NAME="mydriver"
CLEAN="make clean"
BUILT_MODULE_NAME[0]="mydriver"
BUILT_MODULE_LOCATION[0]="./"
DEST_MODULE_LOCATION[0]="/kernel/net"
MAKE[1]="make"
AUTOINSTALL="yes"
It will be copied to usr/src/mydriver-$(VERSION)/ by dh_dkms. #MODULE_VERSION# will be replaced by your module version (note that this won't happen if we omit -V key in dh_dkms invocation). All required files are ready now, we can proceed to building our package with dpkg-buildpackage -us -uc -b It will (list nesting shows call nesting):
  • clean source tree
    • "debian/rules clean"
      • "dh clean"
        • "make clean"
  • build source tree
    • "debian/rules build"
      • "dh build"
        • "make" which is probably doing nothing as your module actually using Kbuild mechanism leaving Makefile in your source without targets.
  • build package
    • "debian/rules binary"
      • install files to a temporary path with
        • "dh_dkms" which uses override_dh_dkms, patching dkms configuration and installing it in an appropriate temporary folder
        • "make override_dh_install" that installs our sources in the very same temporary folder
      • "dh_builddeb" that packages temporary folder into deb package.
You can now look for your ../mydriver_1.2_all.deb file.
Futher reading: Debian packaging