• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright 2018 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 package androidx.build
18 
19 import androidx.build.SupportConfig.INSTRUMENTATION_RUNNER
20 import androidx.build.license.CheckExternalDependencyLicensesTask
21 import com.android.build.gradle.LibraryExtension
22 import com.android.build.gradle.internal.dsl.LintOptions
23 import com.android.build.gradle.tasks.GenerateBuildConfig
24 import net.ltgt.gradle.errorprone.ErrorProneBasePlugin
25 import net.ltgt.gradle.errorprone.ErrorProneToolChain
26 import org.gradle.api.JavaVersion
27 import org.gradle.api.Plugin
28 import org.gradle.api.Project
29 import java.io.File
30 
31 /**
32  * Support library specific com.android.library plugin that sets common configurations needed for
33  * support library modules.
34  */
35 class SupportAndroidLibraryPlugin : Plugin<Project> {
36 
37     override fun apply(project: Project) {
38         val supportLibraryExtension = project.extensions.create("supportLibrary",
39                 SupportLibraryExtension::class.java, project)
40         apply(project, supportLibraryExtension)
41         CheckExternalDependencyLicensesTask.configure(project)
42         val isCoreSupportLibrary = project.rootProject.name == "support"
43 
44         project.afterEvaluate {
45             val library = project.extensions.findByType(LibraryExtension::class.java)
46                     ?: return@afterEvaluate
47 
48             library.defaultConfig.minSdkVersion(supportLibraryExtension.minSdkVersion)
49 
50             // Java 8 is only fully supported on API 24+ and not all Java 8 features are binary
51             // compatible with API < 24, so use Java 7 for both source AND target.
52             val javaVersion: JavaVersion
53             if (supportLibraryExtension.java8Library) {
54                 if (library.defaultConfig.minSdkVersion.apiLevel < 24) {
55                     throw IllegalArgumentException("Libraries can only support Java 8 if "
56                             + "minSdkVersion is 24 or higher")
57                 }
58                 javaVersion = JavaVersion.VERSION_1_8
59             } else {
60                 javaVersion = JavaVersion.VERSION_1_7
61             }
62 
63             library.compileOptions.setSourceCompatibility(javaVersion)
64             library.compileOptions.setTargetCompatibility(javaVersion)
65 
66             VersionFileWriterTask.setUpAndroidLibrary(project, library)
67             DiffAndDocs.registerAndroidProject(project, library, supportLibraryExtension)
68 
69             library.libraryVariants.all { libraryVariant ->
70                 if (libraryVariant.getBuildType().getName().equals("debug")) {
71                     @Suppress("DEPRECATION")
72                     val javaCompile = libraryVariant.javaCompile
73                     if (supportLibraryExtension.failOnUncheckedWarnings) {
74                         javaCompile.options.compilerArgs.add("-Xlint:unchecked")
75                     }
76                     if (supportLibraryExtension.failOnDeprecationWarnings) {
77                         javaCompile.options.compilerArgs.add("-Xlint:deprecation")
78                     }
79                     javaCompile.options.compilerArgs.add("-Werror")
80                 }
81             }
82         }
83 
84         project.apply(mapOf("plugin" to "com.android.library"))
85         project.apply(mapOf("plugin" to ErrorProneBasePlugin::class.java))
86 
87         project.afterEvaluate {
88             project.tasks.all({
89                 if (it is GenerateBuildConfig) {
90                     // Disable generating BuildConfig.java
91                     it.enabled = false
92                 }
93             })
94         }
95 
96         project.configurations.all { configuration ->
97             if (isCoreSupportLibrary && project.name != "annotations") {
98                 // While this usually happens naturally due to normal project dependencies, force
99                 // evaluation on the annotations project in case the below substitution is the only
100                 // dependency to this project. See b/70650240 on what happens when this is missing.
101                 project.evaluationDependsOn(":annotation")
102 
103                 // In projects which compile as part of the "core" support libraries (which include
104                 // the annotations), replace any transitive pointer to the deployed Maven
105                 // coordinate version of annotations with a reference to the local project. These
106                 // usually originate from test dependencies and otherwise cause multiple copies on
107                 // the classpath. We do not do this for non-"core" projects as they need to
108                 // depend on the Maven coordinate variant.
109                 configuration.resolutionStrategy.dependencySubstitution.apply {
110                     substitute(module("androidx.annotation:annotation"))
111                             .with(project(":annotation"))
112                 }
113             }
114         }
115 
116         val library = project.extensions.findByType(LibraryExtension::class.java)
117                 ?: throw Exception("Failed to find Android extension")
118 
119         library.compileSdkVersion(SupportConfig.CURRENT_SDK_VERSION)
120 
121         library.buildToolsVersion = SupportConfig.BUILD_TOOLS_VERSION
122 
123         // Update the version meta-data in each Manifest.
124         library.defaultConfig.addManifestPlaceholders(
125                 mapOf("target-sdk-version" to SupportConfig.CURRENT_SDK_VERSION))
126 
127         // Set test runner.
128         library.defaultConfig.testInstrumentationRunner = INSTRUMENTATION_RUNNER
129 
130         library.testOptions.unitTests.isReturnDefaultValues = true
131 
132         // Use a local debug keystore to avoid build server issues.
133         library.signingConfigs.findByName("debug")?.storeFile =
134                 SupportConfig.getKeystore(project)
135 
136         project.afterEvaluate {
137             setUpLint(library.lintOptions, SupportConfig.getLintBaseline(project),
138                     (supportLibraryExtension.mavenVersion?.isFinalApi()) ?: false)
139         }
140 
141         project.tasks.getByName("uploadArchives").dependsOn("lintRelease")
142 
143         setUpSoureJarTaskForAndroidProject(project, library)
144 
145         val toolChain = ErrorProneToolChain.create(project)
146         project.dependencies.add("errorprone", ERROR_PRONE_VERSION)
147         library.libraryVariants.all { libraryVariant ->
148             if (libraryVariant.getBuildType().getName().equals("debug")) {
149                 @Suppress("DEPRECATION")
150                 libraryVariant.javaCompile.configureWithErrorProne(toolChain)
151             }
152         }
153     }
154 }
155 
setUpLintnull156 private fun setUpLint(lintOptions: LintOptions, baseline: File, verifyTranslations: Boolean) {
157     // Always lint check NewApi as fatal.
158     lintOptions.isAbortOnError = true
159     lintOptions.isIgnoreWarnings = true
160 
161     // Skip lintVital tasks on assemble. We explicitly run lintRelease for libraries.
162     lintOptions.isCheckReleaseBuilds = false
163 
164     // Write output directly to the console (and nowhere else).
165     lintOptions.textOutput("stderr")
166     lintOptions.textReport = true
167     lintOptions.htmlReport = false
168 
169     // Format output for convenience.
170     lintOptions.isExplainIssues = true
171     lintOptions.isNoLines = false
172     lintOptions.isQuiet = true
173 
174     lintOptions.fatal("NewApi")
175     lintOptions.fatal("ObsoleteSdkInt")
176     lintOptions.fatal("VisibleForTests")
177     lintOptions.fatal("NoHardKeywords")
178 
179     if (verifyTranslations) {
180         lintOptions.fatal("MissingTranslation")
181     } else {
182         lintOptions.disable("MissingTranslation")
183     }
184 
185     // Set baseline file for all legacy lint warnings.
186     if (baseline.exists()) {
187         lintOptions.baseline(baseline)
188     }
189 }
190