www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 1046517dcda62c25d96f7346b2b56383b82e3e18
parent 73cd9002adbfa18f331e85e9a177ebe82dc27ab8
Author: Guillaume Bouchard <guillaum.bouchard@gmail.com>
Date:   Sat, 17 Feb 2018 22:49:34 +0100

More robust solution for intel / nvidia / nvidia (bumblebee)

Diffstat:
MREADME.md | 62++++++++++++++++++++++++++++----------------------------------
Mdefault.nix | 62++++++++++++++++++++++++++++++++++++++++++++++++--------------
DnixGL | 50--------------------------------------------------
3 files changed, 76 insertions(+), 98 deletions(-)

diff --git a/README.md b/README.md @@ -19,7 +19,7 @@ libGL error: failed to load driver: swrast This library contains a wrapper which is able to launch GL application: ``` -nixGL program +nixGLXXX program ``` # Installation / Usage @@ -30,53 +30,46 @@ Clone this git repository: git clone https://github.com/guibou/nixGL ``` -(Optional) installation: +Build / install ``` cd nixGL -nix-build +nix-build -A XXX nix-env -i ./result ``` -Usage: +XXX can be one of: -``` -nixGL program args -``` - -# Limitations - -The idea is really simple and should work reliably in most cases. - -However there is still two configurations variables hardcoded in the wrapper. - -- `ignored`: the list of all nix packages which may contain a wrong `libGL.so`. -- `systemLibs`: the list of where on the host system the `libGL.so` can be found. +- `nixGLNvidia`: Nvidia driver without bumblebee (should work, but done from memory: please open a bug report if any issue) +- `nixGLNvidiaBumblebee`: Nvidia driver with bumblebee (tested) +- `nixGLIntel`: Intel driver (tested) -Open a bug / pull request if this does not work on your distribution / driver. - -It works with `primus`, but there is some artifacts, mostly due to the next fundamental issue: - -## Fundamental issue - -If your program libraries depends on different versions of the same library, for example, this dependency tree: +# Usage ``` -program - libFoo-1.2 - libBar-1.4 - libTurtle-1.6 - libBar-1.2 +nixGLXXX program args ``` -One version or the other of `libBar` may be used. In practice this does not happen a lot. +For example (on my dual GPU laptop): -A similar issue will happen if your system `libGL.so` depends on some library which are already in your program dependency list. Undefined behaviors can happen. +```bash +$ nixGLIntel glxinfo | grep -i 'OpenGL version string' +OpenGL version string: 3.0 Mesa 17.3.3 +$ nixGLNvidiaBumblebee glxinfo | grep -i 'OpenGL version string' +OpenGL version string: 4.6.0 NVIDIA 390.25 +``` -## Subprocessus +# Limitations + +The idea is really simple and should work reliably in most cases. It +can be easily extended to AMD drivers, I just don't have the hardware +to test. Contact me. -It does not work with subprocessus, that's all ;( +*Important*: You need an host system driver which match the nixpkgs one. For example, at the time of this writing, nixpkgs contains nvidia `390.25`. Your host system must contain the same version. This limitation can be lifted by using a different version of nixpkgs: -## Haskell Stack `exec` +```shell +export NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz +nix-build -A nixGLNvidia +``` -You need to call `stack --nix exec -- nixGL yourProgram` instead of `nixGL stack exec -- yourProgram` du to the incompatibility with subprocessus. If `nixGL` is not installed in your stack environment, you can use `stack --nix --no-nix-pure exec ...`. +Contact me if this limitation is too important, it may be easy to automate this process. +\ No newline at end of file diff --git a/default.nix b/default.nix @@ -2,28 +2,62 @@ let pkgs = import <nixpkgs> { inherit system; }; + + version = "1.0.0"; in +with pkgs; rec { - nixGl = pkgs.stdenv.mkDerivation rec { - name = "nixGL-${version}"; - version = "1.0.0"; + nixGLNvidiaBumblebee = runCommand "nixGLNvidiaBumblebee-${version}" { + buildInputs = [ libglvnd linuxPackages.nvidia_x11 bumblebee ]; + + meta = with pkgs.stdenv.lib; { + description = "A tool to launch OpenGL application on system other than NixOS - Nvidia bumblebee version"; + homepage = "https://github.com/guibou/nixGL"; + }; + } '' + mkdir -p $out/bin + cat > $out/bin/nixGLNvidiaBumblebee << FOO + #!/usr/bin/env sh + export LD_LIBRARY_PATH=${linuxPackages.nvidia_x11}/lib + ${bumblebee}/bin/optirun --ldpath ${libglvnd}/lib "\$@" + FOO - buildInputs = [ pkgs.python3 pkgs.which pkgs.binutils ]; - outputs = [ "out" ]; + chmod u+x $out/bin/nixGLNvidiaBumblebee + ''; - src = ./.; + nixGLNvidia = runCommand "nixGLNvidia-${version}" { + buildInputs = [ libglvnd linuxPackages.nvidia_x11 ]; - buildPhase = '' - mkdir -p $out/bin - ''; + meta = with pkgs.stdenv.lib; { + description = "A tool to launch OpenGL application on system other than NixOS - Nvidia version"; + homepage = "https://github.com/guibou/nixGL"; + }; + } '' + mkdir -p $out/bin + cat > $out/bin/nixGLNvidia << FOO + #!/usr/bin/env sh + export LD_LIBRARY_PATH=${linuxPackages.nvidia_x11}/lib:${libglvnd}/lib + "\$@" + FOO - installPhase = '' - cp nixGL $out/bin - ''; + chmod u+x $out/bin/nixGLNvidia + ''; + + nixGLIntel = runCommand "nixGLIntel-${version}" { + buildInputs = [ mesa_drivers ]; meta = with pkgs.stdenv.lib; { - description = "A tool to launch OpenGL application on system other than NixOS"; + description = "A tool to launch OpenGL application on system other than NixOS - Intel version"; homepage = "https://github.com/guibou/nixGL"; }; - }; + } '' + mkdir -p $out/bin + cat > $out/bin/nixGLIntel << FOO + #!/usr/bin/env sh + export LIBGL_DRIVERS_PATH=${mesa_drivers}/lib/dri + "\$@" + FOO + + chmod u+x $out/bin/nixGLIntel + ''; } diff --git a/nixGL b/nixGL @@ -1,50 +0,0 @@ -#!/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', b'mesa'] - -# 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 libs deps of the program -paths = [] -for line in subprocess.check_output(['ldd', realProg]).split(b'\n'): - line = line.split() - if len(line) == 4: - lib = line[2] - path = os.path.dirname(lib) - - for c in ignored: - if c in path: - break - else: - paths.append(path) - -# 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 = b':'.join(oldLdLibraryPath + paths + systemLibs) - -newenv.update({b'LD_LIBRARY_PATH': newLibraryPath}) - -os.execvpe(prog, cmd, newenv)