Surely there was a better way to do this right?

Today I wanted to download an unpatched binary for an addon for a game that I play. I made a derivation that uses autopatchelf to link the libraries correctly, but there were two that were giving me a lot of trouble:

  • libcrypto.so.1.0.0
  • libssl.so.1.0.0
    Both of these libraries are normally provided by openssl, but this binary in particular required some really outdated versions of them that are only still used by two packages in the entirety of nixpkgs.

Here’s the solution I found that worked:

{ pkgs ? import <nixpkgs> {} }:

let
  # I genuinely can't believe that I actually need to do this.
  robo3t_movedlibs = pkgs.robo3t.overrideAttrs (oldAttrs: rec {
    installPhase = ''
      runHook preInstall

      mkdir -p $out/lib

      tar -xzf $src

      cp robo3t-${oldAttrs.version}-linux-x86_64-${oldAttrs.rev}/lib/libssl.so.1.0.0 $out/lib/
      cp robo3t-${oldAttrs.version}-linux-x86_64-${oldAttrs.rev}/lib/libcrypto.so.1.0.0 $out/lib/
      runHook postInstall
    '';
  });
in
pkgs.stdenv.mkDerivation rec {
  pname = "ddstats";
  version = "0.6.10-181";

  src = pkgs.fetchurl {
    url = "https://github.com/lsaa/ddstats-rust/releases/download/v${version}/ddstats-rust-linux-x86_64.zip";
    hash = "sha256-FlbmyvQNyV9s360oag9iRmctH+7jje0BlVpYrWDnza4="; # Make sure to replace this with the correct hash
  };

  nativeBuildInputs = with pkgs; [
    unzip
    autoPatchelfHook
    robo3t_movedlibs
  ];

  buildInputs = with pkgs; [
    glibc
    libgcc
    gcc
    zlib
    xorg.libxcb
  ];

  installPhase = ''
    unzip $src
    install -Dm755 ddstats-rust $out/bin/ddstats-rust
  '';

  postInstall = ''
    autoPatchelf $out/bin/ddstats-rust
  '';
}

In the robo3t override I had to move the two library files from their usual directory into $out/lib because that’s apparently just where autopatchelf looks by default. Then I used the package as a build input and it was able to find them.

There has got to be a better way to achieve this outcome right? Was there some way I could have told autopatchelf specifically where to look for those files in the package directory instead of having to override the package to move them around? Or maybe even some way to just download the libraries from somewhere outright using fetchurl or something?

If addons depend on the upstream-provided libs, the robo3t package should provide them similar to what you’ve done in the movedLibs drv. Then you could simply add robo3t to the buildInputs.

I think another possibility would be to install the libs somewhere and then manually patchelf the binary’s rpath to look for the libs in that location. The first idea seems cleaner to me though.