Packaging unfree binary package SDRconnect

I feel like I’m like 95% of the way there, but I cannot quite figure out the last bit here to make this run. I’d like to get it working and submit it formally (although testing it on other platforms probably won’t be trivial).

Anyway, here’s my local sdrconnect.nix file:

{ makeWrapper, pkgs }:
pkgs.stdenv.mkDerivation rec {
  pname = "sdrconnect";
  version = "0.0.0";
  src = builtins.fetchurl {
    url = "https://www.sdrplay.com/software/SDRconnect_linux-x64_0fd82d9dc.run";
    sha256 = "7200f58efc1bd78250f6057cc08b5564ea9e8f33f8ef655805bbff97f56d38c2";
  };
  sourceRoot = ".";
  unpackCmd = "bash $src --quiet --noexec --target .";

  nativeBuildInputs = [
    makeWrapper
    pkgs.autoPatchelfHook
  ];
  #autoPatchelfIgnoreMissingDeps = true;

  buildInputs = with pkgs; [
    alsa-lib
    fontconfig.lib
    icu
    libusb1
    remarkable2-toolchain
    stdenv.cc.cc.lib
    util-linux.lib
  ];

  installPhase = ''
    runHook preInstall
    mkdir -p $out
    mkdir -p $out/bin
    mkdir -p $out/lib
    mv libHarfBuzzSharp.so $out/lib
    mv libSkiaSharp.so $out/lib
    mv swig_bindings.so $out/lib
    mv SDRconnect $out/bin
    wrapProgram $out/bin/SDRconnect --prefix LD_LIBRARY_PATH : "${pkgs.lib.makeLibraryPath [ pkgs.alsa-lib pkgs.fontconfig.lib pkgs.icu pkgs.libusb1 pkgs.remarkable2-toolchain pkgs.stdenv.cc.cc.lib pkgs.util-linux.lib ]}"
    rm install.sh
    rm sdrconnect.ico
    rm sdrplay_license.txt
    runHook postInstall
  '';

  meta = with pkgs.lib; {
    description = "sdrconnect";
    homepage = "https://www.sdrplay.com/sdrconnect/";
    sourceProvenance = with sourceTypes; [ binaryNativeCode ];
    license = licenses.unfree;
    platforms = [ "x86_64-linux" ];
  };
}

I’ve been looking at a few different sources to cobble all of this together:

https://nix-tutorial.gitlabpages.inria.fr/nix-tutorial/first-package.html
https://nixos.wiki/wiki/Packaging/Binaries

I’m building it as my local user under a NixOS system with:

nix-build -E '((import <nixpkgs> {}).callPackage (import ./sdrconnect.nix) {})'

which succeeds. However, once I go to run it, I get the following:

% /nix/store/yvc84y93acm2gb9n52577b5ys6swjj7f-sdrconnect-0.0.0/bin/SDRconnect
Unhandled Exception: System.TypeInitializationException: A type initializer threw an exception. To determine which type, inspect the InnerException's StackTrace property.
 ---> System.TypeInitializationException: A type initializer threw an exception. To determine which type, inspect the InnerException's StackTrace property.
 ---> System.DllNotFoundException: Unable to load shared library 'swig_bindings' or one of its dependencies. In order to help diagnose loading problems, consider using a tool like strace. If you're using glibc, consider setting the LD_DEBUG environment variable:
swig_bindings.so: cannot open shared object file: No such file or directory
libswig_bindings.so: cannot open shared object file: No such file or directory
swig_bindings: cannot open shared object file: No such file or directory
libswig_bindings: cannot open shared object file: No such file or directory

   at SDRconnect!<BaseAddress>+0x1539dce
   at SDRconnect!<BaseAddress>+0x151e5af
   at SDRconnect!<BaseAddress>+0x151e425
   at coreradiobackendPINVOKE.SWIGExceptionHelper.SWIGRegisterExceptionCallbacks_coreradiobackend(coreradiobackendPINVOKE.SWIGExceptionHelper.ExceptionDelegate applicationDelegate, coreradiobackendPINVOKE.SWIGExceptionHelper.ExceptionDelegate arithmeticDelegate, coreradiobackendPINVOKE.SWIGExceptionHelper.ExceptionDelegate divideByZeroDelegate, coreradiobackendPINVOKE.SWIGExceptionHelper.ExceptionDelegate indexOutOfRangeDelegate, coreradiobackendPINVOKE.SWIGExceptionHelper.ExceptionDelegate invalidCastDelegate, coreradiobackendPINVOKE.SWIGExceptionHelper.ExceptionDelegate invalidOperationDelegate, coreradiobackendPINVOKE.SWIGExceptionHelper.ExceptionDelegate ioDelegate, coreradiobackendPINVOKE.SWIGExceptionHelper.ExceptionDelegate nullReferenceDelegate, coreradiobackendPINVOKE.SWIGExceptionHelper.ExceptionDelegate outOfMemoryDelegate, coreradiobackendPINVOKE.SWIGExceptionHelper.ExceptionDelegate overflowDelegate, coreradiobackendPINVOKE.SWIGExceptionHelper.ExceptionDelegate systemExceptionDelegate) + 0x7b
   at SDRconnect!<BaseAddress>+0x10e7b66
   at SDRconnect!<BaseAddress>+0x14ec909
   --- End of inner exception stack trace ---
   at SDRconnect!<BaseAddress>+0x14ec9a3
   at SDRconnect!<BaseAddress>+0x14ec819
   at SDRconnect!<BaseAddress>+0x10c4b68
   at SDRconnect!<BaseAddress>+0x14ec909
   --- End of inner exception stack trace ---
   at SDRconnect!<BaseAddress>+0x14ec9a3
   at SDRconnect!<BaseAddress>+0x14ec819
   at coreradiobackendPINVOKE.new_CoreRadio() + 0x18
   at SDRconnect.CoreRadioSingleton.<>c.<.cctor>b__4_0() + 0x19
   at SDRconnect!<BaseAddress>+0x1eb9737
   at SDRconnect!<BaseAddress>+0x1eb97b8
   at SDRconnect!<BaseAddress>+0x1eb999e
   at SDRconnect.Program.Main(String[] args) + 0x24
   at SDRconnect!<BaseAddress>+0x1f8b4fb

None of the different approaches I’ve tried to get this library visible from the executable have worked, including dropping all of the included libraries directly in $out/bin next to the binary itself.

I’d love some pointers here. I’m sure it’s something “easy”, but after several hours of messing with it, I’m not sure what else to try at this point.

Thanks for any feedback!

Well, going the more manual route seems to work for now. I’ll try messing around more with autoPatchelfHook to see if I can coax it into working. For now, there’s this:

{ pkgs }:
pkgs.stdenv.mkDerivation rec {
  pname = "sdrconnect";
  version = "0.0.0";

  src = builtins.fetchurl {
    url = "https://www.sdrplay.com/software/SDRconnect_linux-x64_0fd82d9dc.run";
    sha256 = "7200f58efc1bd78250f6057cc08b5564ea9e8f33f8ef655805bbff97f56d38c2";
  };

  sourceRoot = ".";
  unpackCmd = "bash $src --quiet --noexec --target .";

  buildInputs = with pkgs; [
    alsa-lib
    fontconfig.lib
    icu
    libusb1
    remarkable2-toolchain
    stdenv.cc.cc.lib
    util-linux.lib
    xorg.libICE
    xorg.libSM
    xorg.libX11
  ];

  installPhase = ''
    runHook preInstall
    mkdir -p $out/{bin,lib} $out/share/{doc,icons}
    patchelf --set-interpreter ${pkgs.stdenv.cc.libc}/lib/ld-linux-x86-64.so.2 SDRconnect
    patchelf --set-rpath \$ORIGIN/../lib:${pkgs.alsa-lib}/lib:${pkgs.fontconfig.lib}/lib:${pkgs.icu}/lib:${pkgs.libusb1}/lib:${pkgs.remarkable2-toolchain}/lib:${pkgs.stdenv.cc.cc.lib}/lib:${pkgs.util-linux.lib}/lib:${pkgs.xorg.libICE}/lib:${pkgs.xorg.libSM}/lib:${pkgs.xorg.libX11}/lib SDRconnect
    patchelf --add-needed libasound.so.2 --add-needed libfontconfig.so.1 --add-needed libSkiaSharp.so --add-needed swig_bindings.so --add-needed libusb-1.0.so.0 --add-needed libuuid.so.1 SDRconnect
    mv SDRconnect $out/bin
    mv libHarfBuzzSharp.so libSkiaSharp.so swig_bindings.so $out/lib
    mv sdrconnect.ico $out/share/icons
    mv sdrplay_license.txt $out/share/doc
    rm install.sh
    runHook postInstall
  '';

  dontFixup = true;

  meta = with pkgs.lib; {
    description = "sdrconnect";
    homepage = "https://www.sdrplay.com/sdrconnect/";
    sourceProvenance = with sourceTypes; [ binaryNativeCode ];
    license = licenses.unfree;
    platforms = [ "x86_64-linux" ];
  };
}