2

Issue:

I have a C# project which relies on the use of two file generation packages:

  1. Package 1 autogenerates some .proto files for me (my own package)
  2. Package 2 generates C# classes from the .proto files (Grpc.Tools NuGet package)

The solution itself builds fine, both through dotnet build on cli, and through building within Visual Studio.

However, when opening the solution in Studio, it infinitely loops the file generation / background build step. I can see it's continually looping as the bottom panel in VS shows my a warning that appears and disappears over and over as it builds. (NB: this is some background build task it is doing for file generation, not a manual build I have kicked off).

I have other solutions which use each of these packages individually and without issue, so my hypothesis is that the two file generation steps must be triggering one another as they change files in the solution.

Since the solution builds I would simply ignore the issues, but the continual infinite loop of the build step is chewing through system resources and slowing everything down.

What I have tried:

Since I want to run package 1 then package 2 (Grpc.Tools) sequentially, I tried to use the BeforeTargets attribute within package 1 target to tie it to a specific step (Protobuf_BeforeCompile) in the Grpc.Tools package:

<Project>
<Target Name="Package1" BeforeTargets="Protobuf_BeforeCompile;BeforeCompile">
    <MyPackages.Package1.MSBuild.OnBuild />
</Target>
</Project>

But this doesn't seem to work.

Another workaround I have managed is replacing the Grpc.Tools package with a command line step, as:

<Target Name="GenerateStep" AfterTargets="Package1">
        <Exec Command="protoc --proto_path=../libraries/protos --csharp_out=Common/Autogenerated myProtoFile.proto" />
 </Target>

But ideally I'd be able to use the Grpc.Tools NuGet package, as I feel it's a cleaner approach.

Summary:

I guess my questions are:

  1. Is my assumption correct, that it's the file generation from one step kicking off the other? Is this proved in a log somewhere? (and why does this not happen when I run dotnet build from terminal
  2. How do I set up the two packages so that they run in the correct sequence, and do not kick off the other process in a loop?

Any/all thoughts and suggestions welcomed!

localghost
  • 329
  • 1
  • 4
  • 11
  • Does Package1 have some `.props` or `.targets` files that you are using to autogenerate the proto files? It would be helpful to see those because I can browse the `Grpc.Tools` package you mentioned. – Hank Jul 25 '22 at 12:57
  • Unfortunately I'm unable to share the package here. Package1 builds based off C# classes with a specific attribute, and outputs `.proto` files. The Grpc.Tools lib then builds additional C# classes from those protos which do not contain that attribute - so I don't believe this should be the cause. – localghost Jul 25 '22 at 13:13
  • You don’t need to post the entire package. But with the current information, it’s impossible to tell how the two packages interact with each other. Mainly the `.targets` file because that’s how you hook into msbuild. We need a minimal reproducible example to help. – Hank Jul 25 '22 at 15:59

1 Answers1

0

Things to consider trying, depending on your requirements:

  • Add an MSBuild property DisableProtobufDesignTimeBuild with value true.
  • Add a condition where you invoke your task: <MyPackages.Package1.MSBuild.OnBuild Condition="'$(DesignTimeBuild)' == 'true' />
  • In your project file, pre-emptively exclude the .cs files Package 2 generates.

The answers to question 1 are likely "yes" and:

https://github.com/dotnet/project-system/blob/main/docs/design-time-builds.md

Visual Studio 2017 or later

  1. Install the Project System Tools extension
  2. In Visual Studio, choose the View > Other Windows > Build Logging menu item.
  3. Click on the "play" button.

This will cause design-time builds to show up in the build logging tool window. If you have the MSBuild Binary and Structured Log Viewer installed, you can double-click on a log to view it in the viewer, otherwise you can right-click and choose Save As... to save the log in the new binary log format.

Diagnosing failing or slow design-time builds

After following the above instructions, open the resulting build log file or Output window (for the new project system).

The answer to question 2 is likely "A target is never run twice during a build".

weir
  • 4,521
  • 2
  • 29
  • 42