1""" Custom rule to generate OSGi Manifest for Kotlin """ 2 3load("@rules_java//java:defs.bzl", "JavaInfo") 4load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") 5 6def osgi_kt_jvm_library( 7 name, 8 automatic_module_name, 9 bundle_description, 10 bundle_doc_url, 11 bundle_license, 12 bundle_name, 13 bundle_symbolic_name, 14 bundle_version, 15 bundle_additional_imports = [], 16 bundle_additional_exports = [], 17 deps = [], 18 exports = [], 19 exported_plugins = [], 20 neverlink = False, 21 runtime_deps = [], 22 visibility = [], 23 **kwargs): 24 """Extends `kt_jvm_library` to add OSGi headers to the MANIFEST.MF using bndlib 25 26 This macro should be usable as a drop-in replacement for kt_jvm_library. 27 28 The additional arguments are given the bndlib tool to generate an OSGi-compliant manifest file. 29 See [bnd documentation](https://bnd.bndtools.org/chapters/110-introduction.html) 30 31 Args: 32 name: (required) A unique name for this target. 33 automatic_module_name: (required) The Automatic-Module-Name header that represents 34 the name of the module when this bundle is used as an automatic 35 module. 36 bundle_description: (required) The Bundle-Description header defines a short 37 description of this bundle. 38 bundle_doc_url: (required) The Bundle-DocURL headers must contain a URL pointing 39 to documentation about this bundle. 40 bundle_license: (required) The Bundle-License header provides an optional machine 41 readable form of license information. 42 bundle_name: (required) The Bundle-Name header defines a readable name for this 43 bundle. This should be a short, human-readable name that can 44 contain spaces. 45 bundle_symbolic_name: (required) The Bundle-SymbolicName header specifies a 46 non-localizable name for this bundle. The bundle symbolic name 47 together with a version must identify a unique bundle though it can 48 be installed multiple times in a framework. The bundle symbolic 49 name should be based on the reverse domain name convention. 50 bundle_version: (required) The Bundle-Version header specifies the version string 51 for this bundle. The version string is expected to follow semantic 52 versioning conventions MAJOR.MINOR.PATCH[.BUILD] 53 bundle_additional_exports: The Export-Package header contains a 54 declaration of exported packages. These are additional export 55 package statements to be added before the default wildcard export 56 "*;version={$Bundle-Version}". 57 bundle_additional_imports: The Import-Package header declares the 58 imported packages for this bundle. These are additional import 59 package statements to be added before the default wildcard import 60 "*". 61 deps: The list of libraries to link into this library. See general 62 comments about deps at Typical attributes defined by most build 63 rules. The jars built by java_library rules listed in deps will be 64 on the compile-time classpath of this rule. Furthermore the 65 transitive closure of their deps, runtime_deps and exports will be 66 on the runtime classpath. By contrast, targets in the data 67 attribute are included in the runfiles but on neither the 68 compile-time nor runtime classpath. 69 exports: Exported libraries. 70 exported_plugins: The list of java_plugins (e.g. annotation processors) 71 to export to libraries that directly depend on this library. The 72 specified list of java_plugins will be applied to any library which 73 directly depends on this library, just as if that library had 74 explicitly declared these labels in plugins. 75 neverlink: Whether this library should only be used for compilation and 76 not at runtime. Useful if the library will be provided by the runtime 77 environment during execution. Examples of such libraries are the IDE 78 APIs for IDE plug-ins or tools.jar for anything running on a standard 79 JDK. 80 runtime_deps: Libraries to make available to the final binary or test 81 at runtime only. Like ordinary deps, these will appear on the runtime 82 classpath, but unlike them, not on the compile-time classpath. 83 Dependencies needed only at runtime should be listed here. 84 Dependency-analysis tools should ignore targets that appear in both 85 runtime_deps and deps 86 visibility: The visibility attribute on a target controls whether the 87 target can be used in other packages. See the documentation for 88 visibility. 89 **kwargs: Additional key-word arguments that are passed to the internal 90 java_library target. 91 92 """ 93 94 # Build the private jar without the OSGI manifest 95 private_library_name = "%s-no-manifest-do-not-use" % name 96 kt_jvm_library( 97 name = private_library_name, 98 deps = deps, 99 runtime_deps = runtime_deps, 100 neverlink = True, 101 visibility = ["//visibility:private"], 102 **kwargs 103 ) 104 105 # Repackage the jar with an OSGI manifest 106 _osgi_kt_jvm_jar( 107 name = name, 108 automatic_module_name = automatic_module_name, 109 bundle_description = bundle_description, 110 bundle_doc_url = bundle_doc_url, 111 bundle_license = bundle_license, 112 bundle_name = bundle_name, 113 bundle_symbolic_name = bundle_symbolic_name, 114 bundle_version = bundle_version, 115 export_package = bundle_additional_exports + ["*;version=${Bundle-Version}"], 116 import_package = bundle_additional_imports + ["*"], 117 target = private_library_name, 118 deps = deps, 119 runtime_deps = runtime_deps, 120 exported_plugins = exported_plugins, 121 neverlink = neverlink, 122 exports = exports, 123 visibility = visibility, 124 ) 125 126def _run_osgi_wrapper(ctx, input_jar, output_jar): 127 args = ctx.actions.args() 128 args.add("--input_jar", input_jar.path) 129 args.add("--output_jar", output_jar.path) 130 args.add("--automatic_module_name", ctx.attr.automatic_module_name) 131 args.add("--bundle_copyright", ctx.attr.bundle_copyright) 132 args.add("--bundle_description", ctx.attr.bundle_description) 133 args.add("--bundle_doc_url", ctx.attr.bundle_doc_url) 134 args.add("--bundle_license", ctx.attr.bundle_license) 135 args.add("--bundle_name", ctx.attr.bundle_name) 136 args.add("--bundle_version", ctx.attr.bundle_version) 137 args.add("--bundle_symbolic_name", ctx.attr.bundle_symbolic_name) 138 args.add_joined("--export_package", ctx.attr.export_package, join_with = ",") 139 args.add_joined("--import_package", ctx.attr.import_package, join_with = ",") 140 141 ctx.actions.run( 142 inputs = [input_jar], 143 executable = ctx.executable._osgi_wrapper_exe, 144 arguments = [args], 145 outputs = [output_jar], 146 progress_message = "Generating OSGi bundle Manifest for %s" % input_jar.path, 147 ) 148 149# Kotlin implementation of osgi jar, removes classpath and source_jar 150def _osgi_kt_jvm_jar_impl(ctx): 151 if len(ctx.attr.target[JavaInfo].java_outputs) != 1: 152 fail("osgi_jar rule can only be used on a single java target.") 153 target_java_output = ctx.attr.target[JavaInfo].java_outputs[0] 154 155 output_jar = ctx.outputs.output_jar 156 157 input_jar = target_java_output.class_jar 158 159 _run_osgi_wrapper(ctx, input_jar, output_jar) 160 161 return [ 162 DefaultInfo( 163 files = depset([output_jar]), 164 # Workaround for https://github.com/bazelbuild/bazel/issues/15043 165 # Bazel's native rule such as sh_test do not pick up 'files' in 166 # DefaultInfo for a target in 'data'. 167 data_runfiles = ctx.runfiles([output_jar]), 168 ), 169 JavaInfo( 170 output_jar = output_jar, 171 172 # compile_jar should be an ijar, but using an ijar results in 173 # missing protobuf import version. 174 compile_jar = output_jar, 175 generated_class_jar = target_java_output.generated_class_jar, 176 native_headers_jar = target_java_output.native_headers_jar, 177 manifest_proto = target_java_output.manifest_proto, 178 neverlink = ctx.attr.neverlink, 179 deps = [dep[JavaInfo] for dep in ctx.attr.deps], 180 runtime_deps = [dep[JavaInfo] for dep in ctx.attr.runtime_deps], 181 exports = [exp[JavaInfo] for exp in ctx.attr.exports], 182 exported_plugins = ctx.attr.exported_plugins, 183 ), 184 ] 185 186_osgi_kt_jvm_jar = rule( 187 implementation = _osgi_kt_jvm_jar_impl, 188 outputs = { 189 "output_jar": "lib%{name}.jar", 190 }, 191 attrs = { 192 "automatic_module_name": attr.string(), 193 "bundle_copyright": attr.string(), 194 "bundle_description": attr.string(), 195 "bundle_doc_url": attr.string(), 196 "bundle_license": attr.string(), 197 "bundle_name": attr.string(), 198 "bundle_version": attr.string(), 199 "bundle_symbolic_name": attr.string(), 200 "export_package": attr.string_list(), 201 "import_package": attr.string_list(), 202 "target": attr.label(), 203 "deps": attr.label_list(), 204 "runtime_deps": attr.label_list(), 205 "exports": attr.label_list(), 206 "neverlink": attr.bool(), 207 "exported_plugins": attr.label_list(), 208 "_osgi_wrapper_exe": attr.label( 209 executable = True, 210 cfg = "exec", 211 allow_files = True, 212 default = Label("//java/osgi:osgi_wrapper"), 213 ), 214 }, 215) 216