mirror of
https://github.com/protocolbuffers/protobuf
synced 2026-08-26 02:23:14 -04:00
Give Kotlin jars an OSGi Manifest (#18812)
Extend our Java OSGi library to have a version that works for Kotlin. Add a `protobuf_versioned_kt_jvm_library` that creates a bundle with the OSGi manifest and call that instead of `kt_jvm_library` for all our kotlin maven release targets.
Closes #18812
COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/18812 from deannagarcia:kotlinOSGi 81bab06f61
PiperOrigin-RevId: 686220820
This commit is contained in:
parent
082cf000ef
commit
27ddb9ce34
4 changed files with 316 additions and 10 deletions
61
build_defs/kotlin_opts.bzl
Normal file
61
build_defs/kotlin_opts.bzl
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
"""Protobuf-specific kotlin build rules."""
|
||||
|
||||
load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION")
|
||||
load("//java/osgi:kotlin_osgi.bzl", "osgi_kt_jvm_library")
|
||||
|
||||
BUNDLE_DOC_URL = "https://developers.google.com/protocol-buffers/"
|
||||
BUNDLE_LICENSE = "https://opensource.org/licenses/BSD-3-Clause"
|
||||
|
||||
def protobuf_versioned_kt_jvm_library(
|
||||
automatic_module_name,
|
||||
bundle_description,
|
||||
bundle_name,
|
||||
bundle_symbolic_name,
|
||||
bundle_additional_imports = [],
|
||||
bundle_additional_exports = [],
|
||||
**kwargs):
|
||||
"""Extends `kt_jvm_library` to add OSGi headers to the MANIFEST.MF using bndlib
|
||||
|
||||
This macro should be usable as a drop-in replacement for kt_jvm_library.
|
||||
|
||||
The additional arguments are given the bndlib tool to generate an OSGi-compliant manifest file.
|
||||
See [bnd documentation](https://bnd.bndtools.org/chapters/110-introduction.html)
|
||||
|
||||
Takes all the args that are standard for a kt_jvm_library target plus the following.
|
||||
Args:
|
||||
bundle_description: (required) The Bundle-Description header defines a short
|
||||
description of this bundle.
|
||||
automatic_module_name: (required) The Automatic-Module-Name header that represents
|
||||
the name of the module when this bundle is used as an automatic
|
||||
module.
|
||||
bundle_name: (required) The Bundle-Name header defines a readable name for this
|
||||
bundle. This should be a short, human-readable name that can
|
||||
contain spaces.
|
||||
bundle_symbolic_name: (required) The Bundle-SymbolicName header specifies a
|
||||
non-localizable name for this bundle. The bundle symbolic name
|
||||
together with a version must identify a unique bundle though it can
|
||||
be installed multiple times in a framework. The bundle symbolic
|
||||
name should be based on the reverse domain name convention.
|
||||
bundle_additional_exports: The Export-Package header contains a
|
||||
declaration of exported packages. These are additional export
|
||||
package statements to be added before the default wildcard export
|
||||
"*;version={$Bundle-Version}".
|
||||
bundle_additional_imports: The Import-Package header declares the
|
||||
imported packages for this bundle. These are additional import
|
||||
package statements to be added before the default wildcard import
|
||||
"*".
|
||||
**kwargs: Additional key-word arguments that are passed to the internal
|
||||
kt_jvm_library target.
|
||||
"""
|
||||
osgi_kt_jvm_library(
|
||||
automatic_module_name = automatic_module_name,
|
||||
bundle_doc_url = BUNDLE_DOC_URL,
|
||||
bundle_license = BUNDLE_LICENSE,
|
||||
bundle_version = PROTOBUF_JAVA_VERSION,
|
||||
bundle_description = bundle_description,
|
||||
bundle_name = bundle_name,
|
||||
bundle_symbolic_name = bundle_symbolic_name,
|
||||
bundle_additional_exports = bundle_additional_exports,
|
||||
bundle_additional_imports = bundle_additional_imports + ["sun.misc;resolution:=optional"],
|
||||
**kwargs
|
||||
)
|
||||
|
|
@ -4,6 +4,7 @@ load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix")
|
|||
load("//:protobuf.bzl", "internal_gen_kt_protos")
|
||||
load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION")
|
||||
load("//bazel:java_lite_proto_library.bzl", "java_lite_proto_library")
|
||||
load("//build_defs:kotlin_opts.bzl", "protobuf_versioned_kt_jvm_library")
|
||||
|
||||
java_lite_proto_library(
|
||||
name = "example_extensible_message_java_proto_lite",
|
||||
|
|
@ -47,6 +48,24 @@ kt_jvm_library(
|
|||
],
|
||||
)
|
||||
|
||||
protobuf_versioned_kt_jvm_library(
|
||||
name = "kotlin-lite_bundle",
|
||||
automatic_module_name = "com.google.protobuf",
|
||||
bundle_description = "Kotlin lite Protocol Buffers library. Protocol " +
|
||||
"Buffers are a way of encoding structured data in " +
|
||||
"an efficient yet extensible format.",
|
||||
bundle_name = "Protocol Buffers [Kotlin-Lite]",
|
||||
bundle_symbolic_name = "com.google.protobuf",
|
||||
visibility = ["//visibility:public"],
|
||||
exports = [
|
||||
":lite_extensions",
|
||||
":well_known_protos_kotlin_lite",
|
||||
"//java/kotlin:bytestring_lib",
|
||||
"//java/kotlin:only_for_use_in_proto_generated_code_its_generator_and_tests",
|
||||
"//java/kotlin:shared_runtime",
|
||||
],
|
||||
)
|
||||
|
||||
kt_jvm_export(
|
||||
name = "kotlin-lite_mvn",
|
||||
deploy_env = [
|
||||
|
|
@ -62,11 +81,7 @@ kt_jvm_export(
|
|||
],
|
||||
tags = ["manual"],
|
||||
runtime_deps = [
|
||||
":lite_extensions",
|
||||
":well_known_protos_kotlin_lite",
|
||||
"//java/kotlin:bytestring_lib",
|
||||
"//java/kotlin:only_for_use_in_proto_generated_code_its_generator_and_tests",
|
||||
"//java/kotlin:shared_runtime",
|
||||
":kotlin-lite_bundle",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ load("//:protobuf.bzl", "internal_gen_kt_protos")
|
|||
load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION")
|
||||
load("//bazel:java_proto_library.bzl", "java_proto_library")
|
||||
load("//bazel:proto_library.bzl", "proto_library")
|
||||
load("//build_defs:kotlin_opts.bzl", "protobuf_versioned_kt_jvm_library")
|
||||
|
||||
exports_files([
|
||||
"src/test/kotlin/com/google/protobuf/Proto3Test.kt",
|
||||
|
|
@ -50,6 +51,24 @@ kt_jvm_library(
|
|||
deps = ["//java/core"],
|
||||
)
|
||||
|
||||
protobuf_versioned_kt_jvm_library(
|
||||
name = "kotlin_bundle",
|
||||
automatic_module_name = "com.google.protobuf",
|
||||
bundle_description = "Kotlin core Protocol Buffers library. Protocol " +
|
||||
"Buffers are a way of encoding structured data in an" +
|
||||
"efficient yet extensible format.",
|
||||
bundle_name = "Protocol Buffers [Kotlin-Core]",
|
||||
bundle_symbolic_name = "com.google.protobuf",
|
||||
visibility = ["//visibility:public"],
|
||||
exports = [
|
||||
":bytestring_lib",
|
||||
":full_extensions",
|
||||
":only_for_use_in_proto_generated_code_its_generator_and_tests",
|
||||
":shared_runtime",
|
||||
":well_known_protos_kotlin",
|
||||
],
|
||||
)
|
||||
|
||||
kt_jvm_export(
|
||||
name = "kotlin_mvn",
|
||||
deploy_env = [
|
||||
|
|
@ -65,11 +84,7 @@ kt_jvm_export(
|
|||
],
|
||||
tags = ["manual"],
|
||||
runtime_deps = [
|
||||
":bytestring_lib",
|
||||
":full_extensions",
|
||||
":only_for_use_in_proto_generated_code_its_generator_and_tests",
|
||||
":shared_runtime",
|
||||
":well_known_protos_kotlin",
|
||||
":kotlin_bundle",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
|||
215
java/osgi/kotlin_osgi.bzl
Normal file
215
java/osgi/kotlin_osgi.bzl
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
""" Custom rule to generate OSGi Manifest for Kotlin """
|
||||
|
||||
load("@rules_java//java:defs.bzl", "JavaInfo")
|
||||
load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library")
|
||||
|
||||
def osgi_kt_jvm_library(
|
||||
name,
|
||||
automatic_module_name,
|
||||
bundle_description,
|
||||
bundle_doc_url,
|
||||
bundle_license,
|
||||
bundle_name,
|
||||
bundle_symbolic_name,
|
||||
bundle_version,
|
||||
bundle_additional_imports = [],
|
||||
bundle_additional_exports = [],
|
||||
deps = [],
|
||||
exports = [],
|
||||
exported_plugins = [],
|
||||
neverlink = False,
|
||||
runtime_deps = [],
|
||||
visibility = [],
|
||||
**kwargs):
|
||||
"""Extends `kt_jvm_library` to add OSGi headers to the MANIFEST.MF using bndlib
|
||||
|
||||
This macro should be usable as a drop-in replacement for kt_jvm_library.
|
||||
|
||||
The additional arguments are given the bndlib tool to generate an OSGi-compliant manifest file.
|
||||
See [bnd documentation](https://bnd.bndtools.org/chapters/110-introduction.html)
|
||||
|
||||
Args:
|
||||
name: (required) A unique name for this target.
|
||||
automatic_module_name: (required) The Automatic-Module-Name header that represents
|
||||
the name of the module when this bundle is used as an automatic
|
||||
module.
|
||||
bundle_description: (required) The Bundle-Description header defines a short
|
||||
description of this bundle.
|
||||
bundle_doc_url: (required) The Bundle-DocURL headers must contain a URL pointing
|
||||
to documentation about this bundle.
|
||||
bundle_license: (required) The Bundle-License header provides an optional machine
|
||||
readable form of license information.
|
||||
bundle_name: (required) The Bundle-Name header defines a readable name for this
|
||||
bundle. This should be a short, human-readable name that can
|
||||
contain spaces.
|
||||
bundle_symbolic_name: (required) The Bundle-SymbolicName header specifies a
|
||||
non-localizable name for this bundle. The bundle symbolic name
|
||||
together with a version must identify a unique bundle though it can
|
||||
be installed multiple times in a framework. The bundle symbolic
|
||||
name should be based on the reverse domain name convention.
|
||||
bundle_version: (required) The Bundle-Version header specifies the version string
|
||||
for this bundle. The version string is expected to follow semantic
|
||||
versioning conventions MAJOR.MINOR.PATCH[.BUILD]
|
||||
bundle_additional_exports: The Export-Package header contains a
|
||||
declaration of exported packages. These are additional export
|
||||
package statements to be added before the default wildcard export
|
||||
"*;version={$Bundle-Version}".
|
||||
bundle_additional_imports: The Import-Package header declares the
|
||||
imported packages for this bundle. These are additional import
|
||||
package statements to be added before the default wildcard import
|
||||
"*".
|
||||
deps: The list of libraries to link into this library. See general
|
||||
comments about deps at Typical attributes defined by most build
|
||||
rules. The jars built by java_library rules listed in deps will be
|
||||
on the compile-time classpath of this rule. Furthermore the
|
||||
transitive closure of their deps, runtime_deps and exports will be
|
||||
on the runtime classpath. By contrast, targets in the data
|
||||
attribute are included in the runfiles but on neither the
|
||||
compile-time nor runtime classpath.
|
||||
exports: Exported libraries.
|
||||
exported_plugins: The list of java_plugins (e.g. annotation processors)
|
||||
to export to libraries that directly depend on this library. The
|
||||
specified list of java_plugins will be applied to any library which
|
||||
directly depends on this library, just as if that library had
|
||||
explicitly declared these labels in plugins.
|
||||
neverlink: Whether this library should only be used for compilation and
|
||||
not at runtime. Useful if the library will be provided by the runtime
|
||||
environment during execution. Examples of such libraries are the IDE
|
||||
APIs for IDE plug-ins or tools.jar for anything running on a standard
|
||||
JDK.
|
||||
runtime_deps: Libraries to make available to the final binary or test
|
||||
at runtime only. Like ordinary deps, these will appear on the runtime
|
||||
classpath, but unlike them, not on the compile-time classpath.
|
||||
Dependencies needed only at runtime should be listed here.
|
||||
Dependency-analysis tools should ignore targets that appear in both
|
||||
runtime_deps and deps
|
||||
visibility: The visibility attribute on a target controls whether the
|
||||
target can be used in other packages. See the documentation for
|
||||
visibility.
|
||||
**kwargs: Additional key-word arguments that are passed to the internal
|
||||
java_library target.
|
||||
|
||||
"""
|
||||
|
||||
# Build the private jar without the OSGI manifest
|
||||
private_library_name = "%s-no-manifest-do-not-use" % name
|
||||
kt_jvm_library(
|
||||
name = private_library_name,
|
||||
deps = deps,
|
||||
runtime_deps = runtime_deps,
|
||||
neverlink = True,
|
||||
visibility = ["//visibility:private"],
|
||||
**kwargs
|
||||
)
|
||||
|
||||
# Repackage the jar with an OSGI manifest
|
||||
_osgi_kt_jvm_jar(
|
||||
name = name,
|
||||
automatic_module_name = automatic_module_name,
|
||||
bundle_description = bundle_description,
|
||||
bundle_doc_url = bundle_doc_url,
|
||||
bundle_license = bundle_license,
|
||||
bundle_name = bundle_name,
|
||||
bundle_symbolic_name = bundle_symbolic_name,
|
||||
bundle_version = bundle_version,
|
||||
export_package = bundle_additional_exports + ["*;version=${Bundle-Version}"],
|
||||
import_package = bundle_additional_imports + ["*"],
|
||||
target = private_library_name,
|
||||
deps = deps,
|
||||
runtime_deps = runtime_deps,
|
||||
exported_plugins = exported_plugins,
|
||||
neverlink = neverlink,
|
||||
exports = exports,
|
||||
visibility = visibility,
|
||||
)
|
||||
|
||||
def _run_osgi_wrapper(ctx, input_jar, output_jar):
|
||||
args = ctx.actions.args()
|
||||
args.add("--input_jar", input_jar.path)
|
||||
args.add("--output_jar", output_jar.path)
|
||||
args.add("--automatic_module_name", ctx.attr.automatic_module_name)
|
||||
args.add("--bundle_copyright", ctx.attr.bundle_copyright)
|
||||
args.add("--bundle_description", ctx.attr.bundle_description)
|
||||
args.add("--bundle_doc_url", ctx.attr.bundle_doc_url)
|
||||
args.add("--bundle_license", ctx.attr.bundle_license)
|
||||
args.add("--bundle_name", ctx.attr.bundle_name)
|
||||
args.add("--bundle_version", ctx.attr.bundle_version)
|
||||
args.add("--bundle_symbolic_name", ctx.attr.bundle_symbolic_name)
|
||||
args.add_joined("--export_package", ctx.attr.export_package, join_with = ",")
|
||||
args.add_joined("--import_package", ctx.attr.import_package, join_with = ",")
|
||||
|
||||
ctx.actions.run(
|
||||
inputs = [input_jar],
|
||||
executable = ctx.executable._osgi_wrapper_exe,
|
||||
arguments = [args],
|
||||
outputs = [output_jar],
|
||||
progress_message = "Generating OSGi bundle Manifest for %s" % input_jar.path,
|
||||
)
|
||||
|
||||
# Kotlin implementation of osgi jar, removes classpath and source_jar
|
||||
def _osgi_kt_jvm_jar_impl(ctx):
|
||||
if len(ctx.attr.target[JavaInfo].java_outputs) != 1:
|
||||
fail("osgi_jar rule can only be used on a single java target.")
|
||||
target_java_output = ctx.attr.target[JavaInfo].java_outputs[0]
|
||||
|
||||
output_jar = ctx.outputs.output_jar
|
||||
|
||||
input_jar = target_java_output.class_jar
|
||||
|
||||
_run_osgi_wrapper(ctx, input_jar, output_jar)
|
||||
|
||||
return [
|
||||
DefaultInfo(
|
||||
files = depset([output_jar]),
|
||||
# Workaround for https://github.com/bazelbuild/bazel/issues/15043
|
||||
# Bazel's native rule such as sh_test do not pick up 'files' in
|
||||
# DefaultInfo for a target in 'data'.
|
||||
data_runfiles = ctx.runfiles([output_jar]),
|
||||
),
|
||||
JavaInfo(
|
||||
output_jar = output_jar,
|
||||
|
||||
# compile_jar should be an ijar, but using an ijar results in
|
||||
# missing protobuf import version.
|
||||
compile_jar = output_jar,
|
||||
generated_class_jar = target_java_output.generated_class_jar,
|
||||
native_headers_jar = target_java_output.native_headers_jar,
|
||||
manifest_proto = target_java_output.manifest_proto,
|
||||
neverlink = ctx.attr.neverlink,
|
||||
deps = [dep[JavaInfo] for dep in ctx.attr.deps],
|
||||
runtime_deps = [dep[JavaInfo] for dep in ctx.attr.runtime_deps],
|
||||
exports = [exp[JavaInfo] for exp in ctx.attr.exports],
|
||||
exported_plugins = ctx.attr.exported_plugins,
|
||||
),
|
||||
]
|
||||
|
||||
_osgi_kt_jvm_jar = rule(
|
||||
implementation = _osgi_kt_jvm_jar_impl,
|
||||
outputs = {
|
||||
"output_jar": "lib%{name}.jar",
|
||||
},
|
||||
attrs = {
|
||||
"automatic_module_name": attr.string(),
|
||||
"bundle_copyright": attr.string(),
|
||||
"bundle_description": attr.string(),
|
||||
"bundle_doc_url": attr.string(),
|
||||
"bundle_license": attr.string(),
|
||||
"bundle_name": attr.string(),
|
||||
"bundle_version": attr.string(),
|
||||
"bundle_symbolic_name": attr.string(),
|
||||
"export_package": attr.string_list(),
|
||||
"import_package": attr.string_list(),
|
||||
"target": attr.label(),
|
||||
"deps": attr.label_list(),
|
||||
"runtime_deps": attr.label_list(),
|
||||
"exports": attr.label_list(),
|
||||
"neverlink": attr.bool(),
|
||||
"exported_plugins": attr.label_list(),
|
||||
"_osgi_wrapper_exe": attr.label(
|
||||
executable = True,
|
||||
cfg = "exec",
|
||||
allow_files = True,
|
||||
default = Label("//java/osgi:osgi_wrapper"),
|
||||
),
|
||||
},
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue