Во-первых, мне не очень нравится ELF и весь этот процесс связывания библиотек. Но после того, как я немного поиграл с Nix / NixOS, я все еще не совсем понял, как драйверы graphi c связаны в двоичные файлы.
Один из проектов Nix / NixOS заключается в том, что драйвер OpenGL не может быть частью воспроизводимой среды, поскольку он будет зависеть от целевого оборудования.
Большинство программ Nix находят драйверы OpenGL в "/run/opengl-driver/lib".
In В случае системы 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
нигде не определен. И вот мой вопрос: почему двоичный файл все еще ищет драйверы в / run / opengl-driver / lib в системе, отличной от NixOS?
Мой пример здесь - compton. Его вывод в 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)
Действительно, использование ldd
показывает, что libGLX_mesa.so
не является динамически связанным.
$ ldd $(readlink -f $(which compton)) | grep mesa | wc -l
0
Так что я предполагаю, что эта библиотека загружается во время выполнения, возможно, с использованием dlopen
, Я не могу найти ссылку на dlopen
в https://github.com/chjj/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
Но это LD_LIBRARY_PATH
, похоже, не определено. И я как бы застрял в своем анализе здесь.
Итак, подведем итог, мои вопросы:
- Как этот путь opengl
/run/opengl-driver/lib
вводится в compton? - Каким был бы стандартный способ добавления этого пути к библиотеке в программы, требующие графических драйверов c в Nix?
- И последний вопрос, на самом деле не связанный с этим анализом, но: если вы хотите, чтобы Compton работал на -NixOS система, будет ли достаточно вручную связать библиотеки opengl с
/usr/lib/x86_64-linux-gnu/
до /run/opengl-drivers/lib/
?