Skip to content
This repository was archived by the owner on Apr 9, 2021. It is now read-only.

Commit b810eb2

Browse files
author
kkm
committed
Address review comments round 1
1 parent b907d39 commit b810eb2

1 file changed

Lines changed: 58 additions & 38 deletions

File tree

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,63 @@
11
---
22
layout: post
3-
title: gRPC Meets .NET SDK And Visual Studio
3+
title: gRPC Meets .NET SDK And Visual Studio: Automatic Codegen On Build
44
published: true
55
permalink: blog/grpc-dotnet-build
66
author: Kirill 'kkm' Katsnelson
77
author-link: https://github.com/kkm000
88
company: SmartAction
99
company-link: https://www.smartaction.ai
1010
---
11+
1112
As part of Microsoft's move towards its cross-platform .NET offering, they have
1213
greatly simplified the project file format, and allowed a tight integration of
1314
third-party code generators with .NET projects. We are listening, and now proud
1415
to introduce integrated compilation of Protocol Buffer and gRPC service
1516
`.proto` files in .NET C# projects starting with the version 1.17 of the
1617
Grpc.Tools NuGet package, now available from Nuget.org.
1718

19+
You no longer need separate scripts to generate code from `.proto` files: The
20+
.NET build magic handles this for you. The integrated tools locate the proto
21+
compiler and gRPC plugin, standard Protocol Buffer imports, and track
22+
dependencies before invoking the code generators, so that the generated C#
23+
source files are never out of date, at the same time keeping regeneration to
24+
the minimum required. In essence, `.proto` files are treated as first-class
25+
sources in a .NET C# project.
26+
1827
<!--more-->
1928

2029
## A Walkthrough
2130

22-
Now you can include `.proto` files along with C# source files into `.csproj`
23-
project files. In this blog post, we'll walk through the simplest and probably
24-
the most common scenario of creating a library from `.proto` files using the
25-
cross-platform `dotnet` command. We will implement essentially a clone of the
26-
`Greeter` library, shared by client and server projects in the [C# `Helloworld`
27-
example directory
31+
In this blog post, we'll walk through the simplest and probably the most common
32+
scenario of creating a library from `.proto` files using the cross-platform
33+
`dotnet` command. We will implement essentially a clone of the `Greeter`
34+
library, shared by client and server projects in the [C# `Helloworld` example
35+
directory
2836
](https://github.com/grpc/grpc/tree/master/examples/csharp/Helloworld/Greeter).
2937

3038
Start by creating a new library project.
3139

3240
```
33-
kkm@yupana:~/work$ dotnet new classlib -o MyGreeter
41+
~/work$ dotnet new classlib -o MyGreeter
3442
The template "Class library" was created successfully.
3543
36-
kkm@yupana:~/work$ cd MyGreeter
37-
kkm@yupana:~/work/MyGreeter$ ls -lF
44+
~/work$ cd MyGreeter
45+
~/work/MyGreeter$ ls -lF
3846
total 12
3947
-rw-rw-r-- 1 kkm kkm 86 Nov 9 16:10 Class1.cs
4048
-rw-rw-r-- 1 kkm kkm 145 Nov 9 16:10 MyGreeter.csproj
4149
drwxrwxr-x 2 kkm kkm 4096 Nov 9 16:10 obj/
4250
```
4351

44-
The `dotnet new` command has created the file `Class1.cs` that we won't need, so
45-
it's ok to remove it. Also, we need some `.proto` files to compile. For this
46-
exercise, we'll copy an example file [`examples/protos/helloworld.proto`
52+
Observe that the `dotnet new` command has created the file `Class1.cs` that
53+
we won't need, so remove it. Also, we need some `.proto` files to compile. For
54+
this exercise, we'll copy an example file [`examples/protos/helloworld.proto`
4755
](https://github.com/grpc/grpc/blob/master/examples/protos/helloworld.proto)
4856
from the gRPC distribution.
4957

5058
```
51-
kkm@yupana:~/work/MyGreeter$ rm Class1.cs
52-
kkm@yupana:~/work/MyGreeter$ wget -q https://raw.githubusercontent.com/grpc/grpc/master/examples/protos/helloworld.proto
59+
~/work/MyGreeter$ rm Class1.cs
60+
~/work/MyGreeter$ wget -q https://raw.githubusercontent.com/grpc/grpc/master/examples/protos/helloworld.proto
5361
```
5462

5563
(on Windows, use `del Class1.cs`, and, if you do not have the wget command,
@@ -60,11 +68,11 @@ and use a *Save As...* command from your Web browser).
6068
Next, add required NuGet packages to the project:
6169

6270
```
63-
kkm@yupana:~/work/MyGreeter$ dotnet add package Grpc
71+
~/work/MyGreeter$ dotnet add package Grpc
6472
info : PackageReference for package 'Grpc' version '1.17.0' added to file '/home/kkm/work/MyGreeter/MyGreeter.csproj'.
65-
kkm@yupana:~/work/MyGreeter$ dotnet add package Grpc.Tools
73+
~/work/MyGreeter$ dotnet add package Grpc.Tools
6674
info : PackageReference for package 'Grpc.Tools' version '1.17.0' added to file '/home/kkm/work/MyGreeter/MyGreeter.csproj'.
67-
kkm@yupana:~/work/MyGreeter$ dotnet add package Google.Protobuf
75+
~/work/MyGreeter$ dotnet add package Google.Protobuf
6876
info : PackageReference for package 'Google.Protobuf' version '3.6.1' added to file '/home/kkm/work/MyGreeter/MyGreeter.csproj'.
6977
```
7078

@@ -73,15 +81,19 @@ file automatically finds all `.cs` files in its directory, although
7381
[Microsoft now recommends suppressing this globbing
7482
behavior](https://docs.microsoft.com/dotnet/core/tools/csproj#recommendation),
7583
so we too decided against globbing `.proto` files. Thus the `.proto`
76-
files must be added to the project explicitly. Second of all, it is important
77-
to add a property `PrivateAssets="All"` to the Grpc.Tools package reference,
78-
so that it will not be needlessly fetched by the consumers of your new library.
79-
This makes sense, as the package only contains compiler, code generators and
80-
import files, which are not needed outside of the project where the `.proto`
81-
files have been compiled. So you must edit the file `MyGreeter.csproj` and
82-
add the `helloworld.proto` to be compiled, and the `PrivateAssets` property to
83-
the Grpc.Tools package reference. Your resulting project file should now look
84-
like this:
84+
files must be added to the project explicitly.
85+
86+
Second of all, it is important to add a property `PrivateAssets="All"` to the
87+
Grpc.Tools package reference, so that it will not be needlessly fetched by the
88+
consumers of your new library. This makes sense, as the package only contains
89+
compilers, code generators and import files, which are not needed outside of
90+
the project where the `.proto` files have been compiled. While not strictly
91+
required in this simple walkthrough, it must be your standard practice to do
92+
that always.
93+
94+
So edit the file `MyGreeter.csproj` to add the `helloworld.proto` so that it
95+
will be compiled, and the `PrivateAssets` property to the Grpc.Tools package
96+
reference. Your resulting project file should now look like this:
8597

8698
```xml
8799
<Project Sdk="Microsoft.NET.Sdk">
@@ -93,24 +105,25 @@ like this:
93105
<ItemGroup>
94106
<PackageReference Include="Google.Protobuf" Version="3.6.1" />
95107
<PackageReference Include="Grpc" Version="1.17.0" />
108+
<!-- Add attribute as shown below. -->
96109
<PackageReference Include="Grpc.Tools" Version="1.17.0" PrivateAssets="All" />
97-
<ProtoBuf Include="helloworld.proto" />
110+
<Protobuf Include="helloworld.proto" /> <!-- Add this entire line. -->
98111
</ItemGroup>
99112

100113
</Project>
101114
```
102115

103-
At this point you can build the project with `dotnet build` command to compile
104-
the `.proto` file and the library assembly. For this walkthrough, we'll add a
105-
logging switch `-v:n` to the command, so we can see that the command to compile
106-
the `helloworld.proto` file was in fact run. You may find it a good idea to do
107-
that the very first time you compile a project!
116+
At this point you can build the project with the `dotnet build` command to
117+
compile the `.proto` file and the library assembly. For this walkthrough, we'll
118+
add a logging switch `-v:n` to the command, so we can see that the command to
119+
compile the `helloworld.proto` file was in fact run. You may find it a good
120+
idea to always do that the very first time you compile a project!
108121

109122
Note that many output lines are omitted below, as the build output is quite
110123
verbose.
111124

112125
```
113-
kkm@yupana:~/work/MyGreeter$ dotnet build -v:n
126+
~/work/MyGreeter$ dotnet build -v:n
114127
115128
Build started 11/9/18 5:33:44 PM.
116129
1:7>Project "/home/kkm/work/MyGreeter/MyGreeter.csproj" on node 1 (Build target(s)).
@@ -129,6 +142,12 @@ Build started 11/9/18 5:33:44 PM.
129142
Build succeeded.
130143
```
131144

145+
If at this point you invoke the `dotnet build -v:n` command again, `protoc`
146+
would not be invoked, and no C# sources would be compiled. But if you change
147+
the `helloworld.proto` source, then its outputs will be regenerated and then
148+
recompiled by the C# compiler during the build. This is a regular dependency
149+
tracking behavior that you expect from modifying any source file.
150+
132151
Of course, you can also add `.cs` files to the same project: It is a regular C#
133152
project building a .NET library, after all. This is done in our [RouteGuide
134153
](https://github.com/grpc/grpc/tree/master/examples/csharp/RouteGuide/RouteGuide)
@@ -144,7 +163,7 @@ tools like the debugger. You can see other autogenerated sources in that
144163
directory, too:
145164

146165
```
147-
kkm@yupana:~/work/MyGreeter$ find obj -name '*.cs'
166+
~/work/MyGreeter$ find obj -name '*.cs'
148167
obj/Debug/netstandard2.0/MyGreeter.AssemblyInfo.cs
149168
obj/Debug/netstandard2.0/Helloworld.cs
150169
obj/Debug/netstandard2.0/HelloworldGrpc.cs
@@ -156,8 +175,8 @@ command prompt).
156175
## There Is More To It
157176

158177
While the simplest default behavior is adequate in many cases, there are many
159-
ways to fine-tune your `.proto` compilation process in a large project. Refer
160-
to the [documentation file BUILD-INTEGRATION.md
178+
ways to fine-tune your `.proto` compilation process in a large project. We
179+
encourage you to read the [documentation file BUILD-INTEGRATION.md
161180
](https://github.com/grpc/grpc/blob/master/src/csharp/BUILD-INTEGRATION.md)
162181
for available options if you find that the default arrangement does not suit
163182
your workflow. The package also extends the Visual Studio's Properties window,
@@ -172,4 +191,5 @@ your feedback. Did something not work as expected? Do you have a scenario that
172191
is not easy to cover with the new tools? Do you have an idea how to improve the
173192
workflow in general? Please read the documentation carefully, and then [open an
174193
issue](https://github.com/grpc/grpc/issues) in the gRPC code repository on
175-
GitHub.
194+
GitHub. Your feedback is important to determine the future direction for our
195+
build integration work!

0 commit comments

Comments
 (0)