https://claude.ai/share/4b3f290a-4f7f-4fdd-9524-77ebf7aac607
# Adding nixGL to Home Manager **human** (May 9, 2025, 04:09 PM) claude i want to add nixgl to home-manager but i don't know how. i think i copied from an AI or something but it doesn't work. <details><summary>errors.log</summary> ````` error: … while calling the 'derivationStrict' builtin at <nix/derivation-internal.nix>:37:12: 36| 37| strict = derivationStrict drvAttrs; | ^ 38| … while evaluating derivation 'home-manager-generation' whose name attribute is located at «github:nixos/nixpkgs/8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7?narHash=sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo%3D»/pkgs/stdenv/generic/make-derivation.nix:438:13 … while evaluating attribute 'buildCommand' of derivation 'home-manager-generation' at «github:nixos/nixpkgs/8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7?narHash=sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo%3D»/pkgs/build-support/trivial-builders/default.nix:80:17: 79| enableParallelBuilding = true; 80| inherit buildCommand name; | ^ 81| passAsFile = [ "buildCommand" ] ++ (derivationArgs.passAsFile or [ ]); … while evaluating the option `home.activation.installPackages.data': … while evaluating definitions from `/nix/store/lpqjvb4ix9m7jfrcqb9n0km5c6gzn7sp-source/modules/home-environment.nix': … while evaluating the option `home.packages': … while evaluating definitions from `/nix/store/957g10wj7xraxva625bnal96ss572nnw-source/home.nix': … while evaluating the module argument `nixgl' in "/nix/store/957g10wj7xraxva625bnal96ss572nnw-source/home.nix": (stack trace truncated; use '--show-trace' to show the full, detailed trace) error: attribute 'nixgl' missing at «github:nixos/nixpkgs/8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7?narHash=sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo%3D»/lib/modules.nix:652:66: 651| extraArgs = mapAttrs ( 652| name: _: addErrorContext (context name) (args.${name} or config._module.args.${name}) | ^ 653| ) (functionArgs f); ````` </details> <details><summary>flake.nix.txt</summary> ````` { description = "Home Manager configuration of karl3"; inputs = { # Specify the source of Home Manager and Nixpkgs. nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; home-manager = { url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; nixgl.url = "github:nix-community/nixGL"; }; outputs = { nixpkgs, home-manager, ... }: let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; nixgl = nixgl.packages.${system}; in { homeConfigurations."karl3" = home-manager.lib.homeManagerConfiguration { inherit pkgs; # Specify your home configuration modules here, for example, # the path to your home.nix. modules = [ ./home.nix ]; # Optionally use extraSpecialArgs # to pass through arguments to home.nix }; }; } ````` </details> <details><summary>home.nix.txt</summary> ````` { config, pkgs, nixgl, ... }: { # Home Manager needs a bit of information about you and the paths it should # manage. home.username = "karl3"; home.homeDirectory = "/home/karl3"; # This value determines the Home Manager release that your configuration is # compatible with. This helps avoid breakage when a new Home Manager release # introduces backwards incompatible changes. # # You should not change this value, even if you update Home Manager. If you do # want to update the value, then make sure to first check the Home Manager # release notes. home.stateVersion = "24.11"; # Please read the comment before changing. # The home.packages option allows you to install Nix packages into your # environment. home.packages = [ pkgs.tmux pkgs.nodejs_22 nixgl.default (pkgs.python3.withPackages (python_pkgs: [ python_pkgs.numpy python_pkgs.torch python_pkgs.transformers python_pkgs.sentencepiece python_pkgs.accelerate python_pkgs.diffusers python_pkgs.pip # this doesn't seem to do anything yet maybe start with a precise example from the internet #python_pkgs.buildPythonPackage { # name = "pyarweave"; # src = /home/karl3/projects/pyarweave; #} python_pkgs.lockfile python_pkgs.requests_toolbelt python_pkgs.pygame python_pkgs.pycryptodome python_pkgs.python-jose python_pkgs.arrow python_pkgs.pyopengl python_pkgs.vispy python_pkgs.moderngl python_pkgs.vulkan python_pkgs.pyqt5 #python_pkgs.pysdl3 python_pkgs.pysdl2 python_pkgs.glfw ])) # # Adds the 'hello' command to your environment. It prints a friendly # # "Hello, world!" when run. # pkgs.hello # # It is sometimes useful to fine-tune packages, for example, by applying # # overrides. You can do that directly here, just don't forget the # # parentheses. Maybe you want to install Nerd Fonts with a limited number of # # fonts? # (pkgs.nerdfonts.override { fonts = [ "FantasqueSansMono" ]; }) # # You can also create simple shell scripts directly inside your # # configuration. For example, this adds a command 'my-hello' to your # # environment: # (pkgs.writeShellScriptBin "my-hello" '' # echo "Hello, ${config.home.username}!" # '') ]; # Home Manager is pretty good at managing dotfiles. The primary way to manage # plain files is through 'home.file'. home.file = { # # Building this configuration will create a copy of 'dotfiles/screenrc' in # # the Nix store. Activating the configuration will then make '~/.screenrc' a # # symlink to the Nix store copy. # ".screenrc".source = dotfiles/screenrc; # # You can also set the file content immediately. # ".gradle/gradle.properties".text = '' # org.gradle.console=verbose # org.gradle.daemon.idletimeout=3600000 # ''; }; # Home Manager can also manage your environment variables through # 'home.sessionVariables'. These will be explicitly sourced when using a # shell provided by Home Manager. If you don't want to manage your shell # through Home Manager then you have to manually source 'hm-session-vars.sh' # located at either # # ~/.nix-profile/etc/profile.d/hm-session-vars.sh # # or # # ~/.local/state/nix/profiles/profile/etc/profile.d/hm-session-vars.sh # # or # # /etc/profiles/per-user/karl3/etc/profile.d/hm-session-vars.sh # home.sessionVariables = { # EDITOR = "emacs"; }; # Let Home Manager install and manage itself. programs.home-manager.enable = true; } ````` </details> **assistant** (May 9, 2025, 04:11 PM) I see you're trying to incorporate nixGL into your Home Manager configuration but running into issues. Let's fix this by examining your error message and configuration files. The key problem is in your `flake.nix` file where the nixGL input isn't being properly passed to your configuration. The error specifically states: `error: attribute 'nixgl' missing`. Here's how to fix it: 1. First, your `flake.nix` needs to properly capture and pass the nixGL input to your configuration. 2. The `outputs` function should include nixGL in its parameters. 3. The `extraSpecialArgs` field needs to be used to pass nixGL to your home.nix. Let me show you the corrected `flake.nix`: #### create Fixed flake.nix ```nix { description = "Home Manager configuration of karl3"; inputs = { # Specify the source of Home Manager and Nixpkgs. nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; home-manager = { url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; nixgl = { url = "github:nix-community/nixGL"; }; }; outputs = { nixpkgs, home-manager, nixgl, ... }: let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; in { homeConfigurations."karl3" = home-manager.lib.homeManagerConfiguration { inherit pkgs; # Specify your home configuration modules here, for example, # the path to your home.nix. modules = [ ./home.nix ]; # Pass nixgl to home.nix extraSpecialArgs = { inherit nixgl; }; }; }; } ``` There are a few key changes I made to fix your configuration: 1. **Added nixgl to outputs function parameters**: I updated `outputs = { nixpkgs, home-manager, ... }:` to include `nixgl` in the parameter list: `outputs = { nixpkgs, home-manager, nixgl, ... }:` 2. **Removed problematic line**: I removed the line `nixgl = nixgl.packages.${system};` which was causing issues because nixgl was being used before it was defined. 3. **Added extraSpecialArgs**: I added `extraSpecialArgs = { inherit nixgl; };` to pass the nixgl input to your home.nix file. With these changes, you should be able to reference `nixgl` in your home.nix. If you want to use nixGL packages in your home.nix, you'll need to access them properly. Here's how to modify your home.nix to properly use nixGL: #### create Fixed home.nix ```nix { config, pkgs, nixgl, ... }: { # Home Manager needs a bit of information about you and the paths it should # manage. home.username = "karl3"; home.homeDirectory = "/home/karl3"; # This value determines the Home Manager release that your configuration is # compatible with. This helps avoid breakage when a new Home Manager release # introduces backwards incompatible changes. # # You should not change this value, even if you update Home Manager. If you do # want to update the value, then make sure to first check the Home Manager # release notes. home.stateVersion = "24.11"; # Please read the comment before changing. # The home.packages option allows you to install Nix packages into your # environment. home.packages = [ pkgs.tmux pkgs.nodejs_22 nixgl.packages.${pkgs.system}.nixGLDefault # Corrected nixGL reference (pkgs.python3.withPackages (python_pkgs: [ python_pkgs.numpy python_pkgs.torch python_pkgs.transformers python_pkgs.sentencepiece python_pkgs.accelerate python_pkgs.diffusers python_pkgs.pip # this doesn't seem to do anything yet maybe start with a precise example from the internet #python_pkgs.buildPythonPackage { # name = "pyarweave"; # src = /home/karl3/projects/pyarweave; #} python_pkgs.lockfile python_pkgs.requests_toolbelt python_pkgs.pygame python_pkgs.pycryptodome python_pkgs.python-jose python_pkgs.arrow python_pkgs.pyopengl python_pkgs.vispy python_pkgs.moderngl python_pkgs.vulkan python_pkgs.pyqt5 #python_pkgs.pysdl3 python_pkgs.pysdl2 python_pkgs.glfw ])) ]; # Home Manager is pretty good at managing dotfiles. The primary way to manage # plain files is through 'home.file'. home.file = { # # Building this configuration will create a copy of 'dotfiles/screenrc' in # # the Nix store. Activating the configuration will then make '~/.screenrc' a # # symlink to the Nix store copy. # ".screenrc".source = dotfiles/screenrc; # # You can also set the file content immediately. # ".gradle/gradle.properties".text = '' # org.gradle.console=verbose # org.gradle.daemon.idletimeout=3600000 # ''; }; # Home Manager can also manage your environment variables through # 'home.sessionVariables'. These will be explicitly sourced when using a # shell provided by Home Manager. If you don't want to manage your shell # through Home Manager then you have to manually source 'hm-session-vars.sh' # located at either # # ~/.nix-profile/etc/profile.d/hm-session-vars.sh # # or # # ~/.local/state/nix/profiles/profile/etc/profile.d/hm-session-vars.sh # # or # # /etc/profiles/per-user/karl3/etc/profile.d/hm-session-vars.sh # home.sessionVariables = { # EDITOR = "emacs"; }; # Let Home Manager install and manage itself. programs.home-manager.enable = true; } ``` The key change in the home.nix file is how nixGL is referenced: I changed `nixgl.default` to `nixgl.packages.${pkgs.system}.nixGLDefault`. This properly accesses the nixGL packages for your system architecture. To apply these changes: 1. Replace your current `flake.nix` with the fixed version I provided. 2. Replace your `home.nix` with the fixed version or just update the nixGL reference. 3. Run `home-manager switch --flake .` to apply the changes. If you want to use other specific nixGL packages, you can replace `nixGLDefault` with other available packages from the nixGL project like: - `nixGLIntel` - `nixGLNvidia` - `nixVulkanIntel` - `nixVulkanNvidia` Depending on your graphics hardware, you might want to choose the appropriate one. **human** (May 9, 2025, 04:15 PM) That seemed to help a lot. I'm now getting a further error. Can you explain it to me? Is this related to why --impure is passed when nixgl is run from the commandline? ``` error: … while calling the 'derivationStrict' builtin at <nix/derivation-internal.nix>:37:12: 36| 37| strict = derivationStrict drvAttrs; | ^ 38| … while evaluating derivation 'home-manager-generation' whose name attribute is located at «github:nixos/nixpkgs/8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7?narHash=sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo%3D»/pkgs/stdenv/generic/make-derivation.nix:438:13 … while evaluating attribute 'buildCommand' of derivation 'home-manager-generation' at «github:nixos/nixpkgs/8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7?narHash=sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo%3D»/pkgs/build-support/trivial-builders/default.nix:80:17: 79| enableParallelBuilding = true; 80| inherit buildCommand name; | ^ 81| passAsFile = [ "buildCommand" ] ++ (derivationArgs.passAsFile or [ ]); … while evaluating the option `home.activation.installPackages.data': … while evaluating definitions from `/nix/store/lpqjvb4ix9m7jfrcqb9n0km5c6gzn7sp-source/modules/home-environment.nix': … while evaluating the option `home.packages': … while evaluating definitions from `/nix/store/nxw5nzapbj77x3fwhjndf4f4c1d97gai-source/home.nix': (stack trace truncated; use '--show-trace' to show the full, detailed trace) error: attribute 'currentTime' missing at «github:nix-community/nixGL/310f8e49a149e4c9ea52f1adf70cdc768ec53f8a?narHash=sha256-lnzZQYG0%2BEXl/6NkGpyIz%2BFEOc/DSEG57AP1VsdeNrM%3D»/nixGL.nix:223:18: 222| # Add an impure parameter to force the rebuild on each access. 223| time = builtins.currentTime; | ^ 224| preferLocalBuild = true; ``` **assistant** (May 9, 2025, 04:16 PM) Yes, this error is definitely related to why nixGL often needs `--impure` when running from the command line. Let me explain what's happening: The error message shows that nixGL is trying to use `builtins.currentTime` which is an impure operation in Nix. In Nix terminology, "impure" means that it can produce different results when run at different times, which breaks Nix's guarantee of reproducible builds. Looking at the specific error in the nixGL.nix file (line 223), we can see: ```nix # Add an impure parameter to force the rebuild on each access. time = builtins.currentTime; ``` The comment itself explains what's happening - nixGL is intentionally using `builtins.currentTime` to force a rebuild each time it's accessed. This is sometimes necessary for hardware-specific operations where the system state needs to be checked at runtime. Here's how to fix this: 1. You need to add `--impure` to your home-manager command: ``` home-manager switch --flake . --impure ``` 2. Alternatively, you can modify your flake.nix to specify that nixGL should be allowed to use impure operations: #### create Fixed flake.nix with impure nixGL ```nix { description = "Home Manager configuration of karl3"; inputs = { # Specify the source of Home Manager and Nixpkgs. nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; home-manager = { url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; nixgl = { url = "github:nix-community/nixGL"; # Make nixGL use a fixed timestamp instead of currentTime inputs.flake-utils.follows = "flake-utils"; }; flake-utils.url = "github:numtide/flake-utils"; }; outputs = { nixpkgs, home-manager, nixgl, ... }: let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; # Create a modified version of nixGL without the impure operation nixGLFixed = let nixGLPkgs = nixgl.packages.${system}; in { packages.${system} = { # You can list specific packages you need here nixGLDefault = nixGLPkgs.nixGLDefault.overrideAttrs (old: { # Remove or override the problematic attribute passthru = (old.passthru or {}) // { # You can add any necessary attributes here, but without currentTime }; }); }; }; in { homeConfigurations."karl3" = home-manager.lib.homeManagerConfiguration { inherit pkgs; # Specify your home configuration modules here, for example, # the path to your home.nix. modules = [ ./home.nix ]; # Pass the modified nixGL to home.nix extraSpecialArgs = { nixgl = nixGLFixed; }; }; }; } ``` There's also another approach you could take that might be simpler. Instead of trying to fix the impurity in nixGL, you could wrap the nixGL tools in your home.nix file: #### create Alternative home.nix approach ```nix { config, pkgs, nixgl, ... }: { # Home Manager needs a bit of information about you and the paths it should # manage. home.username = "karl3"; home.homeDirectory = "/home/karl3"; # This value determines the Home Manager release that your configuration is # compatible with. This helps avoid breakage when a new Home Manager release # introduces backwards incompatible changes. # # You should not change this value, even if you update Home Manager. If you do # want to update the value, then make sure to first check the Home Manager # release notes. home.stateVersion = "24.11"; # Please read the comment before changing. # The home.packages option allows you to install Nix packages into your # environment. home.packages = [ pkgs.tmux pkgs.nodejs_22 # Instead of directly including nixGL, create wrappers for specific applications (pkgs.writeShellScriptBin "nixGL" '' exec ${pkgs.nixgl.packages.${pkgs.system}.nixGLDefault}/bin/nixGL "$@" '') # Example of wrapping a specific application with nixGL (pkgs.writeShellScriptBin "gl-wrapped-application" '' exec ${pkgs.nixgl.packages.${pkgs.system}.nixGLDefault}/bin/nixGL ${pkgs.some-opengl-app}/bin/application "$@" '') (pkgs.python3.withPackages (python_pkgs: [ python_pkgs.numpy python_pkgs.torch python_pkgs.transformers python_pkgs.sentencepiece python_pkgs.accelerate python_pkgs.diffusers python_pkgs.pip python_pkgs.lockfile python_pkgs.requests_toolbelt python_pkgs.pygame python_pkgs.pycryptodome python_pkgs.python-jose python_pkgs.arrow python_pkgs.pyopengl python_pkgs.vispy python_pkgs.moderngl python_pkgs.vulkan python_pkgs.pyqt5 python_pkgs.pysdl2 python_pkgs.glfw ])) ]; # Home Manager is pretty good at managing dotfiles. The primary way to manage # plain files is through 'home.file'. home.file = {}; home.sessionVariables = {}; # Let Home Manager install and manage itself. programs.home-manager.enable = true; } ``` ## Understanding The Issue with nixGL and Impurity The error you're seeing is directly related to why nixGL often requires `--impure` when run from the command line. Here's a breakdown: ### What's Happening: 1. **Impure operation**: nixGL intentionally uses `builtins.currentTime` which is an "impure" operation in Nix. 2. **What "impure" means**: In Nix, any function that can give different results when run at different times is considered "impure", which breaks Nix's guarantee of reproducible builds. 3. **The purpose**: Based on the comment in nixGL's code, this is intentional to force nixGL to rebuild on each access, likely because it needs to detect hardware configurations that might change. ### Why `--impure` is needed: By default, Nix doesn't allow impure operations to ensure reproducible builds. The `--impure` flag tells Nix to allow these operations. ## Solutions: ### Option 1: Use `--impure` flag (Simplest) The easiest solution is to use the `--impure` flag when building: ``` home-manager switch --flake . --impure ``` ### Option 2: Wrapper Approach (Recommended) Create wrapper scripts around nixGL as shown in the "Alternative home.nix approach" artifact. This works by: 1. Creating a shell script that calls nixGL 2. Only using the impure operations when the script is actually executed, not during Nix evaluation ### Option 3: Override nixGL (Advanced) As shown in the "Fixed flake.nix with impure nixGL" artifact, you can try to override the problematic part of nixGL, but this might be fragile as nixGL updates. ## Recommendation: 1. First try the simplest approach - add `--impure` to your command: ``` home-manager switch --flake . --impure ``` 2. If you frequently rebuild your environment and don't want to remember to add `--impure` each time, use the wrapper approach from the "Alternative home.nix approach" artifact. 3. You might also want to look into how you're actually using nixGL. If you're primarily using it to run specific applications with OpenGL support, creating specific wrappers for those applications might be cleaner than including the general nixGL package. This issue is common when working with hardware-specific Nix packages (like those dealing with graphics, audio, etc.) because they often need runtime system information that conflicts with Nix's pure evaluation model. **human** (May 9, 2025, 04:23 PM) it looks like it might work if i specify the intel driver rather than default. can you tell me why? <details><summary>nixGL.nix.txt</summary> ````` { # # Nvidia informations. # Version of the system kernel module. Let it to null to enable auto-detection. nvidiaVersion ? null, # 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. enable32bits ? stdenv.hostPlatform.isx86 , stdenv, writeTextFile, shellcheck, pcre, runCommand, linuxPackages , fetchurl, lib, runtimeShell, bumblebee, libglvnd, vulkan-validation-layers , mesa, libvdpau-va-gl, intel-media-driver, pkgsi686Linux, driversi686Linux , zlib, libdrm, xorg, wayland, gcc, zstd }: let writeExecutable = { name, text }: writeTextFile { inherit name text; 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 ''; }; writeNixGL = name: vadrivers: writeExecutable { inherit name; # add the 32 bits drivers if needed text = let mesa-drivers = [ mesa.drivers ] ++ lib.optional enable32bits pkgsi686Linux.mesa.drivers; libvdpau = [ libvdpau-va-gl ] ++ lib.optional enable32bits pkgsi686Linux.libvdpau-va-gl; glxindirect = runCommand "mesa_glxindirect" { } ('' mkdir -p $out/lib ln -s ${mesa.drivers}/lib/libGLX_mesa.so.0 $out/lib/libGLX_indirect.so.0 ''); in '' #!${runtimeShell} export LIBGL_DRIVERS_PATH=${lib.makeSearchPathOutput "lib" "lib/dri" mesa-drivers} export LIBVA_DRIVERS_PATH=${lib.makeSearchPathOutput "out" "lib/dri" (mesa-drivers ++ vadrivers)} ${''export __EGL_VENDOR_LIBRARY_FILENAMES=${mesa.drivers}/share/glvnd/egl_vendor.d/50_mesa.json${ lib.optionalString enable32bits ":${pkgsi686Linux.mesa.drivers}/share/glvnd/egl_vendor.d/50_mesa.json" }"''${__EGL_VENDOR_LIBRARY_FILENAMES:+:$__EGL_VENDOR_LIBRARY_FILENAMES}"'' } export LD_LIBRARY_PATH=${lib.makeLibraryPath mesa-drivers}:${lib.makeSearchPathOutput "lib" "lib/vdpau" libvdpau}:${glxindirect}/lib:${lib.makeLibraryPath [libglvnd]}"''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" exec "$@" ''; }; top = rec { /* It contains the builder for different nvidia configuration, parametrized by the version of the driver and sha256 sum of the driver installer file. */ nvidiaPackages = { version, sha256 ? null }: rec { nvidiaDrivers = (linuxPackages.nvidia_x11.override { }).overrideAttrs (oldAttrs: rec { pname = "nvidia"; name = "nvidia-x11-${version}-nixGL"; inherit version; src = let url = "https://download.nvidia.com/XFree86/Linux-x86_64/${version}/NVIDIA-Linux-x86_64-${version}.run"; in if sha256 != null then fetchurl { inherit url sha256; } else builtins.fetchurl url; useGLVND = true; nativeBuildInputs = oldAttrs.nativeBuildInputs or [] ++ [zstd]; }); nvidiaLibsOnly = nvidiaDrivers.override { libsOnly = true; kernel = null; }; nixGLNvidiaBumblebee = writeExecutable { name = "nixGLNvidiaBumblebee-${version}"; text = '' #!${runtimeShell} export LD_LIBRARY_PATH=${ lib.makeLibraryPath [ nvidiaDrivers ] }"''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" ${ bumblebee.override { nvidia_x11 = nvidiaDrivers; nvidia_x11_i686 = nvidiaDrivers.lib32; } }/bin/optirun --ldpath ${ lib.makeLibraryPath ([ libglvnd nvidiaDrivers ] ++ lib.optionals enable32bits [ nvidiaDrivers.lib32 pkgsi686Linux.libglvnd ]) } "$@" ''; }; # TODO: 32bit version? Not tested. nixNvidiaWrapper = api: writeExecutable { name = "nix${api}Nvidia-${version}"; text = '' #!${runtimeShell} ${lib.optionalString (api == "Vulkan") "export VK_LAYER_PATH=${vulkan-validation-layers}/share/vulkan/explicit_layer.d"} NVIDIA_JSON=(${nvidiaLibsOnly}/share/glvnd/egl_vendor.d/*nvidia.json) ${lib.optionalString enable32bits "NVIDIA_JSON32=(${nvidiaLibsOnly.lib32}/share/glvnd/egl_vendor.d/*nvidia.json)"} ${''export __EGL_VENDOR_LIBRARY_FILENAMES=''${NVIDIA_JSON[*]}${ lib.optionalString enable32bits '':''${NVIDIA_JSON32[*]}'' }"''${__EGL_VENDOR_LIBRARY_FILENAMES:+:$__EGL_VENDOR_LIBRARY_FILENAMES}"'' } ${ lib.optionalString (api == "Vulkan") ''export VK_ICD_FILENAMES=${nvidiaLibsOnly}/share/vulkan/icd.d/nvidia_icd.x86_64.json${ lib.optionalString enable32bits ":${nvidiaLibsOnly.lib32}/share/vulkan/icd.d/nvidia_icd.i686.json" }"''${VK_ICD_FILENAMES:+:$VK_ICD_FILENAMES}"'' } export LD_LIBRARY_PATH=${ lib.makeLibraryPath ([ libglvnd nvidiaLibsOnly ] ++ lib.optional (api == "Vulkan") vulkan-validation-layers ++ lib.optionals enable32bits [ nvidiaLibsOnly.lib32 pkgsi686Linux.libglvnd ]) }"''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" exec "$@" ''; }; # TODO: 32bit version? Not tested. nixGLNvidia = nixNvidiaWrapper "GL"; # TODO: 32bit version? Not tested. nixVulkanNvidia = nixNvidiaWrapper "Vulkan"; }; nixGLMesa = writeNixGL "nixGLMesa" [ ]; nixGLIntel = writeNixGL "nixGLIntel" ([ intel-media-driver ] ++ lib.optionals enable32bits [ pkgsi686Linux.intel-media-driver ]); nixVulkanMesa = writeExecutable { name = "nixVulkanIntel"; text = let # generate a file with the listing of all the icd files icd = runCommand "mesa_icd" { } ( # 64 bits icd '' ls ${mesa.drivers}/share/vulkan/icd.d/*.json > f '' # 32 bits ones + lib.optionalString enable32bits '' ls ${pkgsi686Linux.mesa.drivers}/share/vulkan/icd.d/*.json >> f '' # concat everything as a one line string with ":" as seperator + ''cat f | xargs | sed "s/ /:/g" > $out''); in '' #!${runtimeShell} if [ -n "$LD_LIBRARY_PATH" ]; then echo "Warning, nixVulkanIntel overwriting existing LD_LIBRARY_PATH" 1>&2 fi export VK_LAYER_PATH=${vulkan-validation-layers}/share/vulkan/explicit_layer.d ICDS=$(cat ${icd}) export VK_ICD_FILENAMES=$ICDS"''${VK_ICD_FILENAMES:+:$VK_ICD_FILENAMES}" export LD_LIBRARY_PATH=${ lib.makeLibraryPath [ zlib libdrm xorg.libX11 xorg.libxcb xorg.libxshmfence wayland gcc.cc ] }"''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" exec "$@" ''; }; nixVulkanIntel = nixVulkanMesa; nixGLCommon = nixGL: runCommand "nixGL" { } '' mkdir -p "$out/bin" # star because nixGLNvidia... have version prefixed name cp ${nixGL}/bin/* "$out/bin/nixGL"; ''; auto = 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; preferLocalBuild = true; allowSubstitutes = false; } "cp /proc/driver/nvidia/version $out 2> /dev/null || touch $out"; # The nvidia version. Either fixed by the `nvidiaVersion` argument, or # auto-detected. Auto-detection is impure. nvidiaVersionAuto = if nvidiaVersion != null then nvidiaVersion else # Get if from the nvidiaVersionFile let data = builtins.readFile _nvidiaVersionFile; versionMatch = builtins.match ".*Module ([0-9.]+) .*" data; in if versionMatch != null then builtins.head versionMatch else null; autoNvidia = nvidiaPackages {version = nvidiaVersionAuto; }; in rec { # The output derivation contains nixGL which point either to # nixGLNvidia or nixGLIntel using an heuristic. nixGLDefault = if nvidiaVersionAuto != null then nixGLCommon autoNvidia.nixGLNvidia else nixGLCommon nixGLIntel; } // autoNvidia; }; in top // (if nvidiaVersion != null then top.nvidiaPackages { version = nvidiaVersion; sha256 = nvidiaHash; } else { }) ````` </details> **assistant** (May 9, 2025, 04:24 PM) After examining the nixGL.nix code, I can see why specifying the Intel driver might work while the default option fails. The issue is indeed related to that impure operation we discussed. ## Why Specifying the Intel Driver Works Looking at the nixGL.nix code, here's what's happening: 1. The `auto` function in nixGL.nix contains the problematic impure code: ```nix # Add an impure parameter to force the rebuild on each access. time = builtins.currentTime; ``` 2. This impure operation is only used when: - You're using `nixGLDefault` (which tries to auto-detect your GPU) - Your system has NVIDIA hardware that needs auto-detection 3. When you specifically request `nixGLIntel`, it bypasses this auto-detection logic completely: ```nix nixGLIntel = writeNixGL "nixGLIntel" [intel-media-driver] ... ``` ## The Auto-Detection Logic The `nixGLDefault` function in the code: ```nix nixGLDefault = if nvidiaVersionAuto != null then nixGLCommon autoNvidia.nixGLNvidia else nixGLCommon nixGLIntel; ``` This attempts to detect if you have NVIDIA hardware. If it can't find NVIDIA drivers, it defaults to Intel. The detection process relies on: 1. Reading `/proc/driver/nvidia/version` (which requires accessing the system at build time) 2. Using the impure `builtins.currentTime` function to force a rebuild on each access ## Solution If you know you have Intel graphics, you can modify your home.nix to use the Intel-specific nixGL package instead of the default one: #### create Intel-specific home.nix ```nix { config, pkgs, nixgl, ... }: { # Home Manager needs a bit of information about you and the paths it should # manage. home.username = "karl3"; home.homeDirectory = "/home/karl3"; # This value determines the Home Manager release that your configuration is # compatible with. This helps avoid breakage when a new Home Manager release # introduces backwards incompatible changes. # # You should not change this value, even if you update Home Manager. If you do # want to update the value, then make sure to first check the Home Manager # release notes. home.stateVersion = "24.11"; # Please read the comment before changing. # The home.packages option allows you to install Nix packages into your # environment. home.packages = [ pkgs.tmux pkgs.nodejs_22 # Use the Intel-specific nixGL package nixgl.packages.${pkgs.system}.nixGLIntel (pkgs.python3.withPackages (python_pkgs: [ python_pkgs.numpy python_pkgs.torch python_pkgs.transformers python_pkgs.sentencepiece python_pkgs.accelerate python_pkgs.diffusers python_pkgs.pip # this doesn't seem to do anything yet maybe start with a precise example from the internet #python_pkgs.buildPythonPackage { # name = "pyarweave"; # src = /home/karl3/projects/pyarweave; #} python_pkgs.lockfile python_pkgs.requests_toolbelt python_pkgs.pygame python_pkgs.pycryptodome python_pkgs.python-jose python_pkgs.arrow python_pkgs.pyopengl python_pkgs.vispy python_pkgs.moderngl python_pkgs.vulkan python_pkgs.pyqt5 #python_pkgs.pysdl3 python_pkgs.pysdl2 python_pkgs.glfw ])) ]; # Home Manager is pretty good at managing dotfiles. The primary way to manage # plain files is through 'home.file'. home.file = {}; home.sessionVariables = {}; # Let Home Manager install and manage itself. programs.home-manager.enable = true; } ``` ## Understanding `--impure` in nixGL You asked about why `--impure` is passed when nixGL is run from the command line. Here's why: 1. **Purpose of impurity**: nixGL needs to detect hardware at runtime. 2. **Nix Philosophy**: Nix normally enforces "pure" evaluation - builds should be reproducible and not depend on the specific machine or time they're built on. 3. **Hardware detection challenge**: OpenGL and GPU libraries often need to adapt to the specific hardware present, which conflicts with Nix's purity model. 4. **The `currentTime` trick**: The nixGL code includes `time = builtins.currentTime` which deliberately makes the build impure to force redetection of hardware. From the comment: "Add an impure parameter to force the rebuild on each access." 5. **Why it's needed**: Without this, Nix would cache the hardware detection result, which could cause problems if your hardware changes or if you move the build to another machine. ## Comparing Your Options 1. **Using `nixGLIntel` (Recommended)**: - Advantages: Works without `--impure` flag - Disadvantages: Only works if you actually have Intel graphics 2. **Using `nixGLDefault` with `--impure`**: - Advantages: Auto-detects your graphics hardware - Disadvantages: Requires impure operation, may break in some Nix environments 3. **Using `nixGLNvidia`** (if you have NVIDIA): - Advantages: Works without `--impure` if you specify the version - Disadvantages: Only works with NVIDIA graphics ## Conclusion The reason specifying the Intel driver works without `--impure` is that it bypasses the auto-detection mechanism that's intentionally designed to be impure. If you know your system has Intel graphics, using `nixGL.packages.${pkgs.system}.nixGLIntel` is the cleanest approach. If you have NVIDIA hardware and know the exact driver version, you could also use `nixGLNvidia` with that specific version to avoid impurity. This is a common pattern in Nix packages that deal with hardware - they often need to choose between auto-detection (which requires impurity) or manual specification (which requires user knowledge but stays pure).