|
| 1 | +From 119d0bf53b1a76436095986ffe11a0c97f1757db Mon Sep 17 00:00:00 2001 |
| 2 | +From: Fabian Meumertzheim < [email protected]> |
| 3 | +Date: Mon, 11 Sep 2023 13:05:32 +0200 |
| 4 | +Subject: [PATCH] javadoc: Allow `javadoc` targets to reference other `javadoc` |
| 5 | + targets |
| 6 | + |
| 7 | +By setting the `doc_url` attribute on a `javadoc` target, other targets |
| 8 | +can depend on it via `doc_deps` and have references resolved |
| 9 | +automatically via appropriate `-linkoffline` arguments passed to |
| 10 | +javadoc. |
| 11 | +--- |
| 12 | + private/rules/java_export.bzl | 21 ++++- |
| 13 | + private/rules/javadoc.bzl | 77 +++++++++++++++++-- |
| 14 | + .../javadoc/JavadocJarMaker.java | 15 ++++ |
| 15 | + 3 files changed, 106 insertions(+), 7 deletions(-) |
| 16 | + |
| 17 | +diff --git a/private/rules/java_export.bzl b/private/rules/java_export.bzl |
| 18 | +index 5c576f95..81138db1 100644 |
| 19 | +--- a/private/rules/java_export.bzl |
| 20 | ++++ b/private/rules/java_export.bzl |
| 21 | +@@ -69,6 +69,10 @@ def java_export( |
| 22 | + that workspace should be replaced by, or `None` if the exclusion shouldn't be replaced |
| 23 | + with an extra dependency. |
| 24 | + classifier_artifacts: A dict of classifier -> artifact of additional artifacts to publish to Maven. |
| 25 | ++ doc_deps: Other `javadoc` targets that are referenced by the generated `javadoc` target |
| 26 | ++ (if not using `tags = ["no-javadoc"]`) |
| 27 | ++ doc_url: The URL at which the generated `javadoc` will be hosted (if not using |
| 28 | ++ `tags = ["no-javadoc"]`). |
| 29 | + visibility: The visibility of the target |
| 30 | + kwargs: These are passed to [`java_library`](https://bazel.build/reference/be/java#java_library), |
| 31 | + and so may contain any valid parameter for that rule. |
| 32 | +@@ -78,6 +82,8 @@ def java_export( |
| 33 | + lib_name = "%s-lib" % name |
| 34 | + |
| 35 | + javadocopts = kwargs.pop("javadocopts", []) |
| 36 | ++ doc_deps = kwargs.pop("doc_deps", []) |
| 37 | ++ doc_url = kwargs.pop("doc_url", "") |
| 38 | + |
| 39 | + # Construct the java_library we'll export from here. |
| 40 | + native.java_library( |
| 41 | +@@ -100,6 +106,8 @@ def java_export( |
| 42 | + testonly, |
| 43 | + javadocopts, |
| 44 | + classifier_artifacts = classifier_artifacts, |
| 45 | ++ doc_deps = doc_deps, |
| 46 | ++ doc_url = doc_url, |
| 47 | + ) |
| 48 | + |
| 49 | + def maven_export( |
| 50 | +@@ -113,7 +121,10 @@ def maven_export( |
| 51 | + tags = [], |
| 52 | + testonly = False, |
| 53 | + javadocopts = [], |
| 54 | +- classifier_artifacts = {}): |
| 55 | ++ classifier_artifacts = {}, |
| 56 | ++ *, |
| 57 | ++ doc_deps = [], |
| 58 | ++ doc_url = ""): |
| 59 | + """ |
| 60 | + All arguments are the same as java_export with the addition of: |
| 61 | + lib_name: Name of the library that has been built. |
| 62 | +@@ -166,6 +177,10 @@ def maven_export( |
| 63 | + that should not be included in the maven jar to a `Label` pointing to the dependency |
| 64 | + that workspace should be replaced by, or `None` if the exclusion shouldn't be replaced |
| 65 | + with an extra dependency. |
| 66 | ++ doc_deps: Other `javadoc` targets that are referenced by the generated `javadoc` target |
| 67 | ++ (if not using `tags = ["no-javadoc"]`) |
| 68 | ++ doc_url: The URL at which the generated `javadoc` will be hosted (if not using |
| 69 | ++ `tags = ["no-javadoc"]`). |
| 70 | + visibility: The visibility of the target |
| 71 | + kwargs: These are passed to [`java_library`](https://bazel.build/reference/be/java#java_library), |
| 72 | + and so may contain any valid parameter for that rule. |
| 73 | +@@ -176,6 +191,8 @@ def maven_export( |
| 74 | + deploy_env = deploy_env if deploy_env else [] |
| 75 | + excluded_workspaces = excluded_workspaces if excluded_workspaces else {} |
| 76 | + javadocopts = javadocopts if javadocopts else [] |
| 77 | ++ doc_url = doc_url if doc_url else "" |
| 78 | ++ doc_deps = doc_deps if doc_deps else [] |
| 79 | + tags = tags if tags else [] |
| 80 | + classifier_artifacts = classifier_artifacts if classifier_artifacts else {} |
| 81 | + |
| 82 | +@@ -227,6 +244,8 @@ def maven_export( |
| 83 | + ":%s-project" % name, |
| 84 | + ] + deploy_env, |
| 85 | + javadocopts = javadocopts, |
| 86 | ++ doc_deps = doc_deps, |
| 87 | ++ doc_url = doc_url, |
| 88 | + excluded_workspaces = excluded_workspaces.keys(), |
| 89 | + additional_dependencies = additional_dependencies, |
| 90 | + visibility = visibility, |
| 91 | +diff --git a/private/rules/javadoc.bzl b/private/rules/javadoc.bzl |
| 92 | +index 3261248a..98ce3a08 100644 |
| 93 | +--- a/private/rules/javadoc.bzl |
| 94 | ++++ b/private/rules/javadoc.bzl |
| 95 | +@@ -1,16 +1,42 @@ |
| 96 | + load(":maven_project_jar.bzl", "DEFAULT_EXCLUDED_WORKSPACES") |
| 97 | + |
| 98 | +-def generate_javadoc(ctx, javadoc, source_jars, classpath, javadocopts, output): |
| 99 | ++_JavadocInfo = provider( |
| 100 | ++ fields = { |
| 101 | ++ "element_list": "The element-list or package-list file generated by javadoc", |
| 102 | ++ "url": "The URL at which this documentation will be hosted", |
| 103 | ++ }, |
| 104 | ++) |
| 105 | ++ |
| 106 | ++def generate_javadoc( |
| 107 | ++ ctx, |
| 108 | ++ javadoc, |
| 109 | ++ source_jars, |
| 110 | ++ classpath, |
| 111 | ++ javadocopts, |
| 112 | ++ doc_deps, |
| 113 | ++ output, |
| 114 | ++ element_list): |
| 115 | ++ inputs = [] |
| 116 | ++ transitive_inputs = [] |
| 117 | + args = ctx.actions.args() |
| 118 | +- args.add_all(["--out", output]) |
| 119 | ++ args.add("--out", output) |
| 120 | ++ args.add("--element-list", element_list) |
| 121 | + args.add_all(source_jars, before_each = "--in") |
| 122 | ++ inputs.extend(source_jars) |
| 123 | + args.add_all(classpath, before_each = "--cp") |
| 124 | ++ transitive_inputs.append(classpath) |
| 125 | ++ for dep in doc_deps: |
| 126 | ++ dep_info = dep[_JavadocInfo] |
| 127 | ++ args.add("-linkoffline") |
| 128 | ++ args.add(dep_info.url) |
| 129 | ++ args.add(dep_info.element_list.dirname) |
| 130 | ++ inputs.append(dep_info.element_list) |
| 131 | + args.add_all(javadocopts) |
| 132 | + |
| 133 | + ctx.actions.run( |
| 134 | + executable = javadoc, |
| 135 | +- outputs = [output], |
| 136 | +- inputs = depset(source_jars, transitive = [classpath]), |
| 137 | ++ outputs = [output, element_list], |
| 138 | ++ inputs = depset(inputs, transitive = transitive_inputs), |
| 139 | + arguments = [args], |
| 140 | + ) |
| 141 | + |
| 142 | +@@ -21,6 +47,10 @@ def _javadoc_impl(ctx): |
| 143 | + |
| 144 | + jar_file = ctx.actions.declare_file("%s.jar" % ctx.attr.name) |
| 145 | + |
| 146 | ++ # This needs to be a in a separate directory as javadoc accepts the containing directory as |
| 147 | ++ # an argument rather than the file itself. |
| 148 | ++ element_list = ctx.actions.declare_file("%s-element-list-dir/element-list" % ctx.attr.name) |
| 149 | ++ |
| 150 | + # javadoc may need to inspect compile-time dependencies (neverlink) |
| 151 | + # of the runtime classpath. |
| 152 | + classpath = depset( |
| 153 | +@@ -34,11 +64,29 @@ def _javadoc_impl(ctx): |
| 154 | + # `None` https://github.com/bazelbuild/bazel/issues/10170). For this |
| 155 | + # reason we allow people to set javadocopts via the rule attrs. |
| 156 | + |
| 157 | +- generate_javadoc(ctx, ctx.executable._javadoc, sources, classpath, ctx.attr.javadocopts, jar_file) |
| 158 | ++ generate_javadoc( |
| 159 | ++ ctx, |
| 160 | ++ ctx.executable._javadoc, |
| 161 | ++ sources, |
| 162 | ++ classpath, |
| 163 | ++ ctx.attr.javadocopts, |
| 164 | ++ ctx.attr.doc_deps, |
| 165 | ++ jar_file, |
| 166 | ++ element_list, |
| 167 | ++ ) |
| 168 | + |
| 169 | +- return [ |
| 170 | ++ providers = [ |
| 171 | + DefaultInfo(files = depset([jar_file])), |
| 172 | + ] |
| 173 | ++ if ctx.attr.doc_url: |
| 174 | ++ providers.append( |
| 175 | ++ _JavadocInfo( |
| 176 | ++ element_list = element_list, |
| 177 | ++ url = ctx.attr.doc_url, |
| 178 | ++ ), |
| 179 | ++ ) |
| 180 | ++ |
| 181 | ++ return providers |
| 182 | + |
| 183 | + javadoc = rule( |
| 184 | + _javadoc_impl, |
| 185 | +@@ -61,6 +109,23 @@ javadoc = rule( |
| 186 | + options can be passed here. |
| 187 | + """, |
| 188 | + ), |
| 189 | ++ "doc_deps": attr.label_list( |
| 190 | ++ doc = """`javadoc` targets referenced by the current target. |
| 191 | ++ |
| 192 | ++ Use this to automatically add appropriate `-linkoffline` javadoc options to resolve |
| 193 | ++ references to packages documented by the given javadoc targets that have `url` |
| 194 | ++ specified. |
| 195 | ++ """, |
| 196 | ++ providers = [ |
| 197 | ++ [_JavadocInfo], |
| 198 | ++ ], |
| 199 | ++ ), |
| 200 | ++ "doc_url": attr.string( |
| 201 | ++ doc = """The URL at which this documentation will be hosted. |
| 202 | ++ |
| 203 | ++ This information is only used by javadoc targets depending on this target. |
| 204 | ++ """, |
| 205 | ++ ), |
| 206 | + "excluded_workspaces": attr.string_list( |
| 207 | + doc = "A list of bazel workspace names to exclude from the generated jar", |
| 208 | + allow_empty = True, |
| 209 | +diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/javadoc/JavadocJarMaker.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/javadoc/JavadocJarMaker.java |
| 210 | +index 6e8b57e6..550e075a 100644 |
| 211 | +--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/javadoc/JavadocJarMaker.java |
| 212 | ++++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/javadoc/JavadocJarMaker.java |
| 213 | +@@ -22,6 +22,7 @@ |
| 214 | + import com.github.bazelbuild.rules_jvm_external.ByteStreams; |
| 215 | + import com.github.bazelbuild.rules_jvm_external.zip.StableZipEntry; |
| 216 | + import java.io.File; |
| 217 | ++import java.io.FileNotFoundException; |
| 218 | + import java.io.IOException; |
| 219 | + import java.io.InputStream; |
| 220 | + import java.io.OutputStream; |
| 221 | +@@ -57,6 +58,7 @@ public class JavadocJarMaker { |
| 222 | + public static void main(String[] args) throws IOException { |
| 223 | + Set<Path> sourceJars = new HashSet<>(); |
| 224 | + Path out = null; |
| 225 | ++ Path elementList = null; |
| 226 | + Set<Path> classpath = new HashSet<>(); |
| 227 | + List<String> options = new ArrayList<>(); |
| 228 | + |
| 229 | +@@ -80,6 +82,11 @@ public static void main(String[] args) throws IOException { |
| 230 | + out = Paths.get(next); |
| 231 | + break; |
| 232 | + |
| 233 | ++ case "--element-list": |
| 234 | ++ next = args[++i]; |
| 235 | ++ elementList = Paths.get(next); |
| 236 | ++ break; |
| 237 | ++ |
| 238 | + default: |
| 239 | + options.add(flag); |
| 240 | + break; |
| 241 | +@@ -167,6 +174,14 @@ public static void main(String[] args) throws IOException { |
| 242 | + return; |
| 243 | + } |
| 244 | + |
| 245 | ++ Path generatedElementList = outputTo.resolve("element-list"); |
| 246 | ++ try { |
| 247 | ++ Files.copy(generatedElementList, elementList); |
| 248 | ++ } catch (FileNotFoundException e) { |
| 249 | ++ // Do not fail the action if the generated element-list couldn't be found. |
| 250 | ++ Files.createFile(generatedElementList); |
| 251 | ++ } |
| 252 | ++ |
| 253 | + try (OutputStream os = Files.newOutputStream(out); |
| 254 | + ZipOutputStream zos = new ZipOutputStream(os); |
| 255 | + Stream<Path> walk = Files.walk(outputTo)) { |
0 commit comments