Majiir
October 1, 2022, 1:07am
1
I’ve written a patch for an in-tree kernel module (r8169). I got it working by patching the kernel:
boot.kernelPatches = [{
name = "r8169";
patch = ./r8169.patch;
}];
But this requires rebuilding the whole kernel. How can I build just the r8169 module with a patched source? I’m hoping I can then include it in boot.extraModulePackages and skip the long kernel build times.
Majiir
September 27, 2023, 2:56pm
2
I ended up doing it like this:
realtek.nix:
{ stdenv, lib, kernel }:
let
modPath = "drivers/net/ethernet/realtek";
modDestDir = "$out/lib/modules/${kernel.modDirVersion}/kernel/${modPath}";
in stdenv.mkDerivation rec {
name = "realtek-${kernel.version}";
inherit (kernel) src version;
postPatch = ''
cd ${modPath}
'';
nativeBuildInputs = kernel.moduleBuildDependencies;
makeFlags = kernel.makeFlags ++ [
"-C ${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
"M=$(PWD)"
"modules"
];
enableParallelBuilding = true;
installPhase = ''
runHook preInstall
mkdir -p ${modDestDir}
find . -name '*.ko' -exec cp --parents '{}' ${modDestDir} \;
find ${modDestDir} -name '*.ko' -exec xz -f '{}' \;
runHook postInstall
'';
meta = with lib; {
description = "Realtek ethernet drivers";
inherit (kernel.meta) license platforms;
};
}
default.nix:
{ config, lib, pkgs, ... }:
let
realtek-kernel-module = pkgs.callPackage ./realtek.nix { inherit (config.boot.kernelPackages) kernel; };
patched = realtek-kernel-module.overrideAttrs (prev: {
patches = [ ./r8169.patch ];
});
in
{
boot.extraModulePackages = [
(lib.hiPrio patched)
];
}
I was surprised there wasn’t a simple mkLinuxKernelModule or similar. I cobbled together the above from examples in nixpkgs.
2 Likes
Majiir
November 23, 2025, 4:35pm
3
The above solution no longer works for me after Move in-tree kernel modules to separate derivation output by jmbaur · Pull Request #423933 · NixOS/nixpkgs · GitHub merged. The module build fails with an error like this:
Running phase: buildPhase
@nix { "action": "setPhase", "phase": "buildPhase" }
build flags: -j12 SHELL=/nix/store/qsydfxm1vq6q9jac2kq3r8kn0xdmsldf-bash-5.3p3/bin/bash O=\$\(buildRoot\) --eval=undefine modules CC=/nix/store/68ndh04pl2hhhizsarvzwa9cnlp7zj3d-gcc-14.3.0/bin/gcc LD=/nix/store/asc30cdibhz4d82jv1bgaadfv529xqli-binutils-2.44/bin/ld AR=/nix/store/ag7fc58qzff4j1sgd7v98irhcr6vcg8v-gcc-wrapper-14.3.0/bin/ar NM=/nix/store/ag7fc58qzff4j1sgd7v98irhcr6vcg8v-gcc-wrapper-14.3.0/bin/nm STRIP=/nix/store/asc30cdibhz4d82jv1bgaadfv529xqli-binutils-2.44/bin/strip OBJCOPY=/nix/store/ag7fc58qzff4j1sgd7v98irhcr6vcg8v-gcc-wrapper-14.3.0/bin/objcopy OBJDUMP=/nix/store/ag7fc58qzff4j1sgd7v98irhcr6vcg8v-gcc-wrapper-14.3.0/bin/objdump READELF=/nix/store/ag7fc58qzff4j1sgd7v98irhcr6vcg8v-gcc-wrapper-14.3.0/bin/readelf HOSTCC=/nix/store/ag7fc58qzff4j1sgd7v98irhcr6vcg8v-gcc-wrapper-14.3.0/bin/cc HOSTCXX=/nix/store/ag7fc58qzff4j1sgd7v98irhcr6vcg8v-gcc-wrapper-14.3.0/bin/c++ HOSTAR=/nix/store/1rrjjyl7davy8znlykxzxwrsxkmxbvbq-binutils-wrapper-2.44/bin/ar HOSTLD=/nix/store/1rrjjyl7davy8znlykxzxwrsxkmxbvbq-binutils-wrapper-2.44/bin/ld ARCH=x86_64 CROSS_COMPILE= -C /nix/store/n350v7jbm90ns4af8fy69b8464w496bm-linux-6.12.58-dev/lib/modules/6.12.58/build M=\$\(PWD\) modules
make: Entering directory '/nix/store/n350v7jbm90ns4af8fy69b8464w496bm-linux-6.12.58-dev/lib/modules/6.12.58/build'
make: *** empty variable name. Stop.
make: Leaving directory '/nix/store/n350v7jbm90ns4af8fy69b8464w496bm-linux-6.12.58-dev/lib/modules/6.12.58/build'
I can fix the build by undoing the makeFlags change from the PR in my kernel module derivation:
nativeBuildInputs = kernel.moduleBuildDependencies;
- makeFlags = kernel.makeFlags ++ [
+ makeFlags = (lib.filter (x: x != "--eval=undefine modules") kernel.makeFlags) ++ [
"-C ${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
"M=$(PWD)"
"modules"
But I honestly have no idea what I’m doing here. So, what is the right way to patch an in-tree kernel module without rebuilding the whole kernel?
Feature request: build single in-tree Linux kernel module · Issue #458785 · NixOS/nixpkgs · GitHub is a related issue about upstreaming a snippet from the wiki.
Majiir
November 27, 2025, 5:34pm
4
I ended up having to remove both O=$(buildRoot) and --eval=undefine modules to get my modules to build. The error (with O=$(buildRoot) in place) was about being unable to find the file in this line of the Makefile:
include $(objtree)/include/config/auto.conf
Maybe related to this kernel commit ?
alois31
November 29, 2025, 12:30pm
5
This is the function I use on my systems (cobbled together from your original post and some out-of-tree modules in nixpkgs):
{
kernelPackages,
module,
patches,
}:
kernelPackages.stdenv.mkDerivation {
pname = builtins.baseNameOf module;
inherit (kernelPackages.kernel) version src;
inherit patches;
nativeBuildInputs = kernelPackages.kernel.moduleBuildDependencies;
enableParallelBuilding = true;
makeFlags = kernelPackages.kernelModuleMakeFlags ++ [
"INSTALL_MOD_PATH=$(out)"
"M=$(PWD)/${module}"
];
buildFlags = [ "modules" ];
installFlags = [ "modules_install" ];
}
In particular, using kernelModuleMakeFlags does not include the problematic flags, removing the need to filter them out.
Majiir
December 1, 2025, 12:51am
6
Oh, that’s much better! Thank you.
We can also do this to replace the modules from the kernel build instead of overriding them in updates/:
makeFlags = kernelPackages.kernelModuleMakeFlags ++ [
"INSTALL_MOD_PATH=$(out)"
+ "INSTALL_MOD_DIR=kernel/${module}"
"M=$(PWD)/${module}"
];
Either way works. I prefer this way because it feels more Nix-like to produce the ultimately correct module tree, rather than including duplicates and having the system decide between them at runtime.
1 Like