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
pull/18833/head
parent
082cf000ef
commit
27ddb9ce34
4 changed files with 316 additions and 10 deletions
@ -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 |
||||||
|
) |
@ -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…
Reference in new issue