1

I'm trying to run protobuf's protoc during a dotnet build process with dotnet core 2.1 (this seemed to more or less work with 2.0, but we want to take advantage of 2.1 features). The .csproj file has a stolen snippet to run this:

  <!-- https://github.com/protocolbuffers/protobuf/issues/3820#issuecomment-399538660 -->
  <PropertyGroup>

    <protoc_linux64>tools\linux_x64\protoc</protoc_linux64>
    <protoc_linux86>tools\linux_x86\protoc</protoc_linux86>
    <protoc_macosx64>tools\macosx_x64\protoc</protoc_macosx64>
    <protoc_macosx86>tools\macosx_x86\protoc</protoc_macosx86>
    <protoc_windows64>tools\windows_x64\protoc.exe</protoc_windows64>
    <protoc_windows86>tools\windows_x86\protoc.exe</protoc_windows86>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(MSBuildRuntimeType)' == 'Core' or&#xD;&#xA;                 ('$(MSBuildVersion)' != '' and&#xD;&#xA;                 $([System.Version]::Parse($(MSBuildVersion))) &gt;= $([System.Version]::Parse(15.3))) ">
    <protoc Condition="'$([MSBuild]::IsOsPlatform(Linux))' And '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)'=='X64'">$(protoc_linux64)</protoc>
    <protoc Condition="'$([MSBuild]::IsOsPlatform(Linux))' And '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)'=='X86'">$(protoc_linux86)</protoc>
    <protoc Condition="'$([MSBuild]::IsOsPlatform(OSX))' And '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)'=='X64'">$(protoc_macosx64)</protoc>
    <protoc Condition="'$([MSBuild]::IsOsPlatform(OSX))' And '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)'=='X86'">$(protoc_macosx86)</protoc>
    <protoc Condition="'$([MSBuild]::IsOsPlatform(Windows))' And '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)'=='X64'">$(protoc_windows64)</protoc>
    <protoc Condition="'$([MSBuild]::IsOsPlatform(Windows))' And '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)'=='X86'">$(protoc_windows86)</protoc>
  </PropertyGroup>

  <Target Name="BuildProto" BeforeTargets="Compile;Restore">
    <ItemGroup>
      <Protos Include="$(ProjectDir)Protobuf\Protos\*.proto" />
    </ItemGroup>
    <Message Importance="high" Text="protobuffing" />
    <Exec Command="$(NuGetPackageRoot)google.protobuf.tools\3.6.1\$(protoc) --proto_path=$(ProjectDir) --csharp_out=$(ProjectDir)Protobuf\ --csharp_opt=file_extension=.g.cs @(Protos, ' ')" />
  </Target>

When this runs, it works. The .g.cs files are generated, everything is great. But if I start with a clean build, and run the build against the solution, then the .g.cs files are not generated. The build obviously fails after that since everything that is generated can't be found.

git clean -dxf < /dev/null ; dotnet build MySolution.sln -m:1

When I search the output for the <Message.. text ("protobuffing"), it's not there. But if I run the dotnet build a second time, then it runs the "protobuffing" right after all the "Restore completed" outputs, and then everything just works. (The reason for the < /dev/null is that I'm running this on Windows where sometimes Visual Studio has stuff locked in the .vs directory, that should be harmless here, so it gets ignored.)

I suppose I could set up the CI build server to run dotnet build twice, but that seems like a hack to me. I'm just looking for a way to get dotnet build under net core 2.1 to run this target before building C# code for this assembly.

1 Answer 1

2

I think the problem is here: <Target Name="BuildProto" BeforeTargets="Compile;Restore">. You used the target 'BuildProto' before 'Restore' and proto tools weren't exist at first run. I removed the target 'Restore' and build was executed without any issue.

Sign up to request clarification or add additional context in comments.

5 Comments

I've tried a million (*) combinations of beforetargets and names and ... and I'm sure I tried that one before. And yet, now when I try your suggestion, it seems to work. Consistently. I'm going to push it to our build servers, and if it still works there, which I'm hopeful of now, I'll mark your answer correct. Thanks!
Doesn't seem like TeamCity likes this still. I'm not sure what the difference is here between what I'm running on my machine and what TC is running.
Really weird situation... I use different steps in TeamCity for restoring, generating, building and it works fine. 1 Step - dotnet restore 2 Step - generating using commandline tools 3 Step - dotnet build Maybe it will help you.
This may be a different question now. If I specify the solution with a full path rather than just using it in the current directory, it fails. If I specify --configuration Release, instead of whatever default it's using, it fails. If I run the command through a shell script that changes directory to the sln path but run from a different directory, it fails. If I run "dotnet build MySolution.sln //m:1" at the bash command line, it works just fine.
The rest of my problem was resolved in other questions, so I'm marking this as correct given the original question. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.