1// Copyright (C) 2017 The Android Open Source Project 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. 14apply from: "${buildscript.sourceFile.parentFile}/constants.gradle" 15apply from: "${buildscript.sourceFile.parentFile}/javadoc_util.gradle" 16 17class CombinedJavadocPlugin implements Plugin<Project> { 18 19 static final String JAVADOC_TASK_NAME = "generateCombinedJavadoc" 20 static final String DACKKA_TASK_NAME = "generateCombinedDackka" 21 22 // Dackka snapshots are listed at https://androidx.dev/dackka/builds. 23 static final String DACKKA_JAR_URL = 24 "https://androidx.dev/dackka/builds/8003564/artifacts/dackka-0.0.14.jar" 25 26 @Override 27 void apply(Project project) { 28 project.gradle.projectsEvaluated { 29 Set<Project> libraryModules = getLibraryModules(project) 30 if (!libraryModules.isEmpty()) { 31 def guavaReferenceUrl = "https://guava.dev/releases/$project.ext.guavaVersion/api/docs" 32 33 project.task(JAVADOC_TASK_NAME, type: Javadoc) { 34 description = "Generates combined Javadoc." 35 title = "ExoPlayer library" 36 source = libraryModules.generateJavadoc.source 37 classpath = project.files([]) 38 destinationDir = project.file("$project.buildDir/docs/javadoc") 39 options { 40 links "https://developer.android.com/reference", guavaReferenceUrl 41 encoding = "UTF-8" 42 } 43 options.addBooleanOption "-no-module-directories", true 44 exclude "**/BuildConfig.java" 45 exclude "**/R.java" 46 doFirst { 47 libraryModules.each { libraryModule -> 48 libraryModule.android.libraryVariants.all { variant -> 49 def name = variant.buildType.name 50 if (name == "release") { 51 classpath += 52 libraryModule.project.files( 53 variant.javaCompileProvider.get().classpath.files, 54 libraryModule.project.android.getBootClasspath()) 55 } 56 } 57 } 58 } 59 doLast { 60 libraryModules.each { libraryModule -> 61 project.copy { 62 from "${libraryModule.projectDir}/src/main/javadoc" 63 into "${project.buildDir}/docs/javadoc" 64 } 65 } 66 project.fixJavadoc() 67 } 68 } 69 70 def dackkaOutputDir = project.file("$project.buildDir/docs/dackka") 71 project.task(DACKKA_TASK_NAME, type: JavaExec) { 72 doFirst { 73 // Recreate the output directory to remove any leftover files from a previous run. 74 project.delete dackkaOutputDir 75 project.mkdir dackkaOutputDir 76 77 // Download the Dackka JAR. 78 new URL(DACKKA_JAR_URL).withInputStream { 79 i -> classpath.getSingleFile().withOutputStream { it << i } 80 } 81 82 // Build lists of source files and dependencies. 83 def sources = [] 84 def dependencies = [] 85 libraryModules.each { libraryModule -> 86 libraryModule.android.libraryVariants.all { variant -> 87 def name = variant.buildType.name 88 if (name == "release") { 89 def classpathFiles = 90 project.files(variant.javaCompileProvider.get().classpath.files) 91 variant.sourceSets.inject(sources) { 92 acc, val -> acc << val.javaDirectories 93 } 94 dependencies << classpathFiles.filter { f -> !(f.path.contains("/buildout/")) } 95 dependencies << libraryModule.project.android.getBootClasspath() 96 } 97 } 98 } 99 100 // Set command line arguments to Dackka. 101 def guavaPackageListFile = getGuavaPackageListFile(getTemporaryDir()) 102 def globalLinksString = "$guavaReferenceUrl^$guavaPackageListFile^^" 103 def sourcesString = project.files(sources.flatten()) 104 .filter({ f -> project.file(f).exists() }).join(";") 105 def dependenciesString = project.files(dependencies).asPath.replace(':', ';') 106 args("-moduleName", "", 107 "-outputDir", "$dackkaOutputDir", 108 "-globalLinks", "$globalLinksString", 109 "-loggingLevel", "WARN", 110 "-sourceSet", "-src $sourcesString -classpath $dependenciesString", 111 "-offlineMode") 112 environment("DEVSITE_TENANT", "androidx/media3") 113 } 114 description = "Generates combined javadoc for developer.android.com." 115 classpath = project.files(new File(getTemporaryDir(), "dackka.jar")) 116 doLast { 117 libraryModules.each { libraryModule -> 118 project.copy { 119 from "${libraryModule.projectDir}/src/main/javadoc" 120 into "${dackkaOutputDir}/reference/" 121 } 122 project.copy { 123 from "${libraryModule.projectDir}/src/main/javadoc" 124 into "${dackkaOutputDir}/reference/kotlin/" 125 } 126 } 127 } 128 } 129 } 130 } 131 } 132 133 // Returns Android library modules that declare a generateJavadoc task. 134 private static Set<Project> getLibraryModules(Project project) { 135 project.subprojects.findAll { 136 it.plugins.findPlugin("com.android.library") && 137 it.tasks.findByName("generateJavadoc") 138 } 139 } 140 141 // Returns a file containing the list of packages that should be linked to Guava documentation. 142 private static File getGuavaPackageListFile(File directory) { 143 def packageListFile = new File(directory, "guava") 144 packageListFile.text = ["com.google.common.base", "com.google.common.collect", 145 "com.google.common.io", "com.google.common.math", 146 "com.google.common.net", "com.google.common.primitives", 147 "com.google.common.truth", "com.google.common.util.concurrent"] 148 .join('\n') 149 return packageListFile 150 } 151 152} 153 154apply plugin: CombinedJavadocPlugin 155