Program compiled with rust cannot find libssl.so.3 at runtime

Using a flake based nix shell environment for development (both on NixOS and Ubuntu 22.04), I am able to compile my rust application against openssl. However, as soon as I try to run the application in that shell environment (either using cargo run, or by directly calling the binary in ./target/debug/) libssl.so.3 and libcrypto.so.3 are unable to be found:

LD_DEBUG=files ./target/debug/sdf
   1177914:
   1177914:	file=libssl.so.3 [0];  needed by ./target/debug/sdf [0]
./target/debug/sdf: error while loading shared libraries: libssl.so.3: cannot open shared object file: No such file or directory
lddtree ./target/debug/sdf
./target/debug/sdf (interpreter => /nix/store/8xk4yl1r3n6kbyn05qhan7nbag7npymx-glibc-2.35-224/lib/ld-linux-x86-64.so.2)
    libssl.so.3 => None
    libcrypto.so.3 => None
    libgcc_s.so.1 => /nix/store/8xk4yl1r3n6kbyn05qhan7nbag7npymx-glibc-2.35-224/lib/libgcc_s.so.1
    libm.so.6 => /nix/store/8xk4yl1r3n6kbyn05qhan7nbag7npymx-glibc-2.35-224/lib/libm.so.6
    libc.so.6 => /nix/store/8xk4yl1r3n6kbyn05qhan7nbag7npymx-glibc-2.35-224/lib/libc.so.6
    ld-linux-x86-64.so.2 => /nix/store/8xk4yl1r3n6kbyn05qhan7nbag7npymx-glibc-2.35-224/lib/ld-linux-x86-64.so.2

I see that there are several PRs against nixpkgs where LD_LIBRARY_PATH is being set with wrapProgram as part of the derivation for various libraries (Ex. flycast, jitsi-videobridge), but that’s not really a reasonable thing to do for being able to run things in a development environment. Adding export LD_LIBRARY_PATH=${openssl.out}/lib to the shellHook of the mkShell in the flake works, but feels like this isn’t the way it’s supposed to be done.

Is there a way to get a binary compiled through cargo build in a development shell to find the openssl libraries at runtime, without having to set LD_LIBRARY_PATH?

AFAIK no, though you can enable the vendor feature of openssl by default, then turn the feature off in the nix package (which it will link correctly).

On a side note, you don’t have to export variables in shellHook, you can do it like this (makeLibraryPath is equivalent to what you are doing, but accepts a list of libraries).

mkShell {
  # ...
  LD_LIBRARY_PATH = lib.makeLibraryPath [ openssl ];
}
1 Like