Skip to content

Commit

Permalink
kotlin protos (#266)
Browse files Browse the repository at this point in the history
* kotlin protos

* kt_jvm_proto_library proof of concept

* Document kt_jvm_proto_library

* Apply Bazel Kotlin proto rules to all examples

* kotlin protos

* add kotlin proto info

* version bumps and cleanup

Co-authored-by: Peter Schmitt <aragos@gmail.com>
  • Loading branch information
jamesward and aragos committed Oct 13, 2021
1 parent e04c888 commit f834a3c
Show file tree
Hide file tree
Showing 29 changed files with 406 additions and 168 deletions.
10 changes: 3 additions & 7 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ maven_install(
artifacts = [
"com.google.jimfs:jimfs:1.1",
"com.google.truth.extensions:truth-proto-extension:1.0.1",
"com.google.protobuf:protobuf-kotlin:3.18.0",
] + IO_GRPC_GRPC_KOTLIN_ARTIFACTS + IO_GRPC_GRPC_JAVA_ARTIFACTS,
generate_compat_repositories = True,
override_targets = dict(
Expand All @@ -56,16 +57,11 @@ grpc_java_repositories()

# Protocol Buffers
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")

protobuf_deps()

# Kotlin
load(
"@io_bazel_rules_kotlin//kotlin:kotlin.bzl",
"kotlin_repositories",
"kt_register_toolchains",
)

load("@io_bazel_rules_kotlin//kotlin:repositories.bzl", "kotlin_repositories")
kotlin_repositories()

load("@io_bazel_rules_kotlin//kotlin:core.bzl", "kt_register_toolchains")
kt_register_toolchains()
76 changes: 48 additions & 28 deletions compiler/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
gRPC Kotlin Codegen Plugin for Protobuf Compiler
================================================

This generates the Kotlin interfaces out of the service definition from a
`.proto` file. It works with the Protobuf Compiler (`protoc`).
This generates the Kotlin interfaces out of the service definition from a`.proto` file. It works with the Protobuf Compiler (`protoc`) and uses a `protoc` plugin to generate Kotlin wrappers for the generated Java classes.
> Note: You can use the gRPC Kotlin compiler without using the protoc Kotlin compiler, but these instructions assume you want to use both together.
### Build Tool Plugins

Expand All @@ -11,38 +11,42 @@ Usually this compiler is used via a build tool plugin, like in Gradle, Maven, et
For Gradle, include the [protobuf plugin](https://github.com/google/protobuf-gradle-plugin) with at least version `0.8.13`, like:
```
plugins {
id("com.google.protobuf") version "SOME_VERSION"
id("com.google.protobuf") version "YOUR_PROTOBUF_PLUGIN_VERSION"
}
```

Add dependencies on `grpc-kotlin-stub` and a protobuf library like:
Add dependencies on `grpc-kotlin-stub` and protobuf libraries like:
```
dependencies {
implementation("io.grpc:grpc-kotlin-stub:SOME_VERSION")
implementation("io.grpc:grpc-protobuf:SOME_VERSION")
implementation("io.grpc:grpc-kotlin-stub:YOUR_GRPC_KOTLIN_VERSION")
implementation("io.grpc:grpc-protobuf:YOUR_GRPC_VERSION")
implementation("com.google.protobuf:protobuf-kotlin:YOUR_PROTOBUF_VERSION")
}
```

Finally, setup the protobuf plugin:
```
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:SOME_VERSION"
artifact = "com.google.protobuf:protoc:YOUR_PROTOBUF_VERSION"
}
plugins {
id("grpc") {
artifact = "io.grpc:protoc-gen-grpc-java:SOME_VERSION"
artifact = "io.grpc:protoc-gen-grpc-java:YOUR_GRPC_VERSION"
}
id("grpckt") {
artifact = "io.grpc:protoc-gen-grpc-kotlin:SOME_VERSION:jdk7@jar"
artifact = "io.grpc:protoc-gen-grpc-kotlin:YOUR_GRPC_KOTLIN_VERSION:jdk7@jar"
}
}
generateProtoTasks {
ofSourceSet("main").forEach {
all().forEach {
it.plugins {
id("grpc")
id("grpckt")
}
it.builtins {
id("kotlin")
}
}
}
}
Expand All @@ -55,44 +59,60 @@ For Maven, include the [protobuf plugin](https://www.xolstice.org/protobuf-maven
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:SOME_VERSION:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:SOME_VERSION:exe:${os.detected.classifier}</pluginArtifact>
<protocPlugins>
<protocPlugin>
<id>grpc-kotlin</id>
<groupId>io.grpc</groupId>
<artifactId>protoc-gen-grpc-kotlin</artifactId>
<version>SOME_VERSION</version>
<classifier>jdk7</classifier>
<mainClass>io.grpc.kotlin.generator.GeneratorRunner</mainClass>
</protocPlugin>
</protocPlugins>
</configuration>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
<configuration>
<protocArtifact>com.google.protobuf:protoc:YOUR_PROTOBUF_VERSION:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:YOUR_GRPC_VERSION:exe:${os.detected.classifier}</pluginArtifact>
<protocPlugins>
<protocPlugin>
<id>grpc-kotlin</id>
<groupId>io.grpc</groupId>
<artifactId>protoc-gen-grpc-kotlin</artifactId>
<version>YOUR_GRPC_KOTLIN_VERSION</version>
<classifier>jdk7</classifier>
<mainClass>io.grpc.kotlin.generator.GeneratorRunner</mainClass>
</protocPlugin>
</protocPlugins>
</configuration>
</execution>
<execution>
<id>compile-kt</id>
<goals>
<goal>compile-custom</goal>
</goals>
<configuration>
<protocArtifact>com.google.protobuf:protoc:YOUR_PROTOBUF_VERSION:exe:${os.detected.classifier}</protocArtifact>
<outputDirectory>${project.build.directory}/generated-sources/protobuf/kotlin</outputDirectory>
<pluginId>kotlin</pluginId>
</configuration>
</execution>
</executions>
</plugin>
```

Make sure you include a dependency on `stub` and a protobuf library like:
Make sure you include a dependency on `stub` and protobuf libraries like:
```
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-kotlin-stub</artifactId>
<version>SOME_VERSION</version>
<version>YOUR_GRPC_KOTLIN_VERSION</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>SOME_VERSION</version>
<version>YOUR_PROTOBUF_VERSION</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-kotlin</artifactId>
<version>YOUR_PROTOBUF_VERSION</version>
</dependency>
```

Expand Down
8 changes: 4 additions & 4 deletions examples/android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {

dependencies {
implementation(project(":stub-android"))
implementation("androidx.appcompat:appcompat:1.2.0")
implementation("androidx.appcompat:appcompat:1.3.1")
runtimeOnly("io.grpc:grpc-okhttp:${rootProject.ext["grpcVersion"]}")
}

Expand All @@ -15,7 +15,7 @@ android {

defaultConfig {
applicationId = "io.grpc.examples.hello"
minSdkVersion(23)
minSdkVersion(26)
targetSdkVersion(30)
versionCode = 1
versionName = "1.0"
Expand All @@ -31,7 +31,7 @@ android {
sourceSets["main"].java.srcDir("src/main/kotlin")

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import io.grpc.ManagedChannel
import io.grpc.ManagedChannelBuilder
import java.net.URL
import java.util.logging.Logger
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.runBlocking
import java.net.URL
import java.util.logging.Logger

// todo: suspend funs
class MainActivity : AppCompatActivity() {
Expand Down Expand Up @@ -58,7 +58,7 @@ class MainActivity : AppCompatActivity() {

fun sendReq() = runBlocking {
try {
val request = HelloRequest.newBuilder().setName(nameText.text.toString()).build()
val request = helloRequest { name = nameText.text.toString() }
val response = greeter.sayHello(request)
responseText.text = response.message
} catch (e: Exception) {
Expand Down
11 changes: 6 additions & 5 deletions examples/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
plugins {
id("com.android.application") version "4.1.1" apply false
id("com.google.protobuf") version "0.8.15" apply false
kotlin("jvm") version "1.4.32" apply false
id("org.jlleitschuh.gradle.ktlint") version "9.2.1"
id("com.google.protobuf") version "0.8.17" apply false
kotlin("jvm") version "1.5.31" apply false
id("org.jlleitschuh.gradle.ktlint") version "10.2.0"
}

// todo: move to subprojects, but how?
ext["grpcVersion"] = "1.37.0"
ext["grpcVersion"] = "1.39.0" // need to wait for grpc kotlin to move past this
ext["grpcKotlinVersion"] = "1.1.0" // CURRENT_GRPC_KOTLIN_VERSION
ext["protobufVersion"] = "3.15.8"
ext["protobufVersion"] = "3.18.1"
ext["coroutinesVersion"] = "1.5.2"

allprojects {
repositories {
Expand Down
12 changes: 6 additions & 6 deletions examples/client/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,37 @@ dependencies {
tasks.register<JavaExec>("HelloWorldClient") {
dependsOn("classes")
classpath = sourceSets["main"].runtimeClasspath
main = "io.grpc.examples.helloworld.HelloWorldClientKt"
mainClass.set("io.grpc.examples.helloworld.HelloWorldClientKt")
}

tasks.register<JavaExec>("RouteGuideClient") {
dependsOn("classes")
classpath = sourceSets["main"].runtimeClasspath
main = "io.grpc.examples.routeguide.RouteGuideClientKt"
mainClass.set("io.grpc.examples.routeguide.RouteGuideClientKt")
}

tasks.register<JavaExec>("AnimalsClient") {
dependsOn("classes")
classpath = sourceSets["main"].runtimeClasspath
main = "io.grpc.examples.animals.AnimalsClientKt"
mainClass.set("io.grpc.examples.animals.AnimalsClientKt")
}

val helloWorldClientStartScripts = tasks.register<CreateStartScripts>("helloWorldClientStartScripts") {
mainClassName = "io.grpc.examples.helloworld.HelloWorldClientKt"
mainClass.set("io.grpc.examples.helloworld.HelloWorldClientKt")
applicationName = "hello-world-client"
outputDir = tasks.named<CreateStartScripts>("startScripts").get().outputDir
classpath = tasks.named<CreateStartScripts>("startScripts").get().classpath
}

val routeGuideClientStartScripts = tasks.register<CreateStartScripts>("routeGuideClientStartScripts") {
mainClassName = "io.grpc.examples.routeguide.RouteGuideClientKt"
mainClass.set("io.grpc.examples.routeguide.RouteGuideClientKt")
applicationName = "route-guide-client"
outputDir = tasks.named<CreateStartScripts>("startScripts").get().outputDir
classpath = tasks.named<CreateStartScripts>("startScripts").get().classpath
}

val animalsClientStartScripts = tasks.register<CreateStartScripts>("animalsClientStartScripts") {
mainClassName = "io.grpc.examples.animals.AnimalsClientKt"
mainClass.set("io.grpc.examples.animals.AnimalsClientKt")
applicationName = "animals-client"
outputDir = tasks.named<CreateStartScripts>("startScripts").get().outputDir
classpath = tasks.named<CreateStartScripts>("startScripts").get().classpath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,19 @@ class AnimalsClient(private val channel: ManagedChannel) : Closeable {
private val sheepStub: SheepGrpcKt.SheepCoroutineStub by lazy { SheepGrpcKt.SheepCoroutineStub(channel) }

suspend fun bark() {
val request = BarkRequest.getDefaultInstance()
val request = barkRequest {}
val response = dogStub.bark(request)
println("Received: ${response.message}")
}

suspend fun oink() {
val request = OinkRequest.getDefaultInstance()
val request = oinkRequest {}
val response = pigStub.oink(request)
println("Received: ${response.message}")
}

suspend fun baa() {
val request = BaaRequest.getDefaultInstance()
val request = baaRequest {}
val response = sheepStub.baa(request)
println("Received: ${response.message}")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ kt_jvm_binary(
main_class = "io.grpc.examples.animals.AnimalsClientKt",
deps = [
"//examples/protos/src/main/proto/io/grpc/examples/animals:animals_kt_grpc",
"//examples/protos/src/main/proto/io/grpc/examples/animals:animals_kt_proto",
"@com_google_protobuf//:protobuf_java_util",
"@io_grpc_grpc_java//netty",
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ kt_jvm_binary(
main_class = "io.grpc.examples.helloworld.HelloWorldClientKt",
deps = [
"//examples/protos/src/main/proto/io/grpc/examples/helloworld:hello_world_kt_grpc",
"//examples/protos/src/main/proto/io/grpc/examples/helloworld:hello_world_kt_proto",
"@io_grpc_grpc_java//netty",
],
)
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class HelloWorldClient(private val channel: ManagedChannel) : Closeable {
private val stub: GreeterCoroutineStub = GreeterCoroutineStub(channel)

suspend fun greet(name: String) {
val request = HelloRequest.newBuilder().setName(name).build()
val request = helloRequest { this.name = name }
val response = stub.sayHello(request)
println("Received: ${response.message}")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ kt_jvm_binary(
resources = ["//examples/stub/src/main/resources/io/grpc/examples/routeguide:route_guide_db"],
deps = [
"//examples/protos/src/main/proto/io/grpc/examples/routeguide:route_guide_kt_grpc",
"//examples/protos/src/main/proto/io/grpc/examples/routeguide:route_guide_kt_proto",
"//examples/stub/src/main/kotlin/io/grpc/examples/routeguide:route_guide_stub",
"@com_google_protobuf//:protobuf_java_util",
"@io_grpc_grpc_java//netty",
Expand Down

0 comments on commit f834a3c

Please sign in to comment.