grpc: Grpc.Tools doesn't support same filename in different folders
What version of gRPC and what language are you using?
Grpc.Tools 1.17.1
What operating system (Linux, Windows, …) and version?
Windows 10
What runtime / compiler are you using (e.g. python version or version of gcc)
C# MSBuild
What did you do?
One project with two protos having the same filename but in different folders.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Protobuf_StandardImportsPath>$(Protobuf_StandardImportsPath);..\protos</Protobuf_StandardImportsPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Grpc.Tools" Version="1.17.1" PrivateAssets="All" />
<Protobuf Include="..\protos\foo.proto" Link="protos\foo.proto" />
<Protobuf Include="..\protos\dir1\bar.proto" Link="protos\dir1\bar.proto" />
<Protobuf Include="..\protos\dir2\bar.proto" Link="protos\dir2\bar.proto" />
</ItemGroup>
</Project>
What did you expect to see?
The code should compile, generating 3 cs files.
What did you see instead?
MSB3105: The item "obj\Debug\netstandard2.0\Bar.cs" was specified more than once in the "Sources" parameter. Duplicate items are not supported by the "Sources" parameter.
Anything else we should know about your project / environment?
We have an extensive library of protos that get reused by different projects that also share some protos. Therefore a common root path is necessary. The name config.proto
for example is used in a couple of directories.
Until now, I used the following command to generate the files:
%protoc_path%\protoc.exe --proto_path=%protoc_path%\..;..\protos --csharp_out=%output_path% --csharp_opt=base_namespace --grpc_out=%output_path% --plugin=protoc-gen-grpc=%protoc-grpc_path%\grpc_csharp_plugin.exe ..\protos\foo.proto ..\protos\dir1\bar.proto ..\protos\dir2\bar.proto
The option base_namespace
placed the generated files in sub-directories and avoided the problem. This problem will still remains for grpc service files, since there is no option like this for grpc_opt
. But that problem can’t be circumvented so easy right now.
/cc @kkm000
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 10
- Comments: 32 (30 by maintainers)
What would you say about having a working solution without any code changes? 💃
$(Protobuf_OutputPath)
- returns obj path%(RelativeDir)
- returns relative proto file structureI am using this in project with 344 proto files (envoy xds api), see example below. All my proto files are located in
Protos
folder.It was a one liner for all of my problems. Can anybody confirm if that works in your setup? @jtattermusch
As the issue was opened almost a year now, I don’t expect it will be fixed soon, I will go for a workdaround
@Falco20019, I have created PR with update to Grpc.Tools documentation, with proposed solution, mainly for those people who are looking for solution today. When your PR will be merged I would ask you to update documentation.
@kkm000 Any news on that? The problem is growing more and more on us. We are using the workaround from @zhangpengchen and have a knowledge-base article on it. But it’s still coming up every couple weeks…
@jtattermusch Sounds like a great idea to me and would be a lot less fragile. And it would also solve the long path problem. So I would be fine with investigating that route as default.
I‘m currently out of office for the rest of the week. If no one else is looking into it, I might be able to look into it on the weekend or next week.
%(Link)
is AFAIK also including the absolute path in this case and would not solve the problem.I’ve looked at https://github.com/grpc/grpc/pull/22630 and it seems too fragile and complicated for what we want to do. We should investigate:
.protodep
files (which are also generated by Grpc.Tools). See here: https://github.com/grpc/grpc/blob/d86acba1daa56ff4867280cb5b4e238d58869ced/src/csharp/Grpc.Tools/DepFileUtil.cs#L166. The idea is that perhaps we could also hash the proto file’s full path (regardless what it originally was) and put the generated .cs file underOutputPath/hash_of_the_full_path/Helloworld.cs
. That way the generated .cs file would have unique path and it would be easy for Grpc.Tools to compute what that path should be.No problem, I just go the clean way and finally bring
base_namespace
to thegrpc_csharp_plugin
. Just created the PR for it: #22627 😃I will add another PR for adding support to Grpc.Tools right now.
Perhaps this has been already discussed, but would this work?
foo/bar/some.proto
, can we just set the output directory for that specific .proto file toobj/Debug/framework/foo/bar/
? The C# compiler doesn’t really care where is the .cs file located and this would prevent the name collision. At the same time, the output directory is easy to determine as it’s just the path of the original .proto file within the project (no protoc mangling of namespaces involved).Maybe the right solution would be to implement
base_namespace
option forgrpc_csharp_plugin
too and make Grpc.Tools use that option by default (for both protoc and the plugin) - that would prevent the name clash.