java_grpc_library: Use toolchain to enable DexArchiveAspect

This removes the "java_import to work around error with android_binary"
hack; see the b/78647825 references to see the really important parts.
But in general using a toolchain cleans up the code considerably and
allows us to reduce the visibility of our protoc plugin. It also is
useful to enable using aspects in the future to avoid using
make_non_strict() which would improve compilation speed avoid avoid many
unnecessary rebuilds.

This is an export of cl/229763103 and brings external up-to-sync with
internal.
This commit is contained in:
Eric Anderson 2019-04-19 11:15:38 -07:00
parent 6d44f46f18
commit 745aa0a2f5
2 changed files with 146 additions and 72 deletions

View File

@ -1,3 +1,5 @@
load("//:java_grpc_library.bzl", "java_rpc_toolchain")
cc_binary( cc_binary(
name = "grpc_java_plugin", name = "grpc_java_plugin",
srcs = [ srcs = [
@ -5,8 +7,47 @@ cc_binary(
"src/java_plugin/cpp/java_generator.h", "src/java_plugin/cpp/java_generator.h",
"src/java_plugin/cpp/java_plugin.cpp", "src/java_plugin/cpp/java_plugin.cpp",
], ],
visibility = ["//visibility:public"],
deps = [ deps = [
"@com_google_protobuf//:protoc_lib", "@com_google_protobuf//:protoc_lib",
], ],
) )
java_library(
name = "java_grpc_library_deps__do_not_reference",
exports = [
"//api",
"//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",
exports = [
"//api",
"//protobuf-lite",
"//stub",
"//stub:javax_annotation",
"@com_google_code_findbugs_jsr305//jar",
"@com_google_guava_guava//jar",
],
)
java_rpc_toolchain(
name = "java_grpc_library_toolchain",
plugin = "//compiler:grpc_java_plugin",
runtime = [":java_grpc_library_deps__do_not_reference"],
visibility = ["//visibility:public"],
)
java_rpc_toolchain(
name = "java_lite_grpc_library_toolchain",
plugin = "//compiler:grpc_java_plugin",
plugin_arg = "lite",
runtime = [":java_lite_grpc_library_deps__do_not_reference"],
visibility = ["//visibility:public"],
)

View File

@ -2,6 +2,62 @@
load("@bazel_tools//tools/jdk:toolchain_utils.bzl", "find_java_runtime_toolchain", "find_java_toolchain") load("@bazel_tools//tools/jdk:toolchain_utils.bzl", "find_java_runtime_toolchain", "find_java_toolchain")
_JavaRpcToolchainInfo = provider(
fields = [
"host_javabase",
"java_toolchain",
"plugin",
"plugin_arg",
"protoc",
"runtime",
],
)
def _java_rpc_toolchain_impl(ctx):
return [
_JavaRpcToolchainInfo(
host_javabase = ctx.attr._host_javabase,
java_toolchain = ctx.attr._java_toolchain,
plugin = ctx.executable.plugin,
plugin_arg = ctx.attr.plugin_arg,
protoc = ctx.executable._protoc,
runtime = ctx.attr.runtime,
),
platform_common.ToolchainInfo(), # Magic for b/78647825
]
java_rpc_toolchain = rule(
attrs = {
# This attribute has a "magic" name recognized by the native DexArchiveAspect (b/78647825).
"runtime": attr.label_list(
cfg = "target",
providers = [JavaInfo],
),
"plugin": attr.label(
cfg = "host",
executable = True,
),
"plugin_arg": attr.string(),
"_protoc": attr.label(
cfg = "host",
default = Label("@com_google_protobuf//:protoc"),
executable = True,
),
"_java_toolchain": attr.label(
default = Label("@bazel_tools//tools/jdk:toolchain"),
),
"_host_javabase": attr.label(
cfg = "host",
default = Label("@bazel_tools//tools/jdk:current_java_runtime"),
),
},
provides = [
_JavaRpcToolchainInfo,
platform_common.ToolchainInfo,
],
implementation = _java_rpc_toolchain_impl,
)
# "repository" here is for Bazel builds that span multiple WORKSPACES. # "repository" here is for Bazel builds that span multiple WORKSPACES.
def _path_ignoring_repository(f): def _path_ignoring_repository(f):
if len(f.owner.workspace_root) == 0: if len(f.owner.workspace_root) == 0:
@ -18,25 +74,22 @@ def _java_rpc_library_impl(ctx):
print(("in srcs attribute of {0}: Proto source with label {1} should be in " + 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)) "same package as consuming rule").format(ctx.label, ctx.attr.srcs[0].label))
toolchain = ctx.attr._toolchain[_JavaRpcToolchainInfo]
srcs = ctx.attr.srcs[0][ProtoInfo].direct_sources srcs = ctx.attr.srcs[0][ProtoInfo].direct_sources
includes = ctx.attr.srcs[0][ProtoInfo].transitive_imports includes = ctx.attr.srcs[0][ProtoInfo].transitive_imports
flavor = ctx.attr.flavor
if flavor == "normal":
flavor = ""
srcjar = ctx.actions.declare_file("%s-proto-gensrc.jar" % ctx.label.name) srcjar = ctx.actions.declare_file("%s-proto-gensrc.jar" % ctx.label.name)
args = ctx.actions.args() args = ctx.actions.args()
args.add(ctx.executable._java_plugin.path, format = "--plugin=protoc-gen-grpc-java=%s") args.add(toolchain.plugin, format = "--plugin=protoc-gen-rpc-plugin=%s")
args.add("--grpc-java_out={0}:{1}".format(flavor, srcjar.path)) args.add("--rpc-plugin_out={0}:{1}".format(toolchain.plugin_arg, srcjar.path))
args.add_all(includes, map_each = _create_include_path) args.add_all(includes, map_each = _create_include_path)
args.add_all(srcs, map_each = _path_ignoring_repository) args.add_all(srcs, map_each = _path_ignoring_repository)
ctx.actions.run( ctx.actions.run(
inputs = depset(srcs, transitive = [includes]), inputs = depset([toolchain.plugin] + srcs, transitive = [includes]),
outputs = [srcjar], outputs = [srcjar],
tools = [ctx.executable._java_plugin], executable = toolchain.protoc,
executable = ctx.executable._protoc,
arguments = [args], arguments = [args],
) )
@ -44,19 +97,19 @@ def _java_rpc_library_impl(ctx):
java_info = java_common.compile( java_info = java_common.compile(
ctx, ctx,
java_toolchain = find_java_toolchain(ctx, ctx.attr._java_toolchain), java_toolchain = find_java_toolchain(ctx, toolchain.java_toolchain),
host_javabase = find_java_runtime_toolchain(ctx, ctx.attr._host_javabase), host_javabase = find_java_runtime_toolchain(ctx, toolchain.host_javabase),
source_jars = [srcjar], source_jars = [srcjar],
output_source_jar = ctx.outputs.srcjar,
output = ctx.outputs.jar, output = ctx.outputs.jar,
output_source_jar = ctx.outputs.srcjar,
deps = [ deps = [
java_common.make_non_strict(deps_java_info), java_common.make_non_strict(deps_java_info),
ctx.attr.runtime[JavaInfo], ] + [dep[JavaInfo] for dep in toolchain.runtime],
],
) )
return [java_info] return [java_info]
_java_rpc_library = rule( _java_grpc_library = rule(
attrs = { attrs = {
"srcs": attr.label_list( "srcs": attr.label_list(
mandatory = True, mandatory = True,
@ -68,32 +121,34 @@ _java_rpc_library = rule(
allow_empty = False, allow_empty = False,
providers = [JavaInfo], providers = [JavaInfo],
), ),
"flavor": attr.string( "_toolchain": attr.label(
values = [ default = Label("//compiler:java_grpc_library_toolchain"),
"normal",
"lite",
],
default = "normal",
), ),
"runtime": attr.label( },
fragments = ["java"],
outputs = {
"jar": "lib%{name}.jar",
"srcjar": "lib%{name}-src.jar",
},
provides = [JavaInfo],
implementation = _java_rpc_library_impl,
)
_java_lite_grpc_library = rule(
attrs = {
"srcs": attr.label_list(
mandatory = True, mandatory = True,
allow_empty = False,
providers = ["proto"],
), ),
"_protoc": attr.label( "deps": attr.label_list(
default = Label("@com_google_protobuf//:protoc"), mandatory = True,
executable = True, allow_empty = False,
cfg = "host", providers = [JavaInfo],
), ),
"_java_plugin": attr.label( # This attribute has a "magic" name recognized by the native DexArchiveAspect (b/78647825).
default = Label("//compiler:grpc_java_plugin"), "_toolchain": attr.label(
executable = True, default = Label("//compiler:java_lite_grpc_library_toolchain"),
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"], fragments = ["java"],
@ -110,8 +165,6 @@ def java_grpc_library(
srcs, srcs,
deps, deps,
flavor = None, flavor = None,
tags = None,
visibility = None,
**kwargs): **kwargs):
"""Generates and compiles gRPC Java sources for services defined in a proto """Generates and compiles gRPC Java sources for services defined in a proto
file. This rule is compatible with proto_library with java_api_version, file. This rule is compatible with proto_library with java_api_version,
@ -130,45 +183,25 @@ def java_grpc_library(
srcs. Required. srcs. Required.
flavor: (str) "normal" (default) for normal proto runtime. "lite" flavor: (str) "normal" (default) for normal proto runtime. "lite"
for the lite runtime. for the lite runtime.
visibility: (list) the visibility list
**kwargs: Passed through to generated targets **kwargs: Passed through to generated targets
""" """
if len(deps) > 1: if len(deps) > 1:
print("Multiple values in 'deps' is deprecated in " + name) print("Multiple values in 'deps' is deprecated in " + name)
if flavor == "lite": if flavor == None or flavor == "normal":
inner_name = name + "__do_not_reference" _java_grpc_library(
inner_visibility = ["//visibility:private"]
inner_tags = ["avoid_dep"]
runtime = "@io_grpc_grpc_java//:java_lite_grpc_library_deps__do_not_reference"
else:
inner_name = name
inner_visibility = visibility
inner_tags = tags
runtime = "@io_grpc_grpc_java//:java_grpc_library_deps__do_not_reference"
_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, name = name,
deps = deps + [runtime], srcs = srcs,
jars = [":lib{}.jar".format(inner_name)], deps = deps,
srcjar = ":lib{}-src.jar".format(inner_name),
visibility = visibility,
tags = tags,
**kwargs **kwargs
) )
elif flavor == "lite":
_java_lite_grpc_library(
name = name,
srcs = srcs,
deps = deps,
**kwargs
)
else:
fail("Flavor must be normal or lite")