Tests will be submitted in separate PRs. PiperOrigin-RevId: 674321127pull/18298/head
parent
50eafe9e11
commit
d77bdacc31
14 changed files with 483 additions and 33 deletions
@ -1,3 +1,18 @@ |
||||
# Copyright (c) 2009-2024, Google LLC |
||||
# All rights reserved. |
||||
# |
||||
# Use of this source code is governed by a BSD-style |
||||
# license that can be found in the LICENSE file or at |
||||
# https://developers.google.com/open-source/licenses/bsd |
||||
"""java_lite_proto_library rule""" |
||||
|
||||
java_lite_proto_library = native.java_lite_proto_library |
||||
load("@proto_bazel_features//:features.bzl", "bazel_features") |
||||
load("//bazel/private:java_lite_proto_library.bzl", _java_lite_proto_library = "java_lite_proto_library") # buildifier: disable=bzl-visibility |
||||
|
||||
def java_lite_proto_library(**kwattrs): |
||||
# This condition causes Starlark rules to be used only on Bazel >=7.0.0 |
||||
if bazel_features.proto.starlark_proto_info: |
||||
_java_lite_proto_library(**kwattrs) |
||||
else: |
||||
# On older Bazel versions keep using native rules, so that mismatch in ProtoInfo doesn't happen |
||||
native.java_lite_proto_library(**kwattrs) |
||||
|
@ -1,3 +1,18 @@ |
||||
# Copyright (c) 2009-2024, Google LLC |
||||
# All rights reserved. |
||||
# |
||||
# Use of this source code is governed by a BSD-style |
||||
# license that can be found in the LICENSE file or at |
||||
# https://developers.google.com/open-source/licenses/bsd |
||||
"""java_proto_library rule""" |
||||
|
||||
java_proto_library = native.java_proto_library |
||||
load("@proto_bazel_features//:features.bzl", "bazel_features") |
||||
load("//bazel/private:bazel_java_proto_library_rule.bzl", _java_proto_library = "java_proto_library") # buildifier: disable=bzl-visibility |
||||
|
||||
def java_proto_library(**kwattrs): |
||||
# This condition causes Starlark rules to be used only on Bazel >=7.0.0 |
||||
if bazel_features.proto.starlark_proto_info: |
||||
_java_proto_library(**kwattrs) |
||||
else: |
||||
# On older Bazel versions keep using native rules, so that mismatch in ProtoInfo doesn't happen |
||||
native.java_proto_library(**kwattrs) |
||||
|
@ -0,0 +1,169 @@ |
||||
# Copyright (c) 2009-2024, Google LLC |
||||
# All rights reserved. |
||||
# |
||||
# Use of this source code is governed by a BSD-style |
||||
# license that can be found in the LICENSE file or at |
||||
# https://developers.google.com/open-source/licenses/bsd |
||||
"""The implementation of the `java_proto_library` rule and its aspect.""" |
||||
|
||||
load("@rules_java//java/common:java_info.bzl", "JavaInfo") |
||||
load("//bazel/common:proto_common.bzl", "proto_common") |
||||
load("//bazel/common:proto_info.bzl", "ProtoInfo") |
||||
load("//bazel/private:java_proto_support.bzl", "java_compile_for_protos", "java_info_merge_for_protos") |
||||
load("//bazel/private:toolchain_helpers.bzl", "toolchains") |
||||
|
||||
# TODO: replace with toolchain type located in protobuf |
||||
_JAVA_PROTO_TOOLCHAIN = "@rules_java//java/proto:toolchain_type" |
||||
|
||||
# The provider is used to collect source and runtime jars in the `proto_library` dependency graph. |
||||
JavaProtoAspectInfo = provider("JavaProtoAspectInfo", fields = ["jars"]) |
||||
|
||||
def _filter_provider(provider, *attrs): |
||||
return [dep[provider] for attr in attrs for dep in attr if provider in dep] |
||||
|
||||
def _bazel_java_proto_aspect_impl(target, ctx): |
||||
"""Generates and compiles Java code for a proto_library. |
||||
|
||||
The function runs protobuf compiler on the `proto_library` target using |
||||
`proto_lang_toolchain` specified by `--proto_toolchain_for_java` flag. |
||||
This generates a source jar. |
||||
|
||||
After that the source jar is compiled, respecting `deps` and `exports` of |
||||
the `proto_library`. |
||||
|
||||
Args: |
||||
target: (Target) The `proto_library` target (any target providing `ProtoInfo`. |
||||
ctx: (RuleContext) The rule context. |
||||
|
||||
Returns: |
||||
([JavaInfo, JavaProtoAspectInfo]) A JavaInfo describing compiled Java |
||||
version of`proto_library` and `JavaProtoAspectInfo` with all source and |
||||
runtime jars. |
||||
""" |
||||
|
||||
proto_toolchain_info = toolchains.find_toolchain(ctx, "_aspect_java_proto_toolchain", _JAVA_PROTO_TOOLCHAIN) |
||||
source_jar = None |
||||
if proto_common.experimental_should_generate_code(target[ProtoInfo], proto_toolchain_info, "java_proto_library", target.label): |
||||
# Generate source jar using proto compiler. |
||||
source_jar = ctx.actions.declare_file(ctx.label.name + "-speed-src.jar") |
||||
proto_common.compile( |
||||
ctx.actions, |
||||
target[ProtoInfo], |
||||
proto_toolchain_info, |
||||
[source_jar], |
||||
experimental_output_files = "single", |
||||
) |
||||
|
||||
# Compile Java sources (or just merge if there aren't any) |
||||
deps = _filter_provider(JavaInfo, ctx.rule.attr.deps) |
||||
exports = _filter_provider(JavaInfo, ctx.rule.attr.exports) |
||||
if source_jar and proto_toolchain_info.runtime: |
||||
deps.append(proto_toolchain_info.runtime[JavaInfo]) |
||||
java_info, jars = java_compile_for_protos( |
||||
ctx, |
||||
"-speed.jar", |
||||
source_jar, |
||||
deps, |
||||
exports, |
||||
) |
||||
|
||||
transitive_jars = [dep[JavaProtoAspectInfo].jars for dep in ctx.rule.attr.deps if JavaProtoAspectInfo in dep] |
||||
return [ |
||||
java_info, |
||||
JavaProtoAspectInfo(jars = depset(jars, transitive = transitive_jars)), |
||||
] |
||||
|
||||
bazel_java_proto_aspect = aspect( |
||||
implementation = _bazel_java_proto_aspect_impl, |
||||
attrs = toolchains.if_legacy_toolchain({ |
||||
"_aspect_java_proto_toolchain": attr.label( |
||||
default = configuration_field(fragment = "proto", name = "proto_toolchain_for_java"), |
||||
), |
||||
}), |
||||
toolchains = ["@bazel_tools//tools/jdk:toolchain_type"] + toolchains.use_toolchain(_JAVA_PROTO_TOOLCHAIN), |
||||
attr_aspects = ["deps", "exports"], |
||||
required_providers = [ProtoInfo], |
||||
provides = [JavaInfo, JavaProtoAspectInfo], |
||||
fragments = ["java"], |
||||
) |
||||
|
||||
def bazel_java_proto_library_rule(ctx): |
||||
"""Merges results of `java_proto_aspect` in `deps`. |
||||
|
||||
Args: |
||||
ctx: (RuleContext) The rule context. |
||||
Returns: |
||||
([JavaInfo, DefaultInfo, OutputGroupInfo]) |
||||
""" |
||||
proto_toolchain = toolchains.find_toolchain(ctx, "_aspect_java_proto_toolchain", _JAVA_PROTO_TOOLCHAIN) |
||||
for dep in ctx.attr.deps: |
||||
proto_common.check_collocated(ctx.label, dep[ProtoInfo], proto_toolchain) |
||||
|
||||
java_info = java_info_merge_for_protos([dep[JavaInfo] for dep in ctx.attr.deps], merge_java_outputs = False) |
||||
|
||||
transitive_src_and_runtime_jars = depset(transitive = [dep[JavaProtoAspectInfo].jars for dep in ctx.attr.deps]) |
||||
transitive_runtime_jars = depset(transitive = [java_info.transitive_runtime_jars]) |
||||
|
||||
return [ |
||||
java_info, |
||||
DefaultInfo( |
||||
files = transitive_src_and_runtime_jars, |
||||
runfiles = ctx.runfiles(transitive_files = transitive_runtime_jars), |
||||
), |
||||
OutputGroupInfo(default = depset()), |
||||
] |
||||
|
||||
java_proto_library = rule( |
||||
implementation = bazel_java_proto_library_rule, |
||||
doc = """ |
||||
<p> |
||||
<code>java_proto_library</code> generates Java code from <code>.proto</code> files. |
||||
</p> |
||||
|
||||
<p> |
||||
<code>deps</code> must point to <a href="protocol-buffer.html#proto_library"><code>proto_library |
||||
</code></a> rules. |
||||
</p> |
||||
|
||||
<p> |
||||
Example: |
||||
</p> |
||||
|
||||
<pre class="code"> |
||||
<code class="lang-starlark"> |
||||
java_library( |
||||
name = "lib", |
||||
runtime_deps = [":foo_java_proto"], |
||||
) |
||||
|
||||
java_proto_library( |
||||
name = "foo_java_proto", |
||||
deps = [":foo_proto"], |
||||
) |
||||
|
||||
proto_library( |
||||
name = "foo_proto", |
||||
) |
||||
</code> |
||||
</pre> |
||||
""", |
||||
attrs = { |
||||
"deps": attr.label_list( |
||||
providers = [ProtoInfo], |
||||
aspects = [bazel_java_proto_aspect], |
||||
doc = """ |
||||
The list of <a href="protocol-buffer.html#proto_library"><code>proto_library</code></a> |
||||
rules to generate Java code for. |
||||
""", |
||||
), |
||||
# buildifier: disable=attr-license (calling attr.license()) |
||||
"licenses": attr.license() if hasattr(attr, "license") else attr.string_list(), |
||||
"distribs": attr.string_list(), |
||||
} | toolchains.if_legacy_toolchain({ |
||||
"_aspect_java_proto_toolchain": attr.label( |
||||
default = configuration_field(fragment = "proto", name = "proto_toolchain_for_java"), |
||||
), |
||||
}), # buildifier: disable=attr-licenses (attribute called licenses) |
||||
provides = [JavaInfo], |
||||
toolchains = toolchains.use_toolchain(_JAVA_PROTO_TOOLCHAIN), |
||||
) |
@ -0,0 +1,179 @@ |
||||
# Copyright (c) 2009-2024, Google LLC |
||||
# All rights reserved. |
||||
# |
||||
# Use of this source code is governed by a BSD-style |
||||
# license that can be found in the LICENSE file or at |
||||
# https://developers.google.com/open-source/licenses/bsd |
||||
"""A Starlark implementation of the java_lite_proto_library rule.""" |
||||
|
||||
load("@rules_java//java/common:java_common.bzl", "java_common") |
||||
load("@rules_java//java/common:java_info.bzl", "JavaInfo") |
||||
load("@rules_java//java/common:proguard_spec_info.bzl", "ProguardSpecInfo") |
||||
load("//bazel/common:proto_common.bzl", "proto_common") |
||||
load("//bazel/common:proto_info.bzl", "ProtoInfo") |
||||
load("//bazel/private:java_proto_support.bzl", "JavaProtoAspectInfo", "java_compile_for_protos", "java_info_merge_for_protos") |
||||
load("//bazel/private:toolchain_helpers.bzl", "toolchains") |
||||
|
||||
_PROTO_TOOLCHAIN_ATTR = "_aspect_proto_toolchain_for_javalite" |
||||
|
||||
# TODO: replace with toolchain type located in protobuf |
||||
_JAVA_LITE_PROTO_TOOLCHAIN = "@rules_java//java/proto:lite_toolchain_type" |
||||
|
||||
def _aspect_impl(target, ctx): |
||||
"""Generates and compiles Java code for a proto_library dependency graph. |
||||
|
||||
Args: |
||||
target: (Target) The `proto_library` target. |
||||
ctx: (RuleContext) The rule context. |
||||
|
||||
Returns: |
||||
([JavaInfo, JavaProtoAspectInfo]) A JavaInfo describing compiled Java |
||||
version of`proto_library` and `JavaProtoAspectInfo` with all source and |
||||
runtime jars. |
||||
""" |
||||
|
||||
deps = [dep[JavaInfo] for dep in ctx.rule.attr.deps] |
||||
exports = [exp[JavaInfo] for exp in ctx.rule.attr.exports] |
||||
proto_toolchain_info = toolchains.find_toolchain( |
||||
ctx, |
||||
"_aspect_proto_toolchain_for_javalite", |
||||
_JAVA_LITE_PROTO_TOOLCHAIN, |
||||
) |
||||
source_jar = None |
||||
|
||||
if proto_common.experimental_should_generate_code(target[ProtoInfo], proto_toolchain_info, "java_lite_proto_library", target.label): |
||||
source_jar = ctx.actions.declare_file(ctx.label.name + "-lite-src.jar") |
||||
proto_common.compile( |
||||
ctx.actions, |
||||
target[ProtoInfo], |
||||
proto_toolchain_info, |
||||
[source_jar], |
||||
experimental_output_files = "single", |
||||
) |
||||
runtime = proto_toolchain_info.runtime |
||||
if runtime: |
||||
deps.append(runtime[JavaInfo]) |
||||
|
||||
java_info, jars = java_compile_for_protos( |
||||
ctx, |
||||
"-lite.jar", |
||||
source_jar, |
||||
deps, |
||||
exports, |
||||
injecting_rule_kind = "java_lite_proto_library", |
||||
) |
||||
transitive_jars = [dep[JavaProtoAspectInfo].jars for dep in ctx.rule.attr.deps] |
||||
|
||||
return [ |
||||
java_info, |
||||
JavaProtoAspectInfo(jars = depset(jars, transitive = transitive_jars)), |
||||
] |
||||
|
||||
_java_lite_proto_aspect = aspect( |
||||
implementation = _aspect_impl, |
||||
attr_aspects = ["deps", "exports"], |
||||
attrs = toolchains.if_legacy_toolchain({ |
||||
_PROTO_TOOLCHAIN_ATTR: attr.label( |
||||
default = configuration_field(fragment = "proto", name = "proto_toolchain_for_java_lite"), |
||||
), |
||||
}), |
||||
fragments = ["java"], |
||||
required_providers = [ProtoInfo], |
||||
provides = [JavaInfo, JavaProtoAspectInfo], |
||||
toolchains = ["@bazel_tools//tools/jdk:toolchain_type"] + |
||||
toolchains.use_toolchain(_JAVA_LITE_PROTO_TOOLCHAIN), |
||||
) |
||||
|
||||
def _rule_impl(ctx): |
||||
"""Merges results of `java_proto_aspect` in `deps`. |
||||
|
||||
`java_lite_proto_library` is identical to `java_proto_library` in every respect, except it |
||||
builds JavaLite protos. |
||||
Implementation of this rule is built on the implementation of `java_proto_library`. |
||||
|
||||
Args: |
||||
ctx: (RuleContext) The rule context. |
||||
Returns: |
||||
([JavaInfo, DefaultInfo, OutputGroupInfo, ProguardSpecInfo]) |
||||
""" |
||||
|
||||
proto_toolchain_info = toolchains.find_toolchain( |
||||
ctx, |
||||
"_aspect_proto_toolchain_for_javalite", |
||||
_JAVA_LITE_PROTO_TOOLCHAIN, |
||||
) |
||||
for dep in ctx.attr.deps: |
||||
proto_common.check_collocated(ctx.label, dep[ProtoInfo], proto_toolchain_info) |
||||
|
||||
runtime = proto_toolchain_info.runtime |
||||
|
||||
if runtime: |
||||
proguard_provider_specs = runtime[ProguardSpecInfo] |
||||
else: |
||||
proguard_provider_specs = ProguardSpecInfo(specs = depset()) |
||||
|
||||
java_info = java_info_merge_for_protos([dep[JavaInfo] for dep in ctx.attr.deps], merge_java_outputs = False) |
||||
|
||||
transitive_src_and_runtime_jars = depset(transitive = [dep[JavaProtoAspectInfo].jars for dep in ctx.attr.deps]) |
||||
transitive_runtime_jars = depset(transitive = [java_info.transitive_runtime_jars]) |
||||
|
||||
if hasattr(java_common, "add_constraints"): |
||||
java_info = java_common.add_constraints(java_info, constraints = ["android"]) |
||||
|
||||
return [ |
||||
java_info, |
||||
DefaultInfo( |
||||
files = transitive_src_and_runtime_jars, |
||||
runfiles = ctx.runfiles(transitive_files = transitive_runtime_jars), |
||||
), |
||||
OutputGroupInfo(default = depset()), |
||||
proguard_provider_specs, |
||||
] |
||||
|
||||
java_lite_proto_library = rule( |
||||
implementation = _rule_impl, |
||||
doc = """ |
||||
<p> |
||||
<code>java_lite_proto_library</code> generates Java code from <code>.proto</code> files. |
||||
</p> |
||||
|
||||
<p> |
||||
<code>deps</code> must point to <a href="protocol-buffer.html#proto_library"><code>proto_library |
||||
</code></a> rules. |
||||
</p> |
||||
|
||||
<p> |
||||
Example: |
||||
</p> |
||||
|
||||
<pre class="code"> |
||||
<code class="lang-starlark"> |
||||
java_library( |
||||
name = "lib", |
||||
runtime_deps = [":foo"], |
||||
) |
||||
|
||||
java_lite_proto_library( |
||||
name = "foo", |
||||
deps = [":bar"], |
||||
) |
||||
|
||||
proto_library( |
||||
name = "bar", |
||||
) |
||||
</code> |
||||
</pre> |
||||
""", |
||||
attrs = { |
||||
"deps": attr.label_list(providers = [ProtoInfo], aspects = [_java_lite_proto_aspect], doc = """ |
||||
The list of <a href="protocol-buffer.html#proto_library"><code>proto_library</code></a> |
||||
rules to generate Java code for. |
||||
"""), |
||||
} | toolchains.if_legacy_toolchain({ |
||||
_PROTO_TOOLCHAIN_ATTR: attr.label( |
||||
default = configuration_field(fragment = "proto", name = "proto_toolchain_for_java_lite"), |
||||
), |
||||
}), |
||||
provides = [JavaInfo], |
||||
toolchains = toolchains.use_toolchain(_JAVA_LITE_PROTO_TOOLCHAIN), |
||||
) |
@ -0,0 +1,62 @@ |
||||
# Protocol Buffers - Google's data interchange format |
||||
# Copyright 2008 Google Inc. All rights reserved. |
||||
# |
||||
# Use of this source code is governed by a BSD-style |
||||
# license that can be found in the LICENSE file or at |
||||
# https://developers.google.com/open-source/licenses/bsd |
||||
"""Support for compiling protoc generated Java code.""" |
||||
|
||||
load("@rules_java//java/private:proto_support.bzl", "compile", "merge") # buildifier: disable=bzl-visibility |
||||
|
||||
# The provider is used to collect source and runtime jars in the `proto_library` dependency graph. |
||||
JavaProtoAspectInfo = provider("JavaProtoAspectInfo", fields = ["jars"]) |
||||
|
||||
java_info_merge_for_protos = merge |
||||
|
||||
def java_compile_for_protos(ctx, output_jar_suffix, source_jar = None, deps = [], exports = [], injecting_rule_kind = "java_proto_library"): |
||||
"""Compiles Java source jar returned by proto compiler. |
||||
|
||||
Use this call for java_xxx_proto_library. It uses java_common.compile with |
||||
some checks disabled (via javacopts) and jspecify disabled, so that the |
||||
generated code passes. |
||||
|
||||
It also takes care that input source jar is not repackaged with a different |
||||
name. |
||||
|
||||
When `source_jar` is `None`, the function only merges `deps` and `exports`. |
||||
|
||||
Args: |
||||
ctx: (RuleContext) Used to call `java_common.compile` |
||||
output_jar_suffix: (str) How to name the output jar. For example: `-speed.jar`. |
||||
source_jar: (File) Input source jar (may be `None`). |
||||
deps: (list[JavaInfo]) `deps` of the `proto_library`. |
||||
exports: (list[JavaInfo]) `exports` of the `proto_library`. |
||||
injecting_rule_kind: (str) Rule kind requesting the compilation. |
||||
It's embedded into META-INF of the produced runtime jar, for debugging. |
||||
Returns: |
||||
((JavaInfo, list[File])) JavaInfo of this target and list containing source |
||||
and runtime jar, when they are created. |
||||
""" |
||||
if source_jar != None: |
||||
path, sep, filename = ctx.label.name.rpartition("/") |
||||
output_jar = ctx.actions.declare_file(path + sep + "lib" + filename + output_jar_suffix) |
||||
java_toolchain = ctx.toolchains["@bazel_tools//tools/jdk:toolchain_type"].java |
||||
java_info = compile( |
||||
ctx = ctx, |
||||
output = output_jar, |
||||
java_toolchain = java_toolchain, |
||||
source_jars = [source_jar], |
||||
deps = deps, |
||||
exports = exports, |
||||
output_source_jar = source_jar, |
||||
injecting_rule_kind = injecting_rule_kind, |
||||
javac_opts = java_toolchain._compatible_javacopts.get("proto", depset()), |
||||
enable_jspecify = False, |
||||
include_compilation_info = False, |
||||
) |
||||
jars = [source_jar, output_jar] |
||||
else: |
||||
# If there are no proto sources just pass along the compilation dependencies. |
||||
java_info = merge(deps + exports, merge_java_outputs = False, merge_source_jars = False) |
||||
jars = [] |
||||
return java_info, jars |
Loading…
Reference in new issue