commit c17063d377daf6227b696e83a4fe6325da8d2c9b Author: Guillaume Bouchard Date: Sat Sep 16 13:45:18 2017 +0200 First version diff --git a/README.md b/README.md new file mode 100644 index 0000000..2ebebe0 --- /dev/null +++ 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 new file mode 100644 index 0000000..b570c0d --- /dev/null +++ b/default.nix @@ -0,0 +1,29 @@ +{ system ? builtins.currentSystem }: + +let + pkgs = import { 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 new file mode 100755 index 0000000..e8268e6 --- /dev/null +++ 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)