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.

See all posts

  1. Dotnet core debugging in Apple Silicon (M1)
  2. Advent of Code 2020
  3. Three Years of OnePlus One
  4. Controlled Output through Rx Streams
  5. Going Mechanical: 60 days of Pok3r
  6. Winning the Hackathon
  7. From MySQL to PostgreSQL
  8. The Best Programming Language
  9. 60 days of Kindle Paperwhite
  10. Ingress Portal Bursting
  11. Image Manipulation with HSL
  12. Scripting WinDBG with PyKd
  13. django-imagekit watermarks
  14. Why is it still Hard to Learn CSS?
  15. Beginnings