1*e6ba1607SAndroid Build Coastguard Worker import groovy.util.Node 2*e6ba1607SAndroid Build Coastguard Worker import org.gradle.plugins.ide.idea.model.IdeaModel 3*e6ba1607SAndroid Build Coastguard Worker import org.robolectric.gradle.ShadowsPlugin.ShadowsPluginExtension 4*e6ba1607SAndroid Build Coastguard Worker 5*e6ba1607SAndroid Build Coastguard Worker // https://github.com/gradle/gradle/issues/21267 6*e6ba1607SAndroid Build Coastguard Worker val axtCoreVersion by project.extra { libs.versions.androidx.test.core.get() } 7*e6ba1607SAndroid Build Coastguard Worker val axtJunitVersion by project.extra { libs.versions.androidx.test.ext.junit.get() } 8*e6ba1607SAndroid Build Coastguard Worker val axtMonitorVersion by project.extra { libs.versions.androidx.test.monitor.get() } 9*e6ba1607SAndroid Build Coastguard Worker val axtRunnerVersion by project.extra { libs.versions.androidx.test.runner.get() } 10*e6ba1607SAndroid Build Coastguard Worker val axtTruthVersion by project.extra { libs.versions.androidx.test.ext.truth.get() } 11*e6ba1607SAndroid Build Coastguard Worker val espressoVersion by project.extra { libs.versions.androidx.test.espresso.get() } 12*e6ba1607SAndroid Build Coastguard Worker 13*e6ba1607SAndroid Build Coastguard Worker // For use of external initialization scripts... 14*e6ba1607SAndroid Build Coastguard Worker val allSdks by project.extra(AndroidSdk.ALL_SDKS) 15*e6ba1607SAndroid Build Coastguard Worker val configAnnotationProcessing by project.extra(emptyList<Project>()) 16*e6ba1607SAndroid Build Coastguard Worker 17*e6ba1607SAndroid Build Coastguard Worker val thisVersion: String by project 18*e6ba1607SAndroid Build Coastguard Worker 19*e6ba1607SAndroid Build Coastguard Worker plugins { 20*e6ba1607SAndroid Build Coastguard Worker alias(libs.plugins.android.library) apply false 21*e6ba1607SAndroid Build Coastguard Worker alias(libs.plugins.detekt) apply false 22*e6ba1607SAndroid Build Coastguard Worker alias(libs.plugins.error.prone) 23*e6ba1607SAndroid Build Coastguard Worker alias(libs.plugins.idea) 24*e6ba1607SAndroid Build Coastguard Worker alias(libs.plugins.kotlin.android) apply false 25*e6ba1607SAndroid Build Coastguard Worker alias(libs.plugins.kotlin.jvm) apply false 26*e6ba1607SAndroid Build Coastguard Worker alias(libs.plugins.robolectric.spotless) 27*e6ba1607SAndroid Build Coastguard Worker alias(libs.plugins.robolectric.javadoc) 28*e6ba1607SAndroid Build Coastguard Worker alias(libs.plugins.roborazzi) apply false 29*e6ba1607SAndroid Build Coastguard Worker } 30*e6ba1607SAndroid Build Coastguard Worker 31*e6ba1607SAndroid Build Coastguard Worker allprojects { 32*e6ba1607SAndroid Build Coastguard Worker group = "org.robolectric" 33*e6ba1607SAndroid Build Coastguard Worker version = thisVersion 34*e6ba1607SAndroid Build Coastguard Worker } 35*e6ba1607SAndroid Build Coastguard Worker 36*e6ba1607SAndroid Build Coastguard Worker project.afterEvaluate { 37*e6ba1607SAndroid Build Coastguard Worker val ideaProject = rootProject.extensions.getByType<IdeaModel>().project 38*e6ba1607SAndroid Build Coastguard Worker ideaProject.ipr.withXml { 39*e6ba1607SAndroid Build Coastguard Worker val compilerConfiguration = 40*e6ba1607SAndroid Build Coastguard Worker asNode().children().filterIsInstance<Node>().first { 41*e6ba1607SAndroid Build Coastguard Worker it.name() == "component" && it.attribute("name") == "CompilerConfiguration" 42*e6ba1607SAndroid Build Coastguard Worker } 43*e6ba1607SAndroid Build Coastguard Worker 44*e6ba1607SAndroid Build Coastguard Worker // Prevent compiler from complaining about duplicate classes... 45*e6ba1607SAndroid Build Coastguard Worker val excludeFromCompile = compilerConfiguration.appendNode("excludeFromCompile") 46*e6ba1607SAndroid Build Coastguard Worker configAnnotationProcessing.forEach { subproject -> 47*e6ba1607SAndroid Build Coastguard Worker val buildDirectory = subproject.layout.buildDirectory.get().asFile 48*e6ba1607SAndroid Build Coastguard Worker excludeFromCompile.appendNode( 49*e6ba1607SAndroid Build Coastguard Worker "directory", 50*e6ba1607SAndroid Build Coastguard Worker mapOf( 51*e6ba1607SAndroid Build Coastguard Worker "url" to "file://$buildDirectory/classes/java/main/generated", 52*e6ba1607SAndroid Build Coastguard Worker "includeSubdirectories" to "true", 53*e6ba1607SAndroid Build Coastguard Worker ), 54*e6ba1607SAndroid Build Coastguard Worker ) 55*e6ba1607SAndroid Build Coastguard Worker } 56*e6ba1607SAndroid Build Coastguard Worker 57*e6ba1607SAndroid Build Coastguard Worker // Replace the existing "annotationProcessing" tag with a new one... 58*e6ba1607SAndroid Build Coastguard Worker val annotationProcessingNode = Node(compilerConfiguration, "annotationProcessing") 59*e6ba1607SAndroid Build Coastguard Worker configAnnotationProcessing.forEach { subproject -> 60*e6ba1607SAndroid Build Coastguard Worker val profileNode = 61*e6ba1607SAndroid Build Coastguard Worker Node( 62*e6ba1607SAndroid Build Coastguard Worker annotationProcessingNode, 63*e6ba1607SAndroid Build Coastguard Worker "profile", 64*e6ba1607SAndroid Build Coastguard Worker mapOf("name" to "${subproject.name}_main", "enabled" to "true"), 65*e6ba1607SAndroid Build Coastguard Worker ) 66*e6ba1607SAndroid Build Coastguard Worker profileNode.appendNode("module", mapOf("name" to "${subproject.name}_main")) 67*e6ba1607SAndroid Build Coastguard Worker profileNode.appendNode( 68*e6ba1607SAndroid Build Coastguard Worker "option", 69*e6ba1607SAndroid Build Coastguard Worker mapOf( 70*e6ba1607SAndroid Build Coastguard Worker "name" to "org.robolectric.annotation.processing.shadowPackage", 71*e6ba1607SAndroid Build Coastguard Worker "value" to project.extensions.getByType<ShadowsPluginExtension>().packageName, 72*e6ba1607SAndroid Build Coastguard Worker ), 73*e6ba1607SAndroid Build Coastguard Worker ) 74*e6ba1607SAndroid Build Coastguard Worker profileNode.appendNode( 75*e6ba1607SAndroid Build Coastguard Worker "processor", 76*e6ba1607SAndroid Build Coastguard Worker mapOf("name" to "org.robolectric.annotation.processing.RobolectricProcessor"), 77*e6ba1607SAndroid Build Coastguard Worker ) 78*e6ba1607SAndroid Build Coastguard Worker 79*e6ba1607SAndroid Build Coastguard Worker val processorPathNode = Node(profileNode, "processorPath", mapOf("useClasspath" to "false")) 80*e6ba1607SAndroid Build Coastguard Worker project.project(":processor").configurations.named("runtime").configure { 81*e6ba1607SAndroid Build Coastguard Worker allArtifacts.forEach { artifact -> 82*e6ba1607SAndroid Build Coastguard Worker processorPathNode.appendNode("entry", mapOf("name" to artifact.file)) 83*e6ba1607SAndroid Build Coastguard Worker } 84*e6ba1607SAndroid Build Coastguard Worker files.forEach { file -> processorPathNode.appendNode("entry", mapOf("name" to file)) } 85*e6ba1607SAndroid Build Coastguard Worker } 86*e6ba1607SAndroid Build Coastguard Worker 87*e6ba1607SAndroid Build Coastguard Worker profileNode.appendNode(processorPathNode) 88*e6ba1607SAndroid Build Coastguard Worker annotationProcessingNode.appendNode(profileNode) 89*e6ba1607SAndroid Build Coastguard Worker } 90*e6ba1607SAndroid Build Coastguard Worker 91*e6ba1607SAndroid Build Coastguard Worker compilerConfiguration.replaceNode(annotationProcessingNode) 92*e6ba1607SAndroid Build Coastguard Worker } 93*e6ba1607SAndroid Build Coastguard Worker } 94*e6ba1607SAndroid Build Coastguard Worker 95*e6ba1607SAndroid Build Coastguard Worker rootProject.gradle.projectsEvaluated { 96*e6ba1607SAndroid Build Coastguard Worker rootProject.tasks.named<Javadoc>("aggregateJavadocs").configure { isFailOnError = false } 97*e6ba1607SAndroid Build Coastguard Worker } 98*e6ba1607SAndroid Build Coastguard Worker 99*e6ba1607SAndroid Build Coastguard Worker gradle.projectsEvaluated { 100*e6ba1607SAndroid Build Coastguard Worker val headerHtml = 101*e6ba1607SAndroid Build Coastguard Worker """ 102*e6ba1607SAndroid Build Coastguard Worker <ul class="navList" style="font-size: 1.5em;"> 103*e6ba1607SAndroid Build Coastguard Worker <li> 104*e6ba1607SAndroid Build Coastguard Worker Robolectric $thisVersion | 105*e6ba1607SAndroid Build Coastguard Worker <a href="/" target="_top"> 106*e6ba1607SAndroid Build Coastguard Worker <img src="https://robolectric.org/images/logo-with-bubbles-down.png" style="max-height: 18pt; vertical-align: sub;"/> 107*e6ba1607SAndroid Build Coastguard Worker </a> 108*e6ba1607SAndroid Build Coastguard Worker </li> 109*e6ba1607SAndroid Build Coastguard Worker </ul> 110*e6ba1607SAndroid Build Coastguard Worker """ 111*e6ba1607SAndroid Build Coastguard Worker .trimIndent() 112*e6ba1607SAndroid Build Coastguard Worker 113*e6ba1607SAndroid Build Coastguard Worker project.allprojects { 114*e6ba1607SAndroid Build Coastguard Worker tasks.withType<Javadoc> { 115*e6ba1607SAndroid Build Coastguard Worker options { 116*e6ba1607SAndroid Build Coastguard Worker this as StandardJavadocDocletOptions 117*e6ba1607SAndroid Build Coastguard Worker 118*e6ba1607SAndroid Build Coastguard Worker noTimestamp(true) 119*e6ba1607SAndroid Build Coastguard Worker links( 120*e6ba1607SAndroid Build Coastguard Worker "https://docs.oracle.com/javase/8/docs/api/", 121*e6ba1607SAndroid Build Coastguard Worker "https://developer.android.com/reference/", 122*e6ba1607SAndroid Build Coastguard Worker ) 123*e6ba1607SAndroid Build Coastguard Worker // Set Javadoc source to JDK 8 to avoid unnamed module problem 124*e6ba1607SAndroid Build Coastguard Worker // when running 'aggregateJavadocs' with OpenJDK 13+. 125*e6ba1607SAndroid Build Coastguard Worker source("8") 126*e6ba1607SAndroid Build Coastguard Worker header = headerHtml 127*e6ba1607SAndroid Build Coastguard Worker footer = headerHtml 128*e6ba1607SAndroid Build Coastguard Worker } 129*e6ba1607SAndroid Build Coastguard Worker } 130*e6ba1607SAndroid Build Coastguard Worker } 131*e6ba1607SAndroid Build Coastguard Worker 132*e6ba1607SAndroid Build Coastguard Worker val aggregateJsondocs by 133*e6ba1607SAndroid Build Coastguard Worker tasks.registering(Copy::class) { 134*e6ba1607SAndroid Build Coastguard Worker project.subprojects 135*e6ba1607SAndroid Build Coastguard Worker .filter { it.pluginManager.hasPlugin(libs.plugins.robolectric.shadows.get().pluginId) } 136*e6ba1607SAndroid Build Coastguard Worker .forEach { subproject -> 137*e6ba1607SAndroid Build Coastguard Worker dependsOn(subproject.tasks.named("compileJava")) 138*e6ba1607SAndroid Build Coastguard Worker from(subproject.layout.buildDirectory.dir("docs/json")) 139*e6ba1607SAndroid Build Coastguard Worker } 140*e6ba1607SAndroid Build Coastguard Worker 141*e6ba1607SAndroid Build Coastguard Worker into(layout.buildDirectory.dir("docs/json")) 142*e6ba1607SAndroid Build Coastguard Worker } 143*e6ba1607SAndroid Build Coastguard Worker } 144*e6ba1607SAndroid Build Coastguard Worker 145*e6ba1607SAndroid Build Coastguard Worker val aggregateDocs by tasks.registering { dependsOn(":aggregateJavadocs", ":aggregateJsondocs") } 146*e6ba1607SAndroid Build Coastguard Worker 147*e6ba1607SAndroid Build Coastguard Worker val prefetchSdks by 148*e6ba1607SAndroid Build Coastguard Worker tasks.registering { 149*e6ba1607SAndroid Build Coastguard Worker allSdks.forEach { androidSdk -> 150*e6ba1607SAndroid Build Coastguard Worker doLast { 151*e6ba1607SAndroid Build Coastguard Worker prefetchSdk( 152*e6ba1607SAndroid Build Coastguard Worker apiLevel = androidSdk.apiLevel, 153*e6ba1607SAndroid Build Coastguard Worker coordinates = androidSdk.coordinates, 154*e6ba1607SAndroid Build Coastguard Worker groupId = androidSdk.groupId, 155*e6ba1607SAndroid Build Coastguard Worker artifactId = androidSdk.artifactId, 156*e6ba1607SAndroid Build Coastguard Worker version = androidSdk.version, 157*e6ba1607SAndroid Build Coastguard Worker ) 158*e6ba1607SAndroid Build Coastguard Worker } 159*e6ba1607SAndroid Build Coastguard Worker } 160*e6ba1607SAndroid Build Coastguard Worker } 161*e6ba1607SAndroid Build Coastguard Worker 162*e6ba1607SAndroid Build Coastguard Worker val prefetchInstrumentedSdks by 163*e6ba1607SAndroid Build Coastguard Worker tasks.registering { 164*e6ba1607SAndroid Build Coastguard Worker allSdks.forEach { androidSdk -> 165*e6ba1607SAndroid Build Coastguard Worker doLast { 166*e6ba1607SAndroid Build Coastguard Worker prefetchSdk( 167*e6ba1607SAndroid Build Coastguard Worker apiLevel = androidSdk.apiLevel, 168*e6ba1607SAndroid Build Coastguard Worker coordinates = androidSdk.preinstrumentedCoordinates, 169*e6ba1607SAndroid Build Coastguard Worker groupId = androidSdk.groupId, 170*e6ba1607SAndroid Build Coastguard Worker artifactId = androidSdk.preinstrumentedArtifactId, 171*e6ba1607SAndroid Build Coastguard Worker version = androidSdk.preinstrumentedVersion, 172*e6ba1607SAndroid Build Coastguard Worker ) 173*e6ba1607SAndroid Build Coastguard Worker } 174*e6ba1607SAndroid Build Coastguard Worker } 175*e6ba1607SAndroid Build Coastguard Worker } 176*e6ba1607SAndroid Build Coastguard Worker 177*e6ba1607SAndroid Build Coastguard Worker fun prefetchSdk( 178*e6ba1607SAndroid Build Coastguard Worker apiLevel: Int, 179*e6ba1607SAndroid Build Coastguard Worker coordinates: String, 180*e6ba1607SAndroid Build Coastguard Worker groupId: String, 181*e6ba1607SAndroid Build Coastguard Worker artifactId: String, 182*e6ba1607SAndroid Build Coastguard Worker version: String, 183*e6ba1607SAndroid Build Coastguard Worker ) { 184*e6ba1607SAndroid Build Coastguard Worker println("Prefetching $coordinates...") 185*e6ba1607SAndroid Build Coastguard Worker 186*e6ba1607SAndroid Build Coastguard Worker // Prefetch into Maven local repo... 187*e6ba1607SAndroid Build Coastguard Worker project.exec { 188*e6ba1607SAndroid Build Coastguard Worker val mvnCommand = 189*e6ba1607SAndroid Build Coastguard Worker "mvn -q dependency:get -DrepoUrl=https://maven.google.com " + 190*e6ba1607SAndroid Build Coastguard Worker "-DgroupId=$groupId -DartifactId=$artifactId -Dversion=$version" 191*e6ba1607SAndroid Build Coastguard Worker 192*e6ba1607SAndroid Build Coastguard Worker commandLine(mvnCommand.split(" ")) 193*e6ba1607SAndroid Build Coastguard Worker } 194*e6ba1607SAndroid Build Coastguard Worker 195*e6ba1607SAndroid Build Coastguard Worker // Prefetch into Gradle local cache... 196*e6ba1607SAndroid Build Coastguard Worker val config = configurations.create("sdk$apiLevel") 197*e6ba1607SAndroid Build Coastguard Worker dependencies.add("sdk$apiLevel", coordinates) 198*e6ba1607SAndroid Build Coastguard Worker 199*e6ba1607SAndroid Build Coastguard Worker // Causes dependencies to be resolved: 200*e6ba1607SAndroid Build Coastguard Worker config.files 201*e6ba1607SAndroid Build Coastguard Worker } 202*e6ba1607SAndroid Build Coastguard Worker 203*e6ba1607SAndroid Build Coastguard Worker val prefetchDependencies by 204*e6ba1607SAndroid Build Coastguard Worker tasks.registering { 205*e6ba1607SAndroid Build Coastguard Worker doLast { 206*e6ba1607SAndroid Build Coastguard Worker allprojects.forEach { p -> 207*e6ba1607SAndroid Build Coastguard Worker p.configurations.forEach { config -> 208*e6ba1607SAndroid Build Coastguard Worker // Causes dependencies to be resolved: 209*e6ba1607SAndroid Build Coastguard Worker if (config.isCanBeResolved) { 210*e6ba1607SAndroid Build Coastguard Worker try { 211*e6ba1607SAndroid Build Coastguard Worker config.files 212*e6ba1607SAndroid Build Coastguard Worker } catch (e: ResolveException) { 213*e6ba1607SAndroid Build Coastguard Worker // Ignore resolution issues for the ':integration_tests' and ':testapp' projects, sigh 214*e6ba1607SAndroid Build Coastguard Worker if (!p.path.startsWith(":integration_tests:") && !p.path.startsWith(":testapp")) { 215*e6ba1607SAndroid Build Coastguard Worker throw e 216*e6ba1607SAndroid Build Coastguard Worker } 217*e6ba1607SAndroid Build Coastguard Worker } 218*e6ba1607SAndroid Build Coastguard Worker } // End config resolution 219*e6ba1607SAndroid Build Coastguard Worker } // End configurations 220*e6ba1607SAndroid Build Coastguard Worker } // End allprojects 221*e6ba1607SAndroid Build Coastguard Worker } // End doLast 222*e6ba1607SAndroid Build Coastguard Worker } // End task registration 223