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