Help with packaging a binary and patchelf

Hi all. I’m trying to pull a derivation together for a non-NixOS binary program (VESTA, a virtual molecule visualizer), mostly by following the guide here, using patchelf to resolve library paths, which is failing to locate a library that seems to be available. This is my first attempt at packaging, so I’m probably doing something stupid. Here’s my default.nix:

{ stdenv, fontconfig, lib, gdk-pixbuf, openjdk, gtk2, gtk3, iconv,    
  libGLU, libGL, libglvnd, pango, xorg, glib, glibc, gcc-unwrapped,
  cairo, makeWrapper, fetchurl, autoPatchelfHook }:
stdenv.mkDerivation rec {
  name = "VESTA-gtk3";
  version = "3.5.8";

  src = fetchurl {
    url = "https://jp-minerals.org/vesta/archives/${version}/VESTA-gtk3.tar.bz2";
    sha256 = "sha256-eL7wJcKzHx1kycfgatKxOdJSs6aGiT7nmsdLMCGGjfg=";
  };

  nativeBuildInputs = [
    autoPatchelfHook
    fontconfig.lib
    gcc-unwrapped.lib
    gcc-unwrapped.libgcc 
    gdk-pixbuf 
    glib
    gtk2 
    gtk3 
    iconv 
    libGLU 
    libglvnd 
    pango 
    xorg.libX11 
    xorg.libXxf86vm
    xorg.libXtst
    openjdk
  ];

  dontConfigure = true;
  dontBuild = true;

  installPhase = ''
    mkdir $out
    cp -ar * $out
  '';

  preFixup = let
    libPath = lib.makeLibraryPath [ cairo
      fontconfig.lib 
      gcc-unwrapped.lib 
      gcc-unwrapped.libgcc 
      gdk-pixbuf     
      glib
      gtk2           
      gtk3           
      iconv          
      libGLU         
      libglvnd       
      pango          
      xorg.libX11    
      xorg.libXxf86vm
      xorg.libXtst
      openjdk
    ];
  in ''
    patchelf \
      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
      --set-rpath "${libPath}" \
      $out/VESTA
    patchelf \
      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
      --set-rpath "${libPath}" \
      $out/VESTA-core
    patchelf \
      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
      --set-rpath "${libPath}" \
      $out/VESTA-gui
  '';

  meta = with lib; {
    homepage = "https://jp-minerals.org/vesta/en/";
    description = "Visualization for Electronic and STructural Analysis";
    license = licenses.free;
    platforms = platforms.linux;
    architectures = [ "amd64" ];
  };
}

I first load utilities in nix-shell

$ nix-shell -p binutils stdenv nix-index stdenv.cc

and then run

$ nix-build -E '((import <nixpkgs> {}).callPackage (import ./default.nix) { })' --keep-failed --no-out-link

The output indicates all libs are resolved except for one java library: libjawt.so, which nevertheless does exist, supplied by the jdk package (and nix-locate confirms this). Here is the tail of the build log:

searching for dependencies of /nix/store/pvlf028qs680ac96l6rq5cn9czapcgbx-VESTA-gtk3/PowderPlot/libswt-awt-gtk-3346.so
    libjawt.so -> not found!
setting interpreter of /nix/store/pvlf028qs680ac96l6rq5cn9czapcgbx-VESTA-gtk3/STRUCTURE_TIDY/structure_tidy
searching for dependencies of /nix/store/pvlf028qs680ac96l6rq5cn9czapcgbx-VESTA-gtk3/STRUCTURE_TIDY/structure_tidy
    libgcc_s.so.1 -> found: /nix/store/5gk8zqasr9hdhm9nhl0y7g0g7bf5lvbc-gcc-12.2.0-libgcc/lib
setting RPATH to: /nix/store/5gk8zqasr9hdhm9nhl0y7g0g7bf5lvbc-gcc-12.2.0-libgcc/lib
auto-patchelf: 1 dependencies could not be satisfied
error: auto-patchelf could not satisfy dependency libjawt.so wanted by /nix/store/pvlf028qs680ac96l6rq5cn9czapcgbx-VESTA-gtk3/PowderPlot/libswt-awt-gtk-3346.so
auto-patchelf failed to find all the required dependencies.
Add the missing dependencies to --libs or use `--ignore-missing="foo.so.1 bar.so etc.so"`.
/nix/store/37p8gq9zijbw6pj3lpi1ckqiv18j2g62-stdenv-linux/setup: line 79: pop_var_context: head of shell_variables not a function context
/nix/store/37p8gq9zijbw6pj3lpi1ckqiv18j2g62-stdenv-linux/setup: line 1457: pop_var_context: head of shell_variables not a function context
/nix/store/37p8gq9zijbw6pj3lpi1ckqiv18j2g62-stdenv-linux/setup: line 1594: pop_var_context: head of shell_variables not a function context
note: keeping build directory '/tmp/nix-build-VESTA-gtk3.drv-58'
error: builder for '/nix/store/qvrryfms3ym39fzzqxii28gldfbldjgh-VESTA-gtk3.drv' failed with exit code 1;
       last 10 log lines:
       > searching for dependencies of /nix/store/pvlf028qs680ac96l6rq5cn9czapcgbx-VESTA-gtk3/STRUCTURE_TIDY/structure_tidy
       >     libgcc_s.so.1 -> found: /nix/store/5gk8zqasr9hdhm9nhl0y7g0g7bf5lvbc-gcc-12.2.0-libgcc/lib
       > setting RPATH to: /nix/store/5gk8zqasr9hdhm9nhl0y7g0g7bf5lvbc-gcc-12.2.0-libgcc/lib
       > auto-patchelf: 1 dependencies could not be satisfied
       > error: auto-patchelf could not satisfy dependency libjawt.so wanted by /nix/store/pvlf028qs680ac96l6rq5cn9czapcgbx-VESTA-gtk3/PowderPlot/libswt-awt-gtk-3346.so
       > auto-patchelf failed to find all the required dependencies.
       > Add the missing dependencies to --libs or use `--ignore-missing="foo.so.1 bar.so etc.so"`.
       > /nix/store/37p8gq9zijbw6pj3lpi1ckqiv18j2g62-stdenv-linux/setup: line 79: pop_var_context: head of shell_variables not a function context
       > /nix/store/37p8gq9zijbw6pj3lpi1ckqiv18j2g62-stdenv-linux/setup: line 1457: pop_var_context: head of shell_variables not a function context
       > /nix/store/37p8gq9zijbw6pj3lpi1ckqiv18j2g62-stdenv-linux/setup: line 1594: pop_var_context: head of shell_variables not a function context
       For full logs, run 'nix log /nix/store/qvrryfms3ym39fzzqxii28gldfbldjgh-VESTA-gtk3.drv'.

Confirming the error,

$ ldd /nix/store/pvlf028qs680ac96l6rq5cn9czapcgbx-VESTA-gtk3/PowderPlot/libswt-awt-gtk-3346.so
ldd: warning: you do not have execution permission for `/nix/store/pvlf028qs680ac96l6rq5cn9czapcgbx-VESTA-gtk3/PowderPlot/libswt-awt-gtk-3346.so'
        linux-vdso.so.1 (0x00007f608bf5f000)
        libjawt.so => not found
        libc.so.6 => /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6 (0x00007f608bc1a000)
        /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib64/ld-linux-x86-64.so.2 (0x00007f608bf61000)

Does anyone know why patchelf can’t seem to find this particular library (everything else it found successfully), despite the fact that libjawt.so is clearly available?

1 Like

Did you ever figure this out?

@xav-ie Sorry for very late reply. In answer to your question, no, and I finally concluded that VESTA’s programmer is using a now fairly ancient JDK, such that pointing the linker to more recent libjawt.so versions fails (the not found error may be somewhat misleading, although here I’m just guessing). As a workaround, I ended up just excluding the compilation steps that included this dependency. Not really a fix, but given that this exclusion was a minor, ancillary part of VESTA, this workaround at least allowed the core program to build successfully. Hope this clarifies.

2 Likes

Hi Professor @rsa4046, newbie here. Can I ask for guidance on how I exclude the compilations steps? Thanks for any help.

Hi @westrangeloops
Here’s the final default.nix I use (not sure how this differs from the above; also, please take note of the lines that are commented out):

{ stdenv, fontconfig, lib, gdk-pixbuf, jdk8, gtk2, gtk3, iconv,  
  libGLU, libGL, libglvnd, pango, xorg, glib, glibc, gcc-unwrapped, 
  cairo, makeWrapper, fetchurl, autoPatchelfHook, wrapGAppsHook }:
stdenv.mkDerivation rec {
  name = "VESTA-gtk3";
  version = "3.5.8";

  src = fetchurl {
    url = "https://jp-minerals.org/vesta/archives/${version}/VESTA-gtk3.tar.bz2";
    sha256 = "sha256-eL7wJcKzHx1kycfgatKxOdJSs6aGiT7nmsdLMCGGjfg=";
  };
  
  nativeBuildInputs = [
    autoPatchelfHook
  ];
  
#  nativeBuildInputs = [
  buildInputs = [
    autoPatchelfHook
    fontconfig.lib
    gcc-unwrapped.lib
    gcc-unwrapped.libgcc 
    gdk-pixbuf 
    glib
    gtk2 
    gtk3 
    iconv 
    libGLU 
    libglvnd 
    pango 
    xorg.libX11 
    xorg.libXxf86vm
    xorg.libXtst
    jdk8
  ];

  dontConfigure = true;
  dontBuild = true;

  installPhase = ''
    mkdir $out
    cp -ar * $out
    rm -rf $out/PowderPlot
  '';

  # preBuild = ''
  #   addAutoPatchelfSearchPath $out/PowderPlot
  # '';

  preFixup = let
    libPath = lib.makeLibraryPath [ cairo
      fontconfig.lib 
      gcc-unwrapped.lib 
      gcc-unwrapped.libgcc 
      gdk-pixbuf     
      glib
      gtk2           
      gtk3           
      iconv          
      libGLU         
      libglvnd       
      pango          
      xorg.libX11    
      xorg.libXxf86vm
      xorg.libXtst
      jdk8
    ];
  in ''
    patchelf \
      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
      --set-rpath "${libPath}" \
      $out/VESTA
    patchelf \
      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
      --set-rpath "${libPath}" \
      $out/VESTA-core
    patchelf \
      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
      --set-rpath "${libPath}" \
      $out/VESTA-gui
    # patchelf \
    #   --set-rpath "${libPath}" \
    #   $out/PowderPlot/libswt-awt-gtk-3346.so 
  '';

  meta = with lib; {
    homepage = "https://jp-minerals.org/vesta/en/";
    description = "Visualization for Electronic and STructural Analysis";
    license = licenses.free;
    mainProgram = "VESTA";
    platforms = platforms.linux;
    architectures = [ "amd64" ];
  };
}

I compile (as above) by first loading nix-shell,

$ nix-shell -p binutils stdenv nix-index stdenv.cc

then

$ nix-build -E 'with import <nixpkgs> { }; callPackage ./default.nix { }'

This should produce a result link you can test with result/VESTA. If VESTA crashes with a GLib-GIO-ERROR error, the error may be due to missing schemas, which you can install locally by copying them (assuming they don’t already exist or aren’t deficient in some way, see link here),

$ mkdir -p ~/.local/share/glib-2.0/schemas
$ cp -pi /nix/store/3xs715zn5mm3isblz1qxa78zwnlhhjgx-gtk+3-3.24.43/share/gsettings-schemas/gtk+3-3.24.43/glib-2.0/schemas/gschemas.compiled ~/.local/share/glib-2.0/schemas/ -iv

This seems to work OK, although I have not really tested it lately. HTH

All my gratitude Professor @rsa4046 , it works very good.

1 Like