Build derivation dependent on libGL

I’m trying to build a derivation for Teamwire. It’s based on NW.JS. I’ve come pretty far, patching it with autoPatchelfHook and miraculously locating all required dependencies to make it build. But I’m running into issues with libGL. I’m deep into foreign territory here, but I understand it has something to do with graphics, is therefore hardware dependent and handled specially (impure) in nix for this reason.

I also seem to have learned that, in order to locate the lib, the env var LD_LIBRARY_PATH is typically used. And that libGL may “need to be enabled” on a system…

Well, I don’t want to write a derivation that’ll only work on systems with a given external (to the derivation) configuration.

Anyway, when trying to run teamwire, I now get the error

[41213:41230:0621/213857.734712:FATAL:udev_loader.cc(38)] Check failed: false. 
#0 0x7f9f029a05a9 (/nix/store/ws5ggfbjdnk91az4aia7ymk5ckkghlvf-teamwire/lib/libnw.so+0x4da05a8)
Task trace:
#0 0x7f9f00599ba6 (/nix/store/ws5ggfbjdnk91az4aia7ymk5ckkghlvf-teamwire/lib/libnw.so+0x2999ba5)

[41238:41238:0621/213857.793045:ERROR:gl_implementation.cc(394)] Failed to load libGL.so.1: libGL.so.1: cannot open shared object file: No such file or directory
[41238:41238:0621/213857.798814:ERROR:viz_main_impl.cc(160)] Exiting GPU process due to errors during initialization
../teamwire: line 1: 41213 Aborted                 (core dumped) /nix/store/ws5ggfbjdnk91az4aia7ymk5ckkghlvf-teamwire/nw /nix/store/ws5ggfbjdnk91az4aia7ymk5ckkghlvf-teamwire/app

Sooooo, how do I fix it? I’ve attempted adding libGL to buildInputs and to runtimeDependencies with no change. I wonder, given the nature of libGL, if that is even a smart thing to do. Ideally, I think, I’d just make sure that LD_LIBRARY_PATH is set in the context (whatever that’d be) of my derivation. But what would it point to, if I can’t be certain that any system even has libGL? Ideally, I’d find a way to write a derivation that instructs the system to “enable” libGL (though I think this is nonsense, how would a derivation (which I think of as a package) do that?).

As you can see, I’m far from comfortable here, throwing terms around I don’t understand. I would appreciate if somebody could elaborate on the problem at hand and possibly point to one or more possible solutions to this issue.

Here’s the current definition

# teamwire.nix
{
  stdenv,
  fetchurl,
  lib,
  autoPatchelfHook,
  xorg,
  pango,
  libXrandr,
  mesa,
  libxkbcommon,
  nspr,
  atk,
  dbus,
  gtk3,
  alsa-lib,
  nss,
  musl,
  libGL,
  ...
}:
stdenv.mkDerivation rec {
  name = "teamwire";

  installer = fetchurl {
    url = "https://desktop.teamwire.eu/download.php?platform=linuxDebian";
    hash = "sha256-qFPG0Y1oX7fQKi28YNIvtAPVrhC837OfdMb/KFcmhsU=";
  };

  nativeBuildInputs = [autoPatchelfHook];

  buildInputs = [
    xorg.libXext
    xorg.libXfixes
    xorg.libxshmfence
    stdenv.cc.cc.libgcc
    stdenv.cc.cc.lib
    stdenv.cc.libc.out
    pango
    libXrandr
    mesa
    (lib.getLib libxkbcommon)
    nspr.out
    atk
    dbus.lib
    gtk3
    alsa-lib
    nss
    musl
  ];

  runtimeDependencies = [
    libGL
  ];

  autoPatchelfIgnoreMissingDeps = [
    #"libc.musl-x86_64.so.1"
  ];

  #phases = ["installPhase"];

  #dontUnpack = true; # skip unpack phase
  unpackPhase = ''
    sh ${installer} --noexec --keep --target .
  '';

  dontConfigure = true;
  dontBuild = true;

  installPhase = ''
    #runHook preInstall
    #cp ${installer} $out/installer.sh
    #chmod +x $out/installer.sh
    #$out/installer.sh --noexec --keep --target $out
    #rm $out/installer.sh

    mkdir -p $out
    cp -r Teamwire/* $out/


    echo "$out/nw $out/app" > $out/teamwire
    find "$out/" -type f -exec chmod 444 {} \;
    find $out/ -type d -exec chmod 555 {} \;
    chmod -f 555 $out/{nw,teamwire,app/ffmpeg,nacl_*}

    #mv /usr/share/Teamwire/teamwire.desktop /usr/share/applications/

    #runHook postInstall
  '';

  meta = with lib; {
    homepage = "https://teamwire.eu";
    description = "team collaboration software";
    platforms = platforms.linux;
  };
}

NWJS… interesting…

Can you provide a file listing of the derivation output?

You can do something like this: find -L /nix/store/ws5ggfbjdnk91az4aia7ymk5ckkghlvf-teamwire

That’s gonna be rather lengthy. The thing contains an entire web project. So I cut it short a bit

tree -L 2
.
├── app
│   ├── css
│   ├── data
│   ├── emoji_data
│   ├── ffmpeg
│   ├── fonts
│   ├── i18n
│   ├── img
│   ├── index.html
│   ├── js
│   ├── node_modules
│   ├── package.json
│   ├── readme.ffmpeg
│   └── views
├── appicon.png
├── crashpad_handler
├── credits.html
├── icudtl.dat
├── lib
│   ├── libEGL.so
│   ├── libffmpeg.so
│   ├── libGLESv2.so
│   ├── libnode.so
│   └── libnw.so
├── locales
│   ├── am.pak
│   ├── am.pak.info
│   ├── ar.pak
│   ├── ar.pak.info
│   ├── ar-XB.pak
│   ├── ar-XB.pak.info
│   ├── bg.pak
│   ├── bg.pak.info
│   ├── bn.pak
│   ├── bn.pak.info
│   ├── ca.pak
│   ├── ca.pak.info
│   ├── cs.pak
│   ├── cs.pak.info
│   ├── da.pak
│   ├── da.pak.info
│   ├── de.pak
│   ├── de.pak.info
│   ├── el.pak
│   ├── el.pak.info
│   ├── en-GB.pak
│   ├── en-GB.pak.info
│   ├── en-US.pak
│   ├── en-US.pak.info
│   ├── en-XA.pak
│   ├── en-XA.pak.info
│   ├── es-419.pak
│   ├── es-419.pak.info
│   ├── es.pak
│   ├── es.pak.info
│   ├── et.pak
│   ├── et.pak.info
│   ├── fa.pak
│   ├── fa.pak.info
│   ├── fil.pak
│   ├── fil.pak.info
│   ├── fi.pak
│   ├── fi.pak.info
│   ├── fr.pak
│   ├── fr.pak.info
│   ├── gu.pak
│   ├── gu.pak.info
│   ├── he.pak
│   ├── he.pak.info
│   ├── hi.pak
│   ├── hi.pak.info
│   ├── hr.pak
│   ├── hr.pak.info
│   ├── hu.pak
│   ├── hu.pak.info
│   ├── id.pak
│   ├── id.pak.info
│   ├── it.pak
│   ├── it.pak.info
│   ├── ja.pak
│   ├── ja.pak.info
│   ├── kn.pak
│   ├── kn.pak.info
│   ├── ko.pak
│   ├── ko.pak.info
│   ├── lt.pak
│   ├── lt.pak.info
│   ├── lv.pak
│   ├── lv.pak.info
│   ├── ml.pak
│   ├── ml.pak.info
│   ├── mr.pak
│   ├── mr.pak.info
│   ├── ms.pak
│   ├── ms.pak.info
│   ├── nb.pak
│   ├── nb.pak.info
│   ├── nl.pak
│   ├── nl.pak.info
│   ├── pl.pak
│   ├── pl.pak.info
│   ├── pt-BR.pak
│   ├── pt-BR.pak.info
│   ├── pt-PT.pak
│   ├── pt-PT.pak.info
│   ├── ro.pak
│   ├── ro.pak.info
│   ├── ru.pak
│   ├── ru.pak.info
│   ├── sk.pak
│   ├── sk.pak.info
│   ├── sl.pak
│   ├── sl.pak.info
│   ├── sr.pak
│   ├── sr.pak.info
│   ├── sv.pak
│   ├── sv.pak.info
│   ├── sw.pak
│   ├── sw.pak.info
│   ├── ta.pak
│   ├── ta.pak.info
│   ├── te.pak
│   ├── te.pak.info
│   ├── th.pak
│   ├── th.pak.info
│   ├── tr.pak
│   ├── tr.pak.info
│   ├── uk.pak
│   ├── uk.pak.info
│   ├── vi.pak
│   ├── vi.pak.info
│   ├── zh-CN.pak
│   ├── zh-CN.pak.info
│   ├── zh-TW.pak
│   └── zh-TW.pak.info
├── nw
├── nw_100_percent.pak
├── nw_200_percent.pak
├── resources.pak
├── setup.sh
├── swiftshader
│   ├── libEGL.so
│   └── libGLESv2.so
├── teamwire
├── teamwire.desktop
└── v8_context_snapshot.bin

14 directories, 133 files

I’ve ldded both nw and libnw.so and couldn’t find any problem with it, particularly nothing about libGL.so.1

That’s perfect.

The app directory that’s used by nwjs exists. Therefore, you may be able to get the app working by using the nwjs that’s in Nixpkgs.

As an example, here’s my Tiddly Desktop Nix package: TiddlyDesktop/tiddlydesktop.nix at f4bf4fbe884e37ae88094ae6622c712019d9b808 · TiddlyWiki/TiddlyDesktop · GitHub

In the Tiddly Desktop package, $out/lib/tiddlydesktop is the app directory. Then I use a shell script, the launcher, to execute nwjs while passing the $out/lib/tiddlydesktop directory as the first parameter.

Haha, yes, I’m planning to go down that road once I made this work. I suspected that that may be the smarter approach, but I want to figure this out now. Anyway, I’ll further study nw in nixpkgs. That should have some hints :slight_smile: