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:
| M | README.md | | | 62 | ++++++++++++++++++++++++++++---------------------------------- |
| M | default.nix | | | 62 | ++++++++++++++++++++++++++++++++++++++++++++++++-------------- |
| D | nixGL | | | 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)