使用 MSBuild 构建 gRPC dotnet 核心项目时如何包含自定义目录

Posted

技术标签:

【中文标题】使用 MSBuild 构建 gRPC dotnet 核心项目时如何包含自定义目录【英文标题】:How to include custom directory when building gRPC dotnet core project with MSBuild 【发布时间】:2020-04-01 12:44:08 【问题描述】:

我有一个 dotnet 核心 gRPC 项目,我正在尝试在我的 proto 文件中包含路由注释,如下所示:

import "google/api/annotations.proto";

文件结构是这样的(原因是我将googleapis存储库作为git子模块导入):

protos/
    myproto.proto

    googleapis/
        google/
           api/
               annotations.proto
               ...

在 go 项目中可以通过以下方式完成:

protoc -I . -I ./googleapis --go_out=plugins=grpc:. *.proto

其中-I ./googleapis 为编译器提供了可以找到annotations.proto 文件及其依赖项的目录。

但是,当我在使用如下配置的 dotnet grpc 项目中使用 MSBuild 时,我无法弄清楚如何包含自定义目录。

<ItemGroup>
    <Protobuf Include="protos/*.proto" GrpcServices="Server" />
</ItemGroup>

Official doc 提到了自定义目标构建的替代方法,以便我可以使用protoc

protoc --plugin=protoc-gen-grpc=$(gRPC_PluginFullPath)  -I $(Protobuf_StandardImportsPath) ...

但上面的命令会忽略服务定义,并且不会像here 中提到的那样生成服务器存根代码,而 MSBuild 会生成。

我找到但不理想的解决方法:

我意识到Grpc.Tools dotnet 包分发了一些常用的 proto 文件,所以我在那里复制了annotations.proto 及其依赖项(在 macOS 中)并且它起作用了:

`~\.nuget\packages\grpc.tools\2.25.0\build\native\include`

更新:

另一种解决方法:

默认包含项目根目录,因此将其用作基本路径并复制导入的 proto 文件也可以(更好但仍然不理想)。

任何想法如何通过 MSBuild 包含上述自定义目录?

【问题讨论】:

您可能在自定义命令中缺少一些特定于 grpc 的选项:例如--grpc_out=OUT_DIR 或者,您可以在 msbuild 中设置 ProtoRoot="protoc" 并确保所有 .proto 文件都在该目录下(子目录对应于包名称)。在您的情况下,您将拥有 protos/myproto.protoprotos/google/api/annotations.proto(没有“googleapis”目录,因为“google/api”需要对应于 annotations.proto 的命名空间)并且一切都应该构建得很好。 【参考方案1】:

终于想通了。正如Jan Tattermusch 所建议的那样,ProtoRoot 指定了 msbuild Include 属性以及 proto import 关键字将从中查找文件的目录,而 ProtoRoot 用于 Include 的方式与它的方式不同适用于import。因此,为了将 proto 文件结构自定义为这样,ProtoRoot 必须包含所有不同的路径,这些路径应该是:

<Protobuf Include="protos/*.proto" ProtoRoot="./protos; ./protos/googleapis" ... />

更新

以上方法适用于 v2.31.0 之前的 grpc-dotnet 版本。对于较新的版本,warnings 将显示为 ProtoRoot path is not a prefix of Include path。要修复它,请改用以下配置:

<Protobuf Include="protos/*.proto" ProtoRoot="protos" AdditionalImportDirs="protos/googleapis" ... />

【讨论】:

以上是关于使用 MSBuild 构建 gRPC dotnet 核心项目时如何包含自定义目录的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 在构建、重建和清理解决方案时使用啥 dotnet core cli 命令(或 msbuild 命令)?

dotnet cli与新vs2017 msbuild的关系

msbuild、dotnet sdks、azure、kudu等使用的环境变量列表

dotnet 通过引用 msbuild 程序集实现自己定制编译器

dotnet 通过引用 msbuild 程序集实现自己定制编译器

MSBuild - 在构建中集成跨平台编译器