More robust dependency lookup

This commit is contained in:
Guillaume Bouchard 2017-09-16 14:28:57 +02:00
parent 23acee6ede
commit 3eaf867565
3 changed files with 35 additions and 19 deletions

View File

@ -46,13 +46,27 @@ nixGL program args
# Limitations
The idea is really simple and should work reliably. However there is still two configurations variables hardcoded in the wrapper. Open a bug / pull request if this does not work on your distribution / driver.
The idea is really simple and should work reliably in most cases.
## Library paths
However there is still two configurations variables hardcoded in the wrapper.
The path of where the `libGL.so` library can be found on your system, usually `/usr/lib`.
- `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.
## Name of the Nix package which contains `libGL.so`
Open a bug / pull request if this does not work on your distribution / driver.
This package will be ignored by the wrapper. It is currently hardcoded as `mesa-noglu` but this can be fixed.
It works with `primus`, but there is some artifacts.
## Fundamental issue
If your program libraries depends on different version 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.

View File

@ -8,7 +8,7 @@ rec {
name = "nixGL-${version}";
version = "1.0.0";
buildInputs = [ pkgs.python3 pkgs.which pkgs.patchelf ];
buildInputs = [ pkgs.python3 pkgs.which pkgs.binutils ];
outputs = [ "out" ];
src = ./.;

28
nixGL
View File

@ -16,18 +16,19 @@ systemLibs = [b"/usr/lib", b"/lib"]
cmd = (prog, *args) = sys.argv[1:]
realProg = subprocess.check_output(["which", prog]).strip()
# extract rpath of the program
rpaths = map(bytes.strip, subprocess.check_output(
['patchelf', '--print-rpath', realProg]).split(b':'))
# 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)
# filter rpath, removing ignored and empty paths
dir = []
for i in rpaths:
for c in ignored:
if c not in i:
if i.strip():
dir.append(i.strip())
for c in ignored:
if c in path:
break
else:
paths.append(path)
# build the new environment
newenv = os.environb
@ -42,7 +43,8 @@ oldLdLibraryPath = newenv.get(b'LD_LIBRARY_PATH', b'').split()
# 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 = oldLdLibraryPath + dir + systemLibs
newLibraryPath = b':'.join(oldLdLibraryPath + paths + systemLibs)
newenv.update({b'LD_LIBRARY_PATH': newLibraryPath})
newenv.update({b'LD_LIBRARY_PATH': b':'.join(newLibraryPath)})
os.execvpe(prog, cmd, newenv)