xref: /aosp_15_r20/tools/metalava/integration/build.gradle.kts (revision 115816f9299ab6ddd6b9673b81f34e707f6bacab)
1 /*
<lambda>null2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // Integration test project that analyzes an external dependency: see libraryToRunAgainst.
18 // Set INTEGRATION=true to enable.
19 
20 import com.android.build.api.attributes.BuildTypeAttr
21 
22 plugins {
23     id("com.android.library") // needed for bootClasspath and AAR transforms to work
24 }
25 
<lambda>null26 repositories {
27     google()
28     mavenCentral()
29 }
30 
31 // Create two configurations used in dependencies {} block.
32 val runner: Configuration by configurations.creating
<lambda>null33 val libraryToRunAgainst: Configuration by configurations.creating {
34     isCanBeResolved = false
35     isCanBeConsumed = false
36 }
37 
<lambda>null38 dependencies {
39     libraryToRunAgainst("androidx.compose.foundation:foundation:1.4.3")
40     runner(project(":metalava"))
41 }
42 
<lambda>null43 android { // minimal set up to make com.android.library plugin work
44     compileSdkVersion = "android-33"
45     namespace = "com.android.tools.metalava.integration"
46 }
47 
48 /**
49  * Configuration used to resolve source jars for projects in libraryToRunAgainst
50  */
<lambda>null51 val sources: Configuration by configurations.creating {
52     extendsFrom(libraryToRunAgainst)
53     attributes {
54         attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
55         attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION))
56         attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.SOURCES))
57         attribute(
58             LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
59             project.objects.named(LibraryElements.JAR)
60         )
61     }
62 }
63 
Configurationnull64 fun Configuration.setResolveClasspathForUsage(usage: String) {
65     isCanBeConsumed = false
66     attributes {
67         attribute(Usage.USAGE_ATTRIBUTE, project.objects.named<Usage>(usage))
68         attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named<Category>(Category.LIBRARY))
69         attribute(BuildTypeAttr.ATTRIBUTE, project.objects.named<BuildTypeAttr>("release"))
70     }
71     extendsFrom(sources)
72 }
73 
74 /**
75  * Configuration used to resolve compile classpath for projects in libraryToRunAgainst
76  */
<lambda>null77 val sourcesCompileClasspath: Configuration by configurations.creating {
78     setResolveClasspathForUsage(Usage.JAVA_API)
79 }
80 /**
81  * Configuration used to resolve runtime classpath for projects in libraryToRunAgainst
82  */
<lambda>null83 val sourcesRuntimeClasspath: Configuration by configurations.creating {
84     setResolveClasspathForUsage(Usage.JAVA_RUNTIME)
85 }
86 /**
87  * Full classpath of all the dependencies needed to analyze projects in libraryToRunAgainst
88  * This includes android.jar, compile and runtime jars
89  */
90 val sourceDependencyClasspath: FileCollection = files(android.bootClasspath) +
<lambda>null91     sourcesCompileClasspath.incoming.artifactView {
92         attributes {
93             attribute(Attribute.of("artifactType", String::class.java), "android-classes")
94         }
95     }.files + sourcesRuntimeClasspath.incoming.artifactView {
<lambda>null96         attributes {
97             attribute(Attribute.of("artifactType", String::class.java), "android-classes")
98         }
99     }.files
100 
101 @CacheableTask
102 abstract class MetalavaRunner : DefaultTask() {
103     @get:Inject
104     abstract val execOperations: ExecOperations
105     @get:[InputFiles PathSensitive(PathSensitivity.NONE)]
106     abstract var sources: File
107     @get:[InputFile PathSensitive(PathSensitivity.NONE)]
108     abstract val apiLintBaseline: RegularFileProperty
109     @get:Classpath
110     abstract val dependencyClasspath: ConfigurableFileCollection
111     @get:Classpath
112     abstract val metalavaClasspath: ConfigurableFileCollection
113     @get:OutputFile
114     abstract val signatureFile: RegularFileProperty
115 
116     @TaskAction
doThingsnull117     fun doThings() {
118         // An approximation of AndroidX usage of metalava for tracking public
119         // api surface of a library and running API lint against it.
120         execOperations.javaexec {
121             mainClass.set("com.android.tools.metalava.Driver")
122             classpath = metalavaClasspath
123             args = listOf(
124                 "--source-path",
125                 sources.absolutePath,
126                 "--api",
127                 signatureFile.get().asFile.absolutePath,
128                 "--classpath",
129                 dependencyClasspath.files.joinToString(File.pathSeparator),
130                 "--hide-annotation",
131                 "androidx.annotation.RestrictTo",
132                 "--show-unannotated",
133                 "--api-lint",
134                 "--baseline",
135                 apiLintBaseline.get().asFile.absolutePath,
136                 "--hide",
137                 listOf(
138                     "Enum",
139                     "StartWithLower",
140                     "MissingJvmstatic",
141                     "ArrayReturn",
142                     "UserHandleName",
143                 ).joinToString(),
144             )
145         }
146     }
147 }
148 
149 interface Injected {
150     @get:Inject val archiveOperations: ArchiveOperations
151 }
152 
153 /**
154  * A task that will extract all of the source jars that are added to libraryToRunAgainst
155  * configuration.
156  */
<lambda>null157 val copyInputSources = tasks.register<Sync>("copyInputSources") {
158     // Store archiveOperations into a local variable to prevent access to project object
159     // during the task execution, as that breaks configuration caching.
160     val archiveOperations = project.objects.newInstance<Injected>().archiveOperations
161     from(
162         sources.incoming.artifactView { }.files.elements.map { jars ->
163             jars.map { jar ->
164                 archiveOperations.zipTree(jar)
165             }
166         }
167     )
168     into(layout.buildDirectory.dir("inputSources"))
169 }
170 
<lambda>null171 tasks.register<MetalavaRunner>("run") {
172     dependsOn(copyInputSources)
173     sources = copyInputSources.get().destinationDir
174     dependencyClasspath.from(sourceDependencyClasspath)
175     metalavaClasspath.from(runner)
176     signatureFile.set(layout.buildDirectory.file("current.txt"))
177     apiLintBaseline.set(layout.projectDirectory.file("api_lint.ignore"))
178     outputs.upToDateWhen { false }
179 }
180