Contents |
Kernel DKMS Package
Note: This document is under construction/revision
DKMS (Dynamic Kernel Module Support) is a system for automatically installing and rebuilding kernel modules that are maintained outside of the kernel tree to ensure that if a new kernel is installed that changes the ABI (Application Binary Interface), existing DKMS-managed modules are automatically built on the local PC against the new kernel's headers - saving the user from needing to manually rebuild the source or download an updated debian binary package./
This guide is intended to help developers and packagers understand how DKMS can help them quickly and easily prepare source packages. It is particularly focused on packagers preparing for Ubuntu PPA (Personal Package Archive) or official build uploads.
Preparing the Source
This will be a practical tutorial based on two web-cam drivers: r5u870 (Sony Vaio MotionEye) and ov51x-jpeg (Playstation EyeToy and Hercules Deluxe). The reason for using both is that they have slightly different configuration requirements - r5u870 installs two kernel modules.
Obtain the Source
We usually have the option of working from the project source version-control repository or a tarball archive.
Get The Latest Source
svn co http://svn.mediati.org/svn/r5u870/trunk r5u870
or
svn co svn://rastageeks.org/svn/ov51x-jpeg/trunk ov51x-jpeg
Install Source Archive
wget http://mediati.org/r5u870/r5u870-0.11.1.tar.gz mkdir r5u870-0.11.1 tar -xzf r5u870-0.11.1.tar.gz -C r5u870-0.11.1
or
wget http://www.rastageeks.org/downloads/ov51x-jpeg/ov51x-jpeg-1.5.8.tar.gz tar -xzf ov51x-jpeg-1.5.8.tar.gz
Source Directory Naming Convention
For debian packages the original source directory needs to be named <package>-<version>/ (e.g. r5u870-0.11.1/) so start by ensuring this is done or copy the existing source directory to a new one for the debianisation process.
If working from a version-control repository such as git, svn, cvs, etc., it is best to create a working copy for packaging:
pwd /home/all/SourceCode/r5u870 cp -a . ../r5u870-0.11.1 cd ../r5u870-0.11.1
or
pwd /home/all/Sourcecode/ov51-jpeg cp -a . ../ov51x-jpeg-1.5.8 cd ../ov51x-jpeg-1.5.8
Removing Version-Control Repository Data
If working from a version-control system there are going to be hidden directories and files which need to be ignored. The safest way to ensure all the tools used during builds avoid these is to remove them.
pwd /home/all/SourceCode/r5u870-0.11.1 ls -da .[^.]* .cproject .project .svn rm -rf .cproject .project .svn
or
pwd /home/all/SourceCode/ov51x-jpeg-1.5.8 ls -da .[^.]* .svn rm -rf .svn
Prepare the Debian Package
Create Initial Debian Files
There are three methods for preparing the DKMS-managed Debian package. Which you use depends on your experience and the degree of control over the process you want. On balance I'd recommend the template-assisted manual approach as the starting-point for the debian files.
DKMS version 2.0.20.0 introduced support for preparing source packages using the mkdsc command. Unfortunately the version in Hardy LTS is the older v2.0.19.0. I've published v2.0.20 in my PPA for Gutsy, Hardy and Intrepid.
Warning: If you use the traditional Debian package preparation method (represented by the second and third methods offered here) you *will* need to modify the DKMS v2.0.20 mkdsc templates if you use them as a basis for the Debian/DKMS package. I've attached the modified template set. These are more suited to Ubuntu packaging, too. If used with the Template-Assisted method and the dkms_preprocess script (also attached) you'll have the best of both worlds. I'm hoping to get the support for installing unpacked source put back into DKMS and then this won't be an issue.
DKMS mkdsc Method
The DKMS tools provide a method for creating a debian source package using the mkdsc command. The essentials are:
$ dkms mkdsc -m ${PKG_NAME} -v ${PKG_VERSION} --source-only
Note: This will do a similar job to dh_make (described in detail next) but will install files tailored for DKMS use.
It is important to understand that dkms mkdsc only works with a package already added to the DKMS Tree. This also means you'll have to work with super-user commands and in the/usr/src/ directory and DKMS Tree, which is usually /var/lib/dkms/${PKG_NAME}/${PKG_VERSION}/
It will not work with familiar debian packaging tools that expect to be in the package source root directory and find a debian/ directory there.
One-time only, edit the files in /etc/dkms/template-dkms-mkdsc so they match your requirements. The alternative option is to create a template in the module source directory. In this case that would be /usr/src/ov51x-jpeg-1.5.8/ov51x-jpeg-dkms-mkdsc/ (Note: the debian/ directory is inside the template directory).
debian/changelog and debian/control will need the maintainer details. In addition debian/changelog will need the release changing from the debian-style "unstable" to an Ubuntu release such as "hardy" or "intrepid". Other files such as debian/copyright might benefit from some basic configuration too.
debian/dir ought to include the man-page directory - it is part of Debian policy for every package to contain a man-page:
/usr/src /usr/share/man/man8
Note: dkms will pre-process all files in the debian/ directory and replace all occurances of the text DEBIAN_PACKAGE, MODULE_NAME, MODULE_VERSION and DATE_STAMP with module-specific values.
I've attached my modified source template - you will need this if you are working with the traditional packaging methods because the latest DKMS v2.0.20 assumes mkdsc has been used and cannot install a module from an unpacked /usr/src/ directory. You'll also find it a more complete and suitable basis for Ubuntu packaging.
It is easy to be caught out by the fact that mkdsc creates the final product. In other words, it does not leave behind a prepared debian/ directory and related files. They are only in the source archive it creates.
With that said, here's how it is done. First, copy the source-code to /usr/src/:
$ sudo cp -a . /usr/src/ov51x-jpeg-1.5.8
Now add the package to the DKMS tree
$ sudo dkms add -m ov51x-jpeg -v 1.5.8 Creating symlink /var/lib/dkms/ov51x-jpeg/1.5.8/source -> /usr/src/ov51x-jpeg-1.5.8 DKMS: add Completed.
To create the debian source archive:
$ sudo dkms mkdsc -m ov51x-jpeg -v 1.5.8 --source-only Using /etc/dkms/template-dkms-mkdsc copying template... modifying debian/changelog... modifying debian/compat... modifying debian/control... modifying debian/copyright... modifying debian/dirs... modifying debian/postinst... modifying debian/postrm... modifying debian/prerm... modifying debian/README.Debian... modifying debian/rules... gathering sources... Marking /var/lib/dkms/ov51x-jpeg/1.5.8/source for archiving... Tarball location: /var/lib/dkms/ov51x-jpeg/1.5.8/tarball/ov51x-jpeg-1.5.8.dkms.tar.gz DKMS: mktarball Completed. Copying DKMS tarball into DKMS tree... Building source package... debian/rules clean dpkg-source -b ov51x-jpeg-dkms-1.5.8 dpkg-genchanges -S >../ov51x-jpeg-dkms_1.5.8_source.changes dpkg-genchanges: including full source code in upload Moving built files to /var/lib/dkms/ov51x-jpeg/1.5.8/dsc... Cleaning up temporary files... DKMS: mkdsc Completed.
At this point the debian/ files are in /var/lib/dkms/ov51x-jpeg/1.5.8/dsc/ov51x-jpeg-dkms_1.5.8.tar.gz
It is important to realise mkdsc doesn't leave a debian/ directory behind so you've got to extract it from the archive.
$ sudo tar -xzf /var/lib/dkms/ov51x-jpeg/1.5.8/dsc/ov51x-jpeg-dkms_1.5.8.tar.gz -C /usr/src/ov51x-jpeg-1.5.8 $ sudo mv /usr/src/ov51x-jpeg-1.5.8/ov51x-jpeg-dkms-1.5.8 /usr/src/ov51x-jpeg-1.5.8/ov51x-jpeg-dkms-mkdsc
Finally, at this point, you've got a default debian package definition you can continue to work from.
Any changes to the debian files should now be made, such as defining the changes in the changelog, any specifics in the control, and the package author details in copyright and specific package information in README.Debian.
Template-Assisted method
My personal preference when preparing packages is to work with user privileges only, and to work in scratch directories rather than in system locations. My experience of using mkdsc is it hinders rather than helps the package-preparation process. It is especially annoying if you've got a set of scripts to automate package build and test which assume they're running in the package-root directory.
On balance I'd rather copy the /etc/dkms/template-dkms-mkdsc/debian/ templates to the package's debian/ directory and pre-process them with this little bash script (dkms_preprocess) that can be run from the package-root:
#!/bin/bash # pre-process DKMS debian templates # hacked from /usr/sbin/dkms # Copyright 2008 TJ <ubuntu@tjworld.net> # Licensed on the terms of the GNU GPL version 2 cp -a /etc/dkms/template-dkms-mkdsc/debian . dir="${PWD##*/}" module="${dir%-*}" debian_package="${module}-dkms" module_version="${dir##*-}" date_str="$(date -R)" echo "Package $debian_package for module $module version $module_version dated $date_str" pushd debian > /dev/null for file in $(find . -type f); do echo "Modifying ${file##*/}" sed -i -e "s/DEBIAN_PACKAGE/$debian_package/g" \ -e "s/MODULE_NAME/$module/g" \ -e "s/MODULE_VERSION/$module_version/g" \ -e "s/DATE_STAMP/$date_str/" "$file" if [ "${file%.*}" == "./MOD_NAME" ]; then echo "Renaming ${file} to ./${module}.${file##*.}" mv "$file" "./${module}.${file##*.}" fi if [ "${file%.*}" == "./PKG_NAME" ]; then echo "Renaming: ${file} to ./${debian_package}.${file##*.}" mv "$file" "./${debian_package}.${file##*.}" fi done popd > /dev/null echo "Setting executable permissions." chmod 755 debian/rules debian/${debian_package}.postinst debian/${debian_package}.prerm debian/${debian_package}.postrm mkdir -p debian/patches
Running it:
$ pwd /home/all/SourceCocde/ov51x-jpeg-1.5.8 $ dkms_preprocess Package ov51x-jpeg-dkms for module ov51x-jpeg version 1.5.8 dated Wed, 13 Aug 2008 16:44:16 +0100 Modifying control Modifying MOD_NAME.8 Renaming ./MOD_NAME.8 to ./ov51x-jpeg.8 Modifying PKG_NAME.postinst Renaming: ./PKG_NAME.postinst to ./ov51x-jpeg-dkms.postinst Modifying PKG_NAME.postrm Renaming: ./PKG_NAME.postrm to ./ov51x-jpeg-dkms.postrm Modifying README.Debian Modifying rules Modifying changelog Modifying copyright Modifying PKG_NAME.install Renaming: ./PKG_NAME.install to ./ov51x-jpeg-dkms.install Modifying PKG_NAME.prerm Renaming: ./PKG_NAME.prerm to ./ov51x-jpeg-dkms.prerm Modifying compat Modifying dirs Setting executable permissions.
After that, all the regular debian packaging tools and scripts can be used as normal.
Debhelper dh_make Method
This is an alternative to the DKMS mkdsc method detailed above.
Use the debhelper tool to create a GPL-ed CDBS (Common Debian Build System) package. I use CDBS because debian/rules is simple and it handles patching easily too:
$ dh_make --cdbs --copyright gpl -f ../${PKG_NAME}_${PKG_VERSION}.orig.tar.gz
There is now a debian/ directory with a collection of example files:
$ ls debian changelog cron.d.ex emacsen-remove.ex manpage.1.ex postinst.ex r5u870-default.ex watch.ex compat dirs emacsen-startup.ex manpage.sgml.ex postrm.ex r5u870.doc-base.EX control docs init.d.ex manpage.xml.ex preinst.ex README.Debian copyright emacsen-install.ex init.d.lsb.ex menu.ex prerm.ex rules
Because this is a kernel package most of the example files can be deleted:
$ cd debian $ rm cron.d.ex dirs docs emacs* init* manpage.sgml.ex mapage.xml.ex menu.ex postrm.ex preinst.ex *-default.ex *.doc-base.EX watch.ex
Configure DKMS
Create debian/dkms.conf and define the DKMS options for the package. During package-build this file will be copied to the installation directories (usr/src/${PKG_NAME}-${PKG_VERSION}) using a custom dh_install target in rules. The directives in the file are shell environment variable assignments:
PACKAGE_VERSION="0.11.1" PACKAGE_NAME="r5u870" CLEAN="make clean" BUILT_MODULE_NAME[0]="usbcam" BUILT_MODULE_LOCATION[0]="usbcam/" DEST_MODULE_LOCATION[0]="/kernel/../extra/usbcam/" BUILT_MODULE_NAME[1]="r5u870" DEST_MODULE_LOCATION[1]="/kernel/../extra/" MAKE[1]="make KVER=$kernelver src=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build" AUTOINSTALL="yes"
Because DKMS will do a manual out-of-tree build the existing Makefile targets (all, install, etc.) are used. Therefore, for each kernel module in the package (in this case usbcam.ko and r5u870.ko) a set of build directives is required that are assigned to array elements in each variable. In this case element [0] is the usbcam module and [1] is the r5u870 module. They should be ordered with prerequisites first (hence [0] is usbcam).
Because usbcam is in a sub-directory this is reflected with BUILT_MODULE_LOCATION[0]. Both modules have a DEST_MODULE_LOCATION[...] that defines where the package's own Makefile install target would install them (/lib/modules/<kernel-version>/extra in this case).
The r5u870 MAKE[1] directive defines the make command and options and accompanying Makefile variables to set. In this case KVER and src are set so that the current Makefile variable assignments will operate correctly. DKMS provides and sets the variables $kernelver and $dkms_tree to enable the Makefile to figure out the correct locations, if necessary.
For ov51x-jpeg:
PACKAGE_VERSION="1.5.8" PACKAGE_NAME="ov51x-jpeg" CLEAN="make clean" BUILT_MODULE_NAME[0]="ov51x-jpeg" DEST_MODULE_LOCATION[0]="/kernel/../extra/" MAKE[0]="make -d OVCAM_KVER=$kernelver" AUTOINSTALL="yes"
Once dkms.conf has been created the only thing that will need changing is to increment PACKAGE_VERSION to reflect changes in the upstream versioning. PACKAGE_NAME is the simple name the package is known as.
CLEAN defines the command to use to clean the build location. AUTOINSTALL ensures that DKMS will both build and install the module when the package is installed using the package manager.
Customise Debian Files
Edit copyright and ensure the authors and dates are correct. In the following text PKG_NAME="r5u870-dkms" and MOD_NAME="r5u870".
Changelog
Edit changelog and correct the version and release strings. The version string needs to include the ubuntu version (and if this is a PPA package, ~ppa version) so for example:
r5u870 (0.11.1-1) unstable; urgency=low
becomes
r5u870-dkms (0.11.1-0ubuntu1~ppa1h) hardy; urgency=low
The version string 0ubuntu1~ppa1h is read as:
0 = Not based on a debian package (otherwise this would be the debian package version number)
ubuntu = This is an Ubuntu package
1 = Version 1 of the Ubuntu package
~ = Means that this has to be ordered "before" any package with the same Ubuntu version that has no ~ suffix. Thereby if there is ever an ...ubuntu1 it will replace ...ubuntu1~ppa1h as ~ orders "before" it.
ppa = This is a Personal Package Archive package, not one from the official Ubuntu repositories
1 = This is the first version of the PPA package. Increment this each time a change is made and new upload to the PPA performed.
As a further enhancement I usually suffix the ~ppaX version with a single letter that represents the release the package is for. This solves an annoying issue when building the same package for multiple releases (e.g. gutsy, hardy, intrepid) where the packages would otherwise have to have different version-numbers in order for the PPA to accept them. So:
h = The release this package is for (g = Gutsy, h = Hardy, i = Intrepid, etc.)
I wrote the ppa_publish shell script to automatically build and publish source packages to the PPA for multiple releases.
Control
A developing convention for kernel source packages (which are source-code) is to set the Package name as ${PGK_NAME}-kernel-source (e.g. r5u870-kernel-source). However, DKMS has adopted the convention of suffixing the package name with -dkms (e.g. r5u870-dkms). On balance I think the -dkms suffix is preferable since it quickly indicates in a package-name that the module is portable across kernel versions.
Architecture should be set to any so that the PPA buildd's create an _all.deb package. If this was set to source, as might be expected based on the Debian policy, the PPA would reject the upload.
Because this is a source package there are no shared-library Depends - instead this is set to dkms since DKMS is required to build and install the kernel modules when the package has been installed. In later version (v2.0.20+) it also depends on bash. Build-Depends should probably include linux-headers-generic although I originally missed it off and the PPA builds were still successful.
Ensure Standards-Version is up-to-date. The current version is 3.7.3. Priority will probably be extra or optional. You'll need to decide which Section to allocate the package to - possibly admin but you can look at other packages in the repositories using Synaptic or aptitude or check the http://packages.ubuntu.com/ Ubuntu Packages archive directly. In the case of r5u870 it is a webcam driver and I saw that gspca is in graphics so used that too. Finally, add a useful description of the package that is displayed by package managers when users examine the package.
So the final control file for r5u870 looks like this:
Source: r5u870-dkms Section: graphics Priority: optional Maintainer: TJ <ubuntu@tjworld.net> Build-Depends: cdbs, debhelper (>= 5), linux-headers-generic Standards-Version: 3.7.3 Package: r5u870-dkms Architecture: all Depends: dkms Description: Source code for Ricoh r5u870 Camera Driver. Kernel driver for a range of Sony Vaio Motion Eye, HP Pavilion and other integrated Ricoh r5u870 cameras: 05ca:1810 HP Pavilion Webcam - UVC OK 05ca:1812 HP Pavilion Webcam - UVC Pavilion DV6502AU In-progress 05ca:1830 Sony Visual Communication Camera VGP-VCC2 VAIO SZ OK 05ca:1832 Sony Visual Communication Camera VGP-VCC3 VAIO UX OK 05ca:1833 Sony Visual Communication Camera VGP-VCC2 VAIO AR1 OK 05ca:1834 Sony Visual Communication Camera VGP-VCC2 VAIO AR2 OK 05ca:1835 Sony Visual Communication Camera VGP-VCC5 VAIO SZ OK 05ca:1836 Sony Visual Communication Camera VGP-VCC4 VAIO FE OK 05ca:1837 Sony Visual Communication Camera VGP-VCC4 VAIO FZ OK 05ca:1839 Sony Visual Communication Camera VGP-VCC6 VAIO CR OK 05ca:1841 Fujitsu F01 UVC Unknown In-progress 05ca:183a Sony Visual Communication Camera VGP-VCC7 VAIO SZ/TZ11 OK 05ca:183b Sony Visual Communication Camera VGP-VCC8 VAIO FZ OK 05ca:1870 HP Pavilion Webcam / HP Webcam 1000 OK
Dh_install Directives
The file ${PKG_NAME}.install feeds the call to dh_install (made by CDBS) and declares origin and destination of any files that need copying into the installation directories.
* usr/src/r5u870-0.11.1 debian/dkms.conf usr/src/r5u870-0.11.1
Note: in this case the rule for dkms.conf will be ignored due to an --exclude= option defined in rules but it is retained here for clarity and accuracy. A source package with its source files in sub-directories would need this.
README.Debian
This is pretty simple:
r5u870 for Debian ----------------- Please see ./README for a description of the r5u870 software. The Debian r5u870 DKMS source package provides:, * r5u870-dkms, which provides the source for the kernel modules -- TJ <ubuntu@tjworld.net> Tue, 22 Jul 2008 02:10:21 +0100
Post Install Script
After the package manager (apt-get, aptitude, Synaptic) has installed the package DKMS needs to be told about the new package and triggered to build and install it. The file ${PKG_NAME}.postinst does this (this is simple version of the all-singing all-dancing version in the DKMS templates):
# Copyright (C) 2002-2005 Flavio Stanchina # Copyright (C) 2005-2006 Aric Cyr # Copyright (C) 2007 Mario Limonciello CVERSION=`dpkg-query -W -f='${Version}' r5u870-dkms | awk -F "-" '{print $1}' | cut -d\: -f2` #DEBHELPER# case "$1" in configure) echo "Adding Module to DKMS build system" dkms add -m r5u870 -v $CVERSION > /dev/null echo "Doing initial module build" dkms build -m r5u870 -v $CVERSION > /dev/null echo "Installing initial module" dkms install -m r5u870 -v $CVERSION --force > /dev/null echo "Done." ;; esac
Note: Ensure the correct package name replaces all mentions of r5u870
Pre Remove Script
When the package is about to be removed by the package manager DKMS needs to be instructed to remove the module from its list. The file ${PKG_NAME}.prerm does this (a simpler version of the one in the DKMS templates):
# Copyright (C) 2002-2005 Flavio Stanchina # Copyright (C) 2005-2006 Aric Cyr # Copyright (C) 2007-2008 Mario Limonciello #DEBHELPER# CVERSION=`dpkg-query -W -f='${Version}' r5u870-dkms | awk -F "-" '{print $1}' | cut -d\: -f2` case "$1" in remove|upgrade) echo "Removing all DKMS Modules" dkms remove -m r5u870 -v $CVERSION --all > /dev/null echo "Done." ;; esac
Note: Ensure the correct package name replaces all mentions of r5u870
Man Page
Rename the example manpage.1.ex:
$ mv manpage.1.ex ${MOD_NAME}.8
Note: Section number 8 (Administration tools) seems most suitable for a kernel module.
Now modify the template to suit the package. Here's how r5u870.8 looks:
.TH R5U870 8 2008-07-22 "r5u870" "Ricoh r5u870 kernel module" .SH NAME r5u870 \- Ricoh r5u870 video camera driver .SH DESCRIPTION .I r5u870 DKMS Kernel module for a range of Sony Vaio Motion Eye, HP Pavilion and other integrated Ricoh r5u870 cameras: 05ca:1810 HP Pavilion Webcam - UVC OK 05ca:1812 HP Pavilion Webcam - UVC Pavilion DV6502AU In-progress 05ca:1830 Sony Visual Communication Camera VGP-VCC2 VAIO SZ OK 05ca:1832 Sony Visual Communication Camera VGP-VCC3 VAIO UX OK 05ca:1833 Sony Visual Communication Camera VGP-VCC2 VAIO AR1 OK 05ca:1834 Sony Visual Communication Camera VGP-VCC2 VAIO AR2 OK 05ca:1835 Sony Visual Communication Camera VGP-VCC5 VAIO SZ OK 05ca:1836 Sony Visual Communication Camera VGP-VCC4 VAIO FE OK 05ca:1837 Sony Visual Communication Camera VGP-VCC4 VAIO FZ OK 05ca:1839 Sony Visual Communication Camera VGP-VCC6 VAIO CR OK 05ca:1841 Fujitsu F01 UVC Unknown In-progress 05ca:183a Sony Visual Communication Camera VGP-VCC7 VAIO SZ/TZ11 OK 05ca:183b Sony Visual Communication Camera VGP-VCC8 VAIO FZ OK 05ca:1870 HP Pavilion Webcam / HP Webcam 1000 OK .TP .B More information r5u870 maintainer: http://wiki.mediati.org/R5u870 .SH AUTHORS Alex Hixon, TJ, Sam Revitch
Dir
Each directory that will be touched by the installation should be listed in dirs. In this case it is relatively simple:
usr/share/man/man8 usr/src
Rules
If using CDBS rules is very simple. If using (or planning for eventually using) a patch system an additional include is all it takes.
Alert: If preparing for PPA upload do not use the makefile.mk include since this will cause the buildd to try and build against the running kernel (on the buildd that is currently 2.6.16.51).
# managed by CDBS include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/rules/simple-patchsys.mk
We need to add some additional settings in order to support the DKMS package layout:
DEB_INSTALL_MANPAGES_r5u870-dkms="debian/r5u870.8" DEB_DH_INSTALL_ARGS=--exclude=debian/ SRC_VERSION := $(shell dpkg-parsechangelog | grep '^Version:' | cut -d' ' -f2 | cut -d- -f1 | cut -d\: -f2) binary-install/r5u870-dkms:: cp $(CURDIR)/debian/dkms.conf $(CURDIR)/debian/$(cdbs_curpkg)/usr/src/r5u870-$(SRC_VERSION)
The first line defines the name of the manual page that will be built. The second line ensures that dh_install doesn't copy any files from the debian/ directory to the installation location. This is needed because the original package has all its files in the root of the package tree (rather than in a sub-directory such as src/). When dh_install runs and processes the ${PKG_NAME}.install instructions it has to copy all the source files to the installation location. Using dh_install --exclude= is an easy way to ensure debian/ isn't installed.
In the case of DKMS however, the package needs to install debian/dkms.conf. This is the reason for the final set of instructions. the binary-install/r5u870-dkms target causes the file to be copied into the correct installation location after dh_install ignored it.
Note: If you want to find out other debhelper dh_* script variables to over-ride you'll need to read the CDBS script in /usr/share/cdbs/1/rules/debhelper.mk. It is quite simple then to figure out which variables need setting for each aspect of the debhelper processes. Here's a snippet:
dh_installdocs -p$(cdbs_curpkg) $(DEB_INSTALL_DOCS_ALL) $(DEB_INSTALL_DOCS_$(cdbs_curpkg)) dh_installexamples -p$(cdbs_curpkg) $(DEB_INSTALL_EXAMPLES_$(cdbs_curpkg)) dh_installman -p$(cdbs_curpkg) $(DEB_INSTALL_MANPAGES_$(cdbs_curpkg)) dh_installinfo -p$(cdbs_curpkg) $(DEB_INSTALL_INFO_$(cdbs_curpkg)) dh_installmenu -p$(cdbs_curpkg) $(DEB_DH_INSTALL_MENU_ARGS) dh_installcron -p$(cdbs_curpkg) $(DEB_DH_INSTALL_CRON_ARGS) dh_installinit -p$(cdbs_curpkg) $(if $(DEB_UPDATE_RCD_PARAMS),--update-rcd-params="$(call cdbs_strip_quotes, \ $(DEB_UPDATE_RCD_PARAMS))",$(if $(DEB_UPDATE_RCD_PARAMS_$(cdbs_curpkg)), \ --update-rcd-params="$(call cdbs_strip_quotes,$(DEB_UPDATE_RCD_PARAMS_$(cdbs_curpkg)))")) \ $(DEB_DH_INSTALLINIT_ARGS) dh_installdebconf -p$(cdbs_curpkg) $(DEB_DH_INSTALLDEBCONF_ARGS) dh_installemacsen -p$(cdbs_curpkg) $(if $(DEB_EMACS_PRIORITY),--priority=$(DEB_EMACS_PRIORITY)) $(if $(DEB_EMACS_FLAVOR), \ --flavor=$(DEB_EMACS_FLAVOR)) $(DEB_DH_INSTALLEMACSEN_ARGS) dh_installcatalogs -p$(cdbs_curpkg) $(DEB_DH_INSTALLCATALOGS_ARGS) dh_installpam -p$(cdbs_curpkg) $(DEB_DH_INSTALLPAM_ARGS) dh_installlogrotate -p$(cdbs_curpkg) $(DEB_DH_INSTALLLOGROTATE_ARGS) dh_installlogcheck -p$(cdbs_curpkg) $(DEB_DH_INSTALLLOGCHECK_ARGS) dh_installmime -p$(cdbs_curpkg) $(DEB_DH_INSTALLMIME_ARGS) dh_installchangelogs -p$(cdbs_curpkg) $(DEB_DH_INSTALLCHANGELOGS_ARGS) $(DEB_INSTALL_CHANGELOGS_ALL) \ $(DEB_INSTALL_CHANGELOGS_$(cdbs_curpkg)) $(if $(wildcard /usr/bin/dh_installudev),dh_installudev -p$(cdbs_curpkg) $(DEB_DH_INSTALLUDEV_ARGS)) dh_install -p$(cdbs_curpkg) $(if $(DEB_DH_INSTALL_SOURCEDIR),--sourcedir=$(DEB_DH_INSTALL_SOURCEDIR)) $(DEB_DH_INSTALL_ARGS) dh_link -p$(cdbs_curpkg) $(DEB_DH_LINK_ARGS) $(DEB_DH_LINK_$(cdbs_curpkg))
Makefile Out-Of-Tree Build Detection Variable
The original source should be checked to ensure that it builds correctly out-of-tree. This will mean that the Makefile must have additional targets and can detect when it is built separately from the kernel itself. There are many variation on the steps to do that. There are several gotchyas that need to be addressed to ensure the package will build using DKMS. For an example see section 4.1 of the kernel documentation (Documentation/kbuild/makefiles.txt)
The primary issue is the Makefile detection of an in-tree or out-of-tree build. It is often done by checking for an empty/undefined variable that is always set by Kbuild (the kernel build system).
- E.g.
ifneq ($(KERNELRELEASE),) include $(src)/Kbuild else all::
As I discovered after several hours of frustration when DKMS failed to build the package, detecting KERNELRELEASE causes the DKMS build to fail. I found that testing an alternative variable, PATCHLEVEL, solved this issue.
Note: The reason for this is confusing since DKMS sets KERNELRELEASE which triggers an in-kernel build which fails. I'm currently having a discussion about this with Mario and will clarify the situation once we've concluded.
This is the only change I had to make to the original source Makefile. It might be necessary to apply a debian patch during build to fix this.
This is an example of a flexible Makefile:
V ?= 0 MDIR := extra KVER ?= $(shell uname -r) KDIR ?= /lib/modules/$(KVER)/build FWDIR ?= /lib/firmware FWFILES = r5u870_1830.fw r5u870_1832.fw r5u870_1833.fw r5u870_1834.fw r5u870_1835.fw \ r5u870_1836.fw r5u870_1870_1.fw r5u870_1870.fw r5u870_1810.fw r5u870_183a.fw r5u870_183b.fw r5u870_1839.fw ifneq ($(PATCHLEVEL),) include $(src)/Kbuild else all:: $(MAKE) -C $(KDIR) M=$(CURDIR) V=$(V) modules install:: all $(MAKE) INSTALL_MOD_PATH=$(DESTDIR) INSTALL_MOD_DIR=$(MDIR) \ -C $(KDIR) M=$(CURDIR) modules_install clean:: $(MAKE) -C $(KDIR) M=$(CURDIR) clean rm -f Module.symvers endif install:: install -m 0644 -o root -g root $(FWFILES) $(FWDIR) /sbin/depmod -a
Alert: Note the use of ?= variable assignments. This causes make to only define the variable if it is currently undefined. This is very useful in many kernel build situations, but is particularly useful with DKMS since make options in dkms.conf can specifically set these variables.
It includes the Kbuild file. This will first build the files in the usbcam/ directory (which has its own Makefile) then the files in the current directory:
include $(src)/debug.mk obj-m += usbcam/ r5u870.o
Which in turn includes the debug.mk file that specifies alternate build options (which I use for debugging):
# EXTRA_CFLAGS += -DCONFIG_USB_USBCAM_DEBUG
Alert: Knowing about this nested build will be very important later when defining the DKMS make options in dkms.conf. It is important in dkms.conf to ensure that the prerequisites (in this case, usbcam/) are built before the main driver.
For the ov51x-jpeg Makefile some patching needs to be done to allow existing variable values to be inherited (using ?= instead of :=). I altered Makefile then created the patch:
pwd /home/all/SourceCode/ov51x-jpeg-1.5.8 diff -Nu ../ov51x-jpeg/Makefile ../ov51x-jpeg-1.5.8/Makefile >debian/patches/01_dkms_makefile_compatibility.patch # remove the leading ../ from the patch paths sed -i 's,^\(--- \|+++ \)\.\./\(.*\)$,\1\2,' debian/patches/01_dkms_makefile_compatibility.patch
And now reverse the patch to return the debianised source-code to virgin state:
patch -R -p1 < debian/patches/01_dkms_makefile_compatibility.patch
Build Package
This step is for local testing before the source package is uploaded to the PPA.
Make sure to be in the root directory of the package:
pwd /home/all/SourceCode/r5u870-0.11.1
Use the regular Debian build process:
fakeroot debian/rules clean fakeroot debian/rules binary
If the build was successful the binary target should report:
dpkg-deb: building package `r5u870-dkms' in `../r5u870-dkms_0.11.1-0ubuntu1~ppa1h_all.deb'.
It is always best to do a build test in a clean environment. I use pbuilder wrapped in custom scripts so I can have one package covering all releases. The changelog has its version and release re-written for the release I'm testing:
$ build_test gutsy ... $ build_test hardy ... $ build_test intrepid ...
Test Package
Now test the actual installation and triggering of DKMS:
sudo dpkg -i ../${PKG_NAME}_${PKG_VERSION}-0ubuntu1~ppa1h_all.deb Selecting previously deselected package r5u870-dkms. (Reading database ... 155086 files and directories currently installed.) Unpacking r5u870-dkms (from .../r5u870-dkms_0.11.1-0ubuntu1~ppa1h_all.deb) ... Setting up r5u870-dkms (0.11.1-0ubuntu1~ppa1h) ... Adding Module to DKMS build system Doing initial module build Installing initial module Done.
Create Source Package
Now the package is known working a source package needs creating for upload to the PPA buildd system:
debuild -S -sa ... Successfully signed dsc and changes files
Upload Source Package
Upload the package to the PPA:
dput ${PPA} ../${PKG_NAME}_${PKG_VERSION}-0ubuntu1~ppa1h_source.changes
Check the PPA Build Status
On the PPA status page (in my case my PPA) you'll see the status of the package. It will confusingly report only doing the i386 build. This is a bugette - it should report building all since the source is architecture-agnostic. Once the build has finished the package details will correctly show that the _all.deb has been created:
Publishing details * Published 13 hours ago Changelog r5u870 (0.11.1-0ubuntu1~ppa1h) hardy; urgency=low * Initial DKMS release * New upstream release 0.11.1 -- TJ <ubuntu@tjworld.net> Tue, 22 Jul 2008 02:10:21 +0100 Builds * [FULLYBUILT] i386 Download files from Librarian * r5u870-dkms_0.11.1-0ubuntu1~ppa1h_all.deb (154.2 KiB) * r5u870_0.11.1-0ubuntu1~ppa1h.diff.gz (1.9 KiB) * r5u870_0.11.1-0ubuntu1~ppa1h.dsc (599 bytes) * r5u870_0.11.1.orig.tar.gz (145.4 KiB)
Conclusions
There are a lot of relatively minor configuration issues that can lead to DKMS failing to build the package. If there are problems with failed DKMS builds and the /var/lib/dkms/${PKG_NAME}/${PKG_VERSION/build/make.log is almost empty of useful information add the make debug option (-d) to the dkms.conf MAKE="" configurations. That'll ensure make reports everything it is doing to the log-file - essential when builds mysteriously fail with DKMS:
MAKE[1]="make -d KVER=$kernelver src=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build"