1 import com.android.tools.metalava.CREATE_ARCHIVE_TASK
2 import com.android.tools.metalava.CREATE_BUILD_INFO_TASK
3 import com.android.tools.metalava.configureBuildInfoTask
4 import com.android.tools.metalava.configurePublishingArchive
5 import org.gradle.api.tasks.testing.logging.TestLogEvent
6 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
7 import java.io.FileInputStream
8 import java.io.FileNotFoundException
9 import java.util.Properties
10
11 buildDir = getBuildDirectory()
12
13 defaultTasks = mutableListOf(
14 "installDist",
15 "test",
16 CREATE_ARCHIVE_TASK,
17 CREATE_BUILD_INFO_TASK,
18 "ktlint"
19 )
20
<lambda>null21 repositories {
22 google()
23 mavenCentral()
24 val lintRepo = project.findProperty("lintRepo") as String?
25 if (lintRepo != null) {
26 logger.warn("Building using custom $lintRepo maven repository")
27 maven {
28 url = uri(lintRepo)
29 }
30 }
31 }
32
<lambda>null33 plugins {
34 alias(libs.plugins.kotlinJvm)
35 id("application")
36 id("java")
37 id("maven-publish")
38 }
39
40 group = "com.android.tools.metalava"
41 version = getMetalavaVersion()
42
<lambda>null43 application {
44 mainClass.set("com.android.tools.metalava.Driver")
45 applicationDefaultJvmArgs = listOf("-ea", "-Xms2g", "-Xmx4g")
46 }
47
<lambda>null48 java {
49 sourceCompatibility = JavaVersion.VERSION_1_8
50 targetCompatibility = JavaVersion.VERSION_1_8
51 }
52
<lambda>null53 tasks.withType(KotlinCompile::class.java) {
54 sourceCompatibility = "1.8"
55 targetCompatibility = "1.8"
56
57 kotlinOptions {
58 jvmTarget = "1.8"
59 apiVersion = "1.6"
60 languageVersion = "1.6"
61 allWarningsAsErrors = true
62 }
63 }
64
65 val customLintVersion = findProperty("lintVersion") as String?
66 val studioVersion: String = if (customLintVersion != null) {
67 logger.warn("Building using custom $customLintVersion version of Android Lint")
68 customLintVersion
69 } else {
70 "30.3.0-alpha08"
71 }
72
<lambda>null73 dependencies {
74 implementation("com.android.tools.external.org-jetbrains:uast:$studioVersion")
75 implementation("com.android.tools.external.com-intellij:kotlin-compiler:$studioVersion")
76 implementation("com.android.tools.external.com-intellij:intellij-core:$studioVersion")
77 implementation("com.android.tools.lint:lint-api:$studioVersion")
78 implementation("com.android.tools.lint:lint-checks:$studioVersion")
79 implementation("com.android.tools.lint:lint-gradle:$studioVersion")
80 implementation("com.android.tools.lint:lint:$studioVersion")
81 implementation("com.android.tools:common:$studioVersion")
82 implementation("com.android.tools:sdk-common:$studioVersion")
83 implementation("com.android.tools:sdklib:$studioVersion")
84 implementation(libs.kotlinStdlib)
85 implementation(libs.kotlinReflect)
86 implementation("org.ow2.asm:asm:8.0")
87 implementation("org.ow2.asm:asm-tree:8.0")
88 implementation("com.google.guava:guava:30.1.1-jre")
89 testImplementation("com.android.tools.lint:lint-tests:$studioVersion")
90 testImplementation("junit:junit:4.13.2")
91 testImplementation("com.google.truth:truth:1.1.3")
92 testImplementation(libs.kotlinTest)
93 }
94
95 val zipTask: TaskProvider<Zip> = project.tasks.register(
96 "zipResultsOf${name.capitalize()}",
97 Zip::class.java
<lambda>null98 ) {
99 destinationDirectory.set(File(getDistributionDirectory(), "host-test-reports"))
100 archiveFileName.set("metalava-tests.zip")
101 }
102
registerTestPrebuiltsSdkTasksnull103 fun registerTestPrebuiltsSdkTasks(sourceDir: String, destJar: String): String {
104 val basename = sourceDir.replace("/", "-")
105 val javaCompileTaskName = "$basename.classes"
106 val jarTaskName = "$basename.jar"
107
108 project.tasks.register(javaCompileTaskName, JavaCompile::class) {
109 source = fileTree(sourceDir)
110 classpath = project.files()
111 destinationDirectory.set(File(getBuildDirectory(), javaCompileTaskName))
112 }
113
114 val dir = destJar.substringBeforeLast("/")
115 val filename = destJar.substringAfterLast("/")
116 if (dir == filename) {
117 throw IllegalArgumentException("bad destJar argument '$destJar'")
118 }
119
120 project.tasks.register(jarTaskName, Jar::class) {
121 from(tasks.named(javaCompileTaskName).get().outputs.files.filter { it.isDirectory })
122 archiveFileName.set(filename)
123 destinationDirectory.set(File(getBuildDirectory(), dir))
124 }
125
126 return jarTaskName
127 }
128
129 val testPrebuiltsSdkApi30 = registerTestPrebuiltsSdkTasks("src/testdata/prebuilts-sdk-test/30", "prebuilts/sdk/30/public/android.jar")
130 val testPrebuiltsSdkApi31 = registerTestPrebuiltsSdkTasks("src/testdata/prebuilts-sdk-test/31", "prebuilts/sdk/31/public/android.jar")
131 val testPrebuiltsSdkExt1 = registerTestPrebuiltsSdkTasks("src/testdata/prebuilts-sdk-test/extensions/1", "prebuilts/sdk/extensions/1/public/framework-ext.jar")
132 val testPrebuiltsSdkExt2 = registerTestPrebuiltsSdkTasks("src/testdata/prebuilts-sdk-test/extensions/2", "prebuilts/sdk/extensions/2/public/framework-ext.jar")
133 val testPrebuiltsSdkExt3 = registerTestPrebuiltsSdkTasks("src/testdata/prebuilts-sdk-test/extensions/3", "prebuilts/sdk/extensions/3/public/framework-ext.jar")
134
<lambda>null135 project.tasks.register("test-sdk-extensions-info.xml", Copy::class) {
136 from("src/testdata/prebuilts-sdk-test/sdk-extensions-info.xml")
137 into(File(getBuildDirectory(), "prebuilts/sdk"))
138 }
139
<lambda>null140 project.tasks.register("test-prebuilts-sdk", Assemble::class) {
141 dependsOn(testPrebuiltsSdkApi30)
142 dependsOn(testPrebuiltsSdkApi31)
143 dependsOn(testPrebuiltsSdkExt1)
144 dependsOn(testPrebuiltsSdkExt2)
145 dependsOn(testPrebuiltsSdkExt3)
146 dependsOn("test-sdk-extensions-info.xml")
147 }
148
149 val testTask = tasks.named("test", Test::class.java)
<lambda>null150 testTask.configure {
151 dependsOn("test-prebuilts-sdk")
152 setEnvironment("METALAVA_TEST_PREBUILTS_SDK_ROOT" to getBuildDirectory().path + "/prebuilts/sdk")
153 maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).takeIf { it > 0 } ?: 1
154 testLogging.events = hashSetOf(
155 TestLogEvent.FAILED,
156 TestLogEvent.PASSED,
157 TestLogEvent.SKIPPED,
158 TestLogEvent.STANDARD_OUT,
159 TestLogEvent.STANDARD_ERROR
160 )
161 if (isBuildingOnServer()) ignoreFailures = true
162 finalizedBy(zipTask)
163 }
<lambda>null164 zipTask.configure {
165 from(testTask.map { it.reports.junitXml.outputLocation.get() })
166 }
167
getMetalavaVersionnull168 fun getMetalavaVersion(): Any {
169 val versionPropertyFile = File(projectDir, "src/main/resources/version.properties")
170 if (versionPropertyFile.canRead()) {
171 val versionProps = Properties()
172 versionProps.load(FileInputStream(versionPropertyFile))
173 val metalavaVersion = versionProps["metalavaVersion"]
174 ?: throw IllegalStateException("metalava version was not set in ${versionPropertyFile.absolutePath}")
175 return if (isBuildingOnServer()) {
176 metalavaVersion
177 } else {
178 // Local builds are not public release candidates.
179 "$metalavaVersion-SNAPSHOT"
180 }
181 } else {
182 throw FileNotFoundException("Could not read ${versionPropertyFile.absolutePath}")
183 }
184 }
185
getBuildDirectorynull186 fun getBuildDirectory(): File {
187 return if (System.getenv("OUT_DIR") != null) {
188 File(System.getenv("OUT_DIR"), "metalava")
189 } else {
190 File(projectDir, "../../out/metalava")
191 }
192 }
193
194 /**
195 * The build server will copy the contents of the distribution directory and make it available for
196 * download.
197 */
getDistributionDirectorynull198 fun getDistributionDirectory(): File {
199 return if (System.getenv("DIST_DIR") != null) {
200 File(System.getenv("DIST_DIR"))
201 } else {
202 File(projectDir, "../../out/dist")
203 }
204 }
205
isBuildingOnServernull206 fun isBuildingOnServer(): Boolean {
207 return System.getenv("OUT_DIR") != null && System.getenv("DIST_DIR") != null
208 }
209
210 /**
211 * @return build id string for current build
212 *
213 * The build server does not pass the build id so we infer it from the last folder of the
214 * distribution directory name.
215 */
getBuildIdnull216 fun getBuildId(): String {
217 return if (System.getenv("DIST_DIR") != null) File(System.getenv("DIST_DIR")).name else "0"
218 }
219
220 // KtLint: https://github.com/pinterest/ktlint
221
Projectnull222 fun Project.getKtlintConfiguration(): Configuration {
223 return configurations.findByName("ktlint") ?: configurations.create("ktlint") {
224 val dependency = project.dependencies.create("com.pinterest:ktlint:0.41.0")
225 dependencies.add(dependency)
226 }
227 }
228
<lambda>null229 tasks.register("ktlint", JavaExec::class.java) {
230 description = "Check Kotlin code style."
231 group = "Verification"
232 classpath = getKtlintConfiguration()
233 mainClass.set("com.pinterest.ktlint.Main")
234 args = listOf("src/**/*.kt", "build.gradle.kts")
235 }
236
<lambda>null237 tasks.register("ktlintFormat", JavaExec::class.java) {
238 description = "Fix Kotlin code style deviations."
239 group = "formatting"
240 classpath = getKtlintConfiguration()
241 mainClass.set("com.pinterest.ktlint.Main")
242 args = listOf("-F", "src/**/*.kt", "build.gradle.kts")
243 }
244
245 val publicationName = "Metalava"
246 val repositoryName = "Dist"
247
<lambda>null248 publishing {
249 publications {
250 create<MavenPublication>(publicationName) {
251 from(components["java"])
252 pom {
253 licenses {
254 license {
255 name.set("The Apache License, Version 2.0")
256 url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
257 }
258 }
259 developers {
260 developer {
261 name.set("The Android Open Source Project")
262 }
263 }
264 scm {
265 connection.set("scm:git:https://android.googlesource.com/platform/tools/metalava")
266 url.set("https://android.googlesource.com/platform/tools/metalava/")
267 }
268 }
269 }
270 }
271
272 repositories {
273 maven {
274 name = repositoryName
275 url = uri("file://${getDistributionDirectory().canonicalPath}/repo/m2repository")
276 }
277 }
278 }
279
280 // Workaround for https://github.com/gradle/gradle/issues/11717
<lambda>null281 tasks.withType(GenerateModuleMetadata::class.java).configureEach {
282 val outDirProvider = project.providers.environmentVariable("DIST_DIR")
283 inputs.property("buildOutputDirectory", outDirProvider).optional(true)
284 doLast {
285 val metadata = outputFile.asFile.get()
286 val text = metadata.readText()
287 val buildId = outDirProvider.orNull?.let { File(it).name } ?: "0"
288 metadata.writeText(
289 text.replace(
290 "\"buildId\": .*".toRegex(),
291 "\"buildId:\": \"${buildId}\""
292 )
293 )
294 }
295 }
296
297 val archiveTaskProvider = configurePublishingArchive(
298 project,
299 publicationName,
300 repositoryName,
301 getBuildId(),
302 getDistributionDirectory()
303 )
304 configureBuildInfoTask(
305 project,
306 isBuildingOnServer(),
307 getDistributionDirectory(),
308 archiveTaskProvider
309 )
310