如何使用 protobuf-gradle-plugin 生成 Go gRPC 代码?

问题描述

这个问题和这个问题一样,How do I use gradle to generate go grpc code?,但由于这个问题还没有得到回答,我再问一次。我制作了一个简化的 Gradle 项目,其结构类似于以下内容

├── build.gradle
└── src
    └── main
        └── proto
            └── helloworld.proto

build.gradle 读取的位置

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.14'
    }
}

plugins {
    id "com.google.protobuf" version "0.8.14"
    id "java"
}

dependencies {
    compile group: 'com.google.protobuf',name: 'protobuf-java',version: '3.0.0'
    implementation group: 'io.grpc',name: 'grpc-protobuf',version: '1.35.0'
    implementation group: 'io.grpc',name: 'grpc-stub',version: '1.35.0'
    compileOnly group: 'org.apache.tomcat',name: 'annotations-api',version: '6.0.53'
}

protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:3.0.0'
    }
    plugins {
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.0.0-pre2'
        }
    }
    generateProtoTasks {
        all()*.plugins {
            grpc {}
        }
        all().each { task ->
            task.builtins {
                go {}
            }
        }
    }
}

helloworld.proto 取自 gRPC 教程:

Syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";

package helloworld;

// The greeting service deFinition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

如果我运行 ./gradlew build,我会得到以下生成的源代码

build/generated/source/
└── proto
    └── main
        ├── go
        │   └── helloworld.pb.go
        ├── grpc
        │   └── io
        │       └── grpc
        │           └── examples
        │               └── helloworld
        │                   └── GreeterGrpc.java
        └── java
            └── io
                └── grpc
                    └── examples
                        └── helloworld
                            ├── HelloReply.java
                            ├── HelloReplyOrBuilder.java
                            ├── HelloRequest.java
                            ├── HelloRequestOrBuilder.java
                            └── HelloWorldProto.java

我已经直接使用 protoc 做了类似的事情,并且希望还有一个 helloworld_grpc.pb.go 由带有 gRPC 服务器和客户端存根的 Go Protobuf 插件生成。如何让 Gradle 生成代码

解决方法

gRPC-Go 的代码生成器 (https://github.com/grpc/grpc-go/tree/master/cmd/protoc-gen-go-grpc) 由 protoc 自动获取,而不是在 --plugin 标志中指定(也许有一种方法,但我从未尝试过)。

首先,您需要在 gRPC quickstart 之后安装 protoc-gen-go-grpc 插件。确保插件在 PATH 中。

然后以与 protoc 内置函数相同的方式使用 protoc-gen-go-grpc 插件:

protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:3.0.0'
    }
    plugins {
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.0.0-pre2'
        }
    }
    generateProtoTasks {
        all()*.plugins {
            grpc {}
        }
        all().each { task ->
            task.builtins {
                go {}
                'go-grpc' {}
            }
        }
    }
}

(请注意,由于破折号,您需要引用 'go-grpc')。

另请注意,生成的 Go 代码不会被 Gradle 编译任务自动获取,您需要自己连接(类似于 Java 的 srcDirs 'build/generated/source/proto/main/grpc' 块中的 sourceSets ,但我不知道 Gradle 是如何用于构建 Go 项目的)。