Current status: alpha
Run OpenGL/Cuda programs built with Nix, on all[*] Linux distributions.
*
- see the support Matrix
Nix is great as a software distribution mechanism. It allows packaging a software once and distribute it securely to all Linux distributions. Because all the dependencies are bundled with the software, it doesn't suffer from incompatible Glibc version issues that other software might have.
Unfortunately while the previous statement is generally true, it breaks down when using programs depending on 3D drivers such as OpenGL or Cuda. Unlike with the Kernel, the interface to interact with the GPU is defined in the driver software, and that is dynamic depending on which host, and version of the driver is running.
This is where NixGLHost comes in handy. NixGLHost is a wrapper around your program that dynamically scans your host Linux system (Ubuntu, Fedora, etc.) and looks for the OpenGL/Cuda drivers. And then makes it available to use to to the Nix-built binary. It aims at solving this problem once and for all.
There are several options to use NixglHost, and the one you choose depends on the way you want to specify the path.
You can run my-gl-program
and re-use your host distribution OpenGL/Cuda setup simply with:
$ nixglhost my-gl-program
When invoked like above, nixglhost
will scan your host library path and look for the relevant driver libraries to use.
If the driver libraries auto-discovery system fails on your setup, you can explicitly point to the directory containing your driver libraries using the --driver-directory
or -d
command line flags.
For instance:
$ nixglhost -d /usr/lib/x86_64-linux-gnu my-gl-program
Finally, you can also print the directories you should inject to your LD_LIBRARY_PATH
to run an OpenGL program using the --print-ld-library-path
or -p
flag:
$ LD_LIBRARY_PATH=$(nixglhost -p):$LD_LIBRARY_PATH my-gl-program
It exists and is documented because you may not have any other options in some situations. However, you should always try to keep the dependency injection as close to the program as possible.
This means that you should always prefer wrapping the dependencies to a single binary rather than globally exporting them to the global execution environment.
The nixglhost
wrapper is exposed through the flake defaultPackage
output.
{
description = "…";
inputs = {
nix-gl-host.url = "github:numtide/nix-gl-host";
};
outputs = { self, nixpkgs, nix-gl-host }: {
packages.x86_64-linux.nix-gl-host = nix-gl-host.defaultPackage.x86_64-linux;
};
}
This project's default.nix
is a derivation you can easily callPackage
, Nixpkgs-style. You can get the nixglhost
wrapper through the following shell.nix
:
{ pkgs ? import <nixpkgs> { }, lib ? pkgs.lib }:
let
nixglhost-sources = pkgs.fetchFromGitHub {
owner = "numtide";
repo = "nix-gl-host";
rev = "main";
# Replace this with the hash Nix will complain about, TOFU style.
hash = "";
};
nixglhost = pkgs.callPackage "${nixglhost-sources}/default.nix" { };
in pkgs.mkShell {
buildInputs = [
nixglhost
];
}
We want to work with the community to integrate this work upstream. The current version demonstrates that solving this problem is possible but before adding more platforms to it, we believe that it would be good to
Currently, this project supports the following features:
Driver | GLX | EGL | Cuda | OpenCL |
---|---|---|---|---|
Proprietary Nvidia | ✅ | ✅ | ✅ | 🚫 |
Mesa | 🚫 | 🚫 | 🚫 | 🚫 |
Nouveau | 🚫 | 🚫 | 🚫 | 🚫 |
Proprietary AMD | 🚫 | 🚫 | 🚫 | 🚫 |
It has been tested on the following distributions:
Distribution | Status |
---|---|
Ubuntu 20.04 | ✅ |
Ubuntu 22.04 | ✅ |
If you require more platforms to be supported, get in touch with us.
You can enable the debug tracing of NixGLHost by setting the DEBUG environment variable.
$ DEBUG=1 nixglhost my-gl-program
If you are seeing the following error messages, your program isn't wrapped
with nixglhost
yet.
OpenGL:
name of display: localhost:10.0
Error: couldn't find RGB GLX visual or fbconfig
EGL:
EGLUT: failed to initialize EGL display
This works has drawn inspiration from NixGL. NixGL solves the same issue with a different approach. Instead of re-using the host GL libraries, it uses the Nixpkgs-provided ones to wrap the OpenGL program. With this approach, the graphic drivers are also distributed through Nix. The Nix closure is fully contained. It’s a safer approach as you’re less likely to stumble upon any DSO ABI incompatibility.
However, this explicit approach comes with tradeoff: you need to build one Nix closure for each graphic driver you plan to support. That also includes versions of the driver. This makes the deployment more complex: for each machine, you need to figure out which GPU-specific Nix closure to use.
How we see it, NixGL is best adapted for closed environment where the target hosts are under the author's control. NixGlHost is best adapted for open environments where the author doesn't control who is going to use their program.
See the INTERNALS.md document.
The code needs to be cleaned up and rewritten before scaling to more drivers.
If you require more platforms to be supported, get in touch with us.
Looking for help or customization?
Get in touch with Numtide to get a quote. We make it easy for companies to work with Open Source projects: https://numtide.com/contact