1# Copyright 2020 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15""" 16Generates a Javadoc jar path/to/target/<name>.jar. 17 18Arguments: 19 srcs: source files to process. This might contain .java files or gen_rule that 20 generates source jars. 21 deps: targets that contain references to other types referenced in Javadoc. This can be the 22 java_library/android_library target(s) for the same sources 23 root_packages: Java packages to include in generated Javadoc. Any subpackages not listed in 24 exclude_packages will be included as well 25 exclude_packages: Java packages to exclude from generated Javadoc 26 android_api_level: If Android APIs are used, the API level to compile against to generate 27 Javadoc 28 doctitle: title for Javadoc's index.html. See javadoc -doctitle 29 bottom_text: text passed to javadoc's `-bottom` flag 30 external_javadoc_links: a list of URLs that are passed to Javadoc's `-linkoffline` flag 31""" 32 33load("@rules_java//java:defs.bzl", "JavaInfo", "java_common") 34 35def _check_non_empty(value, name): 36 if not value: 37 fail("%s must be non-empty" % name) 38 39def _android_jar(android_api_level): 40 if android_api_level == -1: 41 return None 42 return Label("@androidsdk//:platforms/android-%s/android.jar" % android_api_level) 43 44def _javadoc_library(ctx): 45 _check_non_empty(ctx.attr.root_packages, "root_packages") 46 47 transitive_deps = [dep[JavaInfo].transitive_compile_time_jars for dep in ctx.attr.deps] 48 if ctx.attr._android_jar: 49 transitive_deps.append(ctx.attr._android_jar.files) 50 51 classpath = depset([], transitive = transitive_deps).to_list() 52 53 include_packages = ":".join(ctx.attr.root_packages) 54 javadoc_command = [ 55 "%s/bin/javadoc" % ctx.attr._jdk[java_common.JavaRuntimeInfo].java_home, 56 "-sourcepath srcs", 57 "-use", 58 "-subpackages", 59 include_packages, 60 "-encoding UTF8", 61 "-classpath", 62 ":".join([jar.path for jar in classpath]), 63 "-notimestamp", 64 "-d tmp", 65 "-Xdoclint:-missing", 66 "-quiet", 67 ] 68 69 if ctx.attr.doctitle: 70 javadoc_command.append('-doctitle "%s"' % ctx.attr.doctitle) 71 72 if ctx.attr.exclude_packages: 73 javadoc_command.append("-exclude %s" % ":".join(ctx.attr.exclude_packages)) 74 75 for link in ctx.attr.external_javadoc_links: 76 javadoc_command.append("-linkoffline {0} {0}".format(link)) 77 78 if ctx.attr.bottom_text: 79 javadoc_command.append("-bottom '%s'" % ctx.attr.bottom_text) 80 81 srcs = depset(transitive = [src.files for src in ctx.attr.srcs]).to_list() 82 prepare_srcs_command = "mkdir srcs && " 83 path_prefixes = [x.replace(".", "/") for x in ctx.attr.root_packages] 84 for path_prefix in path_prefixes: 85 prepare_srcs_command = "mkdir -p srcs/%s && " % (path_prefix) 86 87 for src in srcs: 88 if src.path.endswith(".jar"): 89 prepare_srcs_command += "unzip -qq -B %s -d srcs && " % src.path 90 elif src.path.endswith(".java"): 91 for path_prefix in path_prefixes: 92 if path_prefix in src.path: 93 prepare_srcs_command += "cp %s srcs/%s && " % (src.path, path_prefix) 94 95 jar_binary = "%s/bin/jar" % ctx.attr._jdk[java_common.JavaRuntimeInfo].java_home 96 jar_command = "%s cf %s -C tmp ." % (jar_binary, ctx.outputs.jar.path) 97 98 ctx.actions.run_shell( 99 inputs = srcs + classpath + ctx.files._jdk, 100 command = "%s %s && %s" % (prepare_srcs_command, " ".join(javadoc_command), jar_command), 101 outputs = [ctx.outputs.jar], 102 ) 103 104javadoc_library = rule( 105 attrs = { 106 "srcs": attr.label_list(allow_files = True), 107 "deps": attr.label_list(), 108 "doctitle": attr.string(default = ""), 109 "root_packages": attr.string_list(), 110 "exclude_packages": attr.string_list(), 111 "android_api_level": attr.int(default = -1), 112 "bottom_text": attr.string(default = ""), 113 "external_javadoc_links": attr.string_list(), 114 "_android_jar": attr.label( 115 default = _android_jar, 116 allow_single_file = True, 117 ), 118 "_jdk": attr.label( 119 default = Label("@bazel_tools//tools/jdk:current_java_runtime"), 120 allow_files = True, 121 providers = [java_common.JavaRuntimeInfo], 122 ), 123 }, 124 outputs = {"jar": "%{name}.jar"}, 125 implementation = _javadoc_library, 126) 127