Miguel Ventura's blog : GitVersion on NixOS

I was recently working with a dotnet project that used GitVersion to stamp builds with version numbers derived from the git history:

<!-- Directory.Packages.props -->
<PackageVersion Include="GitVersion.MsBuild" Version="6.2.0" />

The project also had a few other unusual build dependencies for a dotnet project — nodejs, Java, and others — so I decided to create a flake.nix to be able to quickly spin up a development environment with everything needed.

The problem was that the build started to fail:

.nuget/packages/gitversion.msbuild/6.2.0/tools/GitVersion.MsBuild.targets(26,9): error MSB3073: The command "dotnet --roll-forward Major "~/.nuget/packages/gitversion.msbuild/6.2.0/tools/net8.0/gitversion.dll"" exited with code 139.

Exit code 139 means a segmentation fault. We don't need the full dotnet build to reproduce this — we can run the GitVersion tool directly:

$ dotnet "~/.nuget/packages/gitversion.msbuild/6.2.0/tools/net8.0/gitversion.dll"
[1]    1256082 segmentation fault (core dumped)  dotnet

With help of strace we can see that there's an attempt to load libssl (various versions), and every one of them fails:

$ strace dotnet "~/.nuget/packages/gitversion.msbuild/6.2.0/tools/net8.0/gitversion.dll" 2>&1 | grep ssl
openat(AT_FDCWD, "/nix/store/l0l2ll1lmylczj1ihqn351af2kyp5x19-glibc-2.42-51/lib/libssl.so.1.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/nix/store/r7vdyf8pwlqsgd5ydak9fmq3q1i5nm3m-xgcc-15.2.0-libgcc/lib/glibc-hwcaps/x86-64-v3/libssl.so.1.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/nix/store/r7vdyf8pwlqsgd5ydak9fmq3q1i5nm3m-xgcc-15.2.0-libgcc/lib/glibc-hwcaps/x86-64-v2/libssl.so.1.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/nix/store/r7vdyf8pwlqsgd5ydak9fmq3q1i5nm3m-xgcc-15.2.0-libgcc/lib/libssl.so.1.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/nix/store/l0l2ll1lmylczj1ihqn351af2kyp5x19-glibc-2.42-51/lib/libssl.so.3", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/nix/store/r7vdyf8pwlqsgd5ydak9fmq3q1i5nm3m-xgcc-15.2.0-libgcc/lib/libssl.so.3", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

The dlopen calls are searching in many places, just not the right ones. GitVersion bundles a native library (git2) that uses dlopen() to load libssl at runtime. On NixOS, libraries aren't in the usual /usr/lib paths, and dlopen doesn't respect RPATH — so the library simply can't find OpenSSL.

The fix is to add openssl to the dev shell and expose it via LD_LIBRARY_PATH in the flake.nix:

{
  devShells.default = pkgs.mkShell {
    # ...

    packages = with pkgs; [
      # ...
      openssl
    ];

    shellHook = ''
      # git2-a418d9d.so (bundled with GitVersion) uses dlopen() to find libssl at runtime.
      # Since dlopen doesn't use RPATH, we must expose openssl via LD_LIBRARY_PATH.
      export LD_LIBRARY_PATH="${pkgs.openssl.out}/lib:$LD_LIBRARY_PATH"
    '';
  };
}

This is a recurring pattern on NixOS: any native dependency that's loaded via dlopen at runtime — rather than linked at build time — won't be found unless you explicitly set LD_LIBRARY_PATH. It's one of those things that "just works" on other distros but requires a bit of manual wiring on Nix.