DKMSPackaging

Summary

dkms is a framework which allows kernel modules to be dynamically built for each kernel on your system in a simplified and organized fashion.

This page will show you how to build an DKMS deb package.

dkms.png

Prepare source

Prepare your kernel module source. It contains the C file and its Makefile at least. The following is an hello world kernel module as an example

#include <linux/kernel.h>
#include <linux/init.h>

static int __init hello_init(void)
{
        pr_info("Hello world.\n");
        return 0;
}

static void __exit hello_exit(void)
{
        pr_info("Goodbye world.\n");
}

module_init(hello_init);
module_exit(hello_exit);

The following is its Makefile as example.

obj-m := hello.o
KVERSION := $(shell uname -r)

all:
        $(MAKE) -C /lib/modules/$(KVERSION)/build M=$(PWD) modules

clean:
        $(MAKE) -C /lib/modules/$(KVERSION)/build M=$(PWD) clean

Please use a variable to keep the kernel version we want to compile. In the above example, it is $(KVERSION). We usually run dkms build under the various kernel version, and the DKMS will pass the target kernel version to Makefile.

Please put your Makefile and source code at /usr/src/<module>-<module-version>. For example, I put above two files at /usr/src/hello-0.1

dkms.conf

Add dkms.conf and put it with your Makefile

Here is an example dkms.conf for hello-0.1

PACKAGE_NAME="hello"
PACKAGE_VERSION="0.1"
CLEAN="make clean"
MAKE[0]="make all KVERSION=$kernelver"
BUILT_MODULE_NAME[0]="hello"
DEST_MODULE_LOCATION[0]="/updates"
AUTOINSTALL="yes"

PACKAGE_NAME, PACKAGE_VERSION is necessary information, it shall be the same with the information or your folder name.

CLEAN is the command to clean up the folder. Every time before build, it will be executed. If unset, it is assumed to be "make clean"

MAKE[0] is the first command to build the kernel object. Since this is an example, this is the only command we have. This field tells DKMS how to build the kernel object, and we can pass the target kernel version by using $kernelver that DKMS provides us.

DEST_MODULE_LOCATION[0] tells DKMS where to put the kernel object when installing. In this example, the kernel object will be "/lib/modules/$kernelver/updates". In Ubuntu, this information will be overrade to "/updates/dkms". It means our kernel objects will be put at /lib/modules/$kernelver/updates/dkms". Although this information will be overrade, it is still a necessary field.

AUTOINSTALL set to yes means DKMS will try to build and install the kernel object when booting and it won't be re-built nor re-installed if the kernel object has been installed.

DKMS commands

Now, use "dkms add" to tell DKMS we have a module is ready. DKMS will create symlink from /var/lib/dkms to /usr/src.

user@here:~$ sudo dkms add -m hello -v 0.1

Creating symlink /var/lib/dkms/hello/0.1/source ->
                 /usr/src/hello-0.1

DKMS: add Completed.

Then, you can try to build this module with "DKMS build".

user@here:~$ sudo dkms build -m hello -v 0.1

Kernel preparation unnecessary for this kernel.  Skipping...

Building module:
cleaning build area....
su nobody -c "make KERNELRELEASE=2.6.31-15-generic -C /lib/modules/2.6.31-15-generic/build M=/var/lib/dkms/hello/0.1/build"....
cleaning build area....

DKMS: build Completed.

And, you can install this module to the kernel module tree.

user@here:~$ sudo dkms install -m hello -v 0.1

hello.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/2.6.31-15-generic/updates/dkms/

depmod......

DKMS: install Completed.

Then, you can see the kernel object has been add to your module tree

user@here:~$ ls -al /lib/modules/2.6.31-15-generic/updates/dkms/hello.ko
-rw-r--r-- 1 root root 3328 2009-11-11 11:19 /lib/modules/2.6.31-15-generic/updates/dkms/hello.ko

And you can use it now.

user@here:~$ sudo modprobe hello
user@here:~$ dmesg | tail -1
[ 7328.183867] Hello world.

If the module is useless for you, you can remove the module from DKMS. All files related to this module under /var/lib/dkms and /lib/modules will be removed.

user@here:~$ sudo dkms remove -m hello -v 0.1 --all

You can also ask DKMS to build and install this module for another kernel version after "dkms add".

user@here:~# sudo dkms build -m hello -v 0.1 -k 2.6.31-14-generic

Kernel preparation unnecessary for this kernel.  Skipping...

Building module:
cleaning build area....
su nobody -c "make KERNELRELEASE=2.6.31-14-generic all KVERSION=2.6.31-14-generic"....
cleaning build area....

DKMS: build Completed.
user@here:~# dkms install -m hello -v 0.1 -k 2.6.31-14-generic

hello.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/2.6.31-14-generic/updates/dkms/

depmod....

DKMS: install Completed.

It is also possible to build against multiple kernel versions.

user@here:~# sudo dkms build -m hello -v 0.1 -k 2.6.31-14-generic -k 2.6.31-14-generic-pae

The pre-built modules will be included in the DKMS deb made later. When the versions of the pre-built modules and the kernel on the target computer match, the pre-built modules will just be used rather than compiling on installation.

Debug when DKMS build failed

If DKMS build kernel failed, it will leave the make.log for you to tell what happened.
The log will be at /var/lib/dkms/<your_module_name>/<your_module_version>/build/make.log
In this example, the log will be /var/lib/dkms/hello/0.1/build/make.log

Generate DKMS deb

Using "dkms mkdeb" to build deb package. You shall run "dkms mkdeb" after "dkms add" and "dkms build"

user@here:~$ sudo dkms mkdeb -m hello -v 0.1
Using /etc/dkms/template-dkms-mkdeb
copying template...
modifying debian/changelog...
modifying debian/compat...
modifying debian/control...
modifying debian/copyright...
modifying debian/dirs...
modifying debian/postinst...
modifying debian/prerm...
modifying debian/README.Debian...
modifying debian/rules...
copying legacy postinstall template...
Copying source tree...
Gathering binaries...Marking modules for 2.6.31-15-generic (x86_64) for archiving...

Creating special tarball structure to accomodate only binaries.


Tarball location: /var/lib/dkms/hello/0.1/tarball/hello-0.1.dkms.tar.gz

DKMS: mktarball Completed.

Copying DKMS tarball into DKMS tree...
Building binary package...dpkg-buildpackage: warning: using a gain-root-command while being root
 fakeroot debian/rules clean
 debian/rules build
 fakeroot debian/rules binary
 dpkg-genchanges -b >../hello-dkms_0.1_amd64.changes
dpkg-genchanges: binary-only upload - not including any source code


DKMS: mkdeb Completed.
Moving built files to /var/lib/dkms/hello/0.1/deb...
Cleaning up temporary files...

And you can have the deb package

user@here:~$ ls -al /var/lib/dkms/hello/0.1/deb/hello-dkms_0.1_all.deb
-rw-r--r-- 1 root root 5336 2009-11-11 13:50 /var/lib/dkms/hello/0.1/deb/hello-dkms_0.1_all.deb

with AUTOINSTALL=yes in dkms.conf, you can boot with various kernel and dkms will build the kernel module automatically for you.

Limitation of DKMS

1. DKMS may not work well after a large change of kernel ABI - Using DKMS on a stable release kernel will be a better idea.
2. Make sure the we have toolchains and kernel header installed.
3. Using DKMS on a netbook is not a smart idea - It takes too much time to build the kernel module after kernel upgrading.
4. DKMS modules will not be loaded if there are another ones in initrd.

Kernel/Dev/DKMSPackaging (last edited 2011-04-21 05:55:40 by ikepanhc)