From 7aa1cce7c6e844cbc2552e47f251c8f2d38ab8f1 Mon Sep 17 00:00:00 2001 From: zimbatm Date: Tue, 28 Apr 2020 11:35:04 +0200 Subject: [PATCH] allow to pass a nvidiaVersionFile This allows to better control which driver is being loaded. --- all.nix | 18 +++++++++-- default.nix | 12 +++++++- nixGL.nix | 86 ++++++++++++++++++++++++++++++----------------------- 3 files changed, 75 insertions(+), 41 deletions(-) diff --git a/all.nix b/all.nix index a4ef81b..d0b62ea 100644 --- a/all.nix +++ b/all.nix @@ -1,4 +1,16 @@ -import ./default.nix { - nvidiaVersion = "440.82"; - nvidiaHash = "edd415acf2f75a659e0f3b4f27c1fab770cf21614e84a18152d94f0d004a758e"; +let + pkgs = import { config = { allowUnfree = true; }; }; +in +{ + pure = pkgs.recurseIntoAttrs (pkgs.callPackage ./nixGL.nix { + nvidiaVersion = "440.82"; + nvidiaHash = "edd415acf2f75a659e0f3b4f27c1fab770cf21614e84a18152d94f0d004a758e"; + }); + + versionFile = pkgs.recurseIntoAttrs (pkgs.callPackage ./nixGL.nix { + nvidiaVersionFile = pkgs.writeText "nvidia-version-440.82" '' + NVRM version: NVIDIA UNIX x86_64 Kernel Module 440.82 Wed Apr 1 20:04:33 UTC 2020 + GCC version: gcc version 9.3.0 (Arch Linux 9.3.0-1) + ''; + }); } diff --git a/default.nix b/default.nix index 7455b30..c73ae7c 100644 --- a/default.nix +++ b/default.nix @@ -4,6 +4,11 @@ # Hash of the Nvidia driver .run file. null is fine, but fixing a value here # will be more reproducible and more efficient. nvidiaHash ? null, + # Alternatively, you can pass a path that points to a nvidia version file + # and let nixGL extract the version from it. That file must be a copy of + # /proc/driver/nvidia/version. Nix doesn't like zero-sized files (see + # https://github.com/NixOS/nix/issues/3539 ). + nvidiaVersionFile ? null, # Enable 32 bits driver # This is one by default, you can switch it to off if you want to reduce a # bit the size of nixGL closure. @@ -15,5 +20,10 @@ } }: pkgs.callPackage ./nixGL.nix { - inherit nvidiaVersion nvidiaHash enable32bits; + inherit + nvidiaVersion + nvidiaVersionFile + nvidiaHash + enable32bits + ; } diff --git a/nixGL.nix b/nixGL.nix index 8f70d36..d9675ff 100644 --- a/nixGL.nix +++ b/nixGL.nix @@ -4,6 +4,11 @@ # Hash of the Nvidia driver .run file. null is fine, but fixing a value here # will be more reproducible and more efficient. nvidiaHash ? null, + # Alternatively, you can pass a path that points to a nvidia version file + # and let nixGL extract the version from it. That file must be a copy of + # /proc/driver/nvidia/version. Nix doesn't like zero-sized files (see + # https://github.com/NixOS/nix/issues/3539 ). + nvidiaVersionFile ? null, # Enable 32 bits driver # This is one by default, you can switch it to off if you want to reduce a # bit the size of nixGL closure. @@ -14,50 +19,57 @@ }: let + _nvidiaVersionFile = + if nvidiaVersionFile != null then + nvidiaVersionFile + else + # HACK: Get the version from /proc. It turns out that /proc is mounted + # inside of the build sandbox and varies from machine to machine. + # + # builtins.readFile is not able to read /proc files. See + # https://github.com/NixOS/nix/issues/3539. + runCommand "impure-nvidia-version-file" { + # To avoid sharing the build result over time or between machine, + # Add an impure parameter to force the rebuild on each access. + time = builtins.currentTime; + } + "cp /proc/driver/nvidia/version $out"; + # The nvidia version. Either fixed by the `nvidiaVersion` argument, or - # auto-detected. - _nvidiaVersion = if nvidiaVersion != null - then nvidiaVersion - else - # This is the auto-detection mecanism. This is ugly. - # We read /proc/driver/nvidia/version which is set by the Nvidia driver kernel module. - # This fails if the nvidia driver kernel module is not loaded. - # I'd like to just read the file using `${/proc/driver/nvidia/version}` and - # then let nix invalidate the derivation if the content of this file - # changes, but that's not possible, see - # https://github.com/NixOS/nix/issues/3539 - # But /proc is readable at build time! So runCommand works fine. - import (runCommand "auto-detect-nvidia" { - time = builtins.currentTime; - } - '' - # Written this way so if the version file does not exists, the script crashs - VERSION="$(${pcre}/bin/pcregrep -o1 'Module +([0-9]+\.[0-9]+)' /proc/driver/nvidia/version)" - echo "\"$VERSION\"" > $out - ''); + # auto-detected. Auto-detection is impure. + _nvidiaVersion = + if nvidiaVersion != null then + nvidiaVersion + else + # Get if from the nvidiaVersionFile + let + data = builtins.readFile _nvidiaVersionFile; + versionMatch = builtins.match ".*Module +([0-9]+\\.[0-9]+).*" data; + in + assert builtins.length versionMatch == 1; + builtins.head versionMatch; - addNvidiaVersion = drv: drv.overrideAttrs(oldAttrs: { - name = oldAttrs.name + "-${_nvidiaVersion}"; - }); + addNvidiaVersion = drv: drv.overrideAttrs(oldAttrs: { + name = oldAttrs.name + "-${_nvidiaVersion}"; + }); - writeExecutable = { name, text } : writeTextFile { - inherit name text; + writeExecutable = { name, text } : writeTextFile { + inherit name text; - executable = true; - destination = "/bin/${name}"; + executable = true; + destination = "/bin/${name}"; - checkPhase = '' - ${shellcheck}/bin/shellcheck "$out/bin/${name}" - - # Check that all the files listed in the output binary exists - for i in $(${pcre}/bin/pcregrep -o0 '/nix/store/.*?/[^ ":]+' $out/bin/${name}) - do - ls $i > /dev/null || (echo "File $i, referenced in $out/bin/${name} does not exists."; exit -1) - done - ''; - }; + checkPhase = '' + ${shellcheck}/bin/shellcheck "$out/bin/${name}" + # Check that all the files listed in the output binary exists + for i in $(${pcre}/bin/pcregrep -o0 '/nix/store/.*?/[^ ":]+' $out/bin/${name}) + do + ls $i > /dev/null || (echo "File $i, referenced in $out/bin/${name} does not exists."; exit -1) + done + ''; + }; in rec { nvidia = (linuxPackages.nvidia_x11.override {