dkms

Build dkms module for specific kernel versions only


How do you define dkms.conf such that a DKMS module will only be built for specific kernel version or range of versions?

Background:

A buggy driver is present in the the current kernels we are using (eg 4.4) but fixed in 4.10. I produced as dkms package with the 4.10 source code in it, which all works fine on kernel 4.4. But as we update to later OS releases (or HWE releases) with later kernel releases - eg 4.15 - I want to avoid rebuilding the (now possibly older) 4.10 kernel driver when the kernel version is 4.10 or higher.

Here's my base dkms.conf file

PACKAGE_NAME="cp210x"
PACKAGE_VERSION="#MODULE_VERSION#"
BUILT_MODULE_NAME[0]="$PACKAGE_NAME"
DEST_MODULE_LOCATION[0]="/updates/dkms"
AUTOINSTALL="YES"
REMAKE_INITRD="YES"

I tried BUILD_EXCLUSIVE_KERNEL matching to 4.N kernel versions

BUILD_EXCLUSIVE_KERNEL="^4\.[0-9]\.*"

Expected behaviour - will not install the kernel module for kernel 4.15.0-43-generic. Actual behaviour - installs as normal

My reading suggests an alternate might work (for this test I'm just matching my current kernel version) to change the compile rule to be a no-op.

MAKE_MATCH[1]="^4\.15\.*"
MAKE[1]=":"

I'm on Debian/Ubuntu platforms if that makes any difference.


Solution

  • Ok - the problem was between keyboard and chair - my BUILD_EXCLUSIVE_KERNEL regexp had an error in it - the .* suffix got mixed with the \. number separator. But I'll document a working example here since google didn't find any good examples before I posted here:

    Firstly I wasn't sure what regexp dialect I needed to be using (grep, pcre, etc,..) especially since there is shell escaping mixed in, so thought perhaps the mismatch was there.

    Turns out dkms is a bash script and so uses [[ $ver =~ $match_regexp ]]. So to test the matching this worked:

    re="^(3\.[0-9]+\.|4\.[0-9]\.)" ; [[ "4.15.0-43-generic" =~ $re ]] && echo true
    # but this didn't
    [[ "4.15.0-43-generic" =~ "^(3\.[0-9]+\.|4\.[0-9]\.)" ]] && echo true
    

    Here's the config file I ended up using:

    PACKAGE_NAME="cp210x"
    PACKAGE_VERSION="#MODULE_VERSION#"
    BUILT_MODULE_NAME[0]="$PACKAGE_NAME"
    DEST_MODULE_LOCATION[0]="/updates/dkms"
    AUTOINSTALL="YES"
    REMAKE_INITRD="YES"
    # Since this code comes from 4.10 only update kernels 4.9 and earlier
    BUILD_EXCLUSIVE_KERNEL="^(3\.[0-9]+\.|4\.[0-9]\.)"
    

    Which looks like this when installed via dpkg.

    First Installation: checking all kernels...
    Building only for 4.15.0-43-generic
    Building initial module for 4.15.0-43-generic
    Error!  The dkms.conf for this module includes a BUILD_EXCLUSIVE directive which
    does not match this kernel/arch.  This indicates that it should not be built.
    Skipped.
    

    But installs correctly against lower kernel versions.

    Additionally the wording of the BUILD_EXCLUSIVE_KERNEL documentation suggests it is an error if the kernel mismatches which might not be desirable, however if you check the output above you'll see that the "Error" does not cause a package installation failure, just marked as skipped.