Having trouble installing Nibbler on NixOS

I’ve never tried to build a package using Nix, so I could be completely off base with my approach. I want to install Nibbler which is a Leela Chess Zero GUI that’s distributed through this install script.

I tried to write this default.nix in order to build Nibbler on Linux. When running nix-build default.nix, I got this output which looks fine, but I can’t open Nibbler.

I get this error saying “no such file or directory”, even though it’s definitely there.

    ➜  nibbler ./result/bin/nibbler 
    zsh: no such file or directory: ./result/bin/nibbler

Using ldd, it seems as though I’m missing a bunch of dependencies for Nibbler. What’s the best way to fix this issue? I don’t see a lot of these packages in the repos.

That install script downloads a precompiled binary. This means the first few bytes of the file will be something like:

#!/lib/ld-linux.so

Which is to say, if you execute the binary it will try to run itself with a hard-coded dynamic linker which is supposed to load all the dependencies you see with ldd.

That linker, deliberately, doesn’t exist in that location on NixOS, because it’s an implicit dependency - all binaries would need to share the same version if they used the linker from that path, and NixOS’ entire raison d’etre is making sure we can have dependencies like this be independent.

And that’s why you get that error - the linux kernel will give you that file not found error when you try to execute something whose interpreter doesn’t exist. It’s the most confusingly wrong error message, but that’s what it means. I swear one day I’ll patch the kernel to give a better message.

To add to the confusion, as ldd just executes a linker that isn’t necessarily the hard coded one (and therefore does exist because it comes with the package that provides ldd) to check the libraries, it will look like the linker exists. Go figure.

The dependencies are indeed also a problem, you’ll need to have them set up as buildinputs, and nix will need to have the exact right versions to keep them actually installed at runtime, too, which is practically impossible if you’re using a binary like this.

Either way, that install script is inherently incompatible with NixOS, because it uses a precompiled, dynamically linked binary. It also tries to install files into absolute paths (the various /usr/share dirs), which you’ll note don’t exist on NixOS either, because that’s also implicit and imperative.

You have a few options:

  1. Build the project from scratch and write your own installScript that does something similar to the script you downloaded, but adapted to NixOS.
  1. Just download the binary and patchelf it, hoping that it just works™.
  2. Get a ubuntu VM through something like gnome-boxes and run this in there.

The first option basically means you need to learn nix packaging. IME it ends up being easier for anything that option two would have worked for, and you also learn a skill that you will continue to use whenever this happens. Buuut… I’m not sure I’d recommend an npm package as your first rodeo.

The second is more hacky, but can sometimes work for things that are too complex to package. You’ll probably miss out on installing icons and desktop files, as that’s hard to do if you don’t know how to package stuff, but they’re usually not essential. That said, the more complex the package, the less likely this will actually work - the GUI may break if it doesn’t agree with your driver versions, for example. It’s generally better for situations in which you don’t have the option of building from scratch.

Finally the VM is always a good back up option. Until the world starts writing packages for NixOS as a tier one platform, you’ll occasionally have to resort to using a distro that’s currently a tier one platform, at least if you don’t want to (or can’t) do the work of providing that support yourself.

According to the project’s README the files/src directory contains the Electron resources needed to run the app. Since there’s no build process involved this should be an easy package to create. You can try something like this:

{ pkgs ? import <nixpkgs> { } }:

let
  pname = "nibbler";
  version = "2.4.0";

  launcher = pkgs.writeScript "${pname}-launcher" ''
    #! ${pkgs.bash}/bin/bash

    ${pkgs.electron}/bin/electron @out@/usr/share/${pname}
  '';
in pkgs.stdenv.mkDerivation rec {
  inherit pname version;

  src = fetchFromGitHub {
    owner = "rootlift";
    repo = pname;
    rev = "v${version}";
    sha256 = "HASH GOES HERE";
  };

  installPhase = ''
    mkdir -p $out/bin $out/share/${pname}
    cp -r files/src/* $out/share/${pname}
    install -D -m 777 ${launcher} $out/bin/${pname}
    substituteAllInPlace $out/bin/${pname}
  '';

  meta = with pkgs.lib; {
    description = "${pname} Chess GUI";
    homepage = "https://github.com/rooklift/${pname}";
    license = licenses.mit;
    platforms = platforms.linux;
  };
}
1 Like