8

I'm struggling writing the right configuration for grpc imports.

So the .net solution structure is like:
\Protos\Common\common.proto
\Protos\Vehicle\car.proto
\CarMicroservice

Inside car.proto I have: import "common.proto"

What I want is the generated grpc code to be inside the project CarMicroservice.
Inside CarMicroservice.csproj I have written the path to the protos:

<Protobuf Include="common.proto" ProtoRoot="..\Protos\Common\" />
<Protobuf Include="car.proto" ProtoRoot="..\Protos\Vehicle\" />

But getting error: 'common.proto' no such file or directory

The question is: How do I correctly import common.proto inside the car.proto?

Note: I already looked at the similar issue, but couldn't make it work for my case
Importing .proto files from another project

Bekjan Juma
  • 453
  • 1
  • 5
  • 11
  • I'm unfamiliar with using protobufs with .NET but, in my experience, correctly setting proto paths and includes is always challenging. Have you tried `ProtoRoot="..\Protos"` and `Include="Common/common.proto"` etc.? I think you'll need to revise your import to `import "Common/common.proto"` too. You may need to use absolute rather than relative (`..\Protos`) paths too. – DazWilkin Aug 18 '20 at 21:35
  • Thanks @DazWilkin. I already solved the issue. But your comment is close to correct answer – Bekjan Juma Aug 18 '20 at 23:06
  • I'm pleased to hear it! – DazWilkin Aug 18 '20 at 23:58

2 Answers2

11

Ok, I finally solved the issue. Also @DazWilkin pointed it out.

  1. You can't use relative paths in the import, so you should use absolute path of the project. In my case it was: import "Common/common.proto"
  2. Use the project root for the location of proto files. So instead of ProtoRoot="..\Protos\Common\" use ProtoRoot="../Protos/"
    Now comes the interesting part.
    For some reason when I used backslashes for the ProtoRoot path as "..\Protos\
    I was getting errors as 'file not found'. So don't use the backslashes for paths. The final code in CarMicroservice.csproj is like the following:
<Protobuf Include="Common/common.proto" ProtoRoot="../Protos/" />
<Protobuf Include="Vehicle/car.proto" ProtoRoot="../Protos/" />
Bekjan Juma
  • 453
  • 1
  • 5
  • 11
  • Maybe you can mark this as answer. So that it will help others to find solution quickly if they face similar issue. – 大陸北方網友 Aug 19 '20 at 01:03
  • Can't seem to get this same setup working. Still getting File not found error even though it's visibly linked in the file explorer and I can use the generated stubs in the c# code. – Matthew Heimlich Apr 06 '21 at 18:08
  • I have the same problem like @MatthewHeimlich ! error : File not found. – ManDani Jun 08 '21 at 11:28
  • So the solution is not building? Can you share your code? What I noticed that, there're still warnings generated in Visual Studio, but the program works – Bekjan Juma Jul 06 '21 at 12:15
5

Alternatively, there are two other ways to specify include directories for protoc.

First, there is a global property named Protobuf_AdditionalImportsPath. If you specify this property in your .csproj/.fsproj, it will be passed on to protoc for every .proto in that project. You can use it like this:

<PropertyGroup>
    <Protobuf_AdditionalImportsPath>../../my/other/directory</Protobuf_AdditionalImportsPath>
</PropertyGroup>

There is also a AdditionalImportDirs property you can specify directly on <Protobuf> elements. This will likely only be valid for the .protos you specify it on:

<Protobuf Include="MyProto.proto" Link="MyProto.proto" AdditionalImportDirs="../../my/other/directory" />

Keep in mind that in both cases, you can specify any directory you want, regardless of whether it is a parent of the .proto you're compiling.

Also keep in mind that the import path you specify in your .proto needs be relative to one of the import directories you specify.

Arshia001
  • 1,854
  • 14
  • 19
  • If you need to specify multiple import directories, separate them with a semicolon, as seen on this page: https://github.com/grpc/grpc/issues/22878 – Max Jul 29 '22 at 19:27