The purpose of this post is to understand the libGL ABI problem and why it exists, as well as possible solutions to it. If you’re familiar with the issue, feel free to skip the “Background” section. My hope is that people will correct any mistakes I make in the “The Problem” section and also comment on the solutions in the “Solutions” section, as well as add any others I should have included.
Background
I frequently encounter issues such as /nix/store/.../lib/libc.so.6: version 'GLIBC_2.34' not found (required by ...)
, since I frequently run programs from versions of nixpkgs different from the nixpkgs version used for the current running system. I use numerous development shells for different projects, and these often use different nixpkgs versions than the system nixpkgs version. The frequently mentioned “solution” to this problem of updating the nixpkgs version from either the system or development shell (usually the development shell) to match the other is not satisfactory to me, as I often have a good reason for using a specific nixpkgs version in a development shell. Moreover, the benefit of Nix development shells to me is that I can come back to a project at any time in the future, irrespective of what I’ve changed on my system, and get the same development environment. The libGL ABI problem prevents this from being a reality.
The Problem
As I currently understand it, the problem is as follows. libGL is loaded impurely in Nix. That is, NixOS sets LD_LIBRARY_PATH=/run/opengl-driver/lib:/run/opengl-driver-32/lib
. Then, applications that depend on the libGL shared library use the library under one of these paths.
The libGL library is itself dynamically linked against other libraries. An application can depend on libGL as well as other shared libraries on which libGL also depends. Let’s call this library that the application links against directly as well as indirectly through libGL, library X. When the version of X required by the application and libGL is the same, there is no issue. However, if the application requires a different version of X than that required by libGL, a conflict will result. A very common example of library X is glibc.
This issue commonly occurs on a NixOS system when an application is from a different version of nixpkgs than the nixpkgs used to build the NixOS system. In this case, the application may require a different version of library X than that required by libGL, which links against the current NixOS system version.
Why does libGL need to be loaded impurely? Why can’t each application load it’s own version of libGL in the nix store just like other shared library dependencies in Nix? Is the problem that this would disrupt caching, since each package would need to built for the specific libGL implementation (eg Mesa, Nvidia, etc)? If so, is there a way to accept this tradeoff? I’d happy recompile every package on my computer and not benefit from caching if it meant avoiding this problem. Or, would it be problematic if two different applications running on the same system linked against different versions of libGL? If so, can someone explain the issue?
Solutions
- Statically link libGL. I suppose this would only work when using mesa, or another open-source implementation of libGL. Would this resolve this issue?
- Use nixGL. I don’t really understand how this works/avoids the issue, or really how to use it in a development shell.
- People frequently mention using
LD_PRELOAD
, but this seems more like a temporary workaround. Also, I’ve tried using this in the past without success so I’m not totally sure I understand how to do it correctly. I’ve also seenLD_LIBRARY_PATH
mentioned.
Relevant links