# Protocol Buffers/gRPC Codegen Integration Into .NET Build
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:
* 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.
Using `Grpc.Tools` in `.csproj` files is described below. Other packages providing the runtime libraries for gRPC are described elsewhere.
## Getting Started
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 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.
However this package helps to simplify generating the C# source files by
integrating the code generation into the build process. It can be used when building both
the server and client projects, and by both c-core C# projects and grpc-dotnet projects:
* 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
`Grpc.Tools` is only used at build-time and has no runtime components.
It should be marked with `PrivateAssets="All"` to prevent it from being included at runtime, e.g.
```xml
runtime; build; native; contentfiles; analyzers; buildtransitive
all
```
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)
You may still use the MSBuild integration provided by `Grpc.Tools` for other architectures provided you can supply the codegen binaries for that platform/architecture.
See [Using Grpc.Tools with unsupported architectures](#unsupported-arch) below.
## 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 `` element that refers to the `.proto` file, e.g.
```xml
```
Wildcards can be used to select several `.proto` files, e.g.
```xml
```
By default, a `` reference generates gRPC client and a service base class from the `service` definitions in the `.proto` files.
The `GrpcServices` attribute can be used to limit C# asset generation. See the reference section below for all
options. E.g. to only generate client code:
```xml
```
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.
```xml
```
For more examples see the example project files in GitHub: https://github.com/grpc/grpc-dotnet/tree/master/examples
## Sharing `.proto` files between multiple projects (in the same VS solution)
It's common to want to share `.proto` files between projects. For example, a gRPC client
and gRPC server share the same contract. It is preferable to share contracts without
copying `.proto` files because copies can go out of sync over time.
There are a couple of ways to use `.proto` files in multiple projects without duplication:
* Sharing `.proto` files between projects with MSBuild links.
* Generating code in a class library and sharing the library.
### Sharing `.proto` with MSBuild links
`.proto` files can be placed in a shared location and referenced by multiple projects
using MSBuild's [`Link` or `LinkBase` settings](https://learn.microsoft.com/visualstudio/msbuild/common-msbuild-item-metadata).
```xml
```
In the example above, `greet.proto` is in a shared `Protos` directory outside
the project directory. Multiple projects can reference the proto file.
### Generating code in a class library
Create a class library that references `.proto` files and contains generated code. The other
projects in the solution can then reference this shared class library instead of each project
having to compile the same `.proto` files.
The advantages of this are:
- The `.proto` only need to be compiled once.
- It prevents some projects getting multiple definitions of the same generated code, which can in turn break the build.
There are a couple of examples in GitHub:
- The [Liber example](https://github.com/grpc/grpc-dotnet/tree/master/examples#liber)
demonstrates how common protocol buffers messages can be compiled once and used in other projects:
- The *Common* project creates a class library that includes the generates messages contained in `common.proto`
- The *Client* and *Server* projects reference the *Common* project.
- They do not need to recompile `common.proto` as those .NET types are already in
the *Common* class library.
- They do however each generate their own gRPC client or server code as both have a
`` reference for `greet.proto`. The *Client* and *Server* projects each having their own version of `greet.proto` is OK since they don't reference each other - they only reference the shared *Common* class library.
- The [RouteGuide example](https://github.com/grpc/grpc/tree/v1.46.x/examples/csharp/RouteGuide)
demonstrates how the gRPC client and server code can be generated once and used in other
projects:
- **Note:** this example uses the *legacy c-core C#* packages, but the principles are the same
for *gRPC for .NET* projects.
- The *RouteGuide* project has a `` reference to `route_guide.proto` and
generates both the gRPC client and server code.
- The *RouteGuideClient* and *RouteGuideServer* projects reference the *RouteGuide* project.
- They do not need any `` references since the code has already been
generated in the *RouteGuide* project.
# Reference
## Protobuf item metadata reference
The following metadata are recognized on the `` items.
| Name | Default | Value | Synopsis |
|----------------|-----------|----------------------|----------------------------------|
| 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 |
__Notes__
* __ProtoRoot__
For files _inside_ the project directory or its subdirectories, `ProtoRoot` is set by default to the
project directory.
For files _outside_ of the project directory, the value
is set to the 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 `ProtoRoot`. There is an example of this below. The path in
this variable is relative to the project directory.
* __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.
* __GrpcOutputDir__
Unless explicitly set, will follow `OutputDir` for any given file.
* __Access__
Sets generated class access on _both_ generated message and gRPC stub classes.
* __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.
* __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.
* __GrpcOutputOptions__
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`.
* __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.
__Specifying multiple values in properties__
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.
The properties that can have lists of items are: `OutputOptions`, `AdditionalProtocArguments`,
`GrpcOutputOptions`, `AdditionalImportDirs`
Example: to specify two additional arguments: `--plugin=protoc-gen-myplugin=D:\myplugin.exe --myplugin_out=.`
```xml
```
## `grpc_csharp_plugin` command line options
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:
| Name | Default | Synopsis |
|---------------- |-----------|----------------------------------------------------------|
| no_client | off | Don't generate the client stub |
| no_server | off | Don't generate the server-side stub |
| internal_access | off | Generate classes with "internal" visibility |
| file_suffix | Grpc.cs | The suffix that will get appended to the name of the generated file. **Can only be used on the command line.** |
| base_namespace | none | *Experimental - may change or be removed.* Same as `base_namespace` for `protoc` [C# options](https://protobuf.dev/reference/csharp/csharp-generated/#compiler_options) . **Can only be used on the command line.** |
To use these options with `Grpc.Tools` specify them in the __GrpcOutputOptions__
metadata in the `` item.
Notes:
- `file_suffix` and `base_namespace` should not be used with `Grpc.Tools`. Using them will break the build.
- using `base_namespace` changes the algorithm for the generated file names to align it with the algorithm used by `protoc`.
This only affects files with punctuation or numbers in the name. E.g. `hello.world2d.proto` now generates file `HelloWorld2DGrpc.cs` instead of `Hello.world2dGrpc.cs`
To use these options on the command line specify them with the `--grpc_opt`
option.
Code generated by `protoc` is independent of the plugin and you may also need to specify C# options for this with `--csharp_opt`.
These are [documented here](https://protobuf.dev/reference/csharp/csharp-generated/#compiler_options).
e.g.:
```bash
protoc --plugin=protoc-gen-grpc=grpc_csharp_plugin \
--csharp_out=OUT_DIR \
--csharp_opt=base_namespace=Example \
--grpc_out=OUT_DIR \
--grpc_opt=no_server,base_namespace=Example \
-I INCLUDE_DIR foo.proto
```
## Environment Variables
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.
| Name | Synopsis |
|---------------------|-------------------------------------------------------------------------------|
|`PROTOBUF_TOOLS_OS` | Operating system version of the tools to use: `linux`, `macosx`, or `windows` |
|`PROTOBUF_TOOLS_CPU` | CPU architecture version of the tools to use: `x86`, `x64`, or `arm64` |
|`PROTOBUF_PROTOC` | Full path to the protocol buffers compiler |
|`GRPC_PROTOC_PLUGIN` | Full path to the grpc_csharp_plugin |
For example, to use a custom built protoc compiler and grpc_csharp_plugin:
```bash
export PROTOBUF_PROTOC=$my_custom_build/protoc
export GRPC_PROTOC_PLUGIN=$my_custom_build/grpc_csharp_plugin
dotnet build myproject.csproj
```
## MSBuild Properties
You can set some Properties in your project file or on the MSBuild command line. The
following properties change the behavior of `Grpc.Tools`:
| 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 `` items.|
| `EnableDefaultProtobufItems` | Default: `false`. If `true` then `.proto` files under the project are automatically included without the need to specify any `` 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. |
# Scenarios and Examples
For other examples see also the `.csproj` files in the examples in GitHub:
* [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)
Quick links to the examples below:
* [ProtoRoot - Common root for one or more `.proto` files](#ProtoRoot)
* [AdditionalImportDirs - Setting location of imported `.proto` files](#AdditionalImportDirs)
* [GrpcServices - Generating gRPC services and protocol buffers messages](#grpcservices)
* [Automatically including `.proto` files](#autoinclude)
* [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)
* [Using Grpc.Tools with unsupported architectures](#unsupported-arch)
* [Including `.proto` files in NuGet packages](#proto-only-nuget)
---
## ProtoRoot - Common root for one or more `.proto` files
`ProtoRoot` specifies a common directory that is an ancestor for a set of `.proto` files.
It has two purposes:
* working out relative directories to preserve the structure when generating `.cs` files
* adding a directory to be searched for imported `.proto` files
These are explained in an example below.
For `.proto` files under the project directory `ProtoRoot` is by default set to `.`.
It can also be explicitly set.
For `.proto` files outside of the project the value is set to the file's containing directory name.
If you include a subtree of `.proto` files then you must set `ProtoRoot` to give the
parent of the directory tree.
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.)
Generated files in the output directory will have the same directory structure as the
`.proto` files under `ProtoRoot`.
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
```
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
```
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`
---
## AdditionalImportDirs - Setting location of imported `.proto` files
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 would use this when you want to import `.proto` files that you don't need to
separately compile as they are only used in import statements. E.g.:
```xml
```
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`:
```protobuf
import "google/protobuf/wrappers.proto";
```
---
## 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 `` 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
```
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
true
```
however it is better to set `GrpcServices="None"` on the `.proto` files affected to avoid
unnecessary rebuilds.
---
## Automatically including `.proto` files
For SDK projects it is possible to automatically include `.proto` files found in the project
directory or sub-directories, without having to specify them with a `` item.
To do this the property `EnableDefaultProtobufItems` has be set to `true` in the project file or on the MSBuild command line.
It is recommended that you do not rely on automatic inclusion of `.proto` files except for
the simplest of projects since it does not allow you to control other settings such as
`GrpcServices`.
By default `EnableDefaultProtobufItems` is not set and `` items must be included
in the project for the `.proto` files to be compiled.
---
## Generate proto and gRPC C# sources from .proto files (no C# compile)
If you just want to generate the C# sources from `.proto` files without compiling the C# files
(e.g. for use in other projects) then you can do something similar to this to a `.csproj` file:
```xml
```
* `Include` tells the build system to recursively examine project directory and its
subdirectories (**) include all files matching the wildcard `*.proto`.
* `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.
Note that an empty assembly is still generated which can be ignored.
NOTE: To start with an empty project to add your `.proto` files to you can do the following
at a command prompt:
```bash
dotnet new classlib
rm *.cs # remove .cs files - for Windows the command is: del *.cs /y
dotnet add package Grpc.Tools
```
---
## Visual Studio: setting per-file `.proto` file options
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.
### "dotnet SDK" projects
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
properties window after adding a reference to `Grpc.Tools` package:

You can also change options of multiple files at once by selecting them in the
Project Explorer together.
### "classic" projects
For a "classic" project, you can only add `.proto` files with all options set to
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:

---
## Bypassing Grpc.Tools to run the protocol buffers compiler explicitly
It is possible to bypass all the build logic in `Grpc.Tools` and run the protocol buffers compiler
explicitly in your project file, and just use the `Grpc.Tools` as a means of getting the compiler.
**This is not recommended** but there may be situations where you want to do this.
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"`
* `gRPC_PluginFullPath` points to the full path and filename of gRPC plugin, e.g.
`"...\.nuget\packages\grpc.tools\2.51.0\build\native\bin\windows\grpc_csharp_plugin.exe"`
* `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.
then in your project file:
```xml
$(Protobuf_ProtocFullPath) --plugin=protoc-gen-grpc=$(gRPC_PluginFullPath) -I $(Protobuf_StandardImportsPath) ....rest of your command....
```
Do not include any `` items in the project file as that will invoke the `Grpc.Tools` build and your files will be compiled twice.
---
## Using Grpc.Tools with unsupported architectures
You may still use the MSBuild integration provided by `Grpc.Tools` for architectures where
the binaries are not included in the `Grpc.Tools` NuGet package.
If you are able to build your own binaries for `protoc` and `grpc_csharp_plugin`, or
find pre-built binaries provided by the community, then you can define a couple of
environment variables to tell `Grpc.Tools` to use those binaries instead of the ones
provided in the NuGet package:
* `PROTOBUF_PROTOC` - Full path to the protocol buffers compiler
* `GRPC_PROTOC_PLUGIN` - Full path to the `grpc_csharp_plugin`
Things to note:
* You need `Grpc.Tools` version 2.50.0 or later for these environment variables to
be recognised.
* The binaries bundled in `Grpc.Tools` already ensure that the correct and mutually
compatible version of `protoc` and `grpc_csharp_plugin` will be chosen, but when
providing them yourself, you're in charge.
* If the versions of `protoc` and `grpc_csharp_plugin` you provide are mutually
incompatible then code generated may not work with your application (e.g. breaks
the build).
* Specifically, older version of plugins may generate incompatible code
or may not contain patches/fixes.
_An example for Alpine Linux_
For Alpine Linux (which uses the *musl* C standard library) there are community
provided packages for the protocol buffers compiler and gRPC plugins:
[https://pkgs.alpinelinux.org/packages?name=grpc-plugins](https://pkgs.alpinelinux.org/packages?name=grpc-plugins)
To use these:
```bash
# Build or install the binaries for your architecture.
# e.g. for Alpine Linux the grpc-plugins package can be used
# See https://pkgs.alpinelinux.org/package/edge/community/x86_64/grpc-plugins
apk add grpc-plugins # Alpine Linux specific package installer
# Set environment variables for the built/installed protoc
# and grpc_csharp_plugin binaries
export PROTOBUF_PROTOC=/usr/bin/protoc
export GRPC_PROTOC_PLUGIN=/usr/bin/grpc_csharp_plugin
# When the dotnet build runs the Grpc.Tools NuGet package will
# use the binaries pointed to by the environment variables
dotnet build
```
---
## Including `.proto` files in NuGet packages
There might be occassions when you are given a NuGet package that contains
`.proto` files that you wish to use in your own project, or you may wish to
package your own `.proto` files in a NuGet package for others to use.
There is no automatic way for `Grpc.Tools` to locate and include `.proto`
files from other NuGet packages. Below is a suggested convention to use
when creating NuGet packages that contain `.proto` files.
__Note:__ This is not the same as a NuGet package providing a library built from
the code generated from the `.proto` files. Below just describes how to provide
the uncompiled `.proto` files in a NuGet package and have `Grpc.Tools` automatically
use them.
### Creating the NuGet package
The NuGet package should:
- provide the `.proto` files in a `content\protos` subdirectory in the package
- provide a `packagename.targets` file in the `build` subdirectory in the package that:
- defines an MSBuild property giving the path to the `.proto` files in the
installed package
- conditionally updates the `Protobuf_StandardImportsPath` property with the
above path so that the files can be found by the protocol buffers compiler
- it should be made optional forcing users to *opt in* to including
the `.proto` files
For example, for the package `My.Example.Protos`:
My.Example.Protos.nuspec:
```xml
My.Example.Protos
1.0.0
Example package containing proto files
author
owner
license url
project url
See project site for more info.
Example package containing proto files.
Example package containing proto files
Copyright 2023, My Company.
```
My.Example.Protos.targets:
```xml
$( [System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)../content/protos) )
$(Protobuf_StandardImportsPath);$(MyPackage_ProtosPath)
```
### Using the NuGet package
The project needs to add the package containing the `.proto` files:
```xml
```
If the project only wants to compile the `.proto` files included in the package
then all it needs to do is add the `` items using the property defined
in the package for the path to the files. For example, if the NuGet package contained
the file `greet.proto`, then the project should add:
```xml
```
However if the provided `.proto` files are to be *imported* by the projects own `.proto`
files then the `Protobuf_StandardImportsPath` needs updated to add the directory
containing the package's files. This is done by setting to `true` the property
used in the package. For example, if the project has the local `.proto` file
`my_services.proto` and it imported a file from the package `common_message.proto`,
then:
```xml
true
```
---
## See also
gRPC project documentation:
* [gRPC for .NET](https://github.com/grpc/grpc-dotnet)
* [gRPC C# (legacy implementation using gRPC Core library)](https://github.com/grpc/grpc/blob/master/src/csharp/README.md)
* [Grpc.Tools internals](Grpc.Tools/implementation_notes.md) - implementation notes for how `Grpc.Tools` works
Microsoft documentation:
* [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)