libs 路径“/run/opengl-driver”如何注入到像 compton 这样的 Nix 二进制文件中

Lor*_*ic- 5 linux opengl nixos nix

首先,我对 ELF 和所有这些库链接过程不太满意。但是在玩了一下 Nix/NixOS 之后,我仍然不太理解图形驱动程序链接到二进制文件的方式。

Nix/NixOS 的设计之一是 OpenGL 驱动程序不能成为可重现环境的一部分,因为它将依赖于目标硬件。

大多数 Nix 程序都会在“/run/opengl-driver/lib”中找到 OpenGL 驱动程序。

对于 NixOS 系统,驱动程序将下载并安装在此路径中,然后可以LD_LIBRARY_PATH在配置中使用全局定义hardware.opengl.setLdLibraryPath = true(请参阅https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/hardware /opengl.nix#L166)。

但是,在非 NixOS 操作系统的情况下,我可以注意到程序仍然引用此/run/opengl-driver/lib路径,但未LD_LIBRARY_PATH在任何地方定义。所以我的问题是:为什么二进制文件仍然在非 NixOS 系统上将驱动程序搜索到 /run/opengl-driver/lib 中?

我这里的例子是康普顿。它在 Nixpkgs 中的派生位于以下地址。

https://github.com/NixOS/nixpkgs/blob/274e095f761b2da76a376d105c41591739350b14/pkgs/applications/window-managers/compton/default.nix#L51

我可以使用 strace 看到程序尝试libGLX_mesa.so在运行时加载库。

$ strace -e openat $(readlink -f $(which compton)) 2>&1 | grep -E ".*opengl.*.so"

openat(AT_FDCWD, "/run/opengl-driver/lib/tls/haswell/x86_64/libGLX_mesa.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/run/opengl-driver/lib/tls/haswell/libGLX_mesa.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/run/opengl-driver/lib/tls/x86_64/libGLX_mesa.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/run/opengl-driver/lib/tls/libGLX_mesa.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/run/opengl-driver/lib/haswell/x86_64/libGLX_mesa.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/run/opengl-driver/lib/haswell/libGLX_mesa.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/run/opengl-driver/lib/x86_64/libGLX_mesa.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/run/opengl-driver/lib/libGLX_mesa.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
Run Code Online (Sandbox Code Playgroud)

事实上,使用ldd揭示了libGLX_mesa.so不是动态链接的。

$ ldd $(readlink -f $(which compton)) | grep mesa | wc -l
0
Run Code Online (Sandbox Code Playgroud)

所以我的猜测是这个库是在运行时加载的,可能使用dlopen. dlopen我在https://github.com/chjj/compton中找不到任何参考,但也许它是从 compton 链接的库之一间接完成的。

如果我的猜测是正确的,我发现能够通过搜索环境变量中定义的路径(当路径是叶名称时)dlopen找到所需的库。LD_LIBRARY_PATH

因此,我的下一步是使用以下两个命令之一来分析 compton 在运行时可用的环境变量。

$ strace -v -s 10000 -e execve $(readlink -f $(which compton)) 2>&1 | grep LD_LIBRARY_PATH | wc -l
0

$ ltrace -e getenv $(readlink -f $(which compton)) 2>&1 | grep LD_LIBRARY_PATH | wc -l
0
Run Code Online (Sandbox Code Playgroud)

但这LD_LIBRARY_PATH似乎没有定义。我有点陷入我的分析中。

回顾一下,我的问题是:

  • 这个opengl路径是如何/run/opengl-driver/lib注入到compton中的?
  • 在 Nix 中将此库路径添加到需要图形驱动程序的程序的标准方法是什么?
  • 最后一个问题与此分析并不真正相关,但是:如果想让 compton 在非 NixOS 系统上工作,手动链接 opengl 库是否/usr/lib/x86_64-linux-gnu/足够/run/opengl-drivers/lib/