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:
|
This library contains a wrapper which is able to launch GL application:
|
||||||
|
|
||||||
```
|
```
|
||||||
nixGL program
|
nixGLXXX program
|
||||||
```
|
```
|
||||||
|
|
||||||
# Installation / Usage
|
# Installation / Usage
|
||||||
|
@ -30,53 +30,46 @@ Clone this git repository:
|
||||||
git clone https://github.com/guibou/nixGL
|
git clone https://github.com/guibou/nixGL
|
||||||
```
|
```
|
||||||
|
|
||||||
(Optional) installation:
|
Build / install
|
||||||
|
|
||||||
```
|
```
|
||||||
cd nixGL
|
cd nixGL
|
||||||
nix-build
|
nix-build -A XXX
|
||||||
nix-env -i ./result
|
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
|
# 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`.
|
```shell
|
||||||
- `systemLibs`: the list of where on the host system the `libGL.so` can be found.
|
export NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz
|
||||||
|
nix-build -A nixGLNvidia
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
One version or the other of `libBar` may be used. In practice this does not happen a lot.
|
Contact me if this limitation is too important, it may be easy to automate this process.
|
||||||
|
|
||||||
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 ...`.
|
|
70
default.nix
70
default.nix
|
@ -2,28 +2,62 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
pkgs = import <nixpkgs> { inherit system; };
|
pkgs = import <nixpkgs> { inherit system; };
|
||||||
in
|
|
||||||
rec {
|
|
||||||
nixGl = pkgs.stdenv.mkDerivation rec {
|
|
||||||
name = "nixGL-${version}";
|
|
||||||
version = "1.0.0";
|
version = "1.0.0";
|
||||||
|
in
|
||||||
buildInputs = [ pkgs.python3 pkgs.which pkgs.binutils ];
|
with pkgs;
|
||||||
outputs = [ "out" ];
|
rec {
|
||||||
|
nixGLNvidiaBumblebee = runCommand "nixGLNvidiaBumblebee-${version}" {
|
||||||
src = ./.;
|
buildInputs = [ libglvnd linuxPackages.nvidia_x11 bumblebee ];
|
||||||
|
|
||||||
buildPhase = ''
|
|
||||||
mkdir -p $out/bin
|
|
||||||
'';
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
cp nixGL $out/bin
|
|
||||||
'';
|
|
||||||
|
|
||||||
meta = with pkgs.stdenv.lib; {
|
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";
|
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