More robust solution for intel / nvidia / nvidia (bumblebee)
This commit is contained in:
parent
73cd9002ad
commit
1046517dcd
63
README.md
63
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:
|
||||
|
||||
- `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)
|
||||
|
||||
# Usage
|
||||
|
||||
```
|
||||
nixGL program args
|
||||
nixGLXXX program args
|
||||
```
|
||||
|
||||
For example (on my dual GPU laptop):
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
# Limitations
|
||||
|
||||
The idea is really simple and should work reliably in most cases.
|
||||
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.
|
||||
|
||||
However there is still two configurations variables hardcoded in the wrapper.
|
||||
*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:
|
||||
|
||||
- `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.
|
||||
|
||||
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:
|
||||
|
||||
```
|
||||
program
|
||||
libFoo-1.2
|
||||
libBar-1.4
|
||||
libTurtle-1.6
|
||||
libBar-1.2
|
||||
```shell
|
||||
export NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz
|
||||
nix-build -A nixGLNvidia
|
||||
```
|
||||
|
||||
One version or the other of `libBar` may be used. In practice this does not happen a lot.
|
||||
|
||||
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.
|
||||
|
||||
## Subprocessus
|
||||
|
||||
It does not work with subprocessus, that's all ;(
|
||||
|
||||
## Haskell Stack `exec`
|
||||
|
||||
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.
|
70
default.nix
70
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";
|
||||
|
||||
buildInputs = [ pkgs.python3 pkgs.which pkgs.binutils ];
|
||||
outputs = [ "out" ];
|
||||
|
||||
src = ./.;
|
||||
|
||||
buildPhase = ''
|
||||
mkdir -p $out/bin
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
cp nixGL $out/bin
|
||||
'';
|
||||
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";
|
||||
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
|
||||
|
||||
chmod u+x $out/bin/nixGLNvidiaBumblebee
|
||||
'';
|
||||
|
||||
nixGLNvidia = runCommand "nixGLNvidia-${version}" {
|
||||
buildInputs = [ libglvnd linuxPackages.nvidia_x11 ];
|
||||
|
||||
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
|
||||
|
||||
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 - 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
|
||||
'';
|
||||
}
|
||||
|
|
50
nixGL
50
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)
|
Loading…
Reference in New Issue
Block a user