libGL: undefined symbol __GLXGL_CORE_FUNCTIONS

@Rotaerk

(sorry for the time my answers took, this tab stays open for a while… I had issues explaining the issue succintly, so I finally decided to send my draft, sorry, that’s a bit rough :wink:

(Note: I use OpenGL in the following message, but thats exactly the same idea with vulkain)

Indeed your issue is due to incompatibility between the library used in your package AND the librairies available on the system. nixGL fixs that, you should try it :wink:

You are right, that’s a flaw in nixpkgs, but actually that’s not that simple: Vulkain / OpenGL / Cuda / … are libs which depends on the target machine hardware. When you build in isolation with nix, you cannot know in advance which library will be available in the target system, so you cannot build for them.

Let’s use an example to understand the issue. Imagine you build a program which depends on a bunch of libraries, for example libc and libOpenGL. By definition, the libOpenGL will be provided by the system running the program, because it depends on the hardware of the machine.

On a “traditional” build setup, you’ll build your executable program, and dynamically link them with all the other libraries provided by your system. It will work flawlessly because you build from source with a total knowledge of the system on which the executable will be run. Now imagine that you want to ship you program to another system. You will ship program and hope that the other system correctly ship libc with an ABI compatible with your program. Most of the time it will run, because you are only using one public function (say fopen) from libc, the ABI is stable since many versions. The risk of incompatibility are really small (i.e. the small fopen symbol).

However, this situation is totally inacceptable, because:

  • It may fail because one the library is not available on the system.
  • libc changed its ABI and is not compatible with your expectation. That’s especially important knowing that libc have a compatibility policy where a program built with an older libc will run on a newer libc but the opposite is not true. In my former company we were building on ubuntu 10.04 to ensure the libc compatibility.
  • everything links correctly, runs correctly, but there is a small difference between the libc version you built and test with and the one on the system. This small difference will slowly leads to a corruption of the internal state of your program which will eventually leads to the end of the modern civilization.

This is why nix was created],you know exactly which bytes of which library will be used for the build and at runtime. So:

  • No missing library
  • No ABI incompatibility
  • No incompatible libraries behaviors. That’s especially important when library runMissilles had changed its C API from void launchMissile(bool dryrun) to void launcheMissile(bool realRun) if you see what I mean.

That’s perfect, we should all use nix!

However, there is the libOpenGL issue, which is not known in advance, which depends on the system on which your executable will be run. And now we have a big problem:

  • program depends on libc, provided by your nix store.
  • program depends on libOpenGL provided by the system, it will be alright, the OpenGL symbols are well known, the ABI is stable, no issue at all.
  • libOpenGL on the system, depends on libc from the system!

And now, we have an issue, because the libc of your system and the one from the nix store may be totally incompatible. Both libraries will be loaded in the same address space, they will share the same symboles, there will be conflict, incompatibilities, that’s a nightmare. libc is an example here, but there are too many libraries in this context. In the best case, it fails immediately, in the worse case, it runs and gives weird results.

We have a really simple solution, it is to set LD_LIBRARY_PATH=/usr/lib, this way, your program will load everything from the system. This way it will be compatible with the libOpenGL from the system, but we lose every guarantee provided by nix.

So the question is: is this possible to provide a libOpenGL compatible with my program (i.e. using the same libc, …)? and compatible with the hardware of the system on which your program is run, we need two informations:

  • The nixpkgs version used to build program
  • The OpenGL driver and the version used on the target machine. The version is important because of the binary interface between the userland driver and the kernel space driver.

The quick answer is no: obviously, you don’t know “at build time” if your user will use Nvidia / Intel / Amd… However user can install a tool which will install the right libOpenGL knowing their system and the nixpkgs version used to build the program they want to run. And this tool is nixGL.

This is a hack for a situation which is complicated. Most other solutions need a way to separate the “library space” of libOpenGL from the “library space” of your program. There is work to do that (e.g. https://git.collabora.com/cgit/user/vivek/libcapsule.git/tree/README ). You can also write a client / server solution (we’ll call it libGLNetwork), where each computer have a running server which accepts json representing OpenGL commands and your program will link with the libGLNetworkClient from the nix store. As long as the json protocol used by both end is the same, it will work. You can also have a software implementation of libOpenGL, this way it will be provided by your nix store, but we don’t want any of these solution for performance reasons.

There is no satisfying solution for now (nixGL have its issues too, it breaks every month, it does not support AMD GPU for now (I don’t have the hardware, feel free to contribute), and I, as main and only contributor, will slowly lose interest in it: I don’t have Nvidia hardware anymore and I’m not working in the computer graphic industry anymore.

Good luck.

1 Like