commit c17063d377daf6227b696e83a4fe6325da8d2c9b
Author: Guillaume Bouchard <guillaum.bouchard@gmail.com>
Date: Sat, 16 Sep 2017 13:45:18 +0200
First version
Diffstat:
| A | README.md | | | 58 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | default.nix | | | 29 | +++++++++++++++++++++++++++++ |
| A | nixGL | | | 48 | ++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 135 insertions(+), 0 deletions(-)
diff --git a/README.md b/README.md
@@ -0,0 +1,58 @@
+This tool tries to solve the "OpenGL" problem on nix.
+
+# Motivation
+
+You use Nix on any distribution, and any GL application installed fails with this error:
+
+```
+$ program
+libGL error: unable to load driver: i965_dri.so
+libGL error: driver pointer missing
+libGL error: failed to load driver: i965
+libGL error: unable to load driver: i965_dri.so
+libGL error: driver pointer missing
+libGL error: failed to load driver: i965
+libGL error: unable to load driver: swrast_dri.so
+libGL error: failed to load driver: swrast
+```
+
+This library contains a wrapper which is able to launch GL application:
+
+```
+nixGL program
+```
+
+# Installation / Usage
+
+Clone this git repository:
+
+```
+git clone https://github.com/guibou/nixGL
+```
+
+(Optional) installation:
+
+```
+cd nixGL
+nix-build
+nix-env -i ./result
+```
+
+Usage:
+
+```
+nixGL program args
+```
+
+# Limitations
+
+The idea is really simple and should work reliably. However there is still two configurations variables hardcoded in the wrapper. Open a bug / pull request if this does not work on your distribution / driver.
+
+## Library paths
+
+The path of where the `libGL.so` library can be found on your system, usually `/usr/lib`.
+
+## Name of the Nix package which contains `libGL.so`
+
+This package will be ignored by the wrapper. It is currently hardcoded as `mesa-noglu` but this can be fixed.
+
diff --git a/default.nix b/default.nix
@@ -0,0 +1,29 @@
+{ system ? builtins.currentSystem }:
+
+let
+ pkgs = import <nixpkgs> { inherit system; };
+in
+rec {
+ nixGl = pkgs.stdenv.mkDerivation rec {
+ name = "nixGL-${version}";
+ version = "1.0.0";
+
+ buildInputs = [ pkgs.python3 pkgs.which pkgs.patchelf ];
+ outputs = [ "out" ];
+
+ src = ./.;
+
+ buildPhase = ''
+ mkdir -p $out/bin
+ '';
+
+ installPhase = ''
+ cp nixGL $out/bin
+ '';
+
+ meta = with pkgs.stdenv.lib; {
+ description = "A tool to launch OpenGL application on system other than NixOS";
+ homepage = "https://github.com/guibou/nixGL";
+ };
+ };
+}
diff --git a/nixGL b/nixGL
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+import sys
+import os
+import subprocess
+
+# Any rpath with this pattern is ignored
+# TODO: perhaps libOpenGL.so in nix exists in other packages, we
+# should extend this list
+ignored = [b'mesa-noglu']
+
+# These are the list of system library which are added
+# TODO: extend this list for other systems
+systemLibs = [b"/usr/lib", b"/lib"]
+
+# extract command line and real path of the program
+cmd = (prog, *args) = sys.argv[1:]
+realProg = subprocess.check_output(["which", prog]).strip()
+
+# extract rpath of the program
+rpaths = map(bytes.strip, subprocess.check_output(
+ ['patchelf', '--print-rpath', realProg]).split(b':'))
+
+# filter rpath, removing ignored and empty paths
+dir = []
+
+for i in rpaths:
+ for c in ignored:
+ if c not in i:
+ if i.strip():
+ dir.append(i.strip())
+
+# build the new environment
+newenv = os.environb
+oldLdLibraryPath = newenv.get(b'LD_LIBRARY_PATH', b'').split()
+
+# The build order is IMPORTANT
+# first, any LD_LIBRARY_PATH from outside world. That's the default
+# behavior, LD_LIBRARY_PATH has precedance over rpath
+# Then, the different directory which satisfy our rpaths
+# The the system library where the openGL lib can be located
+
+# This ensure three properties:
+# a) system library (and libOpenGL.so) are used AFTER the one of nix
+# b) the executible respect the LD_LIBRARY_PATH for an user viewpoint
+newLibraryPath = oldLdLibraryPath + dir + systemLibs
+
+newenv.update({b'LD_LIBRARY_PATH': b':'.join(newLibraryPath)})
+os.execvpe(prog, cmd, newenv)