Skip to content

Instantly share code, notes, and snippets.

@konfou
Created April 1, 2021 20:07
Show Gist options
  • Save konfou/d12c0a26fc0d3b432dc9d23c86701fcb to your computer and use it in GitHub Desktop.
Save konfou/d12c0a26fc0d3b432dc9d23c86701fcb to your computer and use it in GitHub Desktop.
Fix gksqt error when plotting with Julia on NixOS

TL;DR Run julia-fix-gksqt.sh, then nix-shell julia-fix-gksqt.nix --run julia.

If you're running NixOS and trying to plot something in Julia you're probably getting the following error (where kon will and 9Vi4m may differ)

sh: /home/kon/.julia/packages/GR/9Vi4m/src/../deps/gr/bin/gksqt: No such file or directory
connect: Connection refused
GKS: can't connect to GKS socket application

This requires patching the binary with patchelf. The libraries required are from qt5.qtbase, qt5Full, and libGL. Also the C++ stdlib which becomes available in a derivation with stdenv.cc.cc. Having them you can patch the binary with

${patchelf}/bin/patchelf \
  --set-interpreter ${glibc}/lib/ld-linux-x86-64.so.2 \
  --set-rpath "${libPath}" \
  $GRDIR/deps/gr/bin/gksqt

where $GRDIR is the path before /src. But that alone won't be enough and then you'll be greeted with

qt.qpa.plugin: Could not find the Qt platform plugin "xcb" in ""
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

You also have to export the correct plugin path. This is done with

export QT_QPA_PLATFORM_PLUGIN_PATH="${qt5.qtbase.bin}/lib/qt-${qt5.qtbase.version}/plugins"

All those can be done through julia-fix-gksqt.sh script, which outputs a derivation you should nix-shell into. First run the script, and then do nix-shell julia-fix-gksqt.nix. Script is a bit slow because it runs Julia, then loads Plots to get the GR directory. This is the reason I didn't combined them in a single Nix expression. Inside the Nix shell you can run Julia and do any plotting you want. To run directly do

$ nix-shell julia-fix-gksqt.nix --run julia

If used interactively, this is like putting exec julia at the end of shellHook. But former can also be used to run scripts.

#!/usr/bin/env bash
GRDIR=$(julia -e 'using Plots; println(ENV["GRDIR"])' | awk -F'/src' '{print $1}')
cat <<EOF > julia-fix-gksqt.nix
with import <nixpkgs> {};
let
libPath = lib.makeLibraryPath [
stdenv.cc.cc.lib qt5.qtbase qt5Full libGL ];
in
pkgs.stdenv.mkDerivation {
name = "julia-fix-gksqt";
shellHook = ''
export QT_QPA_PLATFORM_PLUGIN_PATH="\${qt5.qtbase.bin}/lib/qt-\${qt5.qtbase.version}/plugins"
\${patchelf}/bin/patchelf \\
--set-interpreter \${glibc}/lib/ld-linux-x86-64.so.2 \\
--set-rpath "\${libPath}" \\
$GRDIR/deps/gr/bin/gksqt
ldd $GRDIR/deps/gr/bin/gksqt \\
| grep -q "not found" || \\
echo '../gksqt is patched'
'';
}
EOF
@sje30
Copy link

sje30 commented Mar 13, 2024

Thank you for sharing this. I managed to get a slight variant of this working today.

A small change is needed since GR.jl is now built differently when Plots.jl is installed. The change I needed was to update lines 16 and 17 so that the path was changed from

$GRDIR/deps/gr/bin/gksqt

to

$GRDIR/bin/gksqt

The next issue is that the binary gksqt, at least for me, was set with "read only" permissions, so I also needed to do:

chmod +x  $GRDIR/bin/gksqt

before running the .nix script. It now works on Gnome with X11 and Wayland.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment