nixGL.nix (6831B)
1 { ## Nvidia informations. 2 # Version of the system kernel module. Let it to null to enable auto-detection. 3 nvidiaVersion ? null, 4 # Hash of the Nvidia driver .run file. null is fine, but fixing a value here 5 # will be more reproducible and more efficient. 6 nvidiaHash ? null, 7 # Alternatively, you can pass a path that points to a nvidia version file 8 # and let nixGL extract the version from it. That file must be a copy of 9 # /proc/driver/nvidia/version. Nix doesn't like zero-sized files (see 10 # https://github.com/NixOS/nix/issues/3539 ). 11 nvidiaVersionFile ? null, 12 # Enable 32 bits driver 13 # This is one by default, you can switch it to off if you want to reduce a 14 # bit the size of nixGL closure. 15 enable32bits ? true, 16 writeTextFile, shellcheck, pcre, runCommand, linuxPackages, fetchurl, lib, 17 runtimeShell, bumblebee, libglvnd, vulkan-validation-layers, mesa_drivers, 18 pkgsi686Linux,zlib, libdrm, xorg, wayland, gcc 19 }: 20 21 let 22 _nvidiaVersionFile = 23 if nvidiaVersionFile != null then 24 nvidiaVersionFile 25 else 26 # HACK: Get the version from /proc. It turns out that /proc is mounted 27 # inside of the build sandbox and varies from machine to machine. 28 # 29 # builtins.readFile is not able to read /proc files. See 30 # https://github.com/NixOS/nix/issues/3539. 31 runCommand "impure-nvidia-version-file" { 32 # To avoid sharing the build result over time or between machine, 33 # Add an impure parameter to force the rebuild on each access. 34 time = builtins.currentTime; 35 preferLocalBuild = true; 36 allowSubstitutes = false; 37 } 38 "cp /proc/driver/nvidia/version $out || touch $out"; 39 40 # The nvidia version. Either fixed by the `nvidiaVersion` argument, or 41 # auto-detected. Auto-detection is impure. 42 _nvidiaVersion = 43 if nvidiaVersion != null then 44 nvidiaVersion 45 else 46 # Get if from the nvidiaVersionFile 47 let 48 data = builtins.readFile _nvidiaVersionFile; 49 versionMatch = builtins.match ".*Module +([0-9]+\\.[0-9]+).*" data; 50 in 51 if versionMatch != null then 52 builtins.head versionMatch 53 else 54 null; 55 56 addNvidiaVersion = drv: drv.overrideAttrs(oldAttrs: { 57 name = oldAttrs.name + "-${_nvidiaVersion}"; 58 }); 59 60 writeExecutable = { name, text } : writeTextFile { 61 inherit name text; 62 63 executable = true; 64 destination = "/bin/${name}"; 65 66 67 checkPhase = '' 68 ${shellcheck}/bin/shellcheck "$out/bin/${name}" 69 70 # Check that all the files listed in the output binary exists 71 for i in $(${pcre}/bin/pcregrep -o0 '/nix/store/.*?/[^ ":]+' $out/bin/${name}) 72 do 73 ls $i > /dev/null || (echo "File $i, referenced in $out/bin/${name} does not exists."; exit -1) 74 done 75 ''; 76 }; 77 in 78 rec { 79 nvidia = (linuxPackages.nvidia_x11.override { 80 }).overrideAttrs(oldAttrs: rec { 81 name = "nvidia-${_nvidiaVersion}"; 82 src = let url ="http://download.nvidia.com/XFree86/Linux-x86_64/${_nvidiaVersion}/NVIDIA-Linux-x86_64-${_nvidiaVersion}.run"; 83 in if nvidiaHash != null 84 then fetchurl { 85 inherit url; 86 sha256 = nvidiaHash; 87 } else 88 builtins.fetchurl url; 89 useGLVND = true; 90 }); 91 92 nvidiaLibsOnly = nvidia.override { 93 libsOnly = true; 94 kernel = null; 95 }; 96 97 nixGLNvidiaBumblebee = addNvidiaVersion (writeExecutable { 98 name = "nixGLNvidiaBumblebee"; 99 text = '' 100 #!${runtimeShell} 101 export LD_LIBRARY_PATH=${lib.makeLibraryPath [nvidia]}:$LD_LIBRARY_PATH 102 ${bumblebee.override {nvidia_x11 = nvidia; nvidia_x11_i686 = nvidia.lib32;}}/bin/optirun --ldpath ${lib.makeLibraryPath ([libglvnd nvidia] ++ lib.optionals enable32bits [nvidia.lib32 pkgsi686Linux.libglvnd])} "$@" 103 ''; 104 }); 105 106 # TODO: 32bit version? Not tested. 107 nixNvidiaWrapper = api: addNvidiaVersion (writeExecutable { 108 name = "nix${api}Nvidia"; 109 text = '' 110 #!${runtimeShell} 111 ${lib.optionalString (api == "Vulkan") ''export VK_LAYER_PATH=${vulkan-validation-layers}/share/vulkan/explicit_layer.d''} 112 113 ${lib.optionalString (api == "Vulkan") ''export VK_ICD_FILENAMES=${nvidiaLibsOnly}/share/vulkan/icd.d/nvidia.json${lib.optionalString enable32bits ":${nvidiaLibsOnly.lib32}/share/vulkan/icd.d/nvidia.json"}:$VK_ICD_FILENAMES''} 114 export LD_LIBRARY_PATH=${lib.makeLibraryPath ([ 115 libglvnd 116 nvidiaLibsOnly 117 ] ++ lib.optional (api == "Vulkan") vulkan-validation-layers 118 ++ lib.optionals enable32bits [nvidiaLibsOnly.lib32 pkgsi686Linux.libglvnd]) 119 }:''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} 120 "$@" 121 ''; 122 }); 123 124 # TODO: 32bit version? Not tested. 125 nixGLNvidia = nixNvidiaWrapper "GL"; 126 127 # TODO: 32bit version? Not tested. 128 nixVulkanNvidia = nixNvidiaWrapper "Vulkan"; 129 130 nixGLIntel = writeExecutable { 131 name = "nixGLIntel"; 132 # add the 32 bits drivers if needed 133 text = let 134 drivers = [mesa_drivers] ++ lib.optional enable32bits pkgsi686Linux.mesa_drivers; 135 in '' 136 #!${runtimeShell} 137 export LIBGL_DRIVERS_PATH=${lib.makeSearchPathOutput "lib" "lib/dri" drivers} 138 export LD_LIBRARY_PATH=${ 139 lib.makeLibraryPath drivers 140 }:$LD_LIBRARY_PATH 141 "$@" 142 ''; 143 }; 144 145 nixVulkanIntel = writeExecutable { 146 name = "nixVulkanIntel"; 147 text = let 148 # generate a file with the listing of all the icd files 149 icd = runCommand "mesa_icd" {} 150 ( 151 # 64 bits icd 152 ''ls ${mesa_drivers}/share/vulkan/icd.d/*.json > f 153 '' 154 # 32 bits ones 155 + lib.optionalString enable32bits ''ls ${pkgsi686Linux.mesa_drivers}/share/vulkan/icd.d/*.json >> f 156 '' 157 # concat everything as a one line string with ":" as seperator 158 + ''cat f | xargs | sed "s/ /:/g" > $out'' 159 ); 160 in '' 161 #!${runtimeShell} 162 if [ -n "$LD_LIBRARY_PATH" ]; then 163 echo "Warning, nixVulkanIntel overwriting existing LD_LIBRARY_PATH" 1>&2 164 fi 165 export VK_LAYER_PATH=${vulkan-validation-layers}/share/vulkan/explicit_layer.d 166 ICDS=$(cat ${icd}) 167 export VK_ICD_FILENAMES=$ICDS:$VK_ICD_FILENAMES 168 export LD_LIBRARY_PATH=${lib.makeLibraryPath [ 169 zlib 170 libdrm 171 xorg.libX11 172 xorg.libxcb 173 xorg.libxshmfence 174 wayland 175 gcc.cc 176 ]}:$LD_LIBRARY_PATH 177 exec "$@" 178 ''; 179 }; 180 181 nixGLCommon = nixGL: 182 runCommand "nixGLCommon" { 183 buildInuts = [nixGL]; 184 } 185 '' 186 mkdir -p "$out/bin" 187 # star because nixGLNvidia... have version prefixed name 188 cp ${nixGL}/bin/* "$out/bin/nixGL"; 189 ''; 190 191 # The output derivation contains nixGL which point either to 192 # nixGLNvidia or nixGLIntel using an heuristic. 193 nixGLDefault = 194 if _nvidiaVersion != null then 195 nixGLCommon nixGLNvidia 196 else 197 nixGLCommon nixGLIntel 198 ; 199 }