Protobuf can't be run

I am trying to use NixOs as my Dev machine for my work environment (dotnet core) and it works for most project but not ones with Protobuf libraries.

I get the following error:

  Google.Protobuf.Tools.targets(280, 5): [MSB6003] The specified task executable "/home/myuser/.nuget/packages/grpc.tools/2.36.4/tools/linux_x64/protoc" could not be run. System.ComponentModel.Win32Exception (2): No such file or directory
   at System.Diagnostics.Process.ForkAndExecProcess(String filename, String[] argv, String[] envp, String cwd, Boolean redirectStdin, Boolean redirectStdout, Boolean redirectStderr, Boolean setCredentials, UInt32 userId, UInt32 groupId, UInt32[] groups, Int32& stdinFd, Int32& stdoutFd, Int32& stderrFd, Boolean usesTerminal, Boolean throwOnNoExec)
   at System.Diagnostics.Process.StartCore(ProcessStartInfo startInfo)
   at System.Diagnostics.Process.Start()
   at Microsoft.Build.Utilities.ToolTask.ExecuteTool(String pathToTool, String responseFileCommands, String commandLineCommands)
   at Microsoft.Build.Utilities.ToolTask.Execute()

This does not happen on Linux or with my fellow other-distro linux-users colleagues.

Any idea what is wrong?

I tried the following:

[myuser@home:~]$ /home/myuser/.nuget/packages/grpc.tools/2.36.4/tools/linux_x64/protoc
bash: /home/myuser/.nuget/packages/grpc.tools/2.36.4/tools/linux_x64/protoc: No such file or directory

[myuser@home:~]$ ldd /home/myuser/.nuget/packages/grpc.tools/2.36.4/tools/linux_x64/protoc
	linux-vdso.so.1 (0x00007ffc97ae6000)
	libpthread.so.0 => /nix/store/0c7c96gikmzv87i7lv3vq5s1cmfjd6zf-glibc-2.31-74/lib/libpthread.so.0 (0x00007f3bca866000)
	libm.so.6 => /nix/store/0c7c96gikmzv87i7lv3vq5s1cmfjd6zf-glibc-2.31-74/lib/libm.so.6 (0x00007f3bca725000)
	libc.so.6 => /nix/store/0c7c96gikmzv87i7lv3vq5s1cmfjd6zf-glibc-2.31-74/lib/libc.so.6 (0x00007f3bca566000)
	/lib64/ld-linux-x86-64.so.2 => /nix/store/0c7c96gikmzv87i7lv3vq5s1cmfjd6zf-glibc-2.31-74/lib64/ld-linux-x86-64.so.2 (0x00007f3bca889000)

weird?

When you’re getting a No such file or directory, but the file is there and ldd suggests the libraries can be resolved as well, I suspect it’s the interpreter that’s missing. You can check with patchelf --print-interpreter /home/myuser/.nuget/packages/grpc.tools/2.36.4/tools/linux_x64/protoc: I suspect it might be pointing to something like /lib64.

You could use patchelf to set the interpreter to the location where it is in nixpkgs, with something like patchelf --set-interpreter $(< "$NIX_CC/nix-support/dynamic-linker") /home/myuser/.nuget/packages/grpc.tools/2.36.4/tools/linux_x64/protoc.

However, when protoc is ‘managed’ by nuget, this is kinda inconvenient. In such cases, I usually run the build inside a shell.nix using buildFHSUserEnv:

{ pkgs ? import <nixpkgs> {} }:

(pkgs.buildFHSUserEnv {
  name = "your-app";

  targetPkgs = pkgs: [
    pkgs.glibc
    # ...
  ];
  
}).env
2 Likes

You are right @raboof!

[myuser@home:~]$ patchelf --print-interpreter /home/myuser/.nuget/packages/grpc.tools/2.36.4/tools/linux_x64/protoc
/lib64/ld-linux-x86-64.so.2

As you say, it’s a bit annoying as it’s managed by Nuget.
I’ll try your workaround as I never seen this (I need to read documentation about buildFHSUserEnv to understand it, I imagine the targetPkgs are the lib needed to build your project? All of them?). Will it mean I will need to manually build from the command line before launching my favorite IDE (like rider) ?

Also I don’t seem to have a $NIX_CC in my env:

[myuser@home:~]$ patchelf --set-interpreter $(< "$NIX_CC/nix-support/dynamic-linker") /home/myuser/.nuget/packages/grpc.tools/2.36.4/tools/linux_x64/protoc
bash: /nix-support/dynamic-linker: No such file or directory
patchelf: missing filename

[myuser@home:~]$ echo $NIX_CC

Yes, well, the ones that are managed by Nix and not nuget, at least :wink:

I always build from the CLI myself, but I could imagine this also works from rider when you start it from the nix-shell as well.

$NIX_CC should be available inside of nix-shell

I had a similar issue - Gradle was downloading protobuf binary which resulted in it not being able to execute. My solution:

(probably I should use tmpfiles.d for this )

1 Like

Very nice!! Thank you so much!!

Edit: my impatience is not anybody else’s problem

Little update, for a while I have been using this instead:

  systemd.tmpfiles.rules = [
    "L+ /lib64/ld-linux-x86-64.so.2 - - - - ${pkgs.glibc}/lib64/ld-linux-x86-64.so.2"
  ];