diff --git a/README.md b/README.md index e432634..d5dcfc9 100644 --- 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: + +- `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. \ No newline at end of file diff --git a/default.nix b/default.nix index 9f1e8b7..1608188 100644 --- a/default.nix +++ b/default.nix @@ -2,28 +2,62 @@ let pkgs = import { 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 + ''; } diff --git a/nixGL b/nixGL deleted file mode 100755 index 6326959..0000000 --- a/nixGL +++ /dev/null @@ -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)