Manos’ Blog

Table of Contents

About

Here I write about things I usually figure out, such as pytorch development in nix, game development, or anything that piques my interest. If you want to discuss about something, reach me by email or github issues.

Run Godot made games/apps on NixOS

Trying to run games (or apps) made in Godot in Nixos will result in (in this example Pixelover):

mmxgn@emerdesktop ~/Downloads/pixelover-linux-demo $ ./PixelOver.x86_64  
Could not start dynamically linked executable: ./PixelOver.x86_64
NixOS cannot run dynamically linked executables intended for generic
linux environments out of the box. For more information, see:
https://nix.dev/permalink/stub-ld

The correct nix approach would be to create a derivation with all the necessary dependencies and patchelf the binaries. However noone has time for that. Here’s a solution that has served me well:

environment.systemPackages = with pkgs; [
  (let base = pkgs.appimageTools.defaultFhsEnvArgs; in
    pkgs.buildFHSEnv(base // {
    name = "fhs";
    targetPkgs = pkgs: 
      (base.targetPkgs pkgs) ++ (with pkgs; [
        pkg-config
        ncurses
        zsh
        mesa
        libglvnd
        wayland
        wayland-protocols
        glfw
      ]
      );
    LD_LIBRARY_PATH = with pkgs; lib.makeLibraryPath [
      mesa
      libglvn
    ];
    profile = "export FHS=1";
    runScript = "zsh";
    extraOutputsToInstall = ["dev"];
  }))
];

Then by running fhs first, you can simply execute the binary as you would under an FHS-compliant distribution:

mmxgn@emerdesktop ~/Downloads/pixelover-linux-demo $ fhs
mmxgn@emerdesktop ~/Downloads/pixelover-linux-demo $ ./PixelOver.x86_64

pixelover.png

Figure 1: Pixelover is a great app for converting your 3d models to 2d sprites (spaceship model by yours truly).

How I work with CUDA and devenv for developing with python/pytorch in NixOS

Disclaimer

What I write applies to the following:

  • Date: Jan 30, 2025
  • NixOS version 25.05 (unstable)
  • Nixpkgs channel github:nixos/nixpkgs/nixos-unstable
  • Nvidia Drivers / CUDA Version: 565.77 / 12.7

Your mileage may vary, especially if visiting this article in the future.

The problem

Machine learning with python was one of my big pain with NixOS that occasionally brought me close to abandoning it. There is no single way to make things work and if not using python from nixpkgs it is almost guaranteed to break (e.g. during compilation of numpy or something similar). Furthermore, trying different ways requires writing lots of boilerplate code which can be hard to convince your colleagues to add to the git repo. I have figured two ways to keep my sanity: by using docker and by using devenv. Here I write about the latter while I might write about the former in the future:

devenv to the rescue

I recently came across devenv which looks promising as an easy way to let me collaborate with colleagues on ml-based python projects while still using NixOS on my local environment and not having to fight through docker shenanigans (fixing for permissions, working with git repositories, and stuff). It is easy, first include it with:

environment.systemPackages = [
  pkgs.devenv
];

Then, after rebuilding from configuration.nix, switch to your repository on your disk and run:

# Initialise a devenv package
devenv init

And use the following devenv.nix, and devenv.yaml file (remember to change the python version and requirements.txt file):

{ pkgs, lib, config, inputs, ... }:
{

  # Required for compiling numpy
  packages = [ pkgs.libz ];

  languages.python = {
    enable = true;
    version = "3.10";
    venv.enable = true;
    venv.requirements = ./requirements.txt;
  };

  # This is required if you want your module to see cuda
  env.LD_LIBRARY_PATH = "/run/opengl-driver/lib";
}
inputs:
  nixpkgs-python:
    url: github:cachix/nixpkgs-python
    inputs:
      nixpkgs:
        follows: nixpkgs
  nixpkgs:
    url: github:cachix/devenv-nixpkgs/rolling

numpy
torch
torchaudio
torchvision

So, finally, after devenv shell:

python -c 'import torch; print(torch.cuda.is_available())'
True

Devenv will also modify your .gitignore file to include itself, don’t forget to stage it with git stage .gitignore.

diff --git a/.gitignore b/.gitignore
index 51aa465..7fd8971 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,3 +33,12 @@ build/*
 **/checkpoint*
 **/output**.wav
 **/*.ipynb
+# Devenv
+.devenv*
+devenv.local.nix
+
+# direnv
+.direnv
+
+# pre-commit
+.pre-commit-config.yaml

Troubleshoot

  • Importing module fails with ImportError: libXXX.so.X: cannot open shared object file: No such file or directory

    If you get an error like:

    >>> import numpy
    Traceback (most recent call last):
      File "<your-path>/.devenv/state/venv/lib/python3.10/site-packages/numpy/_core/__init__.py", line 23, in <module>
        from . import multiarray
      File "<your-path>/.devenv/state/venv/lib/python3.10/site-packages/numpy/_core/multiarray.py", line 10, in <module>
        from . import overrides
      File "<your-path>/.devenv/state/venv/lib/python3.10/site-packages/numpy/_core/overrides.py", line 7, in <module>
        from numpy._core._multiarray_umath import (
    ImportError: libz.so.1: cannot open shared object file: No such file or directory
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<your-path>/.devenv/state/venv/lib/python3.10/site-packages/numpy/__init__.py", line 114, in <module>
        from numpy.__config__ import show_config
      File "<your-path>/.devenv/state/venv/lib/python3.10/site-packages/numpy/__config__.py", line 4, in <module>
        from numpy._core._multiarray_umath import (
      File "<your-path>/.devenv/state/venv/lib/python3.10/site-packages/numpy/_core/__init__.py", line 49, in <module>
        raise ImportError(msg)
    ImportError:
    
    IMPORTANT: PLEASE READ THIS FOR ADVICE ON HOW TO SOLVE THIS ISSUE!
    
    Importing the numpy C-extensions failed. This error can happen for
    many reasons, often due to issues with your setup or how NumPy was
    installed.
    
    We have compiled some common reasons and troubleshooting tips at:
    
        https://numpy.org/devdocs/user/troubleshooting-importerror.html
    
    Please note and check the following:
    
      * The Python version is: Python3.10 from "<your-path>/.devenv/state/venv/bin/python"
      * The NumPy version is: "2.2.2"
    
    and make sure that they are the versions you expect.
    Please carefully study the documentation linked above for further help.
    
    Original error was: libz.so.1: cannot open shared object file: No such file or directory
    
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<your-path>/.devenv/state/venv/lib/python3.10/site-packages/numpy/__init__.py", line 119, in <module>
        raise ImportError(msg) from e
    ImportError: Error importing numpy: you should not try to import numpy from
            its source directory; please exit the numpy source tree, and relaunch
            your python interpreter from there.
    >>>
    

    The solution is to add the corresponding pkgs.<library> in devenv.nix. If you don’t know what that is, you can figure it out with nix-locate:

    E.g.:

    # First create the index
    nix-index
    
    # Then find the corresponding package
    nix-locate 'libz.so.1'
    
    ...
    zlib.out                                              0 s /nix/store/jb442jir0a2x7zsk0d63xb6rh8p280ai-zlib-1.3.1/lib/libz.so.1
    zlib.out                                        128,584 x /nix/store/jb442jir0a2x7zsk0d63xb6rh8p280ai-zlib-1.3.1/lib/libz.so.1.3.1
    ...
    libz.out                                              0 s /nix/store/x4hgdkl1i7x76phgkqv24m70jawqa7jm-libz-1.2.8.2015.12.26-unstable-2018-03-31/lib/libz.so.1
    libz.out                                        107,680 r /nix/store/x4hgdkl1i7x76phgkqv24m70jawqa7jm-libz-1.2.8.2015.12.26-unstable-2018-03-31/lib/libz.so.1.2.8
    ...
    

    And now you can add pkgs.libz to devenv.nix:

    ...
    packages = [ pkgs.libz ];
    ...
    

    Another usual suspect is cv2 which requires pkgs.libGL and pkgs.glib.

Created: 2025-04-27 Κυρ 20:08

Emacs 30.1 (Org mode 9.7.11)