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