Fix "missing 'library GL' when using poetry2nix

I’m writing a flake to package wlr-layout-ui GitHub - fdev31/wlr-layout-ui: A tiny GUI to configure screen layouts on wayland

A tiny GUI to configure screen layouts on wayland

I’ve been successful getting it to build using poetry2nix, see https://github.com/dantefromhell/wlr-layout-ui/blob/67de8592442b9fe4e27aaf54c42860c1124b345b/flake.nix

When executing though, I get the following error

Traceback (most recent call last):
  File "/nix/store/k8b8857dlmlmaci73lmhiga3rw66v762-python3.11-wlr-layout-ui-1.3.6/bin/.wlrlui-wrapped", line 6, in <module>
    from wlr_layout_ui import main
  File "/nix/store/k8b8857dlmlmaci73lmhiga3rw66v762-python3.11-wlr-layout-ui-1.3.6/lib/python3.11/site-packages/wlr_layout_ui/__init__.py", line 7, in <module>
    from .gui import UI
  File "/nix/store/k8b8857dlmlmaci73lmhiga3rw66v762-python3.11-wlr-layout-ui-1.3.6/lib/python3.11/site-packages/wlr_layout_ui/gui.py", line 8, in <module>
    from .widgets import Button, HBox, VBox, Dropdown, Style, Widget
  File "/nix/store/k8b8857dlmlmaci73lmhiga3rw66v762-python3.11-wlr-layout-ui-1.3.6/lib/python3.11/site-packages/wlr_layout_ui/widgets.py", line 3, in <module>
    from pyglet.shapes import Rectangle, Triangle
  File "/nix/store/kybkfqzmdn1wf65vh7k2ma5j6bsf12yf-python3.11-pyglet-2.0.14/lib/python3.11/site-packages/pyglet/shapes.py", line 54, in <module>
    from pyglet.gl import GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_BLEND, GL_TRIANGLES
  File "/nix/store/kybkfqzmdn1wf65vh7k2ma5j6bsf12yf-python3.11-pyglet-2.0.14/lib/python3.11/site-packages/pyglet/gl/__init__.py", line 47, in <module>
    from pyglet.gl.gl import *
  File "/nix/store/kybkfqzmdn1wf65vh7k2ma5j6bsf12yf-python3.11-pyglet-2.0.14/lib/python3.11/site-packages/pyglet/gl/gl.py", line 7, in <module>
    from pyglet.gl.lib import link_GL as _link_function
  File "/nix/store/kybkfqzmdn1wf65vh7k2ma5j6bsf12yf-python3.11-pyglet-2.0.14/lib/python3.11/site-packages/pyglet/gl/lib.py", line 98, in <module>
    from pyglet.gl.lib_glx import link_GL, link_GLX
  File "/nix/store/kybkfqzmdn1wf65vh7k2ma5j6bsf12yf-python3.11-pyglet-2.0.14/lib/python3.11/site-packages/pyglet/gl/lib_glx.py", line 11, in <module>
    gl_lib = pyglet.lib.load_library('GL')
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/kybkfqzmdn1wf65vh7k2ma5j6bsf12yf-python3.11-pyglet-2.0.14/lib/python3.11/site-packages/pyglet/lib.py", line 135, in load_library
    raise ImportError(f'Library "{names[0]}" not found.')
ImportError: Library "GL" not found.

I’m not sure which system package provides the missing library to pyglet and how to add it to the python environment.

Any help is suggested.

Unfortunately this likely won’t be an easy fix.

You’ll need to patch the underlying package to replace the load_library call from name to some nix path.

Near what you would want: Add support for web3 package by jonringer · Pull Request #578 · nix-community/poetry2nix · GitHub

Thanks for quick answer @jonringer

If you don’t mind, some follow-up questions :wink:

  1. What is the best way to figure out which package satisfy the library needs of pyglet and what way can I test this easiest?
  2. Looking at overrides/default.nix in general it looks like a collection of known helpful overrides to build python packages.
    Would if be good/ helpful to send a PR with my findings?

GL refers to libGL which provides openGL support

You can find libraries by doing:

$ nix-locate --top-level libGL.so
xorg_sys_opengl.out                                   0 s /nix/store/5iwk3yqvkbxkmibphv5hkvgad1imr7d8-xorg-sys-opengl-3/lib/libGL.so.1
qt6.full.out                                          0 s /nix/store/0800mlxnhc2br7h0123dz92i6w873nnp-qt-full-6.6.1/lib/libGL.so
qt6.full.out                                          0 s /nix/store/0800mlxnhc2br7h0123dz92i6w873nnp-qt-full-6.6.1/lib/libGL.so.1
qt6.full.out                                          0 s /nix/store/0800mlxnhc2br7h0123dz92i6w873nnp-qt-full-6.6.1/lib/libGL.so.1.7.0
primusLib.out                                         0 s /nix/store/dy5yiw2r3lj9k8syfbwy8cwslk4hlamz-primus-lib-unstable-2015-04-28/lib/libGL.so
primusLib.out                                   390,192 x /nix/store/dy5yiw2r3lj9k8syfbwy8cwslk4hlamz-primus-lib-unstable-2015-04-28/lib/libGL.so.1
libglvnd.out                                          0 s /nix/store/yw48bqgswppkcrx303ybgbn6r2nqbda1-libglvnd-1.7.0/lib/libGL.so
libglvnd.out                                          0 s /nix/store/yw48bqgswppkcrx303ybgbn6r2nqbda1-libglvnd-1.7.0/lib/libGL.so.1
libglvnd.out                                    740,448 x /nix/store/yw48bqgswppkcrx303ybgbn6r2nqbda1-libglvnd-1.7.0/lib/libGL.so.1.7.0

libglvnd has more common alias libGL.

Looking at overrides/default.nix in general it looks like a collection of known helpful overrides to build python packages.

Yep, particularly this one poetry2nix/overrides/default.nix at 3c92540611f42d3fb2d0d084a6c694cd6544b609 · nix-community/poetry2nix · GitHub

Thanks for the hints @jonringer I’m making slow progress - at least in understanding.

I stumbled over pyglet in nixpkgs which does solve the library loader problem by completly replacing it.

However the solution ends up being rather long, so I’m wondering if the better path forward would be to tell poetry2nix to use pyglet from upstream nixpkgs?

so I’m wondering if the better path forward would be to tell poetry2nix to use pyglet from upstream nixpkgs?

I don’t think I’ve ever used it in this regard. It should be technically possible, not sure how easy it is to do this though, or if there’s a current happy path for it.

Upping as I stumbled into this same problem and was able to make it work using this :

      ext = ".so";
      system = "x86_64-linux";
      pkgs = nixpkgs.legacyPackages.${system};
      # create a custom "mkPoetryApplication" API function that under the hood uses
      # the packages and versions (python3, poetry etc.) from our pinned nixpkgs above:
	  poetry2nix = inputs.poetry2nix.lib.mkPoetry2Nix { inherit pkgs;};
      myPythonApp = poetry2nix.mkPoetryApplication { 
      	projectDir = ./.;
		overrides = poetry2nix.defaultPoetryOverrides.extend
	    (final: prev: {
	      pyglet = prev.pyglet.overridePythonAttrs
	      (
	        old: {
	          buildInputs = (old.buildInputs or [ ]) ++ [ prev.flit-core ];
	          patchPhase = ''
	           cat > pyglet/lib.py <<EOF
import ctypes
def load_library(*names, **kwargs):
  for name in names:
    path = None
    if name == 'GL':
        path = '${pkgs.libGL}/lib/libGL${ext}'
    elif name == 'EGL':
        path = '${pkgs.libGL}/lib/libEGL${ext}'
    elif name == 'GLU':
        path = '${pkgs.libGLU}/lib/libGLU${ext}'
    elif name == 'c':
        path = '${pkgs.glibc}/lib/libc${ext}.6'
    elif name == 'X11':
        path = '${pkgs.xorg.libX11}/lib/libX11${ext}'
    elif name == 'gdk-x11-2.0':
        path = '${pkgs.gtk2-x11}/lib/libgdk-x11-2.0${ext}'
    elif name == 'gdk_pixbuf-2.0':
        path = '${pkgs.gdk-pixbuf}/lib/libgdk_pixbuf-2.0${ext}'
    elif name == 'Xext':
        path = '${pkgs.xorg.libXext}/lib/libXext${ext}'
    elif name == 'fontconfig':
        path = '${pkgs.fontconfig.lib}/lib/libfontconfig${ext}'
    elif name == 'freetype':
        path = '${pkgs.freetype}/lib/libfreetype${ext}'
    elif name[0:2] == 'av' or name[0:2] == 'sw':
        path = '${pkgs.ffmpeg-full}/lib/lib' + name + '${ext}'
    elif name == 'openal':
        path = '${pkgs.openal}/lib/libopenal${ext}'
    elif name == 'pulse':
        path = '${pkgs.libpulseaudio}/lib/libpulse${ext}'
    elif name == 'Xi':
        path = '${pkgs.xorg.libXi}/lib/libXi${ext}'
    elif name == 'Xinerama':
        path = '${pkgs.xorg.libXinerama}/lib/libXinerama${ext}'
    elif name == 'Xxf86vm':
        path = '${pkgs.xorg.libXxf86vm}/lib/libXxf86vm${ext}'
    if path is not None:
        return ctypes.cdll.LoadLibrary(path)
  raise Exception("Could not load library {}".format(names))
EOF
             '';
	        }
	      );
	    });
      };

inspired by this Fix "missing 'library GL' when using poetry2nix - #5 by don.dfh

Honestly I don’t really have a clue why it works (like ext should probably be specified more properly ? the path given by pkgs. seems to work but it probably relies on having the library installed already ?)