diff --git a/.travis.yml b/.travis.yml index 675219116..9e19f23ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,11 +19,9 @@ env: # See https://github.com/bazelbuild/rules_scala/pull/622 # we want to test the last release #- V=0.16.1 TEST_SCRIPT=test_lint.sh - - V=0.17.1 TEST_SCRIPT=test_rules_scala.sh - - V=0.22.0 TEST_SCRIPT=test_rules_scala.sh + - V=0.23.1 TEST_SCRIPT=test_rules_scala.sh #- V=0.14.1 TEST_SCRIPT=test_intellij_aspect.sh - - V=0.17.1 TEST_SCRIPT=test_reproducibility.sh - - V=0.22.0 TEST_SCRIPT=test_reproducibility.sh + - V=0.23.1 TEST_SCRIPT=test_reproducibility.sh before_install: - | diff --git a/README.md b/README.md index ee1dfd2ad..944221c8d 100644 --- a/README.md +++ b/README.md @@ -83,9 +83,11 @@ for an example workspace using another scala version. ## Bazel compatible versions -| bazel | rules_scala gitsha | -|-------|--------------------| -| 0.16.x | HEAD | +| bazel | rules_scala gitsha | +|--------|--------------------| +| 0.23.x | HEAD | +| 0.22.x | f3113fb6e9e35cb8f441d2305542026d98afc0a2 | +| 0.16.x | f3113fb6e9e35cb8f441d2305542026d98afc0a2 | | 0.15.x | 3b9ab9be31ac217d3337c709cb6bfeb89c8dcbb1 | | 0.14.x | 3b9ab9be31ac217d3337c709cb6bfeb89c8dcbb1 | | 0.13.x | 3c987b6ae8a453886759b132f1572c0efca2eca2 | diff --git a/WORKSPACE b/WORKSPACE index 77757b70d..80f5e5b73 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -121,6 +121,10 @@ load("@io_bazel_rules_scala//scala:toolchains.bzl", "scala_register_unused_deps_ scala_register_unused_deps_toolchains() + +register_toolchains("@io_bazel_rules_scala//test/proto:scalapb_toolchain") + + load("//scala:scala_maven_import_external.bzl", "scala_maven_import_external", "java_import_external") scala_maven_import_external( diff --git a/scala_proto/BUILD b/scala_proto/BUILD index e69de29bb..08d8bd7d9 100644 --- a/scala_proto/BUILD +++ b/scala_proto/BUILD @@ -0,0 +1,38 @@ +load("//scala_proto:scala_proto_toolchain.bzl", "scala_proto_toolchain") + +toolchain_type( + name = "toolchain_type", + visibility = ["//visibility:public"], +) + +scala_proto_toolchain( + name = "default_toolchain_impl", + with_grpc = True, + with_flat_package=False, + with_single_line_to_string=False, + visibility = ["//visibility:public"], +) + +toolchain( + name = "default_toolchain", + toolchain = ":default_toolchain_impl", + toolchain_type = "@io_bazel_rules_scala//scala_proto:toolchain_type", + visibility = ["//visibility:public"], +) + + +scala_proto_toolchain( + name = "enable_all_options_toolchain_impl", + with_grpc = True, + with_flat_package=True, + # with_java=True, + with_single_line_to_string=True, + visibility = ["//visibility:public"], +) + +toolchain( + name = "enable_all_options_toolchain", + toolchain = ":enable_all_options_toolchain_impl", + toolchain_type = "@io_bazel_rules_scala//scala_proto:toolchain_type", + visibility = ["//visibility:public"], +) diff --git a/scala_proto/private/BUILD b/scala_proto/private/BUILD new file mode 100644 index 000000000..e69de29bb diff --git a/scala_proto/private/dep_sets.bzl b/scala_proto/private/dep_sets.bzl new file mode 100644 index 000000000..326ad57df --- /dev/null +++ b/scala_proto/private/dep_sets.bzl @@ -0,0 +1,31 @@ + +SCALAPB_DEPS = [ + "//external:io_bazel_rules_scala/dependency/proto/scalapb_runtime", + "//external:io_bazel_rules_scala/dependency/com_google_protobuf/protobuf_java", + "//external:io_bazel_rules_scala/dependency/proto/scalapb_lenses", + "//external:io_bazel_rules_scala/dependency/proto/scalapb_fastparse", +] + +GRPC_DEPS = [ + "//external:io_bazel_rules_scala/dependency/proto/scalapb_runtime_grpc", + "//external:io_bazel_rules_scala/dependency/proto/grpc_core", + "//external:io_bazel_rules_scala/dependency/proto/grpc_stub", + "//external:io_bazel_rules_scala/dependency/proto/grpc_protobuf", + "//external:io_bazel_rules_scala/dependency/proto/grpc_netty", + "//external:io_bazel_rules_scala/dependency/proto/grpc_context", + "//external:io_bazel_rules_scala/dependency/proto/guava", + "//external:io_bazel_rules_scala/dependency/proto/opencensus_api", + "//external:io_bazel_rules_scala/dependency/proto/opencensus_contrib_grpc_metrics", + "//external:io_bazel_rules_scala/dependency/proto/google_instrumentation", + "//external:io_bazel_rules_scala/dependency/proto/netty_codec", + "//external:io_bazel_rules_scala/dependency/proto/netty_codec_http", + "//external:io_bazel_rules_scala/dependency/proto/netty_codec_http2", + "//external:io_bazel_rules_scala/dependency/proto/netty_codec_socks", + "//external:io_bazel_rules_scala/dependency/proto/netty_handler", + "//external:io_bazel_rules_scala/dependency/proto/netty_buffer", + "//external:io_bazel_rules_scala/dependency/proto/netty_transport", + "//external:io_bazel_rules_scala/dependency/proto/netty_resolver", + "//external:io_bazel_rules_scala/dependency/proto/netty_common", + "//external:io_bazel_rules_scala/dependency/proto/netty_handler_proxy", +] + diff --git a/scala_proto/private/proto_to_scala_src.bzl b/scala_proto/private/proto_to_scala_src.bzl new file mode 100644 index 000000000..24304ca37 --- /dev/null +++ b/scala_proto/private/proto_to_scala_src.bzl @@ -0,0 +1,49 @@ +load( + "//scala/private:common.bzl", + "write_manifest_file", +) +load("//scala/private:rule_impls.bzl", "compile_scala") +load("//scala_proto/private:dep_sets.bzl", "SCALAPB_DEPS", "GRPC_DEPS") + + +def _root_path(f): + if f.is_source: + return f.owner.workspace_root + return "/".join([f.root.path, f.owner.workspace_root]) + + +def _colon_paths(data): + return ":".join([ + f.path + for f in sorted(data) + ]) + + +def proto_to_scala_src(ctx, label, code_generator, compile_proto, include_proto, transitive_proto_paths, flags, jar_output): + worker_content = "{output}\n{included_proto}\n{flags_arg}\n{transitive_proto_paths}\n{inputs}\n{protoc}".format( + output = jar_output.path, + included_proto = "-" + ":".join(sorted(["%s,%s" % (f.root.path, f.path) for f in include_proto])), + # Command line args to worker cannot be empty so using padding + flags_arg = "-" + ",".join(flags), + transitive_proto_paths = "-" + ":".join(sorted(transitive_proto_paths)), + # Command line args to worker cannot be empty so using padding + # Pass inputs seprately because they doesn't always match to imports (ie blacklisted protos are excluded) + inputs = _colon_paths(compile_proto), + protoc = ctx.executable._protoc.path + ) + argfile = ctx.actions.declare_file( + "%s_worker_input" % label.name, + sibling = jar_output, + ) + ctx.actions.write(output = argfile, content = worker_content) + ctx.actions.run( + executable = code_generator.files_to_run, + inputs = compile_proto + include_proto + [argfile, ctx.executable._protoc], + outputs = [jar_output], + mnemonic = "ProtoScalaPBRule", + progress_message = "creating scalapb files %s" % ctx.label, + execution_requirements = {"supports-workers": "1"}, + arguments = ["@" + argfile.path], + ) + + diff --git a/scala_proto/private/scala_proto_default_repositories.bzl b/scala_proto/private/scala_proto_default_repositories.bzl new file mode 100644 index 000000000..586b8e10e --- /dev/null +++ b/scala_proto/private/scala_proto_default_repositories.bzl @@ -0,0 +1,380 @@ +load( + "//scala:scala_cross_version.bzl", + _default_scala_version = "default_scala_version", + _extract_major_version = "extract_major_version", + _scala_mvn_artifact = "scala_mvn_artifact", +) +load( + "@io_bazel_rules_scala//scala:scala_maven_import_external.bzl", + _scala_maven_import_external = "scala_maven_import_external", +) + +def scala_proto_default_repositories( + scala_version = _default_scala_version(), + maven_servers = ["http://central.maven.org/maven2"]): + major_version = _extract_major_version(scala_version) + + native.maven_server( + name = "scala_proto_deps_maven_server", + url = "http://central.maven.org/maven2/", + ) + + scala_jar_shas = { + "2.11": { + "scalapb_plugin": "b67e563d06f1bbb6ea704a063760a85ec7fb5809828402364d5418dd1c5cab06", + "protoc_bridge": "e94cf50d9ba4b3d5f4b491cb9483b4da566afe24d0fa809a003263b4b50ff269", + "scalapbc": "120b7d7f42051da3406b72480eeb331a985a99b2a3c999243fc3c11e6b7530b2", + "scalapb_runtime": "40f93a9ec5ea4dc21e1fa4fb4088cf76768dd3c0137c3fa6683ae0d9a17f5d44", + "scalapb_runtime_grpc": "93a9f5f1c64ef83aacc2e46c9c09f3156f59d979b5b5565eac9437897882c465", + "scalapb_lenses": "bacdee7d8b6fa7a822a3ec55d12a15896d54fe2e4f22bbd8a5194e9bba751193", + "scalapb_fastparse": "1b6d9fc75ca8a62abe0dd7a71e62aa445f2d3198c86aab5088e1f90a96ade30b", + }, + "2.12": { + "scalapb_plugin": "5df9d1ceb3d67ad0cd2de561e7f0e0fc77cf08d305d1a0e21a2f4f135efe76a9", + "protoc_bridge": "6b83ac0be522bf868fcbab27c2b64286912924f1cdbc17e0e12e092abff8bdc5", + "scalapbc": "4a986c7f7447aa2e8cd4be4329c2aa2a42ebdfc8135c6882bef958a527ea7667", + "scalapb_runtime": "82596e3235f8ccda30fbd6290e0ba314ba880283874658fc876217701d3ef5e4", + "scalapb_runtime_grpc": "e5bb54164581d44ea2b2221b5546880deb7073b1d02b56da8f666454f3a14387", + "scalapb_lenses": "79100162924477084ac2ab35b02067ee875e5dade58a33e882ec9f2900418de3", + "scalapb_fastparse": "1227a00a26a4ad76ddcfa6eae2416687df7f3c039553d586324b32ba0a528fcc", + }, + } + + scala_version_jar_shas = scala_jar_shas[major_version] + + _scala_maven_import_external( + name = "scala_proto_rules_scalapb_plugin", + artifact = _scala_mvn_artifact( + "com.thesamet.scalapb:compilerplugin:0.8.4", + major_version, + ), + jar_sha256 = scala_version_jar_shas["scalapb_plugin"], + licenses = ["notice"], + server_urls = maven_servers, + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/scalapb_plugin", + actual = "@scala_proto_rules_scalapb_plugin", + ) + + _scala_maven_import_external( + name = "scala_proto_rules_protoc_bridge", + artifact = _scala_mvn_artifact( + "com.thesamet.scalapb:protoc-bridge:0.7.3", + major_version, + ), + jar_sha256 = scala_version_jar_shas["protoc_bridge"], + licenses = ["notice"], + server_urls = maven_servers, + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/protoc_bridge", + actual = "@scala_proto_rules_protoc_bridge", + ) + + _scala_maven_import_external( + name = "scala_proto_rules_scalapbc", + artifact = _scala_mvn_artifact( + "com.thesamet.scalapb:scalapbc:0.8.4", + major_version, + ), + jar_sha256 = scala_version_jar_shas["scalapbc"], + licenses = ["notice"], + server_urls = maven_servers, + ) + native.bind( + name = "io_bazel_rules_scala/dependency/proto/scalapbc", + actual = "@scala_proto_rules_scalapbc", + ) + + _scala_maven_import_external( + name = "scala_proto_rules_scalapb_runtime", + artifact = _scala_mvn_artifact( + "com.thesamet.scalapb:scalapb-runtime:0.8.4", + major_version, + ), + jar_sha256 = scala_version_jar_shas["scalapb_runtime"], + licenses = ["notice"], + server_urls = maven_servers, + ) + native.bind( + name = "io_bazel_rules_scala/dependency/proto/scalapb_runtime", + actual = "@scala_proto_rules_scalapb_runtime", + ) + + _scala_maven_import_external( + name = "scala_proto_rules_scalapb_runtime_grpc", + artifact = _scala_mvn_artifact( + "com.thesamet.scalapb:scalapb-runtime-grpc:0.8.4", + major_version, + ), + jar_sha256 = scala_version_jar_shas["scalapb_runtime_grpc"], + licenses = ["notice"], + server_urls = maven_servers, + ) + native.bind( + name = "io_bazel_rules_scala/dependency/proto/scalapb_runtime_grpc", + actual = "@scala_proto_rules_scalapb_runtime_grpc", + ) + + _scala_maven_import_external( + name = "scala_proto_rules_scalapb_lenses", + artifact = _scala_mvn_artifact( + "com.thesamet.scalapb:lenses:0.8.4", + major_version, + ), + jar_sha256 = scala_version_jar_shas["scalapb_lenses"], + licenses = ["notice"], + server_urls = maven_servers, + ) + native.bind( + name = "io_bazel_rules_scala/dependency/proto/scalapb_lenses", + actual = "@scala_proto_rules_scalapb_lenses", + ) + + _scala_maven_import_external( + name = "scala_proto_rules_scalapb_fastparse", + artifact = _scala_mvn_artifact( + "com.lihaoyi:fastparse:1.0.0", + major_version, + ), + jar_sha256 = scala_version_jar_shas["scalapb_fastparse"], + licenses = ["notice"], + server_urls = maven_servers, + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/scalapb_fastparse", + actual = "@scala_proto_rules_scalapb_fastparse", + ) + + native.maven_jar( + name = "scala_proto_rules_grpc_core", + artifact = "io.grpc:grpc-core:1.18.0", + sha1 = "e21b343bba2006bac31bb16b7438701cddfbf564", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/grpc_core", + actual = "@scala_proto_rules_grpc_core//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_grpc_stub", + artifact = "io.grpc:grpc-stub:1.18.0", + sha1 = "5e4dbf944814d49499e3cbd9846ef58f629b5f32", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/grpc_stub", + actual = "@scala_proto_rules_grpc_stub//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_grpc_protobuf", + artifact = "io.grpc:grpc-protobuf:1.18.0", + sha1 = "74d794cf9b90b620e0ad698008abc4f55c1ca5e2", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/grpc_protobuf", + actual = "@scala_proto_rules_grpc_protobuf//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_grpc_netty", + artifact = "io.grpc:grpc-netty:1.18.0", + sha1 = "0d813fe080edb188953fea46803777e5ba6f41d4", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/grpc_netty", + actual = "@scala_proto_rules_grpc_netty//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_grpc_context", + artifact = "io.grpc:grpc-context:1.18.0", + sha1 = "c63e8b86af0fb16b5696480dc14f48e6eaa7193b", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/grpc_context", + actual = "@scala_proto_rules_grpc_context//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_guava", + # io.grpc:grpc-core:1.18.0 defines a dependency on guava 25.1-android + # see https://search.maven.org/artifact/io.grpc/grpc-core/1.18.0/jar + artifact = "com.google.guava:guava:25.1-android", + sha1 = "bdaab946ca5ad20253502d873ba0c3313d141036", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/guava", + actual = "@scala_proto_rules_guava//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_google_instrumentation", + artifact = "com.google.instrumentation:instrumentation-api:0.3.0", + sha1 = "a2e145e7a7567c6372738f5c5a6f3ba6407ac354", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/google_instrumentation", + actual = "@scala_proto_rules_google_instrumentation//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_netty_codec", + artifact = "io.netty:netty-codec:4.1.32.Final", + sha1 = "8f32bd79c5a16f014a4372ed979dc62b39ede33a", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/netty_codec", + actual = "@scala_proto_rules_netty_codec//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_netty_codec_http", + artifact = "io.netty:netty-codec-http:4.1.32.Final", + sha1 = "0b9218adba7353ad5a75fcb639e4755d64bd6ddf", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/netty_codec_http", + actual = "@scala_proto_rules_netty_codec_http//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_netty_codec_socks", + artifact = "io.netty:netty-codec-socks:4.1.32.Final", + sha1 = "b1e83cb772f842839dbeebd9a1f053da98bf56d2", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/netty_codec_socks", + actual = "@scala_proto_rules_netty_codec_socks//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_netty_codec_http2", + artifact = "io.netty:netty-codec-http2:4.1.32.Final", + sha1 = "d14eb053a1f96d3330ec48e77d489118d547557a", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/netty_codec_http2", + actual = "@scala_proto_rules_netty_codec_http2//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_netty_handler", + artifact = "io.netty:netty-handler:4.1.32.Final", + sha1 = "b4e3fa13f219df14a9455cc2111f133374428be0", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/netty_handler", + actual = "@scala_proto_rules_netty_handler//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_netty_buffer", + artifact = "io.netty:netty-buffer:4.1.32.Final", + sha1 = "046ede57693788181b2cafddc3a5967ed2f621c8", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/netty_buffer", + actual = "@scala_proto_rules_netty_buffer//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_netty_transport", + artifact = "io.netty:netty-transport:4.1.32.Final", + sha1 = "d5e5a8ff9c2bc7d91ddccc536a5aca1a4355bd8b", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/netty_transport", + actual = "@scala_proto_rules_netty_transport//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_netty_resolver", + artifact = "io.netty:netty-resolver:4.1.32.Final", + sha1 = "3e0114715cb125a12db8d982b2208e552a91256d", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/netty_resolver", + actual = "@scala_proto_rules_netty_resolver//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_netty_common", + artifact = "io.netty:netty-common:4.1.32.Final", + sha1 = "e95de4f762606f492328e180c8ad5438565a5e3b", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/netty_common", + actual = "@scala_proto_rules_netty_common//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_netty_handler_proxy", + artifact = "io.netty:netty-handler-proxy:4.1.32.Final", + sha1 = "58b621246262127b97a871b88c09374c8c324cb7", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/netty_handler_proxy", + actual = "@scala_proto_rules_netty_handler_proxy//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_opencensus_api", + artifact = "io.opencensus:opencensus-api:0.18.0", + sha1 = "b89a8f8dfd1e1e0d68d83c82a855624814b19a6e", + server = "scala_proto_deps_maven_server", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/opencensus_api", + actual = "@scala_proto_rules_opencensus_api//jar", + ) + + native.maven_jar( + name = "scala_proto_rules_opencensus_contrib_grpc_metrics", + artifact = "io.opencensus:opencensus-contrib-grpc-metrics:0.18.0", + sha1 = "8e90fab2930b6a0e67dab48911b9c936470d43dd", + ) + + native.bind( + name = "io_bazel_rules_scala/dependency/proto/opencensus_contrib_grpc_metrics", + actual = "@scala_proto_rules_opencensus_contrib_grpc_metrics//jar", + ) diff --git a/scala_proto/private/scalapb_aspect.bzl b/scala_proto/private/scalapb_aspect.bzl new file mode 100644 index 000000000..f716732d7 --- /dev/null +++ b/scala_proto/private/scalapb_aspect.bzl @@ -0,0 +1,227 @@ +load( + "//scala/private:common.bzl", + "write_manifest_file", +) +load("//scala/private:rule_impls.bzl", "compile_scala") + +load("//scala_proto/private:proto_to_scala_src.bzl", "proto_to_scala_src") + + +ScalaPBAspectInfo = provider(fields = [ + "proto_info", + "src_jars", + "output_files", + "java_info", +]) + + +ScalaPBImport = provider(fields = [ + "java_info", + "proto_info", +]) + + +ScalaPBInfo = provider(fields = [ + "aspect_info", +]) + + +def merge_proto_infos(tis): + return struct( + transitive_sources = [t.transitive_sources for t in tis], + ) + +def merge_scalapb_aspect_info(scalapbs): + return ScalaPBAspectInfo( + src_jars = depset(transitive = [s.src_jars for s in scalapbs]), + output_files = depset(transitive = [s.output_files for s in scalapbs]), + proto_info = merge_proto_infos([s.proto_info for s in scalapbs]), + java_info = java_common.merge([s.java_info for s in scalapbs]), + ) + + +def _compiled_jar_file(actions, scalapb_jar): + scalapb_jar_name = scalapb_jar.basename + + # ends with .srcjar, so remove last 6 characters + without_suffix = scalapb_jar_name[0:len(scalapb_jar_name) - 6] + + # this already ends with _scalapb because that is how scalapb_jar is named + compiled_jar = without_suffix + "jar" + return actions.declare_file(compiled_jar, sibling = scalapb_jar) + +def _compile_scala( + ctx, + scalac, + label, + output, + scalapb_jar, + deps_java_info, + implicit_deps): + manifest = ctx.actions.declare_file( + label.name + "_MANIFEST.MF", + sibling = scalapb_jar, + ) + write_manifest_file(ctx.actions, manifest, None) + statsfile = ctx.actions.declare_file( + label.name + "_scalac.statsfile", + sibling = scalapb_jar, + ) + merged_deps = java_common.merge(deps_java_info + implicit_deps) + + # this only compiles scala, not the ijar, but we don't + # want the ijar for generated code anyway: any change + # in the proto generally will change the interface and + # method bodies + compile_scala( + ctx, + Label("%s-fast" % (label)), + output, + manifest, + statsfile, + sources = [], + cjars = merged_deps.compile_jars, + all_srcjars = depset([scalapb_jar]), + transitive_compile_jars = merged_deps.transitive_compile_time_jars, + plugins = [], + resource_strip_prefix = "", + resources = [], + resource_jars = [], + labels = {}, + in_scalacopts = [], + print_compile_time = False, + expect_java_output = False, + scalac_jvm_flags = [], + scalac = scalac, + ) + + return JavaInfo( + source_jar = scalapb_jar, + deps = deps_java_info + implicit_deps, + runtime_deps = deps_java_info + implicit_deps, + exports = deps_java_info + implicit_deps, + output_jar = output, + compile_jar = output, + ) + +def _empty_java_info(deps_java_info, implicit_deps): + return java_common.merge(deps_java_info + implicit_deps) + +#### +# This is applied to the DAG of proto_librarys reachable from a deps +# or a scalapb_scala_library. Each proto_library will be one scalapb +# invocation assuming it has some sources. +def _scalapb_aspect_impl(target, ctx): + deps = [d[ScalaPBAspectInfo].java_info for d in ctx.rule.attr.deps] + + if ProtoInfo not in target: + # We allow some dependencies which are not protobuf, but instead + # are jvm deps. This is to enable cases of custom generators which + # add a needed jvm dependency. + java_info = target[JavaInfo] + src_jars = depset() + outs = depset() + transitive_ti = merge_proto_infos( + [ + d[ScalaPBAspectInfo].proto_info + for d in ctx.rule.attr.deps + ], + ) + else: + target_ti = target[ProtoInfo] + transitive_ti = merge_proto_infos( + [ + d[ScalaPBAspectInfo].proto_info + for d in ctx.rule.attr.deps + ] + [target_ti], + ) + # we sort so the inputs are always the same for caching + compile_protos = sorted(target_ti.direct_sources) + transitive_protos = sorted(target_ti.transitive_sources) + + toolchain = ctx.toolchains["@io_bazel_rules_scala//scala_proto:toolchain_type"] + flags = [] + imps = [j[JavaInfo] for j in toolchain.implicit_compile_deps] + + if toolchain.with_grpc: + flags.append("grpc") + imps.extend([j[JavaInfo] for j in toolchain.grpc_deps]) + + if toolchain.with_flat_package: + flags.append("flat_package") + + if toolchain.with_single_line_to_string: + flags.append("single_line_to_proto_string") + + # This feels rather hacky and odd, but we can't compare the labels to ignore a target easily + # since the @ or // forms seem to not have good equality :( , so we aim to make them absolute + # + # the backlisted protos in the tool chain get made into to absolute paths + # so we make the local target we are looking at absolute too + target_absolute_label = target.label + if not str(target_absolute_label)[0] == "@": + target_absolute_label = Label("@%s//%s:%s" % (ctx.workspace_name, target.label.package, target.label.name)) + + for lbl in toolchain.blacklisted_protos: + if(lbl.label == target_absolute_label): + compile_protos = False + + code_generator = toolchain.code_generator + + if compile_protos: + scalapb_file = ctx.actions.declare_file( + target.label.name + "_scalapb.srcjar", + ) + proto_to_scala_src( + ctx, + target.label, + code_generator, + compile_protos, + transitive_protos, + target_ti.transitive_proto_path.to_list(), + flags, + scalapb_file, + ) + + src_jars = depset([scalapb_file]) + output = _compiled_jar_file(ctx.actions, scalapb_file) + outs = depset([output]) + java_info = _compile_scala( + ctx, + toolchain.scalac, + target.label, + output, + scalapb_file, + deps, + imps, + ) + else: + # this target is only an aggregation target + src_jars = depset() + outs = depset() + java_info = _empty_java_info(deps, imps) + + return [ + ScalaPBAspectInfo( + src_jars = src_jars, + output_files = outs, + proto_info = transitive_ti, + java_info = java_info, + ), + ] + +scalapb_aspect = aspect( + implementation = _scalapb_aspect_impl, + attr_aspects = ["deps"], + required_aspect_providers = [ + [ProtoInfo], + [ScalaPBImport], + ], + attrs = { + "_protoc": attr.label(executable = True, cfg = "host", default = "@com_google_protobuf//:protoc"), + }, + toolchains = [ + "@io_bazel_rules_scala//scala:toolchain_type", + "@io_bazel_rules_scala//scala_proto:toolchain_type", + ], +) diff --git a/scala_proto/scala_proto.bzl b/scala_proto/scala_proto.bzl index a9b04de94..f0e885ac4 100644 --- a/scala_proto/scala_proto.bzl +++ b/scala_proto/scala_proto.bzl @@ -18,569 +18,60 @@ load( "create_java_provider", ) -def scala_proto_repositories( - scala_version = _default_scala_version(), - maven_servers = ["http://central.maven.org/maven2"]): - major_version = _extract_major_version(scala_version) - - native.maven_server( - name = "scala_proto_deps_maven_server", - url = "http://central.maven.org/maven2/", - ) - - scala_jar_shas = { - "2.11": { - "scalapb_plugin": "b67e563d06f1bbb6ea704a063760a85ec7fb5809828402364d5418dd1c5cab06", - "protoc_bridge": "e94cf50d9ba4b3d5f4b491cb9483b4da566afe24d0fa809a003263b4b50ff269", - "scalapbc": "120b7d7f42051da3406b72480eeb331a985a99b2a3c999243fc3c11e6b7530b2", - "scalapb_runtime": "40f93a9ec5ea4dc21e1fa4fb4088cf76768dd3c0137c3fa6683ae0d9a17f5d44", - "scalapb_runtime_grpc": "93a9f5f1c64ef83aacc2e46c9c09f3156f59d979b5b5565eac9437897882c465", - "scalapb_lenses": "bacdee7d8b6fa7a822a3ec55d12a15896d54fe2e4f22bbd8a5194e9bba751193", - "scalapb_fastparse": "1b6d9fc75ca8a62abe0dd7a71e62aa445f2d3198c86aab5088e1f90a96ade30b", - }, - "2.12": { - "scalapb_plugin": "5df9d1ceb3d67ad0cd2de561e7f0e0fc77cf08d305d1a0e21a2f4f135efe76a9", - "protoc_bridge": "6b83ac0be522bf868fcbab27c2b64286912924f1cdbc17e0e12e092abff8bdc5", - "scalapbc": "4a986c7f7447aa2e8cd4be4329c2aa2a42ebdfc8135c6882bef958a527ea7667", - "scalapb_runtime": "82596e3235f8ccda30fbd6290e0ba314ba880283874658fc876217701d3ef5e4", - "scalapb_runtime_grpc": "e5bb54164581d44ea2b2221b5546880deb7073b1d02b56da8f666454f3a14387", - "scalapb_lenses": "79100162924477084ac2ab35b02067ee875e5dade58a33e882ec9f2900418de3", - "scalapb_fastparse": "1227a00a26a4ad76ddcfa6eae2416687df7f3c039553d586324b32ba0a528fcc", - }, - } - - scala_version_jar_shas = scala_jar_shas[major_version] - - _scala_maven_import_external( - name = "scala_proto_rules_scalapb_plugin", - artifact = _scala_mvn_artifact( - "com.thesamet.scalapb:compilerplugin:0.8.4", - major_version, - ), - jar_sha256 = scala_version_jar_shas["scalapb_plugin"], - licenses = ["notice"], - server_urls = maven_servers, - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/scalapb_plugin", - actual = "@scala_proto_rules_scalapb_plugin", - ) - - _scala_maven_import_external( - name = "scala_proto_rules_protoc_bridge", - artifact = _scala_mvn_artifact( - "com.thesamet.scalapb:protoc-bridge:0.7.3", - major_version, - ), - jar_sha256 = scala_version_jar_shas["protoc_bridge"], - licenses = ["notice"], - server_urls = maven_servers, - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/protoc_bridge", - actual = "@scala_proto_rules_protoc_bridge", - ) - - _scala_maven_import_external( - name = "scala_proto_rules_scalapbc", - artifact = _scala_mvn_artifact( - "com.thesamet.scalapb:scalapbc:0.8.4", - major_version, - ), - jar_sha256 = scala_version_jar_shas["scalapbc"], - licenses = ["notice"], - server_urls = maven_servers, - ) - native.bind( - name = "io_bazel_rules_scala/dependency/proto/scalapbc", - actual = "@scala_proto_rules_scalapbc", - ) - - _scala_maven_import_external( - name = "scala_proto_rules_scalapb_runtime", - artifact = _scala_mvn_artifact( - "com.thesamet.scalapb:scalapb-runtime:0.8.4", - major_version, - ), - jar_sha256 = scala_version_jar_shas["scalapb_runtime"], - licenses = ["notice"], - server_urls = maven_servers, - ) - native.bind( - name = "io_bazel_rules_scala/dependency/proto/scalapb_runtime", - actual = "@scala_proto_rules_scalapb_runtime", - ) - - _scala_maven_import_external( - name = "scala_proto_rules_scalapb_runtime_grpc", - artifact = _scala_mvn_artifact( - "com.thesamet.scalapb:scalapb-runtime-grpc:0.8.4", - major_version, - ), - jar_sha256 = scala_version_jar_shas["scalapb_runtime_grpc"], - licenses = ["notice"], - server_urls = maven_servers, - ) - native.bind( - name = "io_bazel_rules_scala/dependency/proto/scalapb_runtime_grpc", - actual = "@scala_proto_rules_scalapb_runtime_grpc", - ) - - _scala_maven_import_external( - name = "scala_proto_rules_scalapb_lenses", - artifact = _scala_mvn_artifact( - "com.thesamet.scalapb:lenses:0.8.4", - major_version, - ), - jar_sha256 = scala_version_jar_shas["scalapb_lenses"], - licenses = ["notice"], - server_urls = maven_servers, - ) - native.bind( - name = "io_bazel_rules_scala/dependency/proto/scalapb_lenses", - actual = "@scala_proto_rules_scalapb_lenses", - ) - - _scala_maven_import_external( - name = "scala_proto_rules_scalapb_fastparse", - artifact = _scala_mvn_artifact( - "com.lihaoyi:fastparse:1.0.0", - major_version, - ), - jar_sha256 = scala_version_jar_shas["scalapb_fastparse"], - licenses = ["notice"], - server_urls = maven_servers, - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/scalapb_fastparse", - actual = "@scala_proto_rules_scalapb_fastparse", - ) - - native.maven_jar( - name = "scala_proto_rules_grpc_core", - artifact = "io.grpc:grpc-core:1.18.0", - sha1 = "e21b343bba2006bac31bb16b7438701cddfbf564", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/grpc_core", - actual = "@scala_proto_rules_grpc_core//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_grpc_stub", - artifact = "io.grpc:grpc-stub:1.18.0", - sha1 = "5e4dbf944814d49499e3cbd9846ef58f629b5f32", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/grpc_stub", - actual = "@scala_proto_rules_grpc_stub//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_grpc_protobuf", - artifact = "io.grpc:grpc-protobuf:1.18.0", - sha1 = "74d794cf9b90b620e0ad698008abc4f55c1ca5e2", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/grpc_protobuf", - actual = "@scala_proto_rules_grpc_protobuf//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_grpc_netty", - artifact = "io.grpc:grpc-netty:1.18.0", - sha1 = "0d813fe080edb188953fea46803777e5ba6f41d4", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/grpc_netty", - actual = "@scala_proto_rules_grpc_netty//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_grpc_context", - artifact = "io.grpc:grpc-context:1.18.0", - sha1 = "c63e8b86af0fb16b5696480dc14f48e6eaa7193b", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/grpc_context", - actual = "@scala_proto_rules_grpc_context//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_guava", - # io.grpc:grpc-core:1.18.0 defines a dependency on guava 25.1-android - # see https://search.maven.org/artifact/io.grpc/grpc-core/1.18.0/jar - artifact = "com.google.guava:guava:25.1-android", - sha1 = "bdaab946ca5ad20253502d873ba0c3313d141036", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/guava", - actual = "@scala_proto_rules_guava//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_google_instrumentation", - artifact = "com.google.instrumentation:instrumentation-api:0.3.0", - sha1 = "a2e145e7a7567c6372738f5c5a6f3ba6407ac354", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/google_instrumentation", - actual = "@scala_proto_rules_google_instrumentation//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_netty_codec", - artifact = "io.netty:netty-codec:4.1.32.Final", - sha1 = "8f32bd79c5a16f014a4372ed979dc62b39ede33a", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/netty_codec", - actual = "@scala_proto_rules_netty_codec//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_netty_codec_http", - artifact = "io.netty:netty-codec-http:4.1.32.Final", - sha1 = "0b9218adba7353ad5a75fcb639e4755d64bd6ddf", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/netty_codec_http", - actual = "@scala_proto_rules_netty_codec_http//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_netty_codec_socks", - artifact = "io.netty:netty-codec-socks:4.1.32.Final", - sha1 = "b1e83cb772f842839dbeebd9a1f053da98bf56d2", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/netty_codec_socks", - actual = "@scala_proto_rules_netty_codec_socks//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_netty_codec_http2", - artifact = "io.netty:netty-codec-http2:4.1.32.Final", - sha1 = "d14eb053a1f96d3330ec48e77d489118d547557a", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/netty_codec_http2", - actual = "@scala_proto_rules_netty_codec_http2//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_netty_handler", - artifact = "io.netty:netty-handler:4.1.32.Final", - sha1 = "b4e3fa13f219df14a9455cc2111f133374428be0", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/netty_handler", - actual = "@scala_proto_rules_netty_handler//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_netty_buffer", - artifact = "io.netty:netty-buffer:4.1.32.Final", - sha1 = "046ede57693788181b2cafddc3a5967ed2f621c8", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/netty_buffer", - actual = "@scala_proto_rules_netty_buffer//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_netty_transport", - artifact = "io.netty:netty-transport:4.1.32.Final", - sha1 = "d5e5a8ff9c2bc7d91ddccc536a5aca1a4355bd8b", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/netty_transport", - actual = "@scala_proto_rules_netty_transport//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_netty_resolver", - artifact = "io.netty:netty-resolver:4.1.32.Final", - sha1 = "3e0114715cb125a12db8d982b2208e552a91256d", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/netty_resolver", - actual = "@scala_proto_rules_netty_resolver//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_netty_common", - artifact = "io.netty:netty-common:4.1.32.Final", - sha1 = "e95de4f762606f492328e180c8ad5438565a5e3b", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/netty_common", - actual = "@scala_proto_rules_netty_common//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_netty_handler_proxy", - artifact = "io.netty:netty-handler-proxy:4.1.32.Final", - sha1 = "58b621246262127b97a871b88c09374c8c324cb7", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/netty_handler_proxy", - actual = "@scala_proto_rules_netty_handler_proxy//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_opencensus_api", - artifact = "io.opencensus:opencensus-api:0.18.0", - sha1 = "b89a8f8dfd1e1e0d68d83c82a855624814b19a6e", - server = "scala_proto_deps_maven_server", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/opencensus_api", - actual = "@scala_proto_rules_opencensus_api//jar", - ) - - native.maven_jar( - name = "scala_proto_rules_opencensus_contrib_grpc_metrics", - artifact = "io.opencensus:opencensus-contrib-grpc-metrics:0.18.0", - sha1 = "8e90fab2930b6a0e67dab48911b9c936470d43dd", - ) - - native.bind( - name = "io_bazel_rules_scala/dependency/proto/opencensus_contrib_grpc_metrics", - actual = "@scala_proto_rules_opencensus_contrib_grpc_metrics//jar", - ) - -def _root_path(f): - if f.is_source: - return f.owner.workspace_root - return "/".join([f.root.path, f.owner.workspace_root]) - -def _colon_paths(data): - return ":".join([ - "{root},{path}".format(root = _root_path(f), path = f.path) - for f in sorted(data) - ]) - -def _retained_protos(inputs, blacklisted_proto_targets): - blacklisted_protos = [dep for target in blacklisted_proto_targets for dep in target.proto.transitive_sources] - blacklisted_protos_dict = dict(zip(blacklisted_protos, blacklisted_protos)) - return [f for f in inputs if blacklisted_protos_dict.get(f, None) == None] - -def _valid_proto_paths(transitive_proto_path): - """Build a list of valid paths to build the --proto_path arguments for the ScalaPB protobuf compiler - In particular, the '.' path needs to be stripped out. This mirrors a fix in the java proto rules: - https://github.com/bazelbuild/bazel/commit/af3605862047f7b553b7d2c19fa645714ea19bcf - This is explained in this issue: https://github.com/bazelbuild/rules_scala/issues/687 - """ - return depset([path for path in transitive_proto_path if path != "."]) - -def _gen_proto_srcjar_impl(ctx): - acc_imports = [] - transitive_proto_paths = [] - - jvm_deps = [] - for target in ctx.attr.deps: - if hasattr(target, "proto"): - acc_imports.append(target.proto.transitive_sources) - transitive_proto_paths.append(_valid_proto_paths(target.proto.transitive_proto_path)) - else: - jvm_deps.append(target) +load( + "//scala_proto/private:scala_proto_default_repositories.bzl", + "scala_proto_default_repositories", +) - acc_imports = depset(transitive = acc_imports) - if "java_conversions" in ctx.attr.flags and len(jvm_deps) == 0: - fail( - "must have at least one jvm dependency if with_java is True (java_conversions is turned on)", - ) +load( + "//scala_proto/private:scalapb_aspect.bzl", + "scalapb_aspect", + "ScalaPBInfo", + "merge_scalapb_aspect_info", + "ScalaPBAspectInfo", +) - deps_jars = collect_jars(jvm_deps) - worker_content = "{output}\n{paths}\n{flags_arg}\n{packages}\n{inputs}\n{protoc}".format( - output = ctx.outputs.srcjar.path, - paths = _colon_paths(acc_imports.to_list()), - # Command line args to worker cannot be empty so using padding - flags_arg = "-" + ",".join(ctx.attr.flags), - # Command line args to worker cannot be empty so using padding - packages = "-" + - ":".join(depset(transitive = transitive_proto_paths).to_list()), - # Pass inputs seprately because they doesn't always match to imports (ie blacklisted protos are excluded) - inputs = ":".join(sorted([f.path for f in _retained_protos(acc_imports, ctx.attr.blacklisted_protos)])), - protoc = ctx.executable._protoc.path - ) - argfile = ctx.actions.declare_file( - "%s_worker_input" % ctx.label.name, - sibling = ctx.outputs.srcjar, - ) - ctx.actions.write(output = argfile, content = worker_content) - ctx.actions.run( - executable = ctx.executable.generator, - inputs = depset([argfile, ctx.executable._protoc], transitive = [acc_imports]), - outputs = [ctx.outputs.srcjar], - mnemonic = "ProtoScalaPBRule", - progress_message = "creating scalapb files %s" % ctx.label, - execution_requirements = {"supports-workers": "1"}, - arguments = ["@" + argfile.path], - ) - srcjarsattr = struct(srcjar = ctx.outputs.srcjar) - scalaattr = struct( - outputs = None, - compile_jars = deps_jars.compile_jars, - transitive_runtime_jars = deps_jars.transitive_runtime_jars, - ) - java_provider = create_java_provider(scalaattr, depset()) - return struct( - scala = scalaattr, - providers = [java_provider], - srcjars = srcjarsattr, - ) - -scala_proto_srcjar = rule( - _gen_proto_srcjar_impl, - attrs = { - "deps": attr.label_list( - mandatory = True, - providers = [["proto"],[JavaInfo]], - ), - "flags": attr.string_list(default = []), - "generator": attr.label( - executable = True, - cfg = "host", - allow_files = True, - ), - "blacklisted_protos" : attr.label_list(providers = [["proto"]]), - "_protoc": attr.label(executable = True, cfg = "host", default = "@com_google_protobuf//:protoc") - }, - outputs = { - "srcjar": "lib%{name}.srcjar", - }, -) +def scala_proto_repositories( + scala_version = _default_scala_version(), + maven_servers = ["http://central.maven.org/maven2"]): + return scala_proto_default_repositories(scala_version, maven_servers) -SCALAPB_DEPS = [ - "//external:io_bazel_rules_scala/dependency/proto/scalapb_runtime", - "//external:io_bazel_rules_scala/dependency/com_google_protobuf/protobuf_java", - "//external:io_bazel_rules_scala/dependency/proto/scalapb_lenses", - "//external:io_bazel_rules_scala/dependency/proto/scalapb_fastparse", -] -GRPC_DEPS = [ - "//external:io_bazel_rules_scala/dependency/proto/scalapb_runtime_grpc", - "//external:io_bazel_rules_scala/dependency/proto/grpc_core", - "//external:io_bazel_rules_scala/dependency/proto/grpc_stub", - "//external:io_bazel_rules_scala/dependency/proto/grpc_protobuf", - "//external:io_bazel_rules_scala/dependency/proto/grpc_netty", - "//external:io_bazel_rules_scala/dependency/proto/grpc_context", - "//external:io_bazel_rules_scala/dependency/proto/guava", - "//external:io_bazel_rules_scala/dependency/proto/opencensus_api", - "//external:io_bazel_rules_scala/dependency/proto/opencensus_contrib_grpc_metrics", - "//external:io_bazel_rules_scala/dependency/proto/google_instrumentation", - "//external:io_bazel_rules_scala/dependency/proto/netty_codec", - "//external:io_bazel_rules_scala/dependency/proto/netty_codec_http", - "//external:io_bazel_rules_scala/dependency/proto/netty_codec_http2", - "//external:io_bazel_rules_scala/dependency/proto/netty_codec_socks", - "//external:io_bazel_rules_scala/dependency/proto/netty_handler", - "//external:io_bazel_rules_scala/dependency/proto/netty_buffer", - "//external:io_bazel_rules_scala/dependency/proto/netty_transport", - "//external:io_bazel_rules_scala/dependency/proto/netty_resolver", - "//external:io_bazel_rules_scala/dependency/proto/netty_common", - "//external:io_bazel_rules_scala/dependency/proto/netty_handler_proxy", -] """Generate scalapb bindings for a set of proto_library targets. Example: scalapb_proto_library( name = "exampla_proto_scala", - with_grpc = True, deps = ["//src/proto:example_service"] ) Args: name: A unique name for this rule deps: Proto library or java proto library (if with_java is True) targets that this rule depends on - with_grpc: Enables generation of grpc service bindings for services defined in deps - with_java: Enables generation of converters to and from java protobuf bindings - with_flat_package: When true, ScalaPB will not append the protofile base name to the package name - with_single_line_to_string: Enables generation of toString() methods that use the single line format - scalac_jvm_flags: List of JVM flags to pass to the underlying scala_library attribute Outputs: A scala_library rule that includes the generated scalapb bindings, as well as any library dependencies needed to compile and use these. """ -def scalapb_proto_library( - name, - deps = [], - with_grpc = False, - with_java = False, - with_flat_package = False, - with_single_line_to_string = False, - scalac_jvm_flags = [], - visibility = None): - srcjar = name + "_srcjar" - flags = [] - if with_grpc: - flags.append("grpc") - if with_java: - flags.append("java_conversions") - if with_flat_package: - flags.append("flat_package") - if with_single_line_to_string: - flags.append("single_line_to_string") - scala_proto_srcjar( - name = srcjar, - flags = flags, - generator = "@io_bazel_rules_scala//src/scala/scripts:scalapb_generator", - deps = deps, - visibility = visibility, + +def _scalapb_proto_library_impl(ctx): + aspect_info = merge_scalapb_aspect_info( + [dep[ScalaPBAspectInfo] for dep in ctx.attr.deps], ) + all_java = aspect_info.java_info - external_deps = list(SCALAPB_DEPS + GRPC_DEPS if ( - with_grpc - ) else SCALAPB_DEPS) + return [ + all_java, + ScalaPBInfo(aspect_info = aspect_info), + DefaultInfo(files = aspect_info.output_files), + ] - scala_library( - name = name, - srcs = [srcjar], - deps = [srcjar] + external_deps, - unused_dependency_checker_ignored_targets = [srcjar] + external_deps, - exports = external_deps, - scalac_jvm_flags = scalac_jvm_flags, - visibility = visibility, - ) +scalapb_proto_library = rule( + implementation = _scalapb_proto_library_impl, + attrs = { + "deps": attr.label_list(aspects = [scalapb_aspect]) + }, + provides = [DefaultInfo, ScalaPBInfo, JavaInfo], +) diff --git a/scala_proto/scala_proto_toolchain.bzl b/scala_proto/scala_proto_toolchain.bzl new file mode 100644 index 000000000..70dd50518 --- /dev/null +++ b/scala_proto/scala_proto_toolchain.bzl @@ -0,0 +1,57 @@ +load("//scala_proto/private:dep_sets.bzl", "SCALAPB_DEPS", "GRPC_DEPS") + +def _scala_proto_toolchain_impl(ctx): + toolchain = platform_common.ToolchainInfo( + with_grpc = ctx.attr.with_grpc, + with_flat_package = ctx.attr.with_flat_package, + with_single_line_to_string = ctx.attr.with_single_line_to_string, + blacklisted_protos = ctx.attr.blacklisted_protos, + code_generator = ctx.attr.code_generator, + grpc_deps=ctx.attr.grpc_deps, + implicit_compile_deps=ctx.attr.implicit_compile_deps, + scalac=ctx.attr.scalac, + ) + return [toolchain] + + +# Args: +# with_grpc: Enables generation of grpc service bindings for services +# with_flat_package: When true, ScalaPB will not append the protofile base name to the package name +# with_single_line_to_string: Enables generation of toString() methods that use the single line format +# blacklisted_protos: list of protobuf targets to exclude from recursive building +# code_generator: what code generator to use, usually you'll want the default +scala_proto_toolchain = rule( + _scala_proto_toolchain_impl, + attrs = { + "with_grpc": attr.bool(), + "with_flat_package": attr.bool(), + "with_single_line_to_string": attr.bool(), + "blacklisted_protos": attr.label_list(default=[]), + "code_generator": attr.label( + executable = True, + cfg = "host", + default = Label("@io_bazel_rules_scala//src/scala/scripts:scalapb_generator"), + allow_files=True + ), + "grpc_deps": attr.label_list( + providers = [JavaInfo], + default = GRPC_DEPS + ), + "implicit_compile_deps": attr.label_list( + providers = [JavaInfo], + default = SCALAPB_DEPS + [ + Label( + "//external:io_bazel_rules_scala/dependency/scala/scala_library", + ) + ], + ), + "scalac": attr.label( + default = Label( + "@io_bazel_rules_scala//src/java/io/bazel/rulesscala/scalac", + ), + ), + }, +) + + + diff --git a/scala_proto/toolchains.bzl b/scala_proto/toolchains.bzl new file mode 100644 index 000000000..dbc1926cc --- /dev/null +++ b/scala_proto/toolchains.bzl @@ -0,0 +1,7 @@ +def scala_proto_register_toolchains(): + native.register_toolchains("@io_bazel_rules_scala//scala_proto:default_toolchain") + + +def scala_proto_register_enable_all_options_toolchain(): + native.register_toolchains("@io_bazel_rules_scala//scala_proto:enable_all_options_toolchain") + diff --git a/src/scala/scripts/PBGenerateRequest.scala b/src/scala/scripts/PBGenerateRequest.scala index 744b64b17..916b6fd15 100644 --- a/src/scala/scripts/PBGenerateRequest.scala +++ b/src/scala/scripts/PBGenerateRequest.scala @@ -2,48 +2,39 @@ package scripts import java.nio.file.{Files, Path, Paths} -class PBGenerateRequest(val jarOutput: String, val scalaPBOutput: Path, val scalaPBArgs: List[String], val protoc: Path) +case class PBGenerateRequest(jarOutput: String, scalaPBOutput: Path, scalaPBArgs: List[String], includedProto: List[(Path, Path)], protoc: Path) object PBGenerateRequest { def from(args: java.util.List[String]): PBGenerateRequest = { val jarOutput = args.get(0) - val parsedProtoFiles = args.get(1).split(':').toList.map { rootAndFile => - val parsed = rootAndFile.split(',') - val root = parsed(0) - val file = if (root.isEmpty) { - parsed(1) - } else { - parsed(1).substring(root.length).stripPrefix("/") - } - (file, Paths.get(root, file).toString) - } - // This will map the absolute path of a given proto file - // to a relative path that does not contain the repo prefix. - // This is to match the expected behavior of - // proto_library and java_proto_library where proto files - // can import other proto files using only the relative path - val imports = parsedProtoFiles.map { case (relPath, absolutePath) => - s"-I$relPath=$absolutePath" - } val protoFiles = args.get(4).split(':') + val includedProto = args.get(1).drop(1).split(':').distinct.map { e => + val p = e.split(',') + // If its an empty string then it means we are local to the current repo for the key, no op + (Some(p(0)).filter(_.nonEmpty), p(1)) + }.collect { + // if the to compile files contains this absolute path then we are compiling it and shoudln't try move it around(duplicate files.) + case (Some(k), v) if !protoFiles.contains(v) => (Paths.get(k), Paths.get(v)) + }.toList + val flagOpt = args.get(2) match { case "-" => None case s if s.charAt(0) == '-' => Some(s.tail) //drop padding character case other => sys.error(s"expected a padding character of - (dash), but found: $other") } - val transitiveProtoPaths = args.get(3) match { + val transitiveProtoPaths = (args.get(3) match { case "-" => Nil case s if s.charAt(0) == '-' => s.tail.split(':').toList //drop padding character case other => sys.error(s"expected a padding character of - (dash), but found: $other") - } + }) ++ List(".") val tmp = Paths.get(Option(System.getProperty("java.io.tmpdir")).getOrElse("/tmp")) val scalaPBOutput = Files.createTempDirectory(tmp, "bazelscalapb") val flagPrefix = flagOpt.fold("")(_ + ":") - val scalaPBArgs = s"--scala_out=$flagPrefix$scalaPBOutput" :: (padWithProtoPathPrefix(transitiveProtoPaths) ++ imports ++ protoFiles) + val scalaPBArgs = s"--scala_out=$flagPrefix$scalaPBOutput" :: (padWithProtoPathPrefix(transitiveProtoPaths) ++ protoFiles) val protoc = Paths.get(args.get(5)) - new PBGenerateRequest(jarOutput, scalaPBOutput, scalaPBArgs, protoc) + new PBGenerateRequest(jarOutput, scalaPBOutput, scalaPBArgs, includedProto, protoc) } private def padWithProtoPathPrefix(transitiveProtoPathFlags: List[String]) = diff --git a/src/scala/scripts/ScalaPBGenerator.scala b/src/scala/scripts/ScalaPBGenerator.scala index 4627e16a7..85aa5d38d 100644 --- a/src/scala/scripts/ScalaPBGenerator.scala +++ b/src/scala/scripts/ScalaPBGenerator.scala @@ -7,6 +7,9 @@ import io.bazel.rulesscala.io_utils.DeleteRecursively import io.bazel.rulesscala.jar.JarCreator import io.bazel.rulesscala.worker.{GenericWorker, Processor} import protocbridge.ProtocBridge +import scala.collection.JavaConverters._ +import scalapb.ScalaPbCodeGenerator +import java.nio.file.{Files, Paths} import scalapb.{ScalaPBC, ScalaPbCodeGenerator, ScalaPbcException} object ScalaPBWorker extends GenericWorker(new ScalaPBGenerator) { @@ -29,6 +32,15 @@ object ScalaPBWorker extends GenericWorker(new ScalaPBGenerator) { } class ScalaPBGenerator extends Processor { + def setupIncludedProto(includedProto: List[(Path, Path)]): Unit = { + includedProto.foreach { case (root, fullPath) => + require(fullPath.toFile.exists, s"Path $fullPath does not exist, which it should as a dependency of this rule") + val relativePath = root.relativize(fullPath) + + relativePath.toFile.getParentFile.mkdirs + Files.copy(fullPath, relativePath) + } + } def deleteDir(path: Path): Unit = try DeleteRecursively.run(path) catch { @@ -37,6 +49,8 @@ class ScalaPBGenerator extends Processor { def processRequest(args: java.util.List[String]) { val extractRequestResult = PBGenerateRequest.from(args) + setupIncludedProto(extractRequestResult.includedProto) + val config = ScalaPBC.processArgs(extractRequestResult.scalaPBArgs.toArray) val code = ProtocBridge.runWithGenerators( protoc = exec(extractRequestResult.protoc), @@ -44,18 +58,15 @@ class ScalaPBGenerator extends Processor { params = config.args) try { - if (!config.throwException) { - JarCreator.buildJar(Array(extractRequestResult.jarOutput, extractRequestResult.scalaPBOutput.toString)) - } else { if (code != 0) { throw new ScalaPbcException(s"Exit with code $code") } - } + JarCreator.buildJar(Array(extractRequestResult.jarOutput, extractRequestResult.scalaPBOutput.toString)) } finally { deleteDir(extractRequestResult.scalaPBOutput) } } - private def exec(protoc: Path): Seq[String] => Int = (args: Seq[String]) => + protected def exec(protoc: Path): Seq[String] => Int = (args: Seq[String]) => new ProcessBuilder(protoc.toString +: args: _*).inheritIO().start().waitFor() } diff --git a/test/proto/BUILD b/test/proto/BUILD index 278440091..3204eb566 100644 --- a/test/proto/BUILD +++ b/test/proto/BUILD @@ -1,12 +1,48 @@ load( "//scala_proto:scala_proto.bzl", "scalapb_proto_library", - "scala_proto_srcjar" ) - load( "//scala:scala.bzl", + "scala_binary", "scala_library", + "scala_test", +) +load( + "//scala_proto:scala_proto_toolchain.bzl", + "scala_proto_toolchain", +) + +scala_proto_toolchain( + name = "test_scala_proto_toolchain_configuration", + # with_java=True, + blacklisted_protos = [ + "//test/proto:blacklisted_proto", + "//test/proto:other_blacklisted_proto", + ], + visibility = ["//visibility:public"], + with_flat_package = False, + with_grpc = True, + with_single_line_to_string = True, +) + +toolchain( + name = "scalapb_toolchain", + toolchain = ":test_scala_proto_toolchain_configuration", + toolchain_type = "@io_bazel_rules_scala//scala_proto:toolchain_type", + visibility = ["//visibility:public"], +) + +proto_library( + name = "blacklisted_proto", + srcs = ["blacklisted_proto.proto"], + visibility = ["//visibility:public"], +) + +proto_library( + name = "other_blacklisted_proto", + srcs = ["blacklisted_proto.proto"], + visibility = ["//visibility:public"], ) proto_library( @@ -41,8 +77,11 @@ scalapb_proto_library( # Test that the `proto_source_root` attribute is handled properly proto_library( name = "proto_source_root", + srcs = [ + "different_root.proto", + "different_root2.proto", + ], proto_source_root = native.package_name(), - srcs = ["different_root.proto", "different_root2.proto"], visibility = ["//visibility:public"], ) @@ -80,11 +119,8 @@ java_proto_library( scalapb_proto_library( name = "test_proto_java_conversions", visibility = ["//visibility:public"], - with_flat_package = True, - with_java = True, deps = [ ":test2", - ":test_proto_java_lib", "//test/proto2:test", ], ) @@ -92,27 +128,20 @@ scalapb_proto_library( scalapb_proto_library( name = "test_proto", visibility = ["//visibility:public"], - with_grpc = True, - deps = [":test_service"], + deps = [ + ":blacklisted_proto", + ":test_service", + "@io_bazel_rules_scala//test/proto:other_blacklisted_proto", + ], ) -scala_proto_srcjar( - name = "test1_proto_scala", - deps = ["//test/proto2:test"], - generator = "@io_bazel_rules_scala//src/scala/scripts:scalapb_generator") - -scala_proto_srcjar( - name = "test2_proto_scala_with_blacklisted_test1_proto_scala", - deps = [":test2"], - blacklisted_protos = ["//test/proto2:test"], - generator = "@io_bazel_rules_scala//src/scala/scripts:scalapb_generator") - -scala_library( - name = "lib_scala_should_fail_on_duplicated_sources_unless_duplicates_are_blacklisted", +scala_test( + name = "test_blacklisted_proto", srcs = [ - ":test1_proto_scala", - ":test2_proto_scala_with_blacklisted_test1_proto_scala"], + "BlackListedProtoTest.scala", + ], deps = [ - "@com_google_protobuf//:protobuf_java", - "@scala_proto_rules_scalapb_lenses", - "@scala_proto_rules_scalapb_runtime"]) + ":test_proto", + ], +) + diff --git a/test/proto/BlackListedProtoTest.scala b/test/proto/BlackListedProtoTest.scala new file mode 100644 index 000000000..c0b0678b5 --- /dev/null +++ b/test/proto/BlackListedProtoTest.scala @@ -0,0 +1,13 @@ +import org.scalatest.FlatSpec +import scala.util.Try + +class BlackListedProtoTest extends FlatSpec { + + "looking for a blacklisted proto" should "fail" in { + // The direct test dep should be here. + test.proto.test_service.TestServiceGrpc + + assert( + Try(Class.forName("test.proto.blacklisted_proto.BlackListedProtoMessage")).isFailure) + } +} diff --git a/test/proto/blacklisted_proto.proto b/test/proto/blacklisted_proto.proto new file mode 100644 index 000000000..0e7b39aa1 --- /dev/null +++ b/test/proto/blacklisted_proto.proto @@ -0,0 +1,8 @@ +syntax = "proto2"; + +option java_package = "test.proto"; + +message BlackListedProtoMessage { + optional uint32 c = 1; + optional bool d = 2; +} diff --git a/test_version/version_specific_tests_dir/proto/BUILD b/test_version/version_specific_tests_dir/proto/BUILD index 5f4ce4e4d..f60fba726 100644 --- a/test_version/version_specific_tests_dir/proto/BUILD +++ b/test_version/version_specific_tests_dir/proto/BUILD @@ -45,8 +45,6 @@ java_proto_library( scalapb_proto_library( name = "test_proto_java_conversions", visibility = ["//visibility:public"], - with_flat_package = True, - with_java = True, deps = [ ":test2", ":test_proto_java_lib", @@ -57,6 +55,5 @@ scalapb_proto_library( scalapb_proto_library( name = "test_proto", visibility = ["//visibility:public"], - with_grpc = True, deps = [":test_service"], )