diff --git a/BUILD.bazel b/BUILD.bazel index e4175b0ece..a1b416eec7 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -24,3 +24,30 @@ java_grpc_library( srcs = ["@com_google_protobuf//:api_proto"], deps = [":api_proto_java"], ) + +java_library( + name = "java_grpc_library_deps__do_not_reference", + visibility = ["//visibility:public"], + exports = [ + "//core", + "//protobuf", + "//stub", + "//stub:javax_annotation", + "@com_google_code_findbugs_jsr305//jar", + "@com_google_guava_guava//jar", + "@com_google_protobuf//:protobuf_java", + ], +) + +java_library( + name = "java_lite_grpc_library_deps__do_not_reference", + visibility = ["//visibility:public"], + exports = [ + "//core", + "//protobuf-lite", + "//stub", + "//stub:javax_annotation", + "@com_google_code_findbugs_jsr305//jar", + "@com_google_guava_guava//jar", + ], +) diff --git a/java_grpc_library.bzl b/java_grpc_library.bzl index 5ea8386fdd..76264a0d25 100644 --- a/java_grpc_library.bzl +++ b/java_grpc_library.bzl @@ -1,60 +1,74 @@ +# "repository" here is for Bazel builds that span multiple WORKSPACES. def _path_ignoring_repository(f): - if (len(f.owner.workspace_root) == 0): + if len(f.owner.workspace_root) == 0: return f.short_path return f.path[f.path.find(f.owner.workspace_root) + len(f.owner.workspace_root) + 1:] -def _gensource_impl(ctx): - if len(ctx.attr.srcs) > 1: - fail("Only one src value supported", "srcs") - for s in ctx.attr.srcs: - if s.label.package != ctx.label.package: - print(("in srcs attribute of {0}: Proto source with label {1} should be in " + - "same package as consuming rule").format(ctx.label, s.label)) +def _create_include_path(include): + return "-I{0}={1}".format(_path_ignoring_repository(include), include.path) - # Use .jar since .srcjar makes protoc think output will be a directory - srcdotjar = ctx.new_file(ctx.label.name + "_src.jar") - - srcs = [f for dep in ctx.attr.srcs for f in dep.proto.direct_sources] - includes = [f for dep in ctx.attr.srcs for f in dep.proto.transitive_imports] +def _java_rpc_library_impl(ctx): + if len(ctx.attr.srcs) != 1: + fail("Exactly one src value supported", "srcs") + if ctx.attr.srcs[0].label.package != ctx.label.package: + print(("in srcs attribute of {0}: Proto source with label {1} should be in " + + "same package as consuming rule").format(ctx.label, ctx.attr.srcs[0].label)) + srcs = ctx.attr.srcs[0].proto.direct_sources + includes = ctx.attr.srcs[0].proto.transitive_imports flavor = ctx.attr.flavor if flavor == "normal": flavor = "" + + args = ctx.actions.args() + args.add(ctx.executable._java_plugin.path, format = "--plugin=protoc-gen-grpc-java=%s") + args.add("--grpc-java_out={0}:{1}".format(flavor, ctx.outputs.srcjar.path)) + args.add_all(includes, map_each = _create_include_path) + args.add_all(srcs, map_each = _path_ignoring_repository) + ctx.action( - inputs = [ctx.executable._java_plugin] + srcs + includes, - outputs = [srcdotjar], - executable = ctx.executable._protoc, - arguments = [ - "--plugin=protoc-gen-grpc-java=" + ctx.executable._java_plugin.path, - "--grpc-java_out={0},enable_deprecated={1}:{2}" - .format(flavor, str(ctx.attr.enable_deprecated).lower(), srcdotjar.path), - ] + - ["-I{0}={1}".format(_path_ignoring_repository(include), include.path) for include in includes] + - [_path_ignoring_repository(src) for src in srcs], - ) - ctx.action( - command = "cp $1 $2", - inputs = [srcdotjar], + inputs = depset([ctx.executable._java_plugin] + srcs, transitive = [includes]), outputs = [ctx.outputs.srcjar], - arguments = [srcdotjar.path, ctx.outputs.srcjar.path], + executable = ctx.executable._protoc, + arguments = [args], ) -_gensource = rule( + deps_java_info = java_common.merge([dep[JavaInfo] for dep in ctx.attr.deps]) + + java_info = java_common.compile( + ctx, + java_toolchain = ctx.attr._java_toolchain, + host_javabase = ctx.attr._host_javabase, + source_jars = [ctx.outputs.srcjar], + output = ctx.outputs.jar, + deps = [ + java_common.make_non_strict(deps_java_info), + ctx.attr.runtime[JavaInfo], + ], + ) + return [java_info] + +_java_rpc_library = rule( attrs = { "srcs": attr.label_list( mandatory = True, non_empty = True, providers = ["proto"], ), + "deps": attr.label_list( + mandatory = True, + non_empty = True, + providers = [JavaInfo], + ), "flavor": attr.string( values = [ "normal", - "lite", # Not currently supported + "lite", ], default = "normal", ), - "enable_deprecated": attr.bool( - default = False, + "runtime": attr.label( + mandatory = True, ), "_protoc": attr.label( default = Label("@com_google_protobuf//:protoc"), @@ -66,11 +80,21 @@ _gensource = rule( executable = True, cfg = "host", ), + "_java_toolchain": attr.label( + default = Label("@bazel_tools//tools/jdk:current_java_toolchain"), + ), + "_host_javabase": attr.label( + cfg = "host", + default = Label("@bazel_tools//tools/jdk:current_host_java_runtime"), + ), }, + fragments = ["java"], outputs = { - "srcjar": "%{name}.srcjar", + "jar": "lib%{name}.jar", + "srcjar": "lib%{name}-src.jar", }, - implementation = _gensource_impl, + provides = [JavaInfo], + implementation = _java_rpc_library_impl, ) def java_grpc_library( @@ -78,15 +102,17 @@ def java_grpc_library( srcs, deps, flavor = None, - enable_deprecated = None, + tags = None, visibility = None, **kwargs): """Generates and compiles gRPC Java sources for services defined in a proto - file. This rule is compatible with java_proto_library and java_lite_proto_library. + file. This rule is compatible with proto_library with java_api_version, + java_proto_library, and java_lite_proto_library. Do note that this rule only scans through the proto file for RPC services. It does not generate Java classes for proto messages. You will need a separate - java_proto_library or java_lite_proto_library rule. + proto_library with java_api_version, java_proto_library, or + java_lite_proto_library rule. Args: name: (str) A unique name for this rule. Required. @@ -99,44 +125,42 @@ def java_grpc_library( visibility: (list) the visibility list **kwargs: Passed through to generated targets """ - if flavor == None: - flavor = "normal" if len(deps) > 1: print("Multiple values in 'deps' is deprecated in " + name) - gensource_name = name + "__do_not_reference__srcjar" - _gensource( - name = gensource_name, - srcs = srcs, - flavor = flavor, - enable_deprecated = enable_deprecated, - visibility = ["//visibility:private"], - **kwargs - ) - - added_deps = [ - "@io_grpc_grpc_java//core", - "@io_grpc_grpc_java//stub", - "@io_grpc_grpc_java//stub:javax_annotation", - "@com_google_guava_guava//jar", - ] - if flavor == "normal": - added_deps += [ - "@com_google_protobuf//:protobuf_java", - "@io_grpc_grpc_java//protobuf", - ] - elif flavor == "lite": - added_deps += ["@io_grpc_grpc_java//protobuf-lite"] + if flavor == "lite": + inner_name = name + "__do_not_reference" + inner_visibility = ["//visibility:private"] + inner_tags = ["avoid_dep"] + runtime = "@io_grpc_grpc_java//:java_lite_grpc_library_deps__do_not_reference" else: - fail("Unknown flavor type", "flavor") + inner_name = name + inner_visibility = visibility + inner_tags = tags + runtime = "@io_grpc_grpc_java//:java_grpc_library_deps__do_not_reference" - native.java_library( - name = name, - srcs = [gensource_name], - visibility = visibility, - deps = [ - "@com_google_code_findbugs_jsr305//jar", - ] + deps + added_deps, + _java_rpc_library( + name = inner_name, + srcs = srcs, + deps = deps, + flavor = flavor, + runtime = runtime, + visibility = inner_visibility, + tags = inner_tags, **kwargs ) + + if flavor == "lite": + # Use java_import to work around error with android_binary: + # Dependencies on .jar artifacts are not allowed in Android binaries, + # please use a java_import to depend on... + native.java_import( + name = name, + deps = deps + [runtime], + jars = [":lib{}.jar".format(inner_name)], + srcjar = ":lib{}-src.jar".format(inner_name), + visibility = visibility, + tags = tags, + **kwargs + )