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