Set LD_LIBRARY_PATH globally (configuration.nix)

We’re using NixOS for an embedded system and would like to configure the system such that upon boot all packages, our custom app, and environmental settings are configured.

We’re utilizing the Avalonia UI cross-platform framework which relies on X11 and has several dependencies, which needed to be set in the LD_LIBRARY_PATH variable.

We attempted to LD_LIBRARY_PATH in our configuration.nix as follows:

 { config, pkgs, ... }:

let
  # Application dependencies 
   app_deps = with pkgs; [ 
                         xorg.libX11 
                         xorg.libX11.dev 
                         xorg.libICE
                         xorg.libSM
                         xorg.libXinerama
                         fontconfig
                         libGL
                         libxkbcommon
                        glib
                        zlibbuildInputs
                       freetype
              ];
in
{
   environment.systemPackages = with pkgs; [ 
    # Required system packages
     dotnet-sdk
   
   ] ++ app_deps; # Concatenate dependencies

  # Construct LD_LIBRARY_PATH
   environment.sessionVariables.LD_LIBRARY_PATH= "${lib.makeLibraryPath app_deps}";
}

We then attempted to test our configuration via ‘nixos-rebuild switch’ and ran into LD_LIBRARY_PATH already defined and redefinition errors.

How can we address this issue? Is there a better, more ‘nixify’ way of achieving our desired outcome?

Thanks!

LD_LIBRARY_PATH is not set globally on nixos for a reason. Runtime dependency resolution is not how nixos is designed to work.

Installing libraries into environment.systemPackages also does not do anything useful.

The “nix way” to handle this kind of problem is to package the software you want to use with nix, resolving those dependencies at “build time” (even if you don’t actually compile the project, you can still use autoPatchelfHook and such to do this resolution at that point).

If that doesn’t work, the catch-all solution is to package the software with buildFHSUserEnv.

2 Likes

If you really need to in theory you can use environment.variables or wrapProgram ... --prefix LD_LIBRARY_PATH.

But I agree with @tejing: it will certainly break things. patchelf is a safer way to explicitly set RUNPATHs on per binary basis to make sure binaries keep using those paths.

1 Like

Thanks for the feedback. My understanding of how LD_LIBRARY_PATH works was a bit twisted (new to linux.

With that said, the classic approach from what I can see, is to set the LD_LIBRARY_PATH in a script (*.sh) that kicks off the executable that requires said variable.

Here’s my question, how does query the nix store and build this path?

Thanks.

When you coerce a derivation to string it gets expanded into a store path. One usually does not query store path but relies on store generation based on expressions.

$ nix repl '<nixpkgs>'
nix-repl> xorg.libX11
«derivation /nix/store/zf2cx1hr4ha6m1i97r6zs89gk1kcmmk7-libX11-1.8.1.drv»

nix-repl> :b xorg.libX11

This derivation produced the following outputs:
  dev -> /nix/store/sbpyp1v4g0vrnv1x51df61i15j5bzhps-libX11-1.8.1-dev
  man -> /nix/store/vwxskxdj4zlgw8xp2s0dm2kcb4505hpf-libX11-1.8.1-man
  out -> /nix/store/j3f4bw9i9lcan9l2ncpcvrghb57f0iag-libX11-1.8.1

nix-repl> "${xorg.libX11.out}/lib"
"/nix/store/j3f4bw9i9lcan9l2ncpcvrghb57f0iag-libX11-1.8.1/lib"

$ ls /nix/store/j3f4bw9i9lcan9l2ncpcvrghb57f0iag-libX11-1.8.1/lib
libX11.la  libX11.so  libX11.so.6  libX11.so.6.4.0  libX11-xcb.la  libX11-xcb.so  libX11-xcb.so.1  libX11-xcb.so.1.0.0

I suggest checking out various LD_LIBRARY_PATH usage examples in nixpkgs: https://github.com/NixOS/nixpkgs/search?q=LD_LIBRARY_PATH

Using patchelf --add-needed is even more straightforward: https://github.com/NixOS/nixpkgs/blob/45fd6074acd143f12d0b209e6c3db65c956c51b9/pkgs/applications/file-managers/mc/default.nix#L86

  postFixup = lib.optionalString (!stdenv.isDarwin) ''
    # libX11.so is loaded dynamically so autopatch doesn't detect it
    patchelf \
      --add-needed ${libX11}/lib/libX11.so \
      $out/bin/mc
  '';
3 Likes