Out of tree kernel module missing System.map file

I’m trying to get the vrs-ff driver working. I’ve been following along the documentation (Linux kernel - NixOS Wiki) and this repo’s example for a similar driver (nixos-files/src/hid-fanatecff/default.nix at 31a508470b24727edc4effe2d44e66d7ba4ac63b · PhilT/nixos-files · GitHub), but when I nixos-rebuild, I get the warning Warning: modules_install: missing 'System.map' file. Skipping depmod. followed by the error /nix/store/5jw69mbaj5dg4l2bj58acg3gxywfszpj-bash-5.2p26/bin/bash: line 1: depmod: command not found
Anybody able to point me in the right direction with this? The file currently looks like the following:

vrs-ff/default.nix:

{
stdenv,
lib,
fetchFromGitHub,
kernel,
kmod,
linuxConsoleTools
}:

let moduledir = "lib/modules/${kernel.version}/kernel/drivers/hid";
in
stdenv.mkDerivation rec {
  name = "vrs-ff-${version}-${kernel.version}";
  pname = "vrs-ff";
  version = "0.0.1";

  src = fetchFromGitHub {
    owner = "JacKeTUs";
    repo = "vrs-ff";
    rev = "main";
    sha256 = "iaN1qGj0hGfyCDUgpGofC91nRw6f1SW+7U6wDdO6NLc=";
  };

  hardeningDisable = [ "pic" "format" ];
  nativeBuildInputs = kernel.moduleBuildDependencies;

  # makeFlags = [
  #   "KVERSION=${kernel.modDirVersion}"
  #   "KERNEL_SRC=${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
  #   "MODULEDIR=$(out)/${moduledir}"
  # ];

  makeFlags = [
    "KVERSION=${kernel.modDirVersion}"
    "KDIR=${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
    "INSTALL_MOD_PATH=$(out)/${moduledir}"
  ];

  meta = with lib; {
    description = "A kernel module to support VRS Direct Force Pro";
    homepage = "https://github.com/JacKeTUs/vrs-ff";
    license = licenses.gpl2;
    maintainers = [ maintainers.JacKeTUs mainainers.LithiumFox ];
    platforms = platforms.linux;
  };

  patchPhase = ''
    mkdir -p $out/lib/udev/rules.d
    mkdir -p $out/${moduledir}
  #   substituteInPlace Makefile --replace "/etc/udev/rules.d" "$out/lib/udev/rules.d"
  #   # substituteInPlace vrs-ff.rules --replace "/usr/bin/evdev-joystick" "${linuxConsoleTools}/bin/evdev-joystick" --replace "/bin/sh" "${stdenv.shell}"
  #   sed -i '/depmod/d' Makefile
  '';
}

configuration.nix has the following related lines

let
  vrs-ff = config.boot.kernelPackages.callPackage vrs-ff/default.nix {};
in
{
  boot.extraModulePackages = [ vrs-ff ];
  services.udev.packages = [ vrs-ff ];
  boot.kernelModules = [ "vrs-ff" ];
}

I’ve also tried without moduledir but that leads to the same error. Thanks!

Other things to note because I don’t know if they have any effect: my config uses flakes with home-manager.

Uncommenting some lines in the patch phase changes the error so it may be a problem there.

As I was referencing @PhilT’s hid-fanatecff module, my makefile patch was incorrect (since the two drivers have similar but different makefiles). I believe I need to figure out how to patch the following:

install: default
	$(MAKE) -C $(KDIR) M=$$PWD modules_install
	depmod -A

Additionally, I changed my config to the following, although I’m doubtful it has any effect.

let
  vrsff = config.boot.kernelPackages.callPackage vrs-ff/default.nix {};
in
{
  boot.extraModulePackages = [ vrsff ];
  services.udev.packages = [ vrsff ];
  boot.kernelModules = [ "vrs-ff" ];
}

Sorry for the posts in quick succession.

Changing the patch to the following got it to finally compile! I’m doing this through ssh so I’m not able to check that it works, but the compiling code patch is as follows:

  patchPhase = ''
    mkdir -p $out/lib/udev/rules.d
    mkdir -p $out/${moduledir}
    substituteInPlace Makefile --replace "modules_install" "modules"
    substituteInPlace Makefile --replace-fail "depmod -A" "@cp -v vrs-ff.ko ${moduledir}\n\tdepmod"
    sed -i '/depmod/d' Makefile
  '';

Welcome! Always good to document the process :slight_smile:

Don’t forget to mark your solution when you’ve had a chance to test it out.

Glad my derivation helped you. I’ve been using NixOS for almost a year and I still feel like a beginner!

1 Like

I’m now running into the same problem I believe was discussed here but cannot for the life of me figure out how to get the file where it needs to be, or anywhere for that matter. `find . -name “hid-vrs-ff*” run from /run/booted-system doesn’t find anything even though the copy isn’t failing.

  makeFlags = [
    "KVERSION=${kernel.modDirVersion}"
    "KDIR=${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
    "INSTALL_MOD_PATH=$(out)"
    # "INSTALL_MOD_PATH=$(out)/${moduledir}"
    # "MODULEDIR=$(out)/${moduledir}"
  ];

  patchPhase = ''
    mkdir -p $out/lib/udev/rules.d
    mkdir -p $out/${moduledir}
    substituteInPlace Makefile --replace-fail "\$(MAKE) -C \$(KDIR) M=\$\$PWD modules_install" "@cp -v hid-vrs-ff.ko $out/${moduledir}"
    # substituteInPlace Makefile --replace-fail "modules_install" "modules"
    # substituteInPlace Makefile --replace-fail "depmod -A" "@cp -v hid-vrs-ff.ko $out/${moduledir}"
    # substituteInPlace Makefile --replace-fail "modules_install" "modules"
    # substituteInPlace Makefile --replace-fail "depmod -A" "@cp -v hid-vrs-ff.ko ${moduledir}\n\tdepmod"
    # substituteInPlace Makefile --replace-fail "depmod -A" "@cp -v hid-vrs-ff.ko /home/ccalhoun"
    # substituteInPlace Makefile --replace-fail "depmod -A" "@cp -v hid-vrs-ff.ko $(out)/lib/modules/${kernel.version}"
    sed -i '/depmod/d' Makefile
  '';

I’m going to call it for the night, been banging my head against the wall for too many hours trying to do this. Any help would be very much appreciated. I tried using the strategy written here, but it just ran into the same problems. Really missing dkms right now. My configuration is now a mess and looks like the following:

{
stdenv,
lib,
fetchFromGitHub,
kernel,
kmod,
linuxConsoleTools
}:

let moduledir = "${kernel.dev}/lib/modules/${kernel.version}/kernel/drivers/hid";
in
stdenv.mkDerivation rec {
  name = "vrs-ff-${version}-${kernel.version}";
  pname = "vrs-ff";
  version = "0.0.1";

  src = fetchFromGitHub {
    owner = "JacKeTUs";
    repo = "vrs-ff";
    rev = "main";
    sha256 = "iaN1qGj0hGfyCDUgpGofC91nRw6f1SW+7U6wDdO6NLc=";
  };

  # hardeningDisable = [ "pic" "format" ];
  nativeBuildInputs = kernel.moduleBuildDependencies;

  makeFlags = kernel.makeFlags ++ [
    "KVERSION=${kernel.modDirVersion}"
    "KDIR=${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
    "INSTALL_MOD_PATH=$(out)/${moduledir}"
  ];

  # buildFlags = [ "default" ];
  # installTargets = [ "install" ];

  patchPhase = ''
    # mkdir -p $out/${moduledir} 
    # substituteInPlace Makefile --replace-fail "\$(MAKE) -C \$(KDIR) M=\$\$PWD modules_install" "@cp -v hid-vrs-ff.ko $out/${moduledir}"
    sed -i '/depmod/d' Makefile
  '';

  buildPhase = ''
    echo "out dir:" $out/${moduledir}
  '';

  # makeFlags = [
  #   "KVERSION=${kernel.modDirVersion}"
  #   "KDIR=${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
  #   "INSTALL_MOD_PATH=$(out)"
  #   # "INSTALL_MOD_PATH=$(out)/${moduledir}"
  #   # "MODULEDIR=$(out)/${moduledir}"
  # ];

  meta = with lib; {
    description = "A kernel module to support VRS Direct Force Pro";
    homepage = "https://github.com/JacKeTUs/vrs-ff";
    license = licenses.gpl2;
    maintainers = [ maintainers.ccalhoun1999 ];
    platforms = platforms.linux;
  };

  # patchPhase = ''
    # mkdir -p $out/lib/udev/rules.d
    # mkdir -p $out/${moduledir}
    # substituteInPlace Makefile --replace-fail "\$(MAKE) -C \$(KDIR) M=\$\$PWD modules_install" "@cp -v hid-vrs-ff.ko $out/${moduledir}"
    # substituteInPlace Makefile --replace-fail "modules_install" "modules"
    # substituteInPlace Makefile --replace-fail "depmod -A" "@cp -v hid-vrs-ff.ko $out/${moduledir}"
    # substituteInPlace Makefile --replace-fail "modules_install" "modules"
    # substituteInPlace Makefile --replace-fail "depmod -A" "@cp -v hid-vrs-ff.ko ${moduledir}\n\tdepmod"
    # substituteInPlace Makefile --replace-fail "depmod -A" "@cp -v hid-vrs-ff.ko /home/ccalhoun"
    # substituteInPlace Makefile --replace-fail "depmod -A" "@cp -v hid-vrs-ff.ko $(out)/lib/modules/${kernel.version}"
    # sed -i '/depmod/d' Makefile
  # '';
}

I tried copying the hid-fanatecff build into my config and got it running, but I couldn’t modprobe with that either. Has something changed in nixos with regards to out of tree kernel modules that I’m unaware of?
Additionally, I can’t figure out how to test a build to get inmode to work. Following the documentation and running
make -C $(nix-build -E '(import <nixpkgs> {}).linux.dev' --no-out-link)/lib/modules/*/build M=$(pwd) modules
leads to
/nix/store/.../lib/modules/6.6.35/source/scripts/Makefile.build:41: /home/ccalhoun/.local/share/chezmoi/nixos/vrs-ff/Makefile: No such file or directory
Just running nix-build vrs-ff/default.nix
gives

error: cannot evaluate a function that has an argument without a value ('stdenv')
       Nix attempted to evaluate a function as a top level expression; in
       this case it must have its arguments supplied either by default
       values, or passed explicitly with '--arg' or '--argstr'. See
       https://nixos.org/manual/nix/stable/language/constructs.html#functions.

I figured out how to build locally.
First, I needed to move my default.nix over to another .nix file (I moved it to build.nix).
Then, I made a default.nix with the following:

let
  nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-22.11" # You can probably use a newer nixpkgs here
  pkgs = import nixpkgs { config = {}; overlays = []; };
in
{
  vrsff = pkgs.callPackage ./build.nix { };
}

Then, in build.nix since kernel wasn’t passed in and I don’t understand how parameters are passed, I changed parameters to the following

{
stdenv,
lib,
fetchFromGitHub,
pkgs,
kernel ? pkgs.linuxPackages_latest.kernel,
}:

Additionally, taking inspiration from this thread , I reformatted my build.nix to the following:

stdenv.mkDerivation rec {
  name = "vrs-ff-${version}-${kernel.version}";
  pname = "vrs-ff";
  version = "0.0.1";

  src = fetchFromGitHub {
    owner = "JacKeTUs";
    repo = "vrs-ff";
    rev = "main";
    sha256 = "iaN1qGj0hGfyCDUgpGofC91nRw6f1SW+7U6wDdO6NLc=";
  };

  setSourceRoot = ''
	  	export sourceRoot=$(pwd)/source
  '';

  nativeBuildInputs = kernel.moduleBuildDependencies;

  makeFlags = kernel.makeFlags ++ [
    "-C"
    "${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
    "M=$(sourceRoot)"
  ];

  buildFlags = [ "modules" ];
  installFlags = [ "INSTALL_MOD_PATH=${placeholder "out"}" ];
  installTargets = [ "modules_install" ];

  meta = with lib; {
    description = "A kernel module to support VRS Direct Force Pro";
    homepage = "https://github.com/JacKeTUs/vrs-ff";
    license = licenses.gpl2;
    maintainers = [ maintainers.ccalhoun1999 ];
    platforms = platforms.linux;
  };
}

Running nix-build -A vrsff created a result folder with the hid-vrs-ff.ko.xz file at result/lib/modules/6.3.10/updates/hid-vrs-ff.ko.xz.

The reason insmod doesn’t work is because the module is being built on some arbitrary kernel version I have to define, and there doesn’t seem to be a way to pass the host kernel as an argument when building.

Does anyone have a clue why when I do the build through nix-build, I the file ends up in lib/modules/kernel_ver/updates, but when i do nixos-rebuild switch its not in the same place (and doesn’t seem to be anywhere)?

For the time being I can use boot.kernelPackages = pkgs.linuxPackages_latest; in my configuration, and then set the kernel for a manual build to the same. Doing that allows me to use insmod on the package.
I’m running out of things to try at this point with regards to getting it to install properly on nixos-build. Is it possible using flakes + home-manager breaks something that prevents the install step from working?

In your nixos-config, you can access the current kernelPackages using config.boot.kernelPackages. To integrate a custom module build into NixOS, simply do

{
  boot.extraModulePackages = [
    (pkgs.callPackage ./your-module.nix {
      inherit (config.boot.kernelPackages) kernel;
    })
  ];
}

(Obviously make your module’s derivation take a kernel argument that it then uses internally.)

1 Like

Sorry if I wasn’t clear, I meant when building using nix-build I wasn’t able to figure out how to pass the host environment’s kernel parameter. Building using nixos-rebuild doesn’t have the same issue.
Using nixos-rebuild, my problem is that the module doesn’t seem to actually be copied / installed to anywhere.

I’m really at a loss for why

  installPhase = ''
    mkdir -p $out/lib/modules/${kernel.modDirVersion}/kernel/drivers/hid
    cp -v hid-vrs-ff.ko $out/lib/modules/${kernel.modDirVersion}/kernel/drivers/hid
  '';

doesn’t result with the driver in kernel/drivers/hid

Well yes, system environment configuration state is the domain of your NixOS config.

You could use your NixOS config as a data source by evaluating it and then taking out the attr: (import <nixpkgs/nixos> { }).config.boot.kernelPackages.
Though if you’re building a kernel module, integrating it is the goal anyways, so might as well do that?

Additional modules go into $out/lib/modules/${kernel.modDirVersion}/updates/modulename.ko.xz.

Could you also share the snippet where you set boot.extraModulePackages?

1 Like

Thank you so much for the help and information!

my configuration has this with regards to this module:

{
inputs,
outputs,
config,
pkgs,
lib,
...
}:
let
  vrsff = config.boot.kernelPackages.callPackage ../../vrs-ff/default.nix {};
in
{
  boot.extraModulePackages = [ vrsff ];
  services.udev.packages = [ vrsff ];
  boot.kernelModules = [ "hid-vrs-ff" ];

Also, I changed back to trying the following in my default.nix for the module:

  patchPhase = ''
    substituteInPlace Makefile --replace-fail "modules_install" "INSTALL_MOD_PATH=$out modules_install"
    sed -i '/depmod/d' Makefile
  '';

but there is still no updates folder being made and I can’t modprobe it.

You’ll have to take a look at what the makefile does. In the worst case, you can also simply install it there yourself.

Didn’t know the kernelPackages had a callPackage. Is it just the kernel’s packages or pkgs + kernel packages?

Honestly im not sure with regards to callPackage, I just immitated a line from here: nixos-files/src/spruce/default.nix at 31a508470b24727edc4effe2d44e66d7ba4ac63b · PhilT/nixos-files · GitHub

Also, with regards to the driver’s makefile, the make step looks to be

default:
	$(MAKE) -C $(KDIR) M=$$PWD

install: default
	$(MAKE) -C $(KDIR) M=$$PWD modules_install
	depmod -A

which is identical to GitHub - berarma/new-lg4ff: Experimental Logitech force feedback module for Linux which has a build config in nixpkgs: nixpkgs/pkgs/os-specific/linux/new-lg4ff/default.nix at 706eef542dec88cc0ed25b9075d3037564b2d164 · NixOS/nixpkgs · GitHub

However, imitating that build config also fails to put the driver anywhere (even though the build seems to run fine)

So I don’t really know what I did differently this time, perhaps I was overwriting INSTALL_MOD_PATH twice causing issues, but re-mimicing the new-lg4ff module is now working. My finished module is below:

{
stdenv,
lib,
fetchFromGitHub,
kernel,
}:

stdenv.mkDerivation {
  pname = "vrs-ff";
  version = "0.0.1";

  src = fetchFromGitHub {
    owner = "JacKeTUs";
    repo = "vrs-ff";
    rev = "main";
    sha256 = "iaN1qGj0hGfyCDUgpGofC91nRw6f1SW+7U6wDdO6NLc=";
  };

  preBuild = ''
    substituteInPlace Makefile --replace-fail "modules_install" "INSTALL_MOD_PATH=$out modules_install"
    sed -i '/depmod/d' Makefile
  '';

  nativeBuildInputs = kernel.moduleBuildDependencies;

  makeFlags = [
    "KVERSION=${kernel.modDirVersion}"
    "KDIR=${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
  ];

  meta = with lib; {
    description = "A kernel module to support VRS Direct Force Pro";
    homepage = "https://github.com/JacKeTUs/vrs-ff";
    license = licenses.gpl2;
    maintainers = [ maintainers.ccalhoun1999 ];
    platforms = platforms.linux;
  };
}