diff --git a/README.md b/README.md index 4097c87d1..f6ef7054e 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,10 @@ Full documentation for the current and previous versions [can be found here](htt | [Java](https://rules-proto-grpc.com/en/latest/lang/java.html) | [java_grpc_compile](https://rules-proto-grpc.com/en/latest/lang/java.html#java-grpc-compile) | Generates a Java protobuf and gRPC srcjar file ([example](/example/java/java_grpc_compile)) | | [Java](https://rules-proto-grpc.com/en/latest/lang/java.html) | [java_proto_library](https://rules-proto-grpc.com/en/latest/lang/java.html#java-proto-library) | Generates a Java protobuf library using ``java_library`` ([example](/example/java/java_proto_library)) | | [Java](https://rules-proto-grpc.com/en/latest/lang/java.html) | [java_grpc_library](https://rules-proto-grpc.com/en/latest/lang/java.html#java-grpc-library) | Generates a Java protobuf and gRPC library using ``java_library`` ([example](/example/java/java_grpc_library)) | +| [Kotlin](https://rules-proto-grpc.com/en/latest/lang/kotlin.html) | [kotlin_proto_compile](https://rules-proto-grpc.com/en/latest/lang/kotlin.html#kotlin-proto-compile) | Generates a Kotlin (JVM) protobuf srcjar file ([example](/example/kotlin/kotlin_proto_compile)) | +| [Kotlin](https://rules-proto-grpc.com/en/latest/lang/kotlin.html) | [kotlin_grpc_compile](https://rules-proto-grpc.com/en/latest/lang/kotlin.html#kotlin-grpc-compile) | Generates a Kotlin (JVM) protobuf and gRPC srcjar file ([example](/example/kotlin/kotlin_grpc_compile)) | +| [Kotlin](https://rules-proto-grpc.com/en/latest/lang/kotlin.html) | [kotlin_proto_library](https://rules-proto-grpc.com/en/latest/lang/kotlin.html#kotlin-proto-library) | Generates a Kotlin (JVM) protobuf library using ``kt_jvm_library`` ([example](/example/kotlin/kotlin_proto_library)) | +| [Kotlin](https://rules-proto-grpc.com/en/latest/lang/kotlin.html) | [kotlin_grpc_library](https://rules-proto-grpc.com/en/latest/lang/kotlin.html#kotlin-grpc-library) | Generates a Kotlin (JVM) protobuf and gRPC library using ``kt_jvm_library`` ([example](/example/kotlin/kotlin_grpc_library)) | | [JavaScript](https://rules-proto-grpc.com/en/latest/lang/js.html) | [js_proto_compile](https://rules-proto-grpc.com/en/latest/lang/js.html#js-proto-compile) | Generates JavaScript protobuf ``.js`` and ``.d.ts`` files ([example](/example/js/js_proto_compile)) | | [JavaScript](https://rules-proto-grpc.com/en/latest/lang/js.html) | [js_grpc_node_compile](https://rules-proto-grpc.com/en/latest/lang/js.html#js-grpc-node-compile) | Generates JavaScript protobuf and gRPC-node ``.js`` and ``.d.ts`` files ([example](/example/js/js_grpc_node_compile)) | | [JavaScript](https://rules-proto-grpc.com/en/latest/lang/js.html) | [js_grpc_web_compile](https://rules-proto-grpc.com/en/latest/lang/js.html#js-grpc-web-compile) | Generates JavaScript protobuf and gRPC-Web ``.js`` and ``.d.ts`` files ([example](/example/js/js_grpc_web_compile)) | diff --git a/WORKSPACE b/WORKSPACE index 9779a8a97..08b5af47e 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -20,6 +20,50 @@ rules_proto_dependencies() rules_proto_toolchains() +# +# Java +# +load("//java:repositories.bzl", "java_repos") + +java_repos() + +# +# Kotlin-JVM +# +load("//kotlin:repositories.bzl", "kotlin_repos") + +kotlin_repos() + +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() + +load("@rules_jvm_external//:defs.bzl", "maven_install") +load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_ARTIFACTS", "IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS", "grpc_java_repositories") +load("@com_github_grpc_grpc_kotlin//:repositories.bzl", "IO_GRPC_GRPC_KOTLIN_ARTIFACTS", "IO_GRPC_GRPC_KOTLIN_OVERRIDE_TARGETS", "grpc_kt_repositories") + +maven_install( + artifacts = IO_GRPC_GRPC_JAVA_ARTIFACTS + IO_GRPC_GRPC_KOTLIN_ARTIFACTS, + generate_compat_repositories = True, + override_targets = dict(IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS.items() + + IO_GRPC_GRPC_KOTLIN_OVERRIDE_TARGETS.items()), + repositories = [ + "https://repo.maven.apache.org/maven2/", + ], +) + +load("@maven//:compat.bzl", "compat_repositories") + +compat_repositories() + +grpc_java_repositories() + +grpc_kt_repositories() + # # Android # @@ -58,23 +102,23 @@ go_repos() # Load build_bazel_rules_swift before running grpc_deps in C++, since that depends on a very old # version of build_bazel_apple_support # -load("//swift:repositories.bzl", "swift_repos") - -swift_repos() - -load( - "@build_bazel_rules_swift//swift:repositories.bzl", - "swift_rules_dependencies", -) - -swift_rules_dependencies() +#load("//swift:repositories.bzl", "swift_repos") +# +#swift_repos() +# +#load( +# "@build_bazel_rules_swift//swift:repositories.bzl", +# "swift_rules_dependencies", +#) +# +#swift_rules_dependencies() # # C++ # -load("//cpp:repositories.bzl", "cpp_repos") - -cpp_repos() +#load("//cpp:repositories.bzl", "cpp_repos") +# +#cpp_repos() load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") @@ -87,71 +131,53 @@ grpc_extra_deps() # # Android # -load("//android:repositories.bzl", "android_repos") - -android_repos() - -load("@rules_jvm_external//:defs.bzl", "maven_install") -load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_ARTIFACTS", "IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS", "grpc_java_repositories") - -maven_install( - artifacts = IO_GRPC_GRPC_JAVA_ARTIFACTS, - generate_compat_repositories = True, - override_targets = IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS, - repositories = [ - "https://repo.maven.apache.org/maven2/", - ], -) - -load("@maven//:compat.bzl", "compat_repositories") - -compat_repositories() - -grpc_java_repositories() - -load("@build_bazel_rules_android//android:sdk_repository.bzl", "android_sdk_repository") +#load("//android:repositories.bzl", "android_repos") +# +#android_repos() -android_sdk_repository(name = "androidsdk") +#load("@build_bazel_rules_android//android:sdk_repository.bzl", "android_sdk_repository") +# +#android_sdk_repository(name = "androidsdk") # # C#/F# # -load("//csharp:repositories.bzl", "csharp_repos") - -csharp_repos() - -load("@io_bazel_rules_dotnet//dotnet:deps.bzl", "dotnet_repositories") - -dotnet_repositories() - -load( - "@io_bazel_rules_dotnet//dotnet:defs.bzl", - "dotnet_register_toolchains", - "dotnet_repositories_nugets", -) - -dotnet_register_toolchains() - -dotnet_repositories_nugets() - -load("@rules_proto_grpc//csharp/nuget:nuget.bzl", nuget_rules_proto_grpc_packages_csharp = "nuget_rules_proto_grpc_packages") - -nuget_rules_proto_grpc_packages_csharp() - -load("@rules_proto_grpc//fsharp/nuget:nuget.bzl", nuget_rules_proto_grpc_packages_fsharp = "nuget_rules_proto_grpc_packages") - -nuget_rules_proto_grpc_packages_fsharp() +#load("//csharp:repositories.bzl", "csharp_repos") +# +#csharp_repos() +# +#load("@io_bazel_rules_dotnet//dotnet:deps.bzl", "dotnet_repositories") +# +#dotnet_repositories() +# +#load( +# "@io_bazel_rules_dotnet//dotnet:defs.bzl", +# "dotnet_register_toolchains", +# "dotnet_repositories_nugets", +#) +# +#dotnet_register_toolchains() +# +#dotnet_repositories_nugets() +# +#load("@rules_proto_grpc//csharp/nuget:nuget.bzl", nuget_rules_proto_grpc_packages_csharp = "nuget_rules_proto_grpc_packages") +# +#nuget_rules_proto_grpc_packages_csharp() +# +#load("@rules_proto_grpc//fsharp/nuget:nuget.bzl", nuget_rules_proto_grpc_packages_fsharp = "nuget_rules_proto_grpc_packages") +# +#nuget_rules_proto_grpc_packages_fsharp() # # D # -load("//d:repositories.bzl", "d_repos") - -d_repos() - -load("@io_bazel_rules_d//d:d.bzl", "d_repositories") - -d_repositories() +#load("//d:repositories.bzl", "d_repos") +# +#d_repos() +# +#load("@io_bazel_rules_d//d:d.bzl", "d_repositories") +# +#d_repositories() # # Doc @@ -181,15 +207,6 @@ load("@grpc_ecosystem_grpc_gateway//:repositories.bzl", "go_repositories") go_repositories() -# -# Java -# -load("//java:repositories.bzl", "java_repos") - -java_repos() - -# grpc_java_repositories already called above in android - # # JavaScript # @@ -212,16 +229,16 @@ yarn_install( # # Objective-C # -load("//objc:repositories.bzl", "objc_repos") - -objc_repos() +#load("//objc:repositories.bzl", "objc_repos") +# +#objc_repos() # # PHP # -load("//php:repositories.bzl", "php_repos") - -php_repos() +#load("//php:repositories.bzl", "php_repos") +# +#php_repos() # # Python @@ -245,64 +262,64 @@ install_deps() # # Ruby # -load("//ruby:repositories.bzl", "ruby_repos") - -ruby_repos() - -load("@bazelruby_rules_ruby//ruby:deps.bzl", "rules_ruby_dependencies", "rules_ruby_select_sdk") - -rules_ruby_dependencies() - -rules_ruby_select_sdk(version = "3.0.2") - -load("@bazelruby_rules_ruby//ruby:defs.bzl", "ruby_bundle") - -ruby_bundle( - name = "rules_proto_grpc_bundle", - gemfile = "@rules_proto_grpc//ruby:Gemfile", - gemfile_lock = "@rules_proto_grpc//ruby:Gemfile.lock", - includes = {"grpc": ["etc"]}, -) +#load("//ruby:repositories.bzl", "ruby_repos") +# +#ruby_repos() +# +#load("@bazelruby_rules_ruby//ruby:deps.bzl", "rules_ruby_dependencies", "rules_ruby_select_sdk") +# +#rules_ruby_dependencies() +# +#rules_ruby_select_sdk(version = "3.0.2") +# +#load("@bazelruby_rules_ruby//ruby:defs.bzl", "ruby_bundle") +# +#ruby_bundle( +# name = "rules_proto_grpc_bundle", +# gemfile = "@rules_proto_grpc//ruby:Gemfile", +# gemfile_lock = "@rules_proto_grpc//ruby:Gemfile.lock", +# includes = {"grpc": ["etc"]}, +#) # # Rust # -load("//rust:repositories.bzl", "rust_repos") - -rust_repos() - -load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains") - -rules_rust_dependencies() - -rust_register_toolchains(edition = "2021") +#load("//rust:repositories.bzl", "rust_repos") +# +#rust_repos() +# +#load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains") +# +#rules_rust_dependencies() +# +#rust_register_toolchains(edition = "2021") # # Scala # -load("//scala:repositories.bzl", "MAVEN_ARTIFACTS", "scala_repos") - -scala_repos() - -load("@io_bazel_rules_scala//:scala_config.bzl", "scala_config") - -scala_config() - -load("@io_bazel_rules_scala//scala:scala.bzl", "scala_repositories") - -scala_repositories() - -load("@io_bazel_rules_scala//scala:toolchains.bzl", "scala_register_toolchains") - -scala_register_toolchains() - -maven_install( - name = "rules_proto_grpc_scala_maven", - artifacts = MAVEN_ARTIFACTS, - repositories = [ - "https://repo1.maven.org/maven2", - ], -) +#load("//scala:repositories.bzl", "MAVEN_ARTIFACTS", "scala_repos") +# +#scala_repos() +# +#load("@io_bazel_rules_scala//:scala_config.bzl", "scala_config") +# +#scala_config() +# +#load("@io_bazel_rules_scala//scala:scala.bzl", "scala_repositories") +# +#scala_repositories() +# +#load("@io_bazel_rules_scala//scala:toolchains.bzl", "scala_register_toolchains") +# +#scala_register_toolchains() +# +#maven_install( +# name = "rules_proto_grpc_scala_maven", +# artifacts = MAVEN_ARTIFACTS, +# repositories = [ +# "https://repo1.maven.org/maven2", +# ], +#) # # Swift diff --git a/docs/index.rst b/docs/index.rst index 417ed7da0..cfb8e7170 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -92,9 +92,9 @@ notified of new releases, you can use GitHub's 'Watch Releases Only' on the repo http_archive( name = "rules_proto_grpc", - sha256 = "fb7fc7a3c19a92b2f15ed7c4ffb2983e956625c1436f57a3430b897ba9864059", - strip_prefix = "rules_proto_grpc-4.3.0", - urls = ["https://github.com/rules-proto-grpc/rules_proto_grpc/archive/4.3.0.tar.gz"], + sha256 = "{ARCHIVE_TAR_GZ_SHA256}", + strip_prefix = "rules_proto_grpc-{GIT_COMMIT_ID}", + urls = ["https://github.com/rules-proto-grpc/rules_proto_grpc/archive/{GIT_COMMIT_ID}.tar.gz"], ) load("@rules_proto_grpc//:repositories.bzl", "rules_proto_grpc_toolchains", "rules_proto_grpc_repos") diff --git a/docs/lang/kotlin.rst b/docs/lang/kotlin.rst new file mode 100644 index 000000000..ca5151c48 --- /dev/null +++ b/docs/lang/kotlin.rst @@ -0,0 +1,442 @@ +:author: rules_proto_grpc +:description: rules_proto_grpc Bazel rules for Kotlin +:keywords: Bazel, Protobuf, gRPC, Protocol Buffers, Rules, Build, Starlark, Kotlin + + +Kotlin +====== + +Rules for generating Kotlin protobuf and gRPC ``.jar`` files and libraries using standard Protocol Buffers, `gRPC-Java ` and `gRPC-Kotlin `_. Libraries are created with the `rules_kotlin ` kt_jvm_library`` + +.. list-table:: Rules + :widths: 1 2 + :header-rows: 1 + + * - Rule + - Description + * - `kotlin_proto_compile`_ + - Generates a Kotlin (JVM) protobuf srcjar file + * - `kotlin_grpc_compile`_ + - Generates a Kotlin (JVM) protobuf and gRPC srcjar file + * - `kotlin_proto_library`_ + - Generates a Kotlin (JVM) protobuf library using ``kt_jvm_library`` + * - `kotlin_grpc_library`_ + - Generates a Kotlin (JVM) protobuf and gRPC library using ``kt_jvm_library`` + +.. _kotlin_proto_compile: + +kotlin_proto_compile +-------------------- + +Generates a Kotlin (JVM) protobuf srcjar file + +Example +******* + +Full example project can be found `here `__ + +``WORKSPACE`` +^^^^^^^^^^^^^ + +.. code-block:: python + + load("@rules_proto_grpc//kotlin:repositories.bzl", rules_proto_grpc_kotlin_repos = "kotlin_repos") + + rules_proto_grpc_kotlin_repos() + +``BUILD.bazel`` +^^^^^^^^^^^^^^^ + +.. code-block:: python + + load("@rules_proto_grpc//kotlin:defs.bzl", "kotlin_proto_compile") + + kotlin_proto_compile( + name = "person_kotlin_proto", + protos = ["@rules_proto_grpc//example/proto:person_proto"], + ) + + kotlin_proto_compile( + name = "place_kotlin_proto", + protos = ["@rules_proto_grpc//example/proto:place_proto"], + ) + + kotlin_proto_compile( + name = "thing_kotlin_proto", + protos = ["@rules_proto_grpc//example/proto:thing_proto"], + ) + +Attributes +********** + +.. list-table:: Attributes for kotlin_proto_compile + :widths: 1 1 1 1 4 + :header-rows: 1 + + * - Name + - Type + - Mandatory + - Default + - Description + * - ``protos`` + - ``label_list`` + - true + - + - List of labels that provide the ``ProtoInfo`` provider (such as ``proto_library`` from ``rules_proto``) + * - ``options`` + - ``string_list_dict`` + - false + - ``[]`` + - Extra options to pass to plugins, as a dict of plugin label -> list of strings. The key * can be used exclusively to apply to all plugins + * - ``verbose`` + - ``int`` + - false + - ``0`` + - The verbosity level. Supported values and results are 0: Show nothing, 1: Show command, 2: Show command and sandbox after running protoc, 3: Show command and sandbox before and after running protoc, 4. Show env, command, expected outputs and sandbox before and after running protoc + * - ``prefix_path`` + - ``string`` + - false + - ``""`` + - Path to prefix to the generated files in the output directory + * - ``extra_protoc_args`` + - ``string_list`` + - false + - ``[]`` + - A list of extra command line arguments to pass directly to protoc, not as plugin options + * - ``extra_protoc_files`` + - ``label_list`` + - false + - ``[]`` + - List of labels that provide extra files to be available during protoc execution + * - ``output_mode`` + - ``string`` + - false + - ``PREFIXED`` + - The output mode for the target. PREFIXED (the default) will output to a directory named by the target within the current package root, NO_PREFIX will output directly to the current package. Using NO_PREFIX may lead to conflicting writes + +Plugins +******* + +- `@rules_proto_grpc//kotlin:kotlin_plugin `__ + +.. _kotlin_grpc_compile: + +kotlin_grpc_compile +------------------- + +Generates a Kotlin (JVM) protobuf and gRPC srcjar file + +Example +******* + +Full example project can be found `here `__ + +``WORKSPACE`` +^^^^^^^^^^^^^ + +.. code-block:: python + + load("@rules_proto_grpc//kotlin:repositories.bzl", rules_proto_grpc_kotlin_repos = "kotlin_repos") + + rules_proto_grpc_kotlin_repos() + +``BUILD.bazel`` +^^^^^^^^^^^^^^^ + +.. code-block:: python + + load("@rules_proto_grpc//kotlin:defs.bzl", "kotlin_grpc_compile") + + kotlin_grpc_compile( + name = "thing_kotlin_grpc", + protos = ["@rules_proto_grpc//example/proto:thing_proto"], + ) + + kotlin_grpc_compile( + name = "greeter_kotlin_grpc", + protos = ["@rules_proto_grpc//example/proto:greeter_grpc"], + ) + +Attributes +********** + +.. list-table:: Attributes for kotlin_grpc_compile + :widths: 1 1 1 1 4 + :header-rows: 1 + + * - Name + - Type + - Mandatory + - Default + - Description + * - ``protos`` + - ``label_list`` + - true + - + - List of labels that provide the ``ProtoInfo`` provider (such as ``proto_library`` from ``rules_proto``) + * - ``options`` + - ``string_list_dict`` + - false + - ``[]`` + - Extra options to pass to plugins, as a dict of plugin label -> list of strings. The key * can be used exclusively to apply to all plugins + * - ``verbose`` + - ``int`` + - false + - ``0`` + - The verbosity level. Supported values and results are 0: Show nothing, 1: Show command, 2: Show command and sandbox after running protoc, 3: Show command and sandbox before and after running protoc, 4. Show env, command, expected outputs and sandbox before and after running protoc + * - ``prefix_path`` + - ``string`` + - false + - ``""`` + - Path to prefix to the generated files in the output directory + * - ``extra_protoc_args`` + - ``string_list`` + - false + - ``[]`` + - A list of extra command line arguments to pass directly to protoc, not as plugin options + * - ``extra_protoc_files`` + - ``label_list`` + - false + - ``[]`` + - List of labels that provide extra files to be available during protoc execution + * - ``output_mode`` + - ``string`` + - false + - ``PREFIXED`` + - The output mode for the target. PREFIXED (the default) will output to a directory named by the target within the current package root, NO_PREFIX will output directly to the current package. Using NO_PREFIX may lead to conflicting writes + +Plugins +******* + +- `@rules_proto_grpc//kotlin:kotlin_plugin `__ +- `@rules_proto_grpc//kotlin:grpc_kotlin_plugin `__ + +.. _kotlin_proto_library: + +kotlin_proto_library +-------------------- + +Generates a Kotlin (JVM) protobuf library using ``kt_jvm_library`` + +Example +******* + +Full example project can be found `here `__ + +``WORKSPACE`` +^^^^^^^^^^^^^ + +.. code-block:: python + + load("@rules_proto_grpc//kotlin:repositories.bzl", rules_proto_grpc_kotlin_repos = "kotlin_repos") + + rules_proto_grpc_kotlin_repos() + +``BUILD.bazel`` +^^^^^^^^^^^^^^^ + +.. code-block:: python + + load("@rules_proto_grpc//kotlin:defs.bzl", "kotlin_proto_library") + + kotlin_proto_library( + name = "person_kotlin_proto", + protos = ["@rules_proto_grpc//example/proto:person_proto"], + deps = ["place_kotlin_proto"], + ) + + kotlin_proto_library( + name = "place_kotlin_proto", + protos = ["@rules_proto_grpc//example/proto:place_proto"], + deps = ["thing_kotlin_proto"], + ) + + kotlin_proto_library( + name = "thing_kotlin_proto", + protos = ["@rules_proto_grpc//example/proto:thing_proto"], + ) + +Attributes +********** + +.. list-table:: Attributes for kotlin_proto_library + :widths: 1 1 1 1 4 + :header-rows: 1 + + * - Name + - Type + - Mandatory + - Default + - Description + * - ``protos`` + - ``label_list`` + - true + - + - List of labels that provide the ``ProtoInfo`` provider (such as ``proto_library`` from ``rules_proto``) + * - ``options`` + - ``string_list_dict`` + - false + - ``[]`` + - Extra options to pass to plugins, as a dict of plugin label -> list of strings. The key * can be used exclusively to apply to all plugins + * - ``verbose`` + - ``int`` + - false + - ``0`` + - The verbosity level. Supported values and results are 0: Show nothing, 1: Show command, 2: Show command and sandbox after running protoc, 3: Show command and sandbox before and after running protoc, 4. Show env, command, expected outputs and sandbox before and after running protoc + * - ``prefix_path`` + - ``string`` + - false + - ``""`` + - Path to prefix to the generated files in the output directory + * - ``extra_protoc_args`` + - ``string_list`` + - false + - ``[]`` + - A list of extra command line arguments to pass directly to protoc, not as plugin options + * - ``extra_protoc_files`` + - ``label_list`` + - false + - ``[]`` + - List of labels that provide extra files to be available during protoc execution + * - ``output_mode`` + - ``string`` + - false + - ``PREFIXED`` + - The output mode for the target. PREFIXED (the default) will output to a directory named by the target within the current package root, NO_PREFIX will output directly to the current package. Using NO_PREFIX may lead to conflicting writes + * - ``deps`` + - ``label_list`` + - false + - ``[]`` + - List of labels to pass as deps attr to underlying lang_library rule + * - ``exports`` + - ``label_list`` + - false + - ``[]`` + - List of labels to pass as exports attr to underlying lang_library rule + +.. _kotlin_grpc_library: + +kotlin_grpc_library +------------------- + +Generates a Kotlin (JVM) protobuf and gRPC library using ``kt_jvm_library`` + +Example +******* + +Full example project can be found `here `__ + +``WORKSPACE`` +^^^^^^^^^^^^^ + +.. code-block:: python + + load("@rules_proto_grpc//kotlin:repositories.bzl", rules_proto_grpc_kotlin_repos = "kotlin_repos") + + rules_proto_grpc_kotlin_repos() + + 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() + + load("@rules_jvm_external//:defs.bzl", "maven_install") + load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_ARTIFACTS", "IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS", "grpc_java_repositories") + load("@com_github_grpc_grpc_kotlin//:repositories.bzl", "IO_GRPC_GRPC_KOTLIN_ARTIFACTS", "IO_GRPC_GRPC_KOTLIN_OVERRIDE_TARGETS", "grpc_kt_repositories") + + maven_install( + artifacts = IO_GRPC_GRPC_JAVA_ARTIFACTS + IO_GRPC_GRPC_KOTLIN_ARTIFACTS, + generate_compat_repositories = True, + override_targets = dict(IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS.items() + + IO_GRPC_GRPC_KOTLIN_OVERRIDE_TARGETS.items()), + repositories = [ + "https://repo.maven.apache.org/maven2/", + ], + ) + + load("@maven//:compat.bzl", "compat_repositories") + + compat_repositories() + + grpc_java_repositories() + + grpc_kt_repositories() + +``BUILD.bazel`` +^^^^^^^^^^^^^^^ + +.. code-block:: python + + load("@rules_proto_grpc//kotlin:defs.bzl", "kotlin_grpc_library") + + kotlin_grpc_library( + name = "thing_kotlin_grpc", + protos = ["@rules_proto_grpc//example/proto:thing_proto"], + ) + + kotlin_grpc_library( + name = "greeter_kotlin_grpc", + protos = ["@rules_proto_grpc//example/proto:greeter_grpc"], + deps = ["thing_kotlin_grpc"], + ) + +Attributes +********** + +.. list-table:: Attributes for kotlin_grpc_library + :widths: 1 1 1 1 4 + :header-rows: 1 + + * - Name + - Type + - Mandatory + - Default + - Description + * - ``protos`` + - ``label_list`` + - true + - + - List of labels that provide the ``ProtoInfo`` provider (such as ``proto_library`` from ``rules_proto``) + * - ``options`` + - ``string_list_dict`` + - false + - ``[]`` + - Extra options to pass to plugins, as a dict of plugin label -> list of strings. The key * can be used exclusively to apply to all plugins + * - ``verbose`` + - ``int`` + - false + - ``0`` + - The verbosity level. Supported values and results are 0: Show nothing, 1: Show command, 2: Show command and sandbox after running protoc, 3: Show command and sandbox before and after running protoc, 4. Show env, command, expected outputs and sandbox before and after running protoc + * - ``prefix_path`` + - ``string`` + - false + - ``""`` + - Path to prefix to the generated files in the output directory + * - ``extra_protoc_args`` + - ``string_list`` + - false + - ``[]`` + - A list of extra command line arguments to pass directly to protoc, not as plugin options + * - ``extra_protoc_files`` + - ``label_list`` + - false + - ``[]`` + - List of labels that provide extra files to be available during protoc execution + * - ``output_mode`` + - ``string`` + - false + - ``PREFIXED`` + - The output mode for the target. PREFIXED (the default) will output to a directory named by the target within the current package root, NO_PREFIX will output directly to the current package. Using NO_PREFIX may lead to conflicting writes + * - ``deps`` + - ``label_list`` + - false + - ``[]`` + - List of labels to pass as deps attr to underlying lang_library rule + * - ``exports`` + - ``label_list`` + - false + - ``[]`` + - List of labels to pass as exports attr to underlying lang_library rule diff --git a/example/kotlin/kotlin_grpc_compile/BUILD.bazel b/example/kotlin/kotlin_grpc_compile/BUILD.bazel new file mode 100644 index 000000000..08ab419a8 --- /dev/null +++ b/example/kotlin/kotlin_grpc_compile/BUILD.bazel @@ -0,0 +1,11 @@ +load("@rules_proto_grpc//kotlin:defs.bzl", "kotlin_grpc_compile") + +kotlin_grpc_compile( + name = "thing_kotlin_grpc", + protos = ["@rules_proto_grpc//example/proto:thing_proto"], +) + +kotlin_grpc_compile( + name = "greeter_kotlin_grpc", + protos = ["@rules_proto_grpc//example/proto:greeter_grpc"], +) diff --git a/example/kotlin/kotlin_grpc_compile/WORKSPACE b/example/kotlin/kotlin_grpc_compile/WORKSPACE new file mode 100644 index 000000000..e265cd568 --- /dev/null +++ b/example/kotlin/kotlin_grpc_compile/WORKSPACE @@ -0,0 +1,20 @@ +local_repository( + name = "rules_proto_grpc", + path = "../../../", +) + +load("@rules_proto_grpc//:repositories.bzl", "rules_proto_grpc_repos", "rules_proto_grpc_toolchains") + +rules_proto_grpc_toolchains() + +rules_proto_grpc_repos() + +load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") + +rules_proto_dependencies() + +rules_proto_toolchains() + +load("@rules_proto_grpc//kotlin:repositories.bzl", rules_proto_grpc_kotlin_repos = "kotlin_repos") + +rules_proto_grpc_kotlin_repos() diff --git a/example/kotlin/kotlin_grpc_library/BUILD.bazel b/example/kotlin/kotlin_grpc_library/BUILD.bazel new file mode 100644 index 000000000..c79ffa172 --- /dev/null +++ b/example/kotlin/kotlin_grpc_library/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_proto_grpc//kotlin:defs.bzl", "kotlin_grpc_library") + +kotlin_grpc_library( + name = "thing_kotlin_grpc", + protos = ["@rules_proto_grpc//example/proto:thing_proto"], +) + +kotlin_grpc_library( + name = "greeter_kotlin_grpc", + protos = ["@rules_proto_grpc//example/proto:greeter_grpc"], + deps = ["thing_kotlin_grpc"], +) diff --git a/example/kotlin/kotlin_grpc_library/WORKSPACE b/example/kotlin/kotlin_grpc_library/WORKSPACE new file mode 100644 index 000000000..ec426fe12 --- /dev/null +++ b/example/kotlin/kotlin_grpc_library/WORKSPACE @@ -0,0 +1,50 @@ +local_repository( + name = "rules_proto_grpc", + path = "../../../", +) + +load("@rules_proto_grpc//:repositories.bzl", "rules_proto_grpc_repos", "rules_proto_grpc_toolchains") + +rules_proto_grpc_toolchains() + +rules_proto_grpc_repos() + +load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") + +rules_proto_dependencies() + +rules_proto_toolchains() + +load("@rules_proto_grpc//kotlin:repositories.bzl", rules_proto_grpc_kotlin_repos = "kotlin_repos") + +rules_proto_grpc_kotlin_repos() + +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() + +load("@rules_jvm_external//:defs.bzl", "maven_install") +load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_ARTIFACTS", "IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS", "grpc_java_repositories") +load("@com_github_grpc_grpc_kotlin//:repositories.bzl", "IO_GRPC_GRPC_KOTLIN_ARTIFACTS", "IO_GRPC_GRPC_KOTLIN_OVERRIDE_TARGETS", "grpc_kt_repositories") + +maven_install( + artifacts = IO_GRPC_GRPC_JAVA_ARTIFACTS + IO_GRPC_GRPC_KOTLIN_ARTIFACTS, + generate_compat_repositories = True, + override_targets = dict(IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS.items() + + IO_GRPC_GRPC_KOTLIN_OVERRIDE_TARGETS.items()), + repositories = [ + "https://repo.maven.apache.org/maven2/", + ], +) + +load("@maven//:compat.bzl", "compat_repositories") + +compat_repositories() + +grpc_java_repositories() + +grpc_kt_repositories() diff --git a/example/kotlin/kotlin_proto_compile/BUILD.bazel b/example/kotlin/kotlin_proto_compile/BUILD.bazel new file mode 100644 index 000000000..596487220 --- /dev/null +++ b/example/kotlin/kotlin_proto_compile/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_proto_grpc//kotlin:defs.bzl", "kotlin_proto_compile") + +kotlin_proto_compile( + name = "person_kotlin_proto", + protos = ["@rules_proto_grpc//example/proto:person_proto"], +) + +kotlin_proto_compile( + name = "place_kotlin_proto", + protos = ["@rules_proto_grpc//example/proto:place_proto"], +) + +kotlin_proto_compile( + name = "thing_kotlin_proto", + protos = ["@rules_proto_grpc//example/proto:thing_proto"], +) diff --git a/example/kotlin/kotlin_proto_compile/WORKSPACE b/example/kotlin/kotlin_proto_compile/WORKSPACE new file mode 100644 index 000000000..e265cd568 --- /dev/null +++ b/example/kotlin/kotlin_proto_compile/WORKSPACE @@ -0,0 +1,20 @@ +local_repository( + name = "rules_proto_grpc", + path = "../../../", +) + +load("@rules_proto_grpc//:repositories.bzl", "rules_proto_grpc_repos", "rules_proto_grpc_toolchains") + +rules_proto_grpc_toolchains() + +rules_proto_grpc_repos() + +load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") + +rules_proto_dependencies() + +rules_proto_toolchains() + +load("@rules_proto_grpc//kotlin:repositories.bzl", rules_proto_grpc_kotlin_repos = "kotlin_repos") + +rules_proto_grpc_kotlin_repos() diff --git a/example/kotlin/kotlin_proto_library/BUILD.bazel b/example/kotlin/kotlin_proto_library/BUILD.bazel new file mode 100644 index 000000000..40ab4dc35 --- /dev/null +++ b/example/kotlin/kotlin_proto_library/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_proto_grpc//kotlin:defs.bzl", "kotlin_proto_library") + +kotlin_proto_library( + name = "person_kotlin_proto", + protos = ["@rules_proto_grpc//example/proto:person_proto"], + deps = ["place_kotlin_proto"], +) + +kotlin_proto_library( + name = "place_kotlin_proto", + protos = ["@rules_proto_grpc//example/proto:place_proto"], + deps = ["thing_kotlin_proto"], +) + +kotlin_proto_library( + name = "thing_kotlin_proto", + protos = ["@rules_proto_grpc//example/proto:thing_proto"], +) diff --git a/example/kotlin/kotlin_proto_library/WORKSPACE b/example/kotlin/kotlin_proto_library/WORKSPACE new file mode 100644 index 000000000..e265cd568 --- /dev/null +++ b/example/kotlin/kotlin_proto_library/WORKSPACE @@ -0,0 +1,20 @@ +local_repository( + name = "rules_proto_grpc", + path = "../../../", +) + +load("@rules_proto_grpc//:repositories.bzl", "rules_proto_grpc_repos", "rules_proto_grpc_toolchains") + +rules_proto_grpc_toolchains() + +rules_proto_grpc_repos() + +load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") + +rules_proto_dependencies() + +rules_proto_toolchains() + +load("@rules_proto_grpc//kotlin:repositories.bzl", rules_proto_grpc_kotlin_repos = "kotlin_repos") + +rules_proto_grpc_kotlin_repos() diff --git a/java/example/routeguide/io/grpc/examples/routeguide/RouteGuideClient.java b/java/example/routeguide/io/grpc/examples/routeguide/RouteGuideClient.java index 44b2227dd..d46bfba17 100644 --- a/java/example/routeguide/io/grpc/examples/routeguide/RouteGuideClient.java +++ b/java/example/routeguide/io/grpc/examples/routeguide/RouteGuideClient.java @@ -38,7 +38,7 @@ * Sample client code that makes gRPC calls to the server. */ public class RouteGuideClient { - private static final Logger logger = Logger.getLogger(RouteGuideClient.class.getName()); + private static final Logger logger = Logger.getLogger(io.grpc.examples.routeguidekt.RouteGuideClient.class.getName()); private final ManagedChannel channel; private final RouteGuideBlockingStub blockingStub; @@ -268,7 +268,7 @@ public static void main(String[] args) throws InterruptedException { port = Integer.parseInt(serverPort); } - RouteGuideClient client = new RouteGuideClient("localhost", port); + io.grpc.examples.routeguidekt.RouteGuideClient client = new io.grpc.examples.routeguidekt.RouteGuideClient("localhost", port); try { // Looking for a valid feature client.getFeature(409146138, -746188906); diff --git a/java/example/routeguide/io/grpc/examples/routeguide/RouteGuideServer.java b/java/example/routeguide/io/grpc/examples/routeguide/RouteGuideServer.java index ebb3c7bcd..475ebe4ca 100644 --- a/java/example/routeguide/io/grpc/examples/routeguide/RouteGuideServer.java +++ b/java/example/routeguide/io/grpc/examples/routeguide/RouteGuideServer.java @@ -43,7 +43,7 @@ * A sample gRPC server that serve the RouteGuide (see route_guide.proto) service. */ public class RouteGuideServer { - private static final Logger logger = Logger.getLogger(RouteGuideServer.class.getName()); + private static final Logger logger = Logger.getLogger(io.grpc.examples.routeguidekt.RouteGuideServer.class.getName()); private final int port; private final Server server; @@ -74,7 +74,7 @@ public void start() throws IOException { public void run() { // Use stderr here since the logger may has been reset by its JVM shutdown hook. System.err.println("*** shutting down gRPC server since JVM is shutting down"); - RouteGuideServer.this.stop(); + io.grpc.examples.routeguidekt.RouteGuideServer.this.stop(); System.err.println("*** server shut down"); } }); @@ -105,7 +105,7 @@ public static void main(String[] args) throws Exception { if (serverPort != null && !serverPort.isEmpty()) { port = Integer.parseInt(serverPort); } - RouteGuideServer server = new RouteGuideServer(port); + io.grpc.examples.routeguidekt.RouteGuideServer server = new io.grpc.examples.routeguidekt.RouteGuideServer(port); server.start(); server.blockUntilShutdown(); } diff --git a/java/example/routeguide/io/grpc/examples/routeguide/RouteGuideUtil.java b/java/example/routeguide/io/grpc/examples/routeguide/RouteGuideUtil.java index 090a1bf01..9c3ea2ba5 100644 --- a/java/example/routeguide/io/grpc/examples/routeguide/RouteGuideUtil.java +++ b/java/example/routeguide/io/grpc/examples/routeguide/RouteGuideUtil.java @@ -17,6 +17,8 @@ package io.grpc.examples.routeguide; import com.google.protobuf.util.JsonFormat; +import io.grpc.examples.routeguidekt.RouteGuideServer; + import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; diff --git a/kotlin/BUILD.bazel b/kotlin/BUILD.bazel new file mode 100644 index 000000000..3b41e8249 --- /dev/null +++ b/kotlin/BUILD.bazel @@ -0,0 +1,15 @@ +load("//:defs.bzl", "proto_plugin") + +proto_plugin( + name = "kotlin_plugin", + out = "{name}.jar", + protoc_plugin_name = "kotlin", + visibility = ["//visibility:public"], +) + +proto_plugin( + name = "grpc_kotlin_plugin", + out = "{name}_grpc.jar", + tool = "@com_github_grpc_grpc_kotlin//compiler/src/main/java/io/grpc/kotlin/generator:GeneratorRunner", + visibility = ["//visibility:public"], +) diff --git a/kotlin/defs.bzl b/kotlin/defs.bzl new file mode 100644 index 000000000..608a09826 --- /dev/null +++ b/kotlin/defs.bzl @@ -0,0 +1,12 @@ +"""kotlin protobuf and grpc rules.""" + +load(":kotlin_proto_compile.bzl", _kotlin_proto_compile = "kotlin_proto_compile") +load(":kotlin_grpc_compile.bzl", _kotlin_grpc_compile = "kotlin_grpc_compile") +load(":kotlin_proto_library.bzl", _kotlin_proto_library = "kotlin_proto_library") +load(":kotlin_grpc_library.bzl", _kotlin_grpc_library = "kotlin_grpc_library") + +# Export kotlin rules +kotlin_proto_compile = _kotlin_proto_compile +kotlin_grpc_compile = _kotlin_grpc_compile +kotlin_proto_library = _kotlin_proto_library +kotlin_grpc_library = _kotlin_grpc_library diff --git a/kotlin/example/routeguide/BUILD.bazel b/kotlin/example/routeguide/BUILD.bazel new file mode 100644 index 000000000..0c295143f --- /dev/null +++ b/kotlin/example/routeguide/BUILD.bazel @@ -0,0 +1,46 @@ +# Slightly updated routeguide example from https://github.com/grpc/grpc-kotlin + +load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_binary") +load("//kotlin:defs.bzl", "kotlin_grpc_library") + +proto_library( + name = "route_guide_proto", + srcs = ["route_guide.proto"], + deps = ["@com_google_protobuf//:duration_proto"], +) + +kotlin_grpc_library( + name = "routeguide", + protos = [":route_guide_proto"], +) + +kt_jvm_binary( + name = "client", + srcs = [ + "io/grpc/examples/routeguidekt/Database.kt", + "io/grpc/examples/routeguidekt/Points.kt", + "io/grpc/examples/routeguidekt/RouteGuideClient.kt", + ], + main_class = "io.grpc.examples.routeguide.RouteGuideClient", + resources = ["route_guide_db.json"], + visibility = ["//example/routeguide:__pkg__"], + deps = [ + ":routeguide", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm", + ], +) + +kt_jvm_binary( + name = "server", + srcs = [ + "io/grpc/examples/routeguidekt/Database.kt", + "io/grpc/examples/routeguidekt/Points.kt", + "io/grpc/examples/routeguidekt/RouteGuideServer.kt", + ], + main_class = "io.grpc.examples.routeguide.RouteGuideServer", + resources = ["route_guide_db.json"], + visibility = ["//example/routeguide:__pkg__"], + deps = [ + ":routeguide", + ], +) diff --git a/kotlin/example/routeguide/io/grpc/examples/routeguidekt/Database.kt b/kotlin/example/routeguide/io/grpc/examples/routeguidekt/Database.kt new file mode 100644 index 000000000..b0fd1c0fb --- /dev/null +++ b/kotlin/example/routeguide/io/grpc/examples/routeguidekt/Database.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2020 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.examples.routeguidekt + +import com.google.protobuf.util.JsonFormat + +object Database { + fun features(): List { + return javaClass.getResourceAsStream("route_guide_db.json").use { + FeatureDatabase.newBuilder().apply { + JsonFormat.parser().merge(it.reader(), this) + } + }.build().featureList + } +} \ No newline at end of file diff --git a/kotlin/example/routeguide/io/grpc/examples/routeguidekt/Points.kt b/kotlin/example/routeguide/io/grpc/examples/routeguidekt/Points.kt new file mode 100644 index 000000000..52842591b --- /dev/null +++ b/kotlin/example/routeguide/io/grpc/examples/routeguidekt/Points.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2020 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.examples.routeguidekt + +import kotlin.math.atan2 +import kotlin.math.cos +import kotlin.math.pow +import kotlin.math.roundToInt +import kotlin.math.sin +import kotlin.math.sqrt + +private const val EARTH_RADIUS_IN_M = 6371000 + +private fun Int.toRadians() = Math.toRadians(toDouble()) + +infix fun Point.distanceTo(other: Point): Int { + val lat1 = latitude.toRadians() + val long1 = longitude.toRadians() + val lat2 = other.latitude.toRadians() + val long2 = other.latitude.toRadians() + + val dLat = lat2 - lat1 + val dLong = long2 - long1 + + val a = sin(dLat / 2).pow(2) + cos(lat1) * cos(lat2) * sin(dLong / 2).pow(2) + val c = 2 * atan2(sqrt(a), sqrt(1 - a)) + return (EARTH_RADIUS_IN_M * c).roundToInt() +} + +operator fun Rectangle.contains(p: Point): Boolean { + val lowLong = minOf(lo.longitude, hi.longitude) + val hiLong = maxOf(lo.longitude, hi.longitude) + val lowLat = minOf(lo.latitude, hi.latitude) + val hiLat = maxOf(lo.latitude, hi.latitude) + return p.longitude in lowLong..hiLong && p.latitude in lowLat..hiLat +} + +private fun Int.normalizeCoordinate(): Double = this / 1.0e7 + +fun Point.toStr(): String { + val lat = latitude.normalizeCoordinate() + val long = longitude.normalizeCoordinate() + return "$lat, $long" +} + +fun Feature.exists(): Boolean = name.isNotEmpty() diff --git a/kotlin/example/routeguide/io/grpc/examples/routeguidekt/RouteGuideClient.kt b/kotlin/example/routeguide/io/grpc/examples/routeguidekt/RouteGuideClient.kt new file mode 100644 index 000000000..c7c1147e6 --- /dev/null +++ b/kotlin/example/routeguide/io/grpc/examples/routeguidekt/RouteGuideClient.kt @@ -0,0 +1,140 @@ +/* + * Copyright 2020 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.examples.routeguidekt + +import io.grpc.ManagedChannel +import io.grpc.ManagedChannelBuilder +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.flow +import java.io.Closeable +import java.util.concurrent.TimeUnit +import kotlin.random.Random +import kotlin.random.nextLong + +class RouteGuideClient(private val channel: ManagedChannel) : Closeable { + private val random = Random(314159) + private val stub = RouteGuideGrpcKt.RouteGuideCoroutineStub(channel) + + override fun close() { + channel.shutdown().awaitTermination(5, TimeUnit.SECONDS) + } + + suspend fun getFeature(latitude: Int, longitude: Int) { + println("*** GetFeature: lat=$latitude lon=$longitude") + + val request = point(latitude, longitude) + val feature = stub.getFeature(request) + + if (feature.exists()) { + println("Found feature called \"${feature.name}\" at ${feature.location.toStr()}") + } else { + println("Found no feature at ${request.toStr()}") + } + } + + suspend fun listFeatures(lowLat: Int, lowLon: Int, hiLat: Int, hiLon: Int) { + println("*** ListFeatures: lowLat=$lowLat lowLon=$lowLon hiLat=$hiLat liLon=$hiLon") + + val request = rectangle { + lo = point(lowLat, lowLon) + hi = point(hiLat, hiLon) + } + var i = 1 + stub.listFeatures(request).collect { feature -> + println("Result #${i++}: $feature") + } + } + + suspend fun recordRoute(points: Flow) { + println("*** RecordRoute") + val summary = stub.recordRoute(points) + println("Finished trip with ${summary.pointCount} points.") + println("Passed ${summary.featureCount} features.") + println("Travelled ${summary.distance} meters.") + val duration = summary.elapsedTime.seconds + println("It took $duration seconds.") + } + + fun generateRoutePoints(features: List, numPoints: Int): Flow = flow { + for (i in 1..numPoints) { + val feature = features.random(random) + println("Visiting point ${feature.location.toStr()}") + emit(feature.location) + delay(timeMillis = random.nextLong(500L..1500L)) + } + } + + suspend fun routeChat() { + println("*** RouteChat") + val requests = generateOutgoingNotes() + stub.routeChat(requests).collect { note -> + println("Got message \"${note.message}\" at ${note.location.toStr()}") + } + println("Finished RouteChat") + } + + private fun generateOutgoingNotes(): Flow = flow { + val notes = listOf( + routeNote { + message = "First message" + location = point(0, 0) + }, + routeNote { + message = "Second message" + location = point(0, 0) + }, + routeNote { + message = "Third message" + location = point(10000000, 0) + }, + routeNote { + message = "Fourth message" + location = point(10000000, 10000000) + }, + routeNote { + message = "Last message" + location = point(0, 0) + }, + ) + for (note in notes) { + println("Sending message \"${note.message}\" at ${note.location.toStr()}") + emit(note) + delay(500) + } + } +} + +suspend fun main() { + val features = Database.features() + + val channel = ManagedChannelBuilder.forAddress("localhost", 8980).usePlaintext().build() + + RouteGuideClient(channel).use { + it.getFeature(409146138, -746188906) + it.getFeature(0, 0) + it.listFeatures(400000000, -750000000, 420000000, -730000000) + it.recordRoute(it.generateRoutePoints(features, 10)) + it.routeChat() + } +} + +private fun point(lat: Int, lon: Int): Point = io.grpc.examples.routeguidekt.point { + latitude = lat + longitude = lon +} \ No newline at end of file diff --git a/kotlin/example/routeguide/io/grpc/examples/routeguidekt/RouteGuideServer.kt b/kotlin/example/routeguide/io/grpc/examples/routeguidekt/RouteGuideServer.kt new file mode 100644 index 000000000..5783e38cb --- /dev/null +++ b/kotlin/example/routeguide/io/grpc/examples/routeguidekt/RouteGuideServer.kt @@ -0,0 +1,120 @@ +/* + * Copyright 2020 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.examples.routeguidekt + +import com.google.common.base.Stopwatch +import com.google.common.base.Ticker +import com.google.protobuf.util.Durations +import io.grpc.Server +import io.grpc.ServerBuilder +import java.util.Collections +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.TimeUnit +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.asFlow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.flow + +/** + * Kotlin adaptation of RouteGuideServer from the Java gRPC example. + */ +class RouteGuideServer( + val port: Int, + val features: Collection = Database.features(), + val server: Server = ServerBuilder.forPort(port).addService(RouteGuideService(features)).build() +) { + + fun start() { + server.start() + println("Server started, listening on $port") + Runtime.getRuntime().addShutdownHook( + Thread { + println("*** shutting down gRPC server since JVM is shutting down") + this@RouteGuideServer.stop() + println("*** server shut down") + } + ) + } + + fun stop() { + server.shutdown() + } + + fun blockUntilShutdown() { + server.awaitTermination() + } + + class RouteGuideService( + val features: Collection, + val ticker: Ticker = Ticker.systemTicker() + ) : RouteGuideGrpcKt.RouteGuideCoroutineImplBase() { + private val routeNotes = ConcurrentHashMap>() + + override suspend fun getFeature(request: Point): Feature = + // No feature was found, return an unnamed feature. + features.find { it.location == request } ?: Feature.newBuilder().apply { location = request }.build() + + override fun listFeatures(request: Rectangle): Flow { + return features.asFlow().filter { it.exists() && it.location in request } + } + + override suspend fun recordRoute(requests: Flow): RouteSummary { + var pointCount = 0 + var featureCount = 0 + var distance = 0 + var previous: Point? = null + val stopwatch = Stopwatch.createStarted(ticker) + requests.collect { request -> + pointCount++ + if (getFeature(request).exists()) { + featureCount++ + } + val prev = previous + if (prev != null) { + distance += prev distanceTo request + } + previous = request + } + return RouteSummary.newBuilder().apply { + this.pointCount = pointCount + this.featureCount = featureCount + this.distance = distance + this.elapsedTime = Durations.fromMicros(stopwatch.elapsed(TimeUnit.MICROSECONDS)) + }.build() + } + + override fun routeChat(requests: Flow): Flow = flow { + requests.collect { note -> + val notes: MutableList = routeNotes.computeIfAbsent(note.location) { + Collections.synchronizedList(mutableListOf()) + } + for (prevNote in notes.toTypedArray()) { // thread-safe snapshot + emit(prevNote) + } + notes += note + } + } + } +} + +fun main() { + val port = 8980 + val server = RouteGuideServer(port) + server.start() + server.blockUntilShutdown() +} \ No newline at end of file diff --git a/kotlin/example/routeguide/route_guide.proto b/kotlin/example/routeguide/route_guide.proto new file mode 100644 index 000000000..cddfb65c9 --- /dev/null +++ b/kotlin/example/routeguide/route_guide.proto @@ -0,0 +1,115 @@ +// Copyright 2020 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package io.grpc.examples.routeguidekt; + +import "google/protobuf/duration.proto"; + +option java_multiple_files = true; + +// Interface exported by the server. +service RouteGuide { + // A simple RPC. + // + // Obtains the feature at a given position. + // + // A feature with an empty name is returned if there's no feature at the given + // position. + rpc GetFeature(Point) returns (Feature); + + // A server-to-client streaming RPC. + // + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + rpc ListFeatures(Rectangle) returns (stream Feature); + + // A client-to-server streaming RPC. + // + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + rpc RecordRoute(stream Point) returns (RouteSummary); + + // A Bidirectional streaming RPC. + // + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + rpc RouteChat(stream RouteNote) returns (stream RouteNote); +} + +// Points are represented as latitude-longitude pairs in the E7 representation +// (degrees multiplied by 10**7 and rounded to the nearest integer). +// Latitudes should be in the range +/- 90 degrees and longitude should be in +// the range +/- 180 degrees (inclusive). +message Point { + int32 latitude = 1; + int32 longitude = 2; +} + +// A latitude-longitude rectangle, represented as two diagonally opposite +// points "lo" and "hi". +message Rectangle { + // One corner of the rectangle. + Point lo = 1; + + // The other corner of the rectangle. + Point hi = 2; +} + +// A feature names something at a given point. +// +// If a feature could not be named, the name is empty. +message Feature { + // The name of the feature. + string name = 1; + + // The point where the feature is detected. + Point location = 2; +} + +// Not used in the RPC. Instead, this is here for the form serialized to disk. +message FeatureDatabase { + repeated Feature feature = 1; +} + +// A RouteNote is a message sent while at a given point. +message RouteNote { + // The location from which the message is sent. + Point location = 1; + + // The message to be sent. + string message = 2; +} + +// A RouteSummary is received in response to a RecordRoute rpc. +// +// It contains the number of individual points received, the number of +// detected features, and the total distance covered as the cumulative sum of +// the distance between each point. +message RouteSummary { + // The number of points received. + int32 point_count = 1; + + // The number of known features passed while traversing the route. + int32 feature_count = 2; + + // The distance covered in metres. + int32 distance = 3; + + // The duration of the traversal. + google.protobuf.Duration elapsed_time = 4; +} \ No newline at end of file diff --git a/kotlin/example/routeguide/route_guide_db.json b/kotlin/example/routeguide/route_guide_db.json new file mode 100644 index 000000000..7033efeb6 --- /dev/null +++ b/kotlin/example/routeguide/route_guide_db.json @@ -0,0 +1,603 @@ +{ + "feature": [{ + "location": { + "latitude": 407838351, + "longitude": -746143763 + }, + "name": "Patriots Path, Mendham, NJ 07945, USA" + }, { + "location": { + "latitude": 408122808, + "longitude": -743999179 + }, + "name": "101 New Jersey 10, Whippany, NJ 07981, USA" + }, { + "location": { + "latitude": 413628156, + "longitude": -749015468 + }, + "name": "U.S. 6, Shohola, PA 18458, USA" + }, { + "location": { + "latitude": 419999544, + "longitude": -740371136 + }, + "name": "5 Conners Road, Kingston, NY 12401, USA" + }, { + "location": { + "latitude": 414008389, + "longitude": -743951297 + }, + "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" + }, { + "location": { + "latitude": 419611318, + "longitude": -746524769 + }, + "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" + }, { + "location": { + "latitude": 406109563, + "longitude": -742186778 + }, + "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" + }, { + "location": { + "latitude": 416802456, + "longitude": -742370183 + }, + "name": "352 South Mountain Road, Wallkill, NY 12589, USA" + }, { + "location": { + "latitude": 412950425, + "longitude": -741077389 + }, + "name": "Bailey Turn Road, Harriman, NY 10926, USA" + }, { + "location": { + "latitude": 412144655, + "longitude": -743949739 + }, + "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" + }, { + "location": { + "latitude": 415736605, + "longitude": -742847522 + }, + "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" + }, { + "location": { + "latitude": 413843930, + "longitude": -740501726 + }, + "name": "162 Merrill Road, Highland Mills, NY 10930, USA" + }, { + "location": { + "latitude": 410873075, + "longitude": -744459023 + }, + "name": "Clinton Road, West Milford, NJ 07480, USA" + }, { + "location": { + "latitude": 412346009, + "longitude": -744026814 + }, + "name": "16 Old Brook Lane, Warwick, NY 10990, USA" + }, { + "location": { + "latitude": 402948455, + "longitude": -747903913 + }, + "name": "3 Drake Lane, Pennington, NJ 08534, USA" + }, { + "location": { + "latitude": 406337092, + "longitude": -740122226 + }, + "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" + }, { + "location": { + "latitude": 406421967, + "longitude": -747727624 + }, + "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" + }, { + "location": { + "latitude": 416318082, + "longitude": -749677716 + }, + "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" + }, { + "location": { + "latitude": 415301720, + "longitude": -748416257 + }, + "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" + }, { + "location": { + "latitude": 402647019, + "longitude": -747071791 + }, + "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" + }, { + "location": { + "latitude": 412567807, + "longitude": -741058078 + }, + "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" + }, { + "location": { + "latitude": 416855156, + "longitude": -744420597 + }, + "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" + }, { + "location": { + "latitude": 404663628, + "longitude": -744820157 + }, + "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" + }, { + "location": { + "latitude": 407113723, + "longitude": -749746483 + }, + "name": "" + }, { + "location": { + "latitude": 402133926, + "longitude": -743613249 + }, + "name": "" + }, { + "location": { + "latitude": 400273442, + "longitude": -741220915 + }, + "name": "" + }, { + "location": { + "latitude": 411236786, + "longitude": -744070769 + }, + "name": "" + }, { + "location": { + "latitude": 411633782, + "longitude": -746784970 + }, + "name": "211-225 Plains Road, Augusta, NJ 07822, USA" + }, { + "location": { + "latitude": 415830701, + "longitude": -742952812 + }, + "name": "" + }, { + "location": { + "latitude": 413447164, + "longitude": -748712898 + }, + "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" + }, { + "location": { + "latitude": 405047245, + "longitude": -749800722 + }, + "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" + }, { + "location": { + "latitude": 418858923, + "longitude": -746156790 + }, + "name": "" + }, { + "location": { + "latitude": 417951888, + "longitude": -748484944 + }, + "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" + }, { + "location": { + "latitude": 407033786, + "longitude": -743977337 + }, + "name": "26 East 3rd Street, New Providence, NJ 07974, USA" + }, { + "location": { + "latitude": 417548014, + "longitude": -740075041 + }, + "name": "" + }, { + "location": { + "latitude": 410395868, + "longitude": -744972325 + }, + "name": "" + }, { + "location": { + "latitude": 404615353, + "longitude": -745129803 + }, + "name": "" + }, { + "location": { + "latitude": 406589790, + "longitude": -743560121 + }, + "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" + }, { + "location": { + "latitude": 414653148, + "longitude": -740477477 + }, + "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" + }, { + "location": { + "latitude": 405957808, + "longitude": -743255336 + }, + "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" + }, { + "location": { + "latitude": 411733589, + "longitude": -741648093 + }, + "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" + }, { + "location": { + "latitude": 412676291, + "longitude": -742606606 + }, + "name": "1270 Lakes Road, Monroe, NY 10950, USA" + }, { + "location": { + "latitude": 409224445, + "longitude": -748286738 + }, + "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" + }, { + "location": { + "latitude": 406523420, + "longitude": -742135517 + }, + "name": "652 Garden Street, Elizabeth, NJ 07202, USA" + }, { + "location": { + "latitude": 401827388, + "longitude": -740294537 + }, + "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" + }, { + "location": { + "latitude": 410564152, + "longitude": -743685054 + }, + "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" + }, { + "location": { + "latitude": 408472324, + "longitude": -740726046 + }, + "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" + }, { + "location": { + "latitude": 412452168, + "longitude": -740214052 + }, + "name": "5 White Oak Lane, Stony Point, NY 10980, USA" + }, { + "location": { + "latitude": 409146138, + "longitude": -746188906 + }, + "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" + }, { + "location": { + "latitude": 404701380, + "longitude": -744781745 + }, + "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" + }, { + "location": { + "latitude": 409642566, + "longitude": -746017679 + }, + "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" + }, { + "location": { + "latitude": 408031728, + "longitude": -748645385 + }, + "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" + }, { + "location": { + "latitude": 413700272, + "longitude": -742135189 + }, + "name": "367 Prospect Road, Chester, NY 10918, USA" + }, { + "location": { + "latitude": 404310607, + "longitude": -740282632 + }, + "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" + }, { + "location": { + "latitude": 409319800, + "longitude": -746201391 + }, + "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" + }, { + "location": { + "latitude": 406685311, + "longitude": -742108603 + }, + "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" + }, { + "location": { + "latitude": 419018117, + "longitude": -749142781 + }, + "name": "43 Dreher Road, Roscoe, NY 12776, USA" + }, { + "location": { + "latitude": 412856162, + "longitude": -745148837 + }, + "name": "Swan Street, Pine Island, NY 10969, USA" + }, { + "location": { + "latitude": 416560744, + "longitude": -746721964 + }, + "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" + }, { + "location": { + "latitude": 405314270, + "longitude": -749836354 + }, + "name": "" + }, { + "location": { + "latitude": 414219548, + "longitude": -743327440 + }, + "name": "" + }, { + "location": { + "latitude": 415534177, + "longitude": -742900616 + }, + "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" + }, { + "location": { + "latitude": 406898530, + "longitude": -749127080 + }, + "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" + }, { + "location": { + "latitude": 407586880, + "longitude": -741670168 + }, + "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" + }, { + "location": { + "latitude": 400106455, + "longitude": -742870190 + }, + "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" + }, { + "location": { + "latitude": 400066188, + "longitude": -746793294 + }, + "name": "" + }, { + "location": { + "latitude": 418803880, + "longitude": -744102673 + }, + "name": "40 Mountain Road, Napanoch, NY 12458, USA" + }, { + "location": { + "latitude": 414204288, + "longitude": -747895140 + }, + "name": "" + }, { + "location": { + "latitude": 414777405, + "longitude": -740615601 + }, + "name": "" + }, { + "location": { + "latitude": 415464475, + "longitude": -747175374 + }, + "name": "48 North Road, Forestburgh, NY 12777, USA" + }, { + "location": { + "latitude": 404062378, + "longitude": -746376177 + }, + "name": "" + }, { + "location": { + "latitude": 405688272, + "longitude": -749285130 + }, + "name": "" + }, { + "location": { + "latitude": 400342070, + "longitude": -748788996 + }, + "name": "" + }, { + "location": { + "latitude": 401809022, + "longitude": -744157964 + }, + "name": "" + }, { + "location": { + "latitude": 404226644, + "longitude": -740517141 + }, + "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" + }, { + "location": { + "latitude": 410322033, + "longitude": -747871659 + }, + "name": "" + }, { + "location": { + "latitude": 407100674, + "longitude": -747742727 + }, + "name": "" + }, { + "location": { + "latitude": 418811433, + "longitude": -741718005 + }, + "name": "213 Bush Road, Stone Ridge, NY 12484, USA" + }, { + "location": { + "latitude": 415034302, + "longitude": -743850945 + }, + "name": "" + }, { + "location": { + "latitude": 411349992, + "longitude": -743694161 + }, + "name": "" + }, { + "location": { + "latitude": 404839914, + "longitude": -744759616 + }, + "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" + }, { + "location": { + "latitude": 414638017, + "longitude": -745957854 + }, + "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" + }, { + "location": { + "latitude": 412127800, + "longitude": -740173578 + }, + "name": "" + }, { + "location": { + "latitude": 401263460, + "longitude": -747964303 + }, + "name": "" + }, { + "location": { + "latitude": 412843391, + "longitude": -749086026 + }, + "name": "" + }, { + "location": { + "latitude": 418512773, + "longitude": -743067823 + }, + "name": "" + }, { + "location": { + "latitude": 404318328, + "longitude": -740835638 + }, + "name": "42-102 Main Street, Belford, NJ 07718, USA" + }, { + "location": { + "latitude": 419020746, + "longitude": -741172328 + }, + "name": "" + }, { + "location": { + "latitude": 404080723, + "longitude": -746119569 + }, + "name": "" + }, { + "location": { + "latitude": 401012643, + "longitude": -744035134 + }, + "name": "" + }, { + "location": { + "latitude": 404306372, + "longitude": -741079661 + }, + "name": "" + }, { + "location": { + "latitude": 403966326, + "longitude": -748519297 + }, + "name": "" + }, { + "location": { + "latitude": 405002031, + "longitude": -748407866 + }, + "name": "" + }, { + "location": { + "latitude": 409532885, + "longitude": -742200683 + }, + "name": "" + }, { + "location": { + "latitude": 416851321, + "longitude": -742674555 + }, + "name": "" + }, { + "location": { + "latitude": 406411633, + "longitude": -741722051 + }, + "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" + }, { + "location": { + "latitude": 413069058, + "longitude": -744597778 + }, + "name": "261 Van Sickle Road, Goshen, NY 10924, USA" + }, { + "location": { + "latitude": 418465462, + "longitude": -746859398 + }, + "name": "" + }, { + "location": { + "latitude": 411733222, + "longitude": -744228360 + }, + "name": "" + }, { + "location": { + "latitude": 410248224, + "longitude": -747127767 + }, + "name": "3 Hasta Way, Newton, NJ 07860, USA" + }] +} \ No newline at end of file diff --git a/kotlin/kotlin_grpc_compile.bzl b/kotlin/kotlin_grpc_compile.bzl new file mode 100644 index 000000000..fef0d36a3 --- /dev/null +++ b/kotlin/kotlin_grpc_compile.bzl @@ -0,0 +1,25 @@ +"""Generated definition of kotlin_grpc_compile.""" + +load( + "//:defs.bzl", + "ProtoPluginInfo", + "proto_compile_attrs", + "proto_compile_impl", +) + +# Create compile rule +kotlin_grpc_compile = rule( + implementation = proto_compile_impl, + attrs = dict( + proto_compile_attrs, + _plugins = attr.label_list( + providers = [ProtoPluginInfo], + default = [ + Label("//kotlin:kotlin_plugin"), + Label("//kotlin:grpc_kotlin_plugin"), + ], + doc = "List of protoc plugins to apply", + ), + ), + toolchains = [str(Label("//protobuf:toolchain_type"))], +) diff --git a/kotlin/kotlin_grpc_library.bzl b/kotlin/kotlin_grpc_library.bzl new file mode 100644 index 000000000..4bc58eb2e --- /dev/null +++ b/kotlin/kotlin_grpc_library.bzl @@ -0,0 +1,61 @@ +"""Generated definition of kotlin_grpc_library.""" + +load("//kotlin:kotlin_grpc_compile.bzl", "kotlin_grpc_compile") +load("//:defs.bzl", "bazel_build_rule_common_attrs", "proto_compile_attrs") +load("//java:defs.bzl", "java_grpc_library") +load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") + +def kotlin_grpc_library(name, java_grpc_target = None, **kwargs): + # Compile protos + name_pb = name + "_pb" + kotlin_grpc_compile( + name = name_pb, + **{ + k: v + for (k, v) in kwargs.items() + if k in proto_compile_attrs.keys() or + k in bazel_build_rule_common_attrs + } # Forward args + ) + + # Create kotlin Java dependency library, if not provided + if java_grpc_target == None: + java_grpc_target = ":%s_DO_NOT_DEPEND_java_grpc" % name + + java_grpc_library( + name = java_grpc_target[1:], + **{ + k: v + for (k, v) in kwargs.items() + if k in proto_compile_attrs.keys() or + k in bazel_build_rule_common_attrs + } # Forward args + ) + + # Create kotlin library + kt_jvm_library( + name = name, + srcs = [name_pb], + deps = GRPC_DEPS + [java_grpc_target] + kwargs.get("deps", []), + exports = GRPC_DEPS + [java_grpc_target] + kwargs.get("exports", []), + **{ + k: v + for (k, v) in kwargs.items() + if k in bazel_build_rule_common_attrs + } # Forward Bazel common args + ) + +GRPC_DEPS = [ + # From https://github.com/grpc/grpc-java/blob/f6c2d221e2b6c975c6cf465d68fe11ab12dabe55/BUILD.bazel#L32-L38 + "@io_grpc_grpc_java//api", + "@io_grpc_grpc_java//protobuf", + "@io_grpc_grpc_java//stub", + "@io_grpc_grpc_java//stub:javax_annotation", + "@com_github_grpc_grpc_kotlin//stub/src/main/java/io/grpc/kotlin:stub", + "@com_github_grpc_grpc_kotlin//stub/src/main/java/io/grpc/kotlin:context", + "@com_google_code_findbugs_jsr305//jar", + "@com_google_guava_guava//jar", + "@com_google_protobuf//:protobuf_java", + "@com_google_protobuf//:protobuf_java_util", + "@com_google_protobuf//java/kotlin:shared_runtime", +] diff --git a/kotlin/kotlin_proto_compile.bzl b/kotlin/kotlin_proto_compile.bzl new file mode 100644 index 000000000..d5b666fbb --- /dev/null +++ b/kotlin/kotlin_proto_compile.bzl @@ -0,0 +1,24 @@ +"""Generated definition of kotlin_proto_compile.""" + +load( + "//:defs.bzl", + "ProtoPluginInfo", + "proto_compile_attrs", + "proto_compile_impl", +) + +# Create compile rule +kotlin_proto_compile = rule( + implementation = proto_compile_impl, + attrs = dict( + proto_compile_attrs, + _plugins = attr.label_list( + providers = [ProtoPluginInfo], + default = [ + Label("//kotlin:kotlin_plugin"), + ], + doc = "List of protoc plugins to apply", + ), + ), + toolchains = [str(Label("//protobuf:toolchain_type"))], +) diff --git a/kotlin/kotlin_proto_library.bzl b/kotlin/kotlin_proto_library.bzl new file mode 100644 index 000000000..9b2215444 --- /dev/null +++ b/kotlin/kotlin_proto_library.bzl @@ -0,0 +1,51 @@ +"""Generated definition of kotlin_proto_library.""" + +load("//kotlin:kotlin_proto_compile.bzl", "kotlin_proto_compile") +load("//:defs.bzl", "bazel_build_rule_common_attrs", "proto_compile_attrs") +load("//java:defs.bzl", "java_proto_library") +load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") + +def kotlin_proto_library(name, java_proto_target = None, **kwargs): + # Compile protos + name_pb = name + "_pb" + kotlin_proto_compile( + name = name_pb, + **{ + k: v + for (k, v) in kwargs.items() + if k in proto_compile_attrs.keys() or + k in bazel_build_rule_common_attrs + } # Forward args + ) + + # Create kotlin Java dependency library, if not provided + if java_proto_target == None: + java_proto_target = ":%s_DO_NOT_DEPEND_java_proto" % name + + java_proto_library( + name = java_proto_target[1:], + **{ + k: v + for (k, v) in kwargs.items() + if k in proto_compile_attrs.keys() or + k in bazel_build_rule_common_attrs + } # Forward args + ) + + # Create kotlin library + kt_jvm_library( + name = name, + srcs = [name_pb], + deps = PROTO_DEPS + [java_proto_target] + kwargs.get("deps", []), + exports = PROTO_DEPS + [java_proto_target] + kwargs.get("exports", []), + **{ + k: v + for (k, v) in kwargs.items() + if k in bazel_build_rule_common_attrs + } # Forward Bazel common args + ) + +PROTO_DEPS = [ + "@com_google_protobuf//:protobuf_java", + "@com_google_protobuf//java/kotlin:shared_runtime", +] diff --git a/kotlin/repositories.bzl b/kotlin/repositories.bzl new file mode 100644 index 000000000..1344ec3e7 --- /dev/null +++ b/kotlin/repositories.bzl @@ -0,0 +1,15 @@ +"""Common dependencies for rules_proto_grpc Kotlin rules.""" + +load( + "//:repositories.bzl", + "com_github_grpc_grpc_kotlin", + "io_bazel_rules_kotlin", +) + +def kotlin_repos(**kwargs): # buildifier: disable=function-docstring + io_bazel_rules_kotlin(**kwargs) + com_github_grpc_grpc_kotlin(**kwargs) + +# rules_proto_grpc_repos(**kwargs) +# io_grpc_grpc_java(**kwargs) +# rules_jvm_external(**kwargs) diff --git a/repositories.bzl b/repositories.bzl index e036a183b..e4020b09a 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -204,6 +204,21 @@ VERSIONS = { "sha256": "6e9f2b94ecb6aa7e7ec4a0fbf882b226ff5257581163e88bf70ae521555ad271", }, + # Kotlin + # Use .tar.gz in release assets, not the Github generated source .tar.gz + "io_bazel_rules_kotlin": { + "type": "http", + "urls": ["https://github.com/bazelbuild/rules_kotlin/releases/download/v1.8-RC-1/rules_kotlin_release.tgz"], + "sha256": "1779628569eb3b0fe97a3fb5c3ed8090e6503e425600b401c7b1afb6b23a3098", + }, + "com_github_grpc_grpc_kotlin": { + "type": "github", + "org": "grpc", + "repo": "grpc-kotlin", + "ref": "v1.3.0", + "sha256": "466d33303aac7e825822b402efa3dcfddd68e6f566ed79443634180bb75eab6e", + }, + # JavaScript # Use .tar.gz in release assets, not the Github generated source .tar.gz "build_bazel_rules_nodejs": { @@ -585,6 +600,15 @@ def io_grpc_grpc_java(**kwargs): def rules_jvm_external(**kwargs): _generic_dependency("rules_jvm_external", **kwargs) +# +# Kotlin +# +def io_bazel_rules_kotlin(**kwargs): + _generic_dependency("io_bazel_rules_kotlin", **kwargs) + +def com_github_grpc_grpc_kotlin(**kwargs): + _generic_dependency("com_github_grpc_grpc_kotlin", **kwargs) + # # JavaScript # diff --git a/tools/rulegen/kt_jvm.go b/tools/rulegen/kt_jvm.go new file mode 100644 index 000000000..2caaf4891 --- /dev/null +++ b/tools/rulegen/kt_jvm.go @@ -0,0 +1,167 @@ +package main + +var ktJvmProtoWorkspaceTemplate = mustTemplate(`load("@rules_proto_grpc//{{ .Lang.Dir }}:repositories.bzl", rules_proto_grpc_{{ .Lang.Name }}_repos = "{{ .Lang.Name }}_repos") + +rules_proto_grpc_{{ .Lang.Name }}_repos()`) + +var ktJvmGrpcWorkspaceTemplate = mustTemplate(`load("@rules_proto_grpc//{{ .Lang.Dir }}:repositories.bzl", rules_proto_grpc_{{ .Lang.Name }}_repos = "{{ .Lang.Name }}_repos") + +rules_proto_grpc_{{ .Lang.Name }}_repos() + +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() + +load("@rules_jvm_external//:defs.bzl", "maven_install") +load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_ARTIFACTS", "IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS", "grpc_java_repositories") +load("@com_github_grpc_grpc_kotlin//:repositories.bzl", "IO_GRPC_GRPC_KOTLIN_ARTIFACTS", "IO_GRPC_GRPC_KOTLIN_OVERRIDE_TARGETS", "grpc_kt_repositories") + +maven_install( + artifacts = IO_GRPC_GRPC_JAVA_ARTIFACTS + IO_GRPC_GRPC_KOTLIN_ARTIFACTS, + generate_compat_repositories = True, + override_targets = dict(IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS.items() + + IO_GRPC_GRPC_KOTLIN_OVERRIDE_TARGETS.items()), + repositories = [ + "https://repo.maven.apache.org/maven2/", + ], +) + +load("@maven//:compat.bzl", "compat_repositories") + +compat_repositories() + +grpc_java_repositories() + +grpc_kt_repositories()`) + +var ktJvmLibraryRuleTemplateString = `load("//{{ .Lang.Dir }}:{{ .Lang.Name }}_{{ .Rule.Kind }}_compile.bzl", "{{ .Lang.Name }}_{{ .Rule.Kind }}_compile") +load("//:defs.bzl", "bazel_build_rule_common_attrs", "proto_compile_attrs") +load("//java:defs.bzl", "java_{{ .Rule.Kind }}_library") +load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") + +def {{ .Rule.Name }}(name, java_{{ .Rule.Kind }}_target = None, **kwargs): + # Compile protos + name_pb = name + "_pb" + {{ .Lang.Name }}_{{ .Rule.Kind }}_compile( + name = name_pb, + {{ .Common.CompileArgsForwardingSnippet }} + ) + + # Create {{ .Lang.Name }} Java dependency library, if not provided + if java_{{ .Rule.Kind }}_target == None: + java_{{ .Rule.Kind }}_target = ":%s_DO_NOT_DEPEND_java_{{ .Rule.Kind }}" % name + + java_{{ .Rule.Kind }}_library( + name = java_{{ .Rule.Kind }}_target[1:], + **{ + k: v + for (k, v) in kwargs.items() + if k in proto_compile_attrs.keys() or + k in bazel_build_rule_common_attrs + } # Forward args + ) +` + +var ktJvmProtoLibraryRuleTemplate = mustTemplate(ktJvmLibraryRuleTemplateString + ` + # Create {{ .Lang.Name }} library + kt_jvm_library( + name = name, + srcs = [name_pb], + deps = PROTO_DEPS + [java_{{ .Rule.Kind }}_target] + kwargs.get("deps", []), + exports = PROTO_DEPS + [java_{{ .Rule.Kind }}_target] + kwargs.get("exports", []), + {{ .Common.LibraryArgsForwardingSnippet }} + ) + +PROTO_DEPS = [ + "@com_google_protobuf//:protobuf_java", + "@com_google_protobuf//java/kotlin:shared_runtime", +]`) + +var ktJvmGrpcLibraryRuleTemplate = mustTemplate(ktJvmLibraryRuleTemplateString + ` + # Create {{ .Lang.Name }} library + kt_jvm_library( + name = name, + srcs = [name_pb], + deps = GRPC_DEPS + [java_{{ .Rule.Kind }}_target] + kwargs.get("deps", []), + exports = GRPC_DEPS + [java_{{ .Rule.Kind }}_target] + kwargs.get("exports", []), + {{ .Common.LibraryArgsForwardingSnippet }} + ) + +GRPC_DEPS = [ + # From https://github.com/grpc/grpc-java/blob/f6c2d221e2b6c975c6cf465d68fe11ab12dabe55/BUILD.bazel#L32-L38 + "@io_grpc_grpc_java//api", + "@io_grpc_grpc_java//protobuf", + "@io_grpc_grpc_java//stub", + "@io_grpc_grpc_java//stub:javax_annotation", + "@com_github_grpc_grpc_kotlin//stub/src/main/java/io/grpc/kotlin:stub", + "@com_github_grpc_grpc_kotlin//stub/src/main/java/io/grpc/kotlin:context", + "@com_google_code_findbugs_jsr305//jar", + "@com_google_guava_guava//jar", + "@com_google_protobuf//:protobuf_java", + "@com_google_protobuf//:protobuf_java_util", + "@com_google_protobuf//java/kotlin:shared_runtime", +]`) + +var ktJvmLibraryRuleAttrs = append(append([]*Attr(nil), libraryRuleAttrs...), []*Attr{ + &Attr{ + Name: "exports", + Type: "label_list", + Default: "[]", + Doc: "List of labels to pass as exports attr to underlying lang_library rule", + Mandatory: false, + }, +}...) + +func makeKtJvm() *Language { + return &Language{ + Dir: "kotlin", + Name: "kotlin", + DisplayName: "Kotlin", + Notes: mustTemplate("Rules for generating Kotlin protobuf and gRPC ``.jar`` files and libraries using standard Protocol Buffers, `gRPC-Java ` and `gRPC-Kotlin `_. Libraries are created with the `rules_kotlin ` kt_jvm_library``"), + Flags: commonLangFlags, + Rules: []*Rule{ + &Rule{ + Name: "kotlin_proto_compile", + Kind: "proto", + Implementation: compileRuleTemplate, + Plugins: []string{"//kotlin:kotlin_plugin"}, + WorkspaceExample: protoWorkspaceTemplate, + BuildExample: protoCompileExampleTemplate, + Doc: "Generates a Kotlin (JVM) protobuf srcjar file", + Attrs: compileRuleAttrs, + }, + &Rule{ + Name: "kotlin_grpc_compile", + Kind: "grpc", + Implementation: compileRuleTemplate, + Plugins: []string{"//kotlin:kotlin_plugin", "//kotlin:grpc_kotlin_plugin"}, + WorkspaceExample: protoWorkspaceTemplate, + BuildExample: grpcCompileExampleTemplate, + Doc: "Generates a Kotlin (JVM) protobuf and gRPC srcjar file", + Attrs: compileRuleAttrs, + }, + &Rule{ + Name: "kotlin_proto_library", + Kind: "proto", + Implementation: ktJvmProtoLibraryRuleTemplate, + WorkspaceExample: ktJvmProtoWorkspaceTemplate, + BuildExample: protoLibraryExampleTemplate, + Doc: "Generates a Kotlin (JVM) protobuf library using ``kt_jvm_library``", + Attrs: ktJvmLibraryRuleAttrs, + }, + &Rule{ + Name: "kotlin_grpc_library", + Kind: "grpc", + Implementation: ktJvmGrpcLibraryRuleTemplate, + WorkspaceExample: ktJvmGrpcWorkspaceTemplate, + BuildExample: grpcLibraryExampleTemplate, + Doc: "Generates a Kotlin (JVM) protobuf and gRPC library using ``kt_jvm_library``", + Attrs: ktJvmLibraryRuleAttrs, + }, + }, + } +} diff --git a/tools/rulegen/main.go b/tools/rulegen/main.go index d1b7d2467..75fbfb218 100644 --- a/tools/rulegen/main.go +++ b/tools/rulegen/main.go @@ -122,6 +122,7 @@ func action(c *cli.Context) error { makeGo(), makeGrpcGateway(), makeJava(), + makeKtJvm(), makeJavaScript(), makeObjc(), makePhp(),