Translation(s): English - Русский
This page describes how to create Debian packages containing Linux kernel modules sources to be built automatically upon installation using DKMS.
Contents
Introduction
As documented in its man page, the DKMS ("Dynamic Kernel Module Support") framework allows kernel modules to be dynamically built for each kernel on users' systems in a simplified and organized fashion. Such building of kernel modules happens "on the fly" (mainly at a given module package installation time) on users' machines, rather than on the Debian infrastructure. DKMS "binary" module packages usually contain only their module sources and depend on dkms package. See ddcci-dkms as an example.
Using DKMS vs binary module packages has the following advantages:
- It removes from module maintainers the burden of rebuilding their module packages for each released kernel package.
It automates signing of modules with Machine Owner Keys (MOK), which is necessary on systems that use SecureBoot (keys need to be generated, enrolled and configured for module signing).
Package Configuration
DKMS config
For each "binary" DKMS package, create a file named "package-name.dkms" in debian folder, for example debian/mydriver-kernel-dkms.dkms. If there's only 1 binary package, the file may be named simply debian/dkms. These files should either follow the format documented in the dkms man page or contain a path (relative to the package's root) to a relevant upstream DKMS config file. A typical example:
PACKAGE_NAME="mydriver"
PACKAGE_VERSION="1"
AUTOINSTALL=yes
BUILT_MODULE_NAME[0]="$PACKAGE_NAME"
DEST_MODULE_LOCATION[0]=/updates
MAKE[0]="make -C ${kernel_source_dir} M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build"
CLEAN="make -C ${kernel_source_dir} M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build clean"Notes:
If "#MODULE_VERSION#" is used as PACKAGE_VERSION, it will be replaced with the upstream version of the package by dh_dkms, but this would require to #install sources into a folder with a version-dependent name (see dh_install, dh-exec and pkg-info.mk) and it wouldn't bring much value as you can't have 2 versions of the same package installed anyway.
If your module replaces an existing one with the same name, DEST_MODULE_LOCATION[0] should point to its location to create its backup, so that it can be restored if your DKMS package is uninstalled later. Otherwise the value of this field is ignored, but still required to be defined and must start with /updates/dkms (note: this prefix is distro-dependent: it may be /extra or /updates elsewhere).
CLEAN is no longer necessary since DKMS 3.1.8 and a notice will be printed, if it is defined. Older versions (pre-Trixie) may still require it however.
On newer versions, MAKE[0] is only needed if you need to call a specific target from the Makefile or add some options. Otherwise it defaults to something along the lines of the above example and can be omitted. (In case you are wondering, M is a special var used by kernel Makefiles to find a given module's sources, which are copied by DKMS to ${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build before executing MAKE[0]).
Module Makefile
As rules to build or clean module binaries are provided by the kernel Makefile infrastructure, a Makefile for a DKMS module usually only needs to append its modules' object filenames to obj-m var, for example:
obj-m += mydriver.o
If your module's source is divided into several files (for example mydriver-dma-helpers.c and mydriver-main.c), you need to specify, what object-files your module is composed of, by defining a variable named ${MODULE_NAME}-objs. For example:
obj-m += mydriver.o mydriver-objs := mydriver-dma-helpers.o mydriver-main.o
If you need some special CC flags, append them to ccflags-y var:
ccflags-y += -D__MYDRIVER_USE_DMA
See the related kernel Makefile docs.
An upstream Makefile may try to autodetect and override values for -C and M, which sometimes does not work as intended in a DKMS context. In such case the Makefile may need to be patched accordingly.
rules
In a generic case, all that is necessary is to add --with dkms to dh arguments: (ToDo: there must be no space before #!/usr/bin/make -f but it is then inproperly rendered by this wiki)
#!/usr/bin/make -f
%:
dh $@ --with dkmsThis will trigger dh_dkms to generate postinst and prerm for each binary package for which a DKMS config file exists.
control
dh-dkms must be added to Build-Depends: (since DebianBookworm it is a separate package from dkms).
As usually, ${misc:Depends} must be added to each binary package's Depends: list (it will be expanded to contain dkms in case of DKMS "binary" packages).
It is recommended to add linux-headers-generic to Depends: lists of "binary" DKMS packages.
By convention, "binary" DKMS packages are usually named ${drivername}-kernel-dkms (for example Package: mydriver-kernel-dkms) and they provide virtual packages named ${drivername}-kernel (for example Provides: mydriver-kernel).
install
Each "binary" DKMS package's source files and Makefile must be installed in /usr/src/${PACKAGE_NAME}-${PACKAGE_VERSION}/ folder, where PACKAGE_NAME and PACKAGE_VERSION values are the ones from the corresponding DKMS config. For example if kernel module files and Makefile for mydriver defined in the config above are located in kernel subfolder of the source package, its install file may look like this:
kernel/* /usr/src/mydriver-1/
Common problems
dpkg-buildpackage builds modules instead of packaging sources
This happens because the module's Makefile (or its parent) is in the root folder of the source package, so dh_auto_clean, dh_auto_build and dh_auto_install pick it up. Use override_dh_auto_* rules to fix it.
Missing generated/autoconf.h when building modules
Symptoms:
Module build fails and make.log contains a message similar to the below:
/usr/src/linux-headers-6.12.57+deb13-common/include/linux/kconfig.h:5:10: fatal error: generated/autoconf.h: No such file or directory
Possible reasons and resolutions:
This sometimes randomly happens across various distros (for example Manjaro, Arch). The exact reasons are not clearly explained anywhere, but purging a given module package, then purging a given kernel version headers packages, then removing manually any leftovers of both and finally reinstalling, usually solves the problem.
Related resources
Original discussion: <1255800860.2488.616.camel@localhost>
Debian links:
External guides:
Help wanted
ToDo: other documentation that might need changes:
