mirror of https://github.com/grpc/grpc.git
Rewrite Grpc.Tools BUILD-INTEGRATION.md docs (#32075)
* Rewrite Grpc.Tools BUILD-INTEGRATION.md docs * Minor edits to text * various adjustments and typos for Grpc.Tools readme * Updated with review suggestions * Further refinements to the docs * Add README for Grpc.Tools package * Update BUILD-INTEGRATION.md * Updated from review comments Co-authored-by: Jan Tattermusch <jtattermusch@google.com>pull/32180/head
parent
13186065a8
commit
3e70a163e2
3 changed files with 420 additions and 340 deletions
@ -1,442 +1,499 @@ |
|||||||
Protocol Buffers/gRPC Codegen Integration Into .NET Build |
# Protocol Buffers/gRPC Codegen Integration Into .NET Build |
||||||
================================================= |
|
||||||
|
|
||||||
With Grpc.Tools package version 1.17 we made it easier to compile .proto files |
The [Grpc.Tools](https://www.nuget.org/packages/Grpc.Tools) NuGet package provides C# tooling support for generating C# code from `.proto` files in `.csproj` projects: |
||||||
in your project using the `dotnet build` command, Visual Studio, or command-line |
* It contains protocol buffers compiler and gRPC plugin to generate C# code. |
||||||
MSBuild. You need to configure the .csproj project according to the way you want |
* It can be used in building both grpc-dotnet projects and legacy c-core C# projects. |
||||||
to integrate Protocol Buffer files into your build. |
|
||||||
|
|
||||||
There is also a Reference section at the end of the file. |
Using `Grpc.Tools` in `.csproj` files is described below. Other packages providing the runtime libraries for gRPC are described elsewhere. |
||||||
|
|
||||||
Common scenarios |
## Getting Started |
||||||
---------------- |
|
||||||
|
|
||||||
### I just want to compile .proto files into my library |
The package [Grpc.Tools](https://www.nuget.org/packages/Grpc.Tools) is used automatically to generate the C# code for protocol buffer messages and gRPC service stubs from |
||||||
|
`.proto` files. These files: |
||||||
|
* are generated on an as-needed basis each time the project is built. |
||||||
|
* aren't added to the project or checked into source control. |
||||||
|
* are a build artifact usually contained in the obj directory. |
||||||
|
|
||||||
This is the approach taken by the examples in the `csharp/examples` directory. |
This package is optional. You may instead choose to generate the C# source files from |
||||||
Protoc output files (for example, `Helloworld.cs` and `HelloworldGrpc.cs` |
`.proto` files by running the `protoc` compiler manually or from a script. |
||||||
compiled from `helloworld.proto`) are placed among *object* and other temporary |
However this package helps to simplify generating the C# source files by |
||||||
files of your project, and automatically provided as inputs to the C# compiler. |
integrating the code generation into the build process. It can be used when building both |
||||||
As with other automatically generated .cs files, they are included in the source |
the server and client projects, and by both c-core C# projects and grpc-dotnet projects: |
||||||
and symbols NuGet package, if you build one. |
* The `Grpc.AspNetCore` metapackage already includes a reference to `Grpc.Tools`. |
||||||
|
* gRPC for .NET client projects and projects using `Grpc.Core` need to reference `Grpc.Tools` explicity if you want code generation for those projects |
||||||
|
|
||||||
Simply reference your .proto files in a `<Protobuf>` item group. The following |
`Grpc.Tools` is only used at build-time and has no runtime components. |
||||||
example will add all .proto files in a project and all its subdirectories |
It should be marked with `PrivateAssets="All"` to prevent it from being included at runtime, e.g. |
||||||
(excluding special directories such as `bin` and `obj`): |
```xml |
||||||
|
<PackageReference Include="Grpc.Tools" Version="2.50.0"> |
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> |
||||||
|
<PrivateAssets>all</PrivateAssets> |
||||||
|
</PackageReference> |
||||||
|
``` |
||||||
|
|
||||||
|
Support is provided for the following platforms: |
||||||
|
* Windows (x86, x64, and arm64 via using the x86 binaries) |
||||||
|
* MacOS (x64 and arm64 via using the x64 binaries) |
||||||
|
* Linux (x86, x64, and arm64) |
||||||
|
|
||||||
|
## Adding `.proto` files to a project |
||||||
|
|
||||||
|
To add `.proto` files to a project edit the project’s `.csproj` file and add an item group with a `<Protobuf>` element that refers to the `.proto` file, e.g. |
||||||
|
|
||||||
```xml |
```xml |
||||||
<ItemGroup> |
<ItemGroup> |
||||||
<Protobuf Include="**/*.proto" /> |
<Protobuf Include="Protos\greet.proto" /> |
||||||
</ItemGroup> |
</ItemGroup> |
||||||
``` |
``` |
||||||
|
|
||||||
You must add a reference to the NuGet packages Grpc.Tools and Grpc (the latter |
Wildcards can be used to select several `.proto` files, e.g. |
||||||
is a meta-package, in turn referencing Grpc.Core and Google.Protobuf packages). |
|
||||||
It is **very important** to mark Grpc.Tools as a development-only dependency, so |
|
||||||
that the *users* of your library do not fetch the tools package: |
|
||||||
|
|
||||||
* "dotnet SDK" .csproj (Visual Studio, `dotnet new`): Add an attribute |
```xml |
||||||
`PrivateAssets="All"` to the Grpc.Tools package reference. See an example in the |
<ItemGroup> |
||||||
[Greeter.csproj](../../examples/csharp/Helloworld/Greeter/Greeter.csproj#L10) |
<Protobuf Include="**\*.proto" /> |
||||||
example project in this repository. If adding a package reference in Visual |
</ItemGroup> |
||||||
Studio, edit the project file and add this attribute. [This is a bug in NuGet |
``` |
||||||
client](https://github.com/NuGet/Home/issues/4125). |
|
||||||
|
|
||||||
* "Classic" .csproj with `packages.config` (Visual Studio before 2017, old versions of Mono): |
By default, a `<Protobuf>` reference generates gRPC client and a service base class from the `service` definitions in the `.proto` files. |
||||||
This is handled automatically by NuGet after you set the `developmentDependency="true"` |
The `GrpcServices` attribute can be used to limit C# asset generation. See the reference section below for all |
||||||
attribute on the `<package>` tag in `packages.config`. |
options. E.g. to only generate client code: |
||||||
|
|
||||||
If building a NuGet package from your library with the nuget command line tool |
```xml |
||||||
from a .nuspec file, then the spec file may (and probably should) reference the |
<ItemGroup> |
||||||
Grpc metapackage, but **do not add a reference to Grpc.Tools** to it. "dotnet SDK" |
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" /> |
||||||
projects handle this automatically when called from `dotnet pack` by excluding |
</ItemGroup> |
||||||
any packages with private assets, such as thus marked Grpc.Tools. |
``` |
||||||
|
|
||||||
#### Per-file options that can be set in Visual Studio |
For `.proto` files that are outside of the project directory a link can be added so that the files are visible in Visual Studio. E.g. |
||||||
|
|
||||||
For a "dotnet SDK" project, you have more control of some frequently used options. |
```xml |
||||||
**You may need to open and close Visual Studio** for this form to appear in the |
<ItemGroup> |
||||||
properties window after adding a reference to Grpc.Tools package (we do not know |
<Protobuf Include="..\Proto\aggregate.proto" GrpcServices="Client" Link="Protos\aggregate.proto"/> |
||||||
whether this is a bug or by design, but it looks like a bug): |
<Protobuf Include="..\Proto\greet.proto" GrpcServices="None" Link="Protos\greet.proto"/> |
||||||
|
<Protobuf Include="..\Proto\count.proto" GrpcServices="None" Link="Protos\count.proto"/> |
||||||
|
</ItemGroup> |
||||||
|
``` |
||||||
|
|
||||||
![Properties in an SDK project](doc/integration.md-fig.2-sdk.png) |
For more examples see the example project files in GitHub: https://github.com/grpc/grpc-dotnet/tree/master/examples |
||||||
|
|
||||||
You can also change options of multiple files at once by selecting them in the |
# Reference |
||||||
Project Explorer together. |
|
||||||
|
|
||||||
For a "classic" project, you can only add .proto files with all options set to |
## Protobuf item metadata reference |
||||||
default (if you find it necessary to modify these options, then hand-edit the |
|
||||||
.csproj file). Click on the "show all files" button, add files to project, then |
|
||||||
change file type of the .proto files to "Protobuf" in the Properties window |
|
||||||
drop-down. This menu item will appear after you import the Grpc.Tools package: |
|
||||||
|
|
||||||
![Properties in a classic project](doc/integration.md-fig.1-classic.png) |
The following metadata are recognized on the `<Protobuf>` items. |
||||||
|
|
||||||
See the Reference section at end of this file for options that can be set |
| Name | Default | Value | Synopsis | |
||||||
per-file by modifying the source .csproj directly. |
|----------------|-----------|----------------------|----------------------------------| |
||||||
|
| Access | `public` | `public`, `internal` | Generated class access | |
||||||
|
| AdditionalProtocArguments | | arbitrary cmdline arguments | Extra command line flags passed to `protoc` command. To specify multiple arguments use semi-colons (;) to separate them. See example below | |
||||||
|
| ProtoCompile | `true` | `true`, `false` | If `false`, don't invoke `protoc` to generate code. | |
||||||
|
| ProtoRoot | See notes | A directory | Common root for set of files | |
||||||
|
| CompileOutputs | `true` | `true`, `false` | If `false`, C# code will be generated, but it won't be included in the C# build. | |
||||||
|
| OutputDir | See notes | A directory | Directory for generated C# files with protobuf messages | |
||||||
|
| OutputOptions | | arbitrary options | Extra options passed to C# codegen as `--csharp_opt=opt1,opt2` | |
||||||
|
| GrpcOutputDir | See notes | A directory | Directory for generated gRPC stubs | |
||||||
|
| GrpcOutputOptions | | arbitrary options | Extra options passed to gRPC codegen as `--grpc_opt=opt1,opt2` | |
||||||
|
| GrpcServices | `Both` | `None`, `Client`, `Server`, `Both` | Generated gRPC stubs | |
||||||
|
| AdditionalImportDirs | See notes | Directories | Specify additional directories in which to search for imports `.proto` files | |
||||||
|
|
||||||
#### My .proto files are in a directory outside the project |
__Notes__ |
||||||
|
|
||||||
Refer to the example files |
* __ProtoRoot__ |
||||||
[RouteGuide.csproj](../../examples/csharp/RouteGuide/RouteGuide/RouteGuide.csproj#L58-L60) |
For files _inside_ the project directory or its subdirectories, `ProtoRoot` is set by default to the |
||||||
and [Greeter.csproj](../../examples/csharp/Helloworld/Greeter/Greeter.csproj#L11) |
project directory. |
||||||
in this repository. For the files to show up in Visual Studio properly, add a |
|
||||||
`Link` attribute with just a filename to the `<Protobuf>` item. This will be the |
|
||||||
display name of the file. In the `Include` attribute, specify the complete path |
|
||||||
to file. A relative path is based off the project directory. |
|
||||||
|
|
||||||
Or, if using Visual Studio, add files _as links_ from outside directory. In the |
For files _outside_ of the project directory, the value |
||||||
Add Files dialog, there is a little [down arrow near the Open |
is set to the file's containing directory name, individually per file. If you |
||||||
button](https://stackoverflow.com/a/9770061). Click on it, and choose "Add as |
include a subtree of `.proto` files that lies outside of the project directory, you |
||||||
link". If you do not select this option, Visual Studio will copy files to the |
need to set `ProtoRoot`. There is an example of this below. The path in |
||||||
project directory instead. |
this variable is relative to the project directory. |
||||||
|
|
||||||
Alternatively, you can also specify `AdditionalImportDirs` and provide a list of directories to search for imported .proto files. The directories are searched in the order given. |
* __OutputDir__ |
||||||
|
The default value is the value of the property |
||||||
|
`Protobuf_OutputPath`. This property, in turn, unless you set it in your |
||||||
|
project, will be set to the value of the standard MSBuild property |
||||||
|
`IntermediateOutputPath`, which points to the location of compilation object |
||||||
|
outputs, such as `"obj/Release/netstandard1.5/"`. The path in this property is |
||||||
|
considered relative to the project directory. |
||||||
|
|
||||||
Eg. |
* __GrpcOutputDir__ |
||||||
|
Unless explicitly set, will follow `OutputDir` for any given file. |
||||||
|
|
||||||
```xml |
* __Access__ |
||||||
<Protobuf Include="protos/*.proto" ProtoRoot="protos" |
Sets generated class access on _both_ generated message and gRPC stub classes. |
||||||
AdditionalImportDirs="/folder/ouside/project/protos/myapis/;/another/folder/" ... /> |
|
||||||
``` |
|
||||||
|
|
||||||
#### My .proto files have same filename in different folders |
* __AdditionalProtocArguments__ |
||||||
|
Pass additional commandline arguments to the `protoc` command being invoked. |
||||||
|
Normally this option should not be used, but it exists for scenarios when you need to pass |
||||||
|
otherwise unsupported (e.g. experimental) flags to protocol buffer compiler. |
||||||
|
|
||||||
Starting from Grpc.Tools version 2.31, protocol buffers compilation preserves original folder structure for generated files. Eg. |
* __OutputOptions__ |
||||||
|
Pass additional C# code generation options to `protoc` in the form `--csharp_opt=opt1,opt2`. See [C#-specific options](https://protobuf.dev/reference/csharp/csharp-generated/#compiler_options) for possible values. |
||||||
|
|
||||||
- `../ProjectFolder/Protos/v2/http.proto` |
* __GrpcOutputOptions__ |
||||||
- `../ProjectFolder/Protos/v3/http.proto` |
Pass additional options to the `grpc_csharp_plugin` in form of the `--grpc_opt` flag. |
||||||
|
Normally this option should not be used as its values are already controlled by `Access` |
||||||
|
and `GrpcServices` metadata, but it might be useful in situations where you want |
||||||
|
to explicitly pass some otherwise unsupported (e.g. experimental) options to the |
||||||
|
`grpc_csharp_plugin`. |
||||||
|
|
||||||
Will result in: |
* __AdditionalImportDirs__ |
||||||
|
Specify additional directories in which to search for imports in `.proto` files. The directories are searched in the order given. You may specify directories _outside_ of the |
||||||
|
project directory. The directories are passed to the `protoc` code generator via the `-I/--proto_path` option |
||||||
|
together with `Protobuf_StandardImportsPath` and `ProtoRoot` directories. |
||||||
|
|
||||||
- `../ProjectFolder/obj/CONFIGURATION/FRAMEWORK/Protos/v2/Greet.cs` |
__Specifying multiple values in properties__ |
||||||
- `../ProjectFolder/obj/CONFIGURATION/FRAMEWORK/Protos/v2/GreetGrpc.cs` |
|
||||||
- `../ProjectFolder/obj/CONFIGURATION/FRAMEWORK/Protos/v3/Greet.cs` |
|
||||||
- `../ProjectFolder/obj/CONFIGURATION/FRAMEWORK/Protos/v3/GreetGrpc.cs` |
|
||||||
|
|
||||||
This feature resolves problems we have faced in large projects. Moreover, There is now also a project-wide new option Protobuf_ProtoRoot to define the fallback ProtoRoot. If the ProtoRoot is set, this also reduces the amount of problems that lead to duplicates. Eg. |
Some properties allow you to specify multiple values in a list. The items in a list need to |
||||||
|
be separated by semi-colons (;). This is the syntax that MsBuild uses for lists. |
||||||
|
|
||||||
```xml |
The properties that can have lists of items are: `OutputOptions`, `AdditionalProtocArguments`, |
||||||
<ItemGroup> |
`GrpcOutputOptions`, `AdditionalImportDirs` |
||||||
<Protobuf Include="Protos\v2\greet.proto" ProtoRoot="Protos" /> |
|
||||||
</ItemGroup> |
|
||||||
``` |
|
||||||
|
|
||||||
Before Grpc.Tools version 2.31 all .proto files were compiled into `obj` directory, flattening relative paths. For proto files with duplicated names it cause following errors `NETSDK1022 Duplicate 'Compile' items were included. [...]` or `MSB3105 [...] Duplicate items are not supported by the "Sources" parameter`. The workaround for this problem was introducing relative paths in your `obj` folder, by manipulating output path. Eg. |
Example: to specify two additional arguments: `--plugin=protoc-gen-myplugin=D:\myplugin.exe --myplugin_out=.` |
||||||
|
|
||||||
```xml |
```xml |
||||||
<ItemGroup> |
<ItemGroup> |
||||||
<Protobuf Include="Protos/v2/http.proto" OutputDir="$(Protobuf_OutputPath)%(RelativeDir)" /> |
<Protobuf Include="proto_root/**/*.proto" ProtoRoot="proto_root" |
||||||
<Protobuf Include="Protos/v3/http.proto" OutputDir="$(Protobuf_OutputPath)%(RelativeDir)" /> |
OutputDir="%(RelativeDir)" CompileOutputs="false" |
||||||
|
AdditionalProtocArguments="--plugin=protoc-gen-myplugin=D:\myplugin.exe;--myplugin_out=." /> |
||||||
</ItemGroup> |
</ItemGroup> |
||||||
``` |
``` |
||||||
|
|
||||||
__Note, this was a workaround approach, we recommend updating Grpc.Tools to the latest version.__ |
## `grpc_csharp_plugin` command line options |
||||||
|
|
||||||
### I just want to generate proto and gRPC C# sources from my .proto files (no C# compile) |
Under the hood, the `Grpc.Tools` build integration invokes the `protoc` and `grpc_csharp_plugin` binaries |
||||||
|
to perform code generation. Here is an overview of the available `grpc_csharp_plugin` options: |
||||||
|
|
||||||
Suppose you want to place generated files right beside each respective source |
| Name | Default | Synopsis | |
||||||
.proto file. Create a .csproj library file in the common root of your .proto |
|---------------- |-----------|----------------------------------------------------------| |
||||||
tree, and add a reference to Grpc.Tools package (this works in Windows too, `$` |
| no_client | off | Don't generate the client stub | |
||||||
below stands for a command prompt in either platform): |
| no_server | off | Don't generate the server-side stub | |
||||||
|
| internal_access | off | Generate classes with "internal" visibility | |
||||||
|
|
||||||
|
Note that the protocol buffer compiler has a special commandline syntax for plugin options. |
||||||
|
Example: |
||||||
``` |
``` |
||||||
/myproject/myprotofiles$ dotnet new classlib |
protoc --plugin=protoc-gen-grpc=grpc_csharp_plugin --csharp_out=OUT_DIR \ |
||||||
. . . |
--grpc_out=OUT_DIR --grpc_opt=lite_client,no_server \ |
||||||
Restoring packages for /myproject/myprotofiles/myprotofiles.csproj... |
-I INCLUDE_DIR foo.proto |
||||||
. . . |
|
||||||
/myproject/myprotofiles$ rm *.cs <-- remove all *.cs files from template; |
|
||||||
C:\myproject\myprotofiles> del *.cs /y <-- on Windows, use the del command instead. |
|
||||||
/myproject/myprotofiles$ dotnet add package Grpc.Tools |
|
||||||
``` |
``` |
||||||
|
## Environment Variables |
||||||
(the latter command also accepts an optional `--version X.Y` switch for a |
|
||||||
specific version of package, should you need one). Next open the generated |
Environment variables can be set to change the behavior of `Grpc.Tools` - setting the CPU architecture or operating system, or using custom built protocol buffers compiler and gRPC plugin. |
||||||
.csproj file in a text editor. |
|
||||||
|
| Name | Synopsis | |
||||||
Since you are not building a package, you may not worry about adding |
|---------------------|-------------------------------------------------------------------------------| |
||||||
`PrivateAssets="All"` attribute, but it will not hurt, in case you are |
|`PROTOBUF_TOOLS_OS` | Operating system version of the tools to use: `linux`, `macosx`, or `windows` | |
||||||
repurposing the project at some time later. The important part is (1) tell the |
|`PROTOBUF_TOOLS_CPU` | CPU architecture version of the tools to use: `x86`, `x64`, or `arm64` | |
||||||
gRPC tools to select the whole directory of files; (2) order placement of each |
|`PROTOBUF_PROTOC` | Full path to the protocol buffers compiler | |
||||||
output besides its source, and (3) not compile the generated .cs files. Add the |
|`GRPC_PROTOC_PLUGIN` | Full path to the grpc_csharp_plugin | |
||||||
following stanza under the `<Project>` xml node: |
|
||||||
|
For example, to use a custom built protoc compiler and grpc_csharp_plugin: |
||||||
```xml |
```bash |
||||||
<ItemGroup> |
export PROTOBUF_PROTOC=$my_custom_build/protoc |
||||||
<Protobuf Include="**/*.proto" OutputDir="%(RelativeDir)" CompileOutputs="false" /> |
export GRPC_PROTOC_PLUGIN=$my_custom_build/grpc_csharp_plugin |
||||||
</ItemGroup> |
dotnet build myproject.csproj |
||||||
``` |
``` |
||||||
|
|
||||||
The `Include` tells the build system to recursively examine project directory |
## MSBuild Properties |
||||||
and its subdirectories (`**`) include all files matching the wildcard `*.proto`. |
|
||||||
You can instead selectively include your files or selectively exclude files from |
|
||||||
the glob pattern; [MSBuild documentation explains |
|
||||||
that](https://docs.microsoft.com/visualstudio/msbuild/msbuild-items). The |
|
||||||
`OutputDir="%(RelativeDir)"` orders the output directory for each .cs file be |
|
||||||
same as the corresponding .proto directory. Finally, `CompileOutputs="false"` |
|
||||||
prevents compiling the generated files into an assembly. |
|
||||||
|
|
||||||
Note that an empty assembly is still generated, but you should ignore it. As |
You can set some Properties in your project file or on the MSBuild command line. The |
||||||
with any build system, it is used to detect out-of-date dependencies and |
following properties change the behavior of `Grpc.Tools`: |
||||||
recompile them. |
|
||||||
|
|
||||||
#### I am getting a warning about a missing expected file! |
| Name | Synopsis | |
||||||
|
|---------------------|-------------------------------------------------------------------------------| |
||||||
|
| `Protobuf_ToolsOs` | Same as `PROTOBUF_TOOLS_OS` environment variable | |
||||||
|
| `Protobuf_ToolsCpu` | Same as `PROTOBUF_TOOLS_CPU` environment variable | |
||||||
|
| `Protobuf_ProtocFullPath` | Same as `PROTOBUF_PROTOC` environment variable | |
||||||
|
| `gRPC_PluginFullPath` | Same as `GRPC_PROTOC_PLUGIN` environment variable | |
||||||
|
| `Protobuf_NoWarnMissingExpected` | Default: `false`. If `true` then no warnings are given if expected files not generated. See example below for an explanation. | |
||||||
|
| `Protobuf_OutputPath`| Default: `IntermediateOutputPath` - ususally the `obj` directory. Sets the default value for `OutputDir` on `<Protobuf>` items.| |
||||||
|
| `EnableDefaultProtobufItems` | Default: `false`. If `true` then `.proto` files under the project are automatically included without the need to specify any `<Protobuf>` items. | |
||||||
|
| `Protobuf_StandardImportsPath` | The path for protobuf's [well known types](https://protobuf.dev/reference/protobuf/google.protobuf/) included in the NuGet package. It is automcatically passed to `protoc` via the `-I/--proto_path` option. | |
||||||
|
|
||||||
When we are preparing compile, there is no way to know whether a given proto |
# Scenarios and Examples |
||||||
file will produce a *Grpc.cs output or not. If the proto file has a `service` |
|
||||||
clause, it will; otherwise, it won't, but the build script cannot know that in |
|
||||||
advance. When we are treating generated .cs files as temporary, this is ok, but |
|
||||||
when generating them for you, creating empty files is probably not. You need to |
|
||||||
tell the compiler which files should be compiled with gRPC services, and which |
|
||||||
only contain protobuffer message definitions. |
|
||||||
|
|
||||||
One option is just ignore the warning. Another is quench it by setting the |
For other examples see also the `.csproj` files in the examples in GitHub: |
||||||
property `Protobuf_NoWarnMissingExpected` to `true`: |
* [grpc-dotnet examples](https://github.com/grpc/grpc-dotnet/tree/master/examples) |
||||||
|
* [`Grpc.Core` examples](https://github.com/grpc/grpc/tree/v1.46.x/examples/csharp) |
||||||
|
|
||||||
```xml |
Quick links to the examples below: |
||||||
<PropertyGroup> |
|
||||||
<Protobuf_NoWarnMissingExpected>true</Protobuf_NoWarnMissingExpected> |
|
||||||
</PropertyGroup> |
|
||||||
``` |
|
||||||
|
|
||||||
For a small to medium projects this is sufficient. But because of a missing |
* [ProtoRoot - Common root for one or more `.proto` files](#ProtoRoot) |
||||||
output dependency, the corresponding .proto file will be recompiled on every |
* [AdditionalImportDirs - Setting location of imported `.proto` files](#AdditionalImportDirs) |
||||||
build. If your project is large, or if other large builds depend on generated |
* [GrpcServices - Generating gRPC services and protocol buffers messages](#grpcservices) |
||||||
files, and are also needlessly recompiled, you'll want to prevent these rebuilds |
* [Automatically including `.proto` files](#autoinclude) |
||||||
when files have not in fact changed, as follows: |
* [Generate proto and gRPC C# sources from .proto files (no C# compile)](#nocompile) |
||||||
|
* [Visual Studio: setting per-file `.proto` file options](#visualstudio) |
||||||
|
* [Bypassing Grpc.Tools to run the protocol buffers compiler explicitly](#compiler) |
||||||
|
|
||||||
##### Explicitly tell protoc for which files it should use the gRPC plugin |
--- |
||||||
|
## <a name="ProtoRoot"></a>ProtoRoot - Common root for one or more `.proto` files |
||||||
|
|
||||||
You need to set the `Protobuf` item property `GrpcServices` to `None` for those |
`ProtoRoot` specifies a common directory that is an ancestor for a set of `.proto` files. |
||||||
.proto inputs which do not have a `service` declared (or, optionally, those |
|
||||||
which do but you do not want a service/client stub for). The default value for |
|
||||||
the `GrpcServices` is `Both` (both client and server stub are generated). This |
|
||||||
is easy enough to do with glob patterns if your files are laid out in |
|
||||||
directories according to their service use, for example: |
|
||||||
|
|
||||||
```xml |
It has two purposes: |
||||||
<ItemGroup> |
* working out relative directories to preserve the structure when generating `.cs` files |
||||||
<Protobuf Include="**/*.proto" OutputDir="%(RelativeDir)" |
* adding a directory to be searched for imported `.proto` files |
||||||
CompileOutputs="false" GrpcServices="None" /> |
|
||||||
<Protobuf Update="**/hello/*.proto;**/bye/*.proto" GrpcServices="Both" /> |
|
||||||
</ItemGroup> |
|
||||||
``` |
|
||||||
|
|
||||||
In this sample, all .proto files are compiled with `GrpcServices="None"`, except |
These are explained in an example below. |
||||||
for .proto files in subdirectories on any tree level named `hello/` and `bye`, |
|
||||||
which will take `GrpcServices="Both"` Note the use of the `Update` attribute |
|
||||||
instead of `Include`. If you write `Include` by mistake, the files will be added |
|
||||||
to compile *twice*, once with, and once without GrpcServices. Pay attention not |
|
||||||
to do that! |
|
||||||
|
|
||||||
Another example would be the use of globbing if your service .proto files are |
For `.proto` files under the project directory `ProtoRoot` is by default set to `.`. |
||||||
named according to a pattern, for example `*_services.proto`. In this case, The |
It can also be explicitly set. |
||||||
`Update` attribute can be written as `Update="**/*_service.proto"`, to set the |
|
||||||
attribute `GrpcServices="Both"` only on these files. |
|
||||||
|
|
||||||
But what if no patterns work, and you cannot sort a large set of .proto file |
For `.proto` files outside of the project the value is set to the file's containing directory name. |
||||||
into those containing a service and those not? As a last resort, |
If you include a subtree of `.proto` files then you must set `ProtoRoot` to give the |
||||||
|
parent of the directory tree. |
||||||
|
|
||||||
##### Force creating empty .cs files for missing outputs. |
In either case if you are importing a `.proto` file from within another file then you should set |
||||||
|
`ProtoRoot` so that the import paths can be found. (See also `AdditionalImportDirs` below.) |
||||||
|
|
||||||
Naturally, this results in a dirtier compiler output tree, but you may clean it |
Generated files in the output directory will have the same directory structure as the |
||||||
using other ways (for example, by not copying zero-length .cs files to their |
`.proto` files under `ProtoRoot`. |
||||||
final destination). Remember, though, that the files are still important to keep |
|
||||||
in their output locations to prevent needless recompilation. You may force |
|
||||||
generating empty files by setting the property `Protobuf_TouchMissingExpected` |
|
||||||
to `true`: |
|
||||||
|
|
||||||
|
By default the output directory for generated files is `obj\CONFIGURATION\FRAMEWORK\` (e.g. `obj\Debug\net6.0\`) unless `OutputDir` or `GrpcOutputDir` are specified. |
||||||
|
### Example use of `ProtoRoot` |
||||||
|
Specifying: |
||||||
```xml |
```xml |
||||||
<PropertyGroup> |
<Protobuf Include="Protos\Services\**\*.proto" |
||||||
<Protobuf_TouchMissingExpected>true</Protobuf_TouchMissingExpected> |
ProtoRoot="Protos" /> |
||||||
</PropertyGroup> |
<Protobuf Include="Protos\Messages\**\*.proto" |
||||||
|
ProtoRoot="Protos" |
||||||
|
GrpcServices="None" /> |
||||||
|
<Protobuf Include="..\OutsideProjectProtos\**\*.proto" |
||||||
|
ProtoRoot="..\OutsideProjectProtos" /> |
||||||
``` |
``` |
||||||
|
for files: |
||||||
|
``` |
||||||
|
ProjectFolder\Protos\Services\v1\hello.proto |
||||||
|
ProjectFolder\Protos\Services\v2\hello.proto |
||||||
|
ProjectFolder\Protos\Messages\v1\message.proto |
||||||
|
..\OutsideProjectProtos\MyApi\alpha.proto |
||||||
|
..\OutsideProjectProtos\MyApi\beta.proto |
||||||
|
``` |
||||||
|
will generate files: |
||||||
|
``` |
||||||
|
ProjectFolder\obj\Debug\net6.0\Services\v1\Hello.cs |
||||||
|
ProjectFolder\obj\Debug\net6.0\Services\v1\HelloGrpc.cs |
||||||
|
ProjectFolder\obj\Debug\net6.0\Services\v2\Hello.cs |
||||||
|
ProjectFolder\obj\Debug\net6.0\Services\v2\HelloGrpc.cs |
||||||
|
ProjectFolder\obj\Debug\net6.0\Messages\v1\Message.cs |
||||||
|
ProjectFolder\obj\Debug\net6.0\MyApi\Alpha.cs |
||||||
|
ProjectFolder\obj\Debug\net6.0\MyApi\AlphaGrpc.cs |
||||||
|
ProjectFolder\obj\Debug\net6.0\MyApi\Beta.cs |
||||||
|
ProjectFolder\obj\Debug\net6.0\MyApi\BetaGrpc.cs |
||||||
|
|
||||||
#### But I do not use gRPC at all, I need only protobuffer messages compiled |
|
||||||
|
|
||||||
Set `GrpcServices="None"` on all proto files: |
|
||||||
|
|
||||||
```xml |
|
||||||
<ItemGroup> |
|
||||||
<Protobuf Include="**/*.proto" OutputDir="%(RelativeDir)" |
|
||||||
CompileOutputs="false" GrpcServices="None" /> |
|
||||||
</ItemGroup> |
|
||||||
``` |
``` |
||||||
|
Things to notes: |
||||||
|
* the directory structures under `ProjectFolder\Protos\` and `..\OutsideProjectProtos\` are mirrored in the output directory. |
||||||
|
* the import search paths passed to `protoc` via `-I/--proto_path` option will include |
||||||
|
`ProjectFolder\Protos` and `..\OutsideProjectProtos` |
||||||
|
--- |
||||||
|
## <a name="AdditionalImportDirs"></a>AdditionalImportDirs - Setting location of imported `.proto` files |
||||||
|
|
||||||
#### That's good so far, but I do not want the `bin` and `obj` directories in my tree |
In addition to specifying `ProtoRoot` other import directories can be specified for |
||||||
|
directories to search when importing `.proto` files by specifying `AdditionalImportDirs` |
||||||
|
and provide a list of directories. The directories are searched in the order given. |
||||||
|
|
||||||
You may create the project in a subdirectory of the root of your files, such as, |
You would use this when you want to import `.proto` files that you don't need to |
||||||
for example, `.build`. In this case, you want to refer to the proto files |
separately compile as they are only used in import statements. E.g.: |
||||||
relative to that `.build/` directory as |
|
||||||
|
|
||||||
```xml |
```xml |
||||||
<ItemGroup> |
<Protobuf Include="protos/*.proto" |
||||||
<Protobuf Include="../**/*.proto" ProtoRoot=".." |
ProtoRoot="protos" |
||||||
OutputDir="%(RelativeDir)" CompileOutputs="false" /> |
AdditionalImportDirs="/folder/protos/mytypes/;/another/folder/" |
||||||
</ItemGroup> |
... /> |
||||||
``` |
``` |
||||||
|
|
||||||
Pay attention to the `ProtoRoot` property. It needs to be set to the directory |
Note: The path for protobuf's [well known types](https://protobuf.dev/reference/protobuf/google.protobuf/) is automatically included. E.g. the `import` below will work without having to explicity specifying the path in `AdditionalImportDirs`: |
||||||
where `import` declarations in the .proto files are looking for files, since the |
```protobuf |
||||||
project root is no longer the same as the proto root. |
import "google/protobuf/wrappers.proto"; |
||||||
|
``` |
||||||
Alternatively, you may place the project in a directory *above* your proto root, |
--- |
||||||
and refer to the files with a subdirectory name: |
## <a name="grpcservices"></a>GrpcServices - Generating gRPC services and protocol buffers messages |
||||||
|
The protocol buffers files (`.proto` files) define both the service interface and the |
||||||
|
structure of the payload messages. |
||||||
|
|
||||||
|
Two `.cs` file can be generated from a `.proto` file. For example, if the `.proto` file |
||||||
|
is `myfile.proto` then the two possible files are: |
||||||
|
* `Myfile.cs` - contains the generated code for protocol buffers messages |
||||||
|
* `MyfileGrpc.cs` - contains the generated code for gRPC client and/or server |
||||||
|
|
||||||
|
When a `.proto` file contains service definitions the protocol buffers compiler calls |
||||||
|
the gRPC plugin to generate gRPC client and/or server stub code. Whether or not the `*Grpc.cs` file |
||||||
|
is generated and what it contains is controlled by the `GrpcServices` metadata |
||||||
|
on the `<Protobuf>` item. |
||||||
|
|
||||||
|
* `GrpcServices="Both"` (the default) - `Myfile.cs` and `MyfileGrpc.cs` generated |
||||||
|
* `GrpcServices="None"` - just `Myfile.cs` generated |
||||||
|
* `GrpcServices="Client"` - `Myfile.cs` and `MyfileGrpc.cs` (just client code) |
||||||
|
* `GrpcServices="Server"` - `Myfile.cs` and `MyfileGrpc.cs` (just server code) |
||||||
|
|
||||||
|
However when a `.proto` **does not file contains any service definitions** but only contains |
||||||
|
message definitions then an empty (zero length) `MyfileGrpc.cs` may still be created |
||||||
|
by `Grpc.Tools` unless the `.proto` file is specified with `GrpcServices="None"` in the project file. |
||||||
|
|
||||||
|
This is because `Grpc.Tools` has no way of knowing in advanced of running the protocol buffers |
||||||
|
compiler whether a `.proto` file has a service clause. It creates the empty files as a marker |
||||||
|
for incremental builds so that the `.proto` files are not unnecessarily recompiled. Empty files |
||||||
|
are not a problem on a small project but you may wish to avoid them on a larger project. |
||||||
|
|
||||||
|
Therefore it is better to explicitly mark files with the correct `GrpcServices` metadata if you can. For |
||||||
|
example: |
||||||
|
|
||||||
```xml |
```xml |
||||||
<ItemGroup> |
<ItemGroup> |
||||||
<Protobuf Include="proto_root/**/*.proto" ProtoRoot="proto_root" |
<Protobuf Include="**/*.proto" GrpcServices="None" /> |
||||||
OutputDir="%(RelativeDir)" CompileOutputs="false" /> |
<Protobuf Update="**/hello/*.proto;**/bye/*.proto" GrpcServices="Both" /> |
||||||
</ItemGroup> |
</ItemGroup> |
||||||
``` |
``` |
||||||
|
In the above example all `.proto` files are compiled with `GrpcServices="None"`, except for `.proto` |
||||||
|
files in subdirectories on any tree level named `hello` and `bye`, which will take |
||||||
|
`GrpcServices="Both"`. Note the use of the `Update` attribute instead of `Include` - otherwise |
||||||
|
the files would be added twice. |
||||||
|
|
||||||
|
Another example would be the use of globbing if your service `.proto` files are named according |
||||||
|
to a pattern, for example `*_services.proto`. In this case the `Update` attribute can be written |
||||||
|
as `Update="**/*_service.proto"` to set the attribute `GrpcServices="Both"` only on these files. |
||||||
|
|
||||||
|
### Seeing a warning about a missing expected file |
||||||
|
|
||||||
|
You will see the warning message: |
||||||
|
``` |
||||||
|
Some expected protoc outputs were not generated |
||||||
|
``` |
||||||
|
if all these are true: |
||||||
|
* the location for the generated files is configured to a directory outside of the project, e.g. `OutputDir="..\outside-project\"` |
||||||
|
* `*Grpc.cs` files have not been created because the `.proto` file does not contain a |
||||||
|
service definintion |
||||||
|
* you have not specified `GrpcServices="None"` |
||||||
|
|
||||||
|
This is because `Grpc.Tools` only creates empty `*Grpc.cs` files in directories |
||||||
|
within the project (such as the intermediate `obj` directory). Empty files are not created |
||||||
|
outside of the project directory so as not to pollute non-project directories. |
||||||
|
|
||||||
|
This warning can be suppressed by setting the MSBuild property: |
||||||
|
```xml |
||||||
|
<PropertyGroup> |
||||||
|
<Protobuf_NoWarnMissingExpected>true</Protobuf_NoWarnMissingExpected> |
||||||
|
</PropertyGroup> |
||||||
|
``` |
||||||
|
however it is better to set `GrpcServices="None"` on the `.proto` files affected to avoid |
||||||
|
unnecessary rebuilds. |
||||||
|
|
||||||
### Alas, this all is nice, but my scenario is more complex, -OR- |
|
||||||
### I'll investigate that when I have time. I just want to run protoc as I did before. |
|
||||||
|
|
||||||
One option is examine our [.targets and .props files](Grpc.Tools/build/) and see |
--- |
||||||
if you can create your own build sequence from the provided targets so that it |
## <a name="autoinclude"></a>Automatically including `.proto` files |
||||||
fits your needs. Also please open an issue (and tag @kkm000 in it!) with your |
|
||||||
scenario. We'll try to support it if it appears general enough. |
|
||||||
|
|
||||||
But if you just want to run `protoc` using MsBuild `<Exec>` task, as you |
For SDK projects it is possible to automatically include `.proto` files found in the project |
||||||
probably did before the version 1.17 of Grpc.Tools, we have a few build |
directory or sub-directories, without having to specify them with a `<Protobuf>` item. |
||||||
variables that point to resolved names of tools and common protoc imports. |
To do this the property `EnableDefaultProtobufItems` has be set to `true` in the project file or on the MSBuild command line. |
||||||
You'll have to roll your own dependency checking (or go with a full |
|
||||||
recompilation each time, if that works for you), but at the very least each |
|
||||||
version of the Tools package will point to the correct location of the files, |
|
||||||
and resolve the compiler and plugin executables appropriate for the host system. |
|
||||||
These property variables are: |
|
||||||
|
|
||||||
* `Protobuf_ProtocFullPath` points to the full path and filename of protoc executable, e. g., |
It is recommended that you do not rely on automatic inclusion of `.proto` files except for |
||||||
"C:\Users\kkm\.nuget\packages\grpc.tools\1.17.0\build\native\bin\windows\protoc.exe". |
the simplest of projects since it does not allow you to control other settings such as |
||||||
|
`GrpcServices`. |
||||||
|
|
||||||
* `gRPC_PluginFullPath` points to the full path and filename of gRPC plugin, such as |
By default `EnableDefaultProtobufItems` is not set and `<Protobuf>` items must be included |
||||||
"C:\Users\kkm\.nuget\packages\grpc.tools\1.17.0\build\native\bin\windows\grpc_csharp_plugin.exe" |
in the project for the `.proto` files to be compiled. |
||||||
|
|
||||||
* `Protobuf_StandardImportsPath` points to the standard proto import directory, for example, |
--- |
||||||
"C:\Users\kkm\.nuget\packages\grpc.tools\1.17.0\build\native\include". This is |
|
||||||
the directory where a declaration such as `import "google/protobuf/wrappers.proto";` |
|
||||||
in a proto file would find its target. |
|
||||||
|
|
||||||
Use MSBuild property expansion syntax `$(VariableName)` in your protoc command |
## <a name="nocompile"></a>Generate proto and gRPC C# sources from .proto files (no C# compile) |
||||||
line to substitute these variables, for instance, |
|
||||||
|
|
||||||
```xml |
If you just want to generate the C# sources from `.proto` files without compiling the C# files |
||||||
<Target Name="MyProtoCompile"> |
(e.g. for use in other projects) then you can do something similar to this to a `.csproj` file: |
||||||
<PropertyGroup> |
```xml |
||||||
<ProtoCCommand>$(Protobuf_ProtocFullPath) --plugin=protoc-gen-grpc=$(gRPC_PluginFullPath) -I $(Protobuf_StandardImportsPath) ....rest of your command.... </ProtoCCommand> |
<ItemGroup> |
||||||
</PropertyGroup> |
<Protobuf Include="**/*.proto" |
||||||
<Message Importance="high" Text="$(ProtoCCommand)" /> |
OutputDir="%(RelativeDir)" CompileOutputs="false" /> |
||||||
<Exec Command="$(ProtoCCommand)" /> |
</ItemGroup> |
||||||
</Target> |
|
||||||
``` |
``` |
||||||
|
|
||||||
Also make sure *not* to include any file names to the `Protobuf` item |
* `Include` tells the build system to recursively examine project directory and its |
||||||
collection, otherwise they will be compiled by default. If, by any chance, you |
subdirectories (**) include all files matching the wildcard `*.proto`. |
||||||
used that name for your build scripting, you must rename it. |
* `OutputDir="%(RelativeDir)"` makes the output directory for each `.cs` file to be |
||||||
|
same as the corresponding `.proto` directory. |
||||||
|
* `CompileOutputs="false"` prevents compiling the generated files into an assembly. |
||||||
|
|
||||||
### What about C++ projects? |
Note that an empty assembly is still generated which can be ignored. |
||||||
|
|
||||||
This is in the works. Currently, the same variables as above are set to point to |
NOTE: To start with an empty project to add your `.proto` files to you can do the following |
||||||
the protoc binary, C++ gRPC plugin and the standard imports, but nothing else. |
at a command prompt: |
||||||
Do not use the `Protobuf` item collection name so that your project remains |
```bash |
||||||
future-proof. We'll use it for C++ projects too. |
dotnet new classlib |
||||||
|
rm *.cs # remove .cs files - for Windows the command is: del *.cs /y |
||||||
|
dotnet add package Grpc.Tools |
||||||
|
``` |
||||||
|
|
||||||
Reference |
--- |
||||||
--------- |
## <a name="visualstudio"></a>Visual Studio: setting per-file `.proto` file options |
||||||
|
|
||||||
### Protobuf item metadata reference |
In Visual Studio it is possible to set some frequently used per-file options on `.proto` files |
||||||
|
without editing the `.csproj` file directly. However editing the `.csproj` gives you more |
||||||
|
flexibilty. |
||||||
|
|
||||||
The following metadata are recognized on the `<Protobuf>` items. |
### "dotnet SDK" projects |
||||||
|
|
||||||
| Name | Default | Value | Synopsis | |
For a "dotnet SDK" project, you have more control of some frequently used options. |
||||||
|----------------|-----------|----------------------|----------------------------------| |
**You may need to open and close Visual Studio** for this form to appear in the |
||||||
| Access | `public` | `public`, `internal` | Generated class access | |
properties window after adding a reference to `Grpc.Tools` package: |
||||||
| AdditionalProtocArguments | | arbitrary cmdline arguments | Extra command line flags passed to `protoc` command. To specify multiple arguments use semi-colons (;) to separate them. See example below | |
|
||||||
| ProtoCompile | `true` | `true`, `false` | Pass files to protoc? | |
|
||||||
| ProtoRoot | See notes | A directory | Common root for set of files | |
|
||||||
| CompileOutputs | `true` | `true`, `false` | C#-compile generated files? | |
|
||||||
| OutputDir | See notes | A directory | Directory for generated C# files with protobuf messages | |
|
||||||
| OutputOptions | | arbitrary options | Extra options passed to C# codegen as `--csharp_opt=opt1,opt2` | |
|
||||||
| GrpcOutputDir | See notes | A directory | Directory for generated gRPC stubs | |
|
||||||
| GrpcOutputOptions | | arbitrary options | Extra options passed to gRPC codegen as `--grpc_opt=opt1,opt2` | |
|
||||||
| GrpcServices | `both` | `none`, `client`, `server`, `both` | Generated gRPC stubs | |
|
||||||
| AdditionalImportDirs | See notes | Directories | Specify additional directories in which to search for imports .proto files | |
|
||||||
|
|
||||||
__Notes__ |
|
||||||
|
|
||||||
* __ProtoRoot__ |
![Properties in an SDK project](doc/integration.md-fig.2-sdk.png) |
||||||
For files _inside_ the project cone, `ProtoRoot` is set by default to the |
|
||||||
project directory. For every file _outside_ of the project directory, the value |
|
||||||
is set to this file's containing directory name, individually per file. If you |
|
||||||
include a subtree of proto files that lies outside of the project directory, you |
|
||||||
need to set this metadatum. There is an example in this file above. The path in |
|
||||||
this variable is relative to the project directory. |
|
||||||
|
|
||||||
* __OutputDir__ |
You can also change options of multiple files at once by selecting them in the |
||||||
The default value for this metadatum is the value of the property |
Project Explorer together. |
||||||
`Protobuf_OutputPath`. This property, in turn, unless you set it in your |
|
||||||
project, will be set to the value of the standard MSBuild property |
|
||||||
`IntermediateOutputPath`, which points to the location of compilation object |
|
||||||
outputs, such as "obj/Release/netstandard1.5/". The path in this property is |
|
||||||
considered relative to the project directory. |
|
||||||
|
|
||||||
* __GrpcOutputDir__ |
### "classic" projects |
||||||
Unless explicitly set, will follow `OutputDir` for any given file. |
|
||||||
|
|
||||||
* __Access__ |
For a "classic" project, you can only add `.proto` files with all options set to |
||||||
Sets generated class access on _both_ generated message and gRPC stub classes. |
default. Click on the "show all files" button, add files to project, then |
||||||
|
change file type of the `.proto` files to "Protobuf" in the Properties window |
||||||
|
drop-down. This menu item will appear after you import the `Grpc.Tools` package: |
||||||
|
|
||||||
* __AdditionalProtocArguments__ |
![Properties in a classic project](doc/integration.md-fig.1-classic.png) |
||||||
Pass additional commandline arguments to the `protoc` command being invoked. |
|
||||||
Normally this option should not be used, but it exists for scenarios when you need to pass |
|
||||||
otherwise unsupported (e.g. experimental) flags to protocol buffer compiler. |
|
||||||
|
|
||||||
* __GrpcOutputOptions__ |
--- |
||||||
Pass additional options to the `grpc_csharp_plugin` in form of the `--grpc_opt` flag. |
## <a name="compiler"></a>Bypassing Grpc.Tools to run the protocol buffers compiler explicitly |
||||||
Normally this option should not be used as it's values are already controlled by "Access" |
|
||||||
and "GrpcServices" metadata, but it might be useful in situations where you want |
|
||||||
to explicitly pass some otherwise unsupported (e.g. experimental) options to the |
|
||||||
`grpc_csharp_plugin`. |
|
||||||
|
|
||||||
* __AdditionalImportDirs__ |
It is possible to bypass all the build logic in `Grpc.Tools` and run the protocol buffers compiler |
||||||
Specify additional directories in which to search for imports in .proto files. The directories are searched in the order given. You may specify directories _outside_ of the |
explicitly in your project file, and just use the `Grpc.Tools` as a means of getting the compiler. |
||||||
project directory. The directories are passed to the `protoc` code generator via the `-I/--proto_path` option |
**This is not recommended** but there may be situations where you want to do this. |
||||||
together with `Protobuf_StandardImportsPath` and `ProtoRoot` directories. |
|
||||||
|
|
||||||
__Specifying multiple values in properties__ |
You can use the following Properties: |
||||||
|
* `Protobuf_ProtocFullPath` points to the full path and filename of protoc executable, e.g. |
||||||
|
`"...\.nuget\packages\grpc.tools\2.51.0\build\native\bin\windows\protoc.exe"` |
||||||
|
|
||||||
Some properties allow you to specify multiple values in a list. The items in a list need to |
* `gRPC_PluginFullPath` points to the full path and filename of gRPC plugin, e.g. |
||||||
be separated by semi-colons (;). This is the syntax that MsBuild uses for lists. |
`"...\.nuget\packages\grpc.tools\2.51.0\build\native\bin\windows\grpc_csharp_plugin.exe"` |
||||||
|
|
||||||
The properties that can have lists of items are: __OutputOptions__, __AdditionalProtocArguments__, __GrpcOutputOptions__, __AdditionalImportDirs__ |
* `Protobuf_StandardImportsPath` points to the standard proto import directory, e.g. |
||||||
|
`"...\.nuget\packages\grpc.tools\2.51.0\build\native\include"`. This is |
||||||
|
the directory where a declaration such as `import "google/protobuf/wrappers.proto";` |
||||||
|
in a proto file would find its target. |
||||||
|
|
||||||
Example: to specify two additional arguments: ```--plugin=protoc-gen-myplugin=D:\myplugin.exe --myplugin_out=.``` |
then in your project file: |
||||||
|
|
||||||
```xml |
```xml |
||||||
<ItemGroup> |
<Target Name="MyProtoCompile"> |
||||||
<Protobuf Include="proto_root/**/*.proto" ProtoRoot="proto_root" |
<PropertyGroup> |
||||||
OutputDir="%(RelativeDir)" CompileOutputs="false" |
<ProtoCCommand>$(Protobuf_ProtocFullPath) --plugin=protoc-gen-grpc=$(gRPC_PluginFullPath) -I $(Protobuf_StandardImportsPath) ....rest of your command.... </ProtoCCommand> |
||||||
AdditionalProtocArguments="--plugin=protoc-gen-myplugin=D:\myplugin.exe;--myplugin_out=." /> |
</PropertyGroup> |
||||||
</ItemGroup> |
<Message Importance="high" Text="$(ProtoCCommand)" /> |
||||||
|
<Exec Command="$(ProtoCCommand)" /> |
||||||
|
</Target> |
||||||
``` |
``` |
||||||
|
Do not include any `<Protobuf>` items in the project file as that will invoke the `Grpc.Tools` build and your files will be compiled twice. |
||||||
|
|
||||||
`grpc_csharp_plugin` command line options |
--- |
||||||
--------- |
|
||||||
|
|
||||||
Under the hood, the `Grpc.Tools` build integration invokes the `protoc` and `grpc_csharp_plugin` binaries |
## See also |
||||||
to perform code generation. Here is an overview of the available `grpc_csharp_plugin` options: |
|
||||||
|
|
||||||
| Name | Default | Synopsis | |
gRPC project documentation: |
||||||
|---------------- |-----------|----------------------------------------------------------| |
* [gRPC for .NET](https://github.com/grpc/grpc-dotnet) |
||||||
| no_client | off | Don't generate the client stub | |
* [gRPC C# (legacy implementation using gRPC Core library)](https://github.com/grpc/grpc/blob/master/src/csharp/README.md) |
||||||
| no_server | off | Don't generate the server-side stub | |
* [Grpc.Tools internals](Grpc.Tools/implementation_notes.md) - implementation notes for how `Grpc.Tools` works |
||||||
| internal_access | off | Generate classes with "internal" visibility | |
|
||||||
|
|
||||||
Note that the protocol buffer compiler has a special commandline syntax for plugin options. |
Microsoft documentation: |
||||||
Example: |
* [Microsoft: Overview for gRPC on .NET](https://learn.microsoft.com/en-us/aspnet/core/grpc/) |
||||||
``` |
* [Microsoft: C# Tooling support for .proto files](https://learn.microsoft.com/en-us/aspnet/core/grpc/basics#c-tooling-support-for-proto-files) |
||||||
protoc --plugin=protoc-gen-grpc=grpc_csharp_plugin --csharp_out=OUT_DIR \ |
|
||||||
--grpc_out=OUT_DIR --grpc_opt=lite_client,no_server \ |
|
||||||
-I INCLUDE_DIR foo.proto |
|
||||||
``` |
|
||||||
|
@ -0,0 +1,26 @@ |
|||||||
|
# Grpc.Tools - Protocol Buffers/gRPC C# Code Generation Build Integration |
||||||
|
|
||||||
|
This package provides C# tooling support for generating C# code from `.proto` files in `.csproj` projects: |
||||||
|
* It contains protocol buffers compiler and gRPC plugin to generate C# code. |
||||||
|
* It can be used in building both grpc-dotnet projects and legacy c-core C# projects. |
||||||
|
|
||||||
|
The package is used to automatically generate the C# code for protocol buffer messages |
||||||
|
and gRPC service stubs from `.proto` files. These files: |
||||||
|
* are generated on an as-needed basis each time the project is built. |
||||||
|
* aren't added to the project or checked into source control. |
||||||
|
* are a build artifact usually contained in the `obj` directory. |
||||||
|
|
||||||
|
This package is optional. You may instead choose to generate the C# source files from |
||||||
|
`.proto` files by running the `protoc` compiler manually or from a script. |
||||||
|
|
||||||
|
## Simple example |
||||||
|
|
||||||
|
To add a `.proto` file to a project edit the project’s `.csproj` file and add an item group with a `<Protobuf>` element that refers to the `.proto` file, e.g. |
||||||
|
|
||||||
|
```xml |
||||||
|
<ItemGroup> |
||||||
|
<Protobuf Include="Protos\greet.proto" /> |
||||||
|
</ItemGroup> |
||||||
|
``` |
||||||
|
|
||||||
|
For more complex examples and detailed information on how to use this package see: [BUILD-INTEGRATION.md](https://github.com/grpc/grpc/blob/master/src/csharp/BUILD-INTEGRATION.md) |
Loading…
Reference in new issue