Aurimas Liutikas | 92d9756 | 2017-11-13 13:54:27 -0800 | [diff] [blame] | 1 | /* |
Aurimas Liutikas | 526389b | 2018-02-27 14:01:24 -0800 | [diff] [blame] | 2 | * Copyright 2018 The Android Open Source Project |
Aurimas Liutikas | 92d9756 | 2017-11-13 13:54:27 -0800 | [diff] [blame] | 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 | |
Aurimas Liutikas | 526389b | 2018-02-27 14:01:24 -0800 | [diff] [blame] | 17 | package androidx.build |
Aurimas Liutikas | 92d9756 | 2017-11-13 13:54:27 -0800 | [diff] [blame] | 18 | |
Aurimas Liutikas | c53db9a | 2020-10-08 17:22:52 -0700 | [diff] [blame] | 19 | import androidx.build.checkapi.shouldConfigureApiTasks |
Ember Rose | c662e1a | 2022-09-16 14:37:50 -0400 | [diff] [blame^] | 20 | import androidx.build.transform.configureAarAsJarForConfiguration |
David Saff | d6a966c | 2022-07-26 10:54:47 -0400 | [diff] [blame] | 21 | import com.android.build.gradle.internal.crash.afterEvaluate |
Aurimas Liutikas | 92d9756 | 2017-11-13 13:54:27 -0800 | [diff] [blame] | 22 | import groovy.lang.Closure |
Jeff Gaston | ce468a9 | 2020-01-08 12:51:16 -0500 | [diff] [blame] | 23 | import org.gradle.api.GradleException |
Aurimas Liutikas | 92d9756 | 2017-11-13 13:54:27 -0800 | [diff] [blame] | 24 | import org.gradle.api.Project |
Aurimas Liutikas | 2e85edf | 2021-08-11 14:36:23 -0700 | [diff] [blame] | 25 | import org.gradle.api.provider.Property |
Aurimas Liutikas | d084e36 | 2021-11-19 09:25:43 -0800 | [diff] [blame] | 26 | import java.io.File |
| 27 | |
Aurimas Liutikas | 92d9756 | 2017-11-13 13:54:27 -0800 | [diff] [blame] | 28 | /** |
Jeff Gaston | d30e019 | 2021-08-18 21:53:23 -0400 | [diff] [blame] | 29 | * Extension for [AndroidXImplPlugin] that's responsible for holding configuration options. |
Aurimas Liutikas | 92d9756 | 2017-11-13 13:54:27 -0800 | [diff] [blame] | 30 | */ |
Aurimas Liutikas | b63ef63 | 2019-04-01 04:37:49 -0700 | [diff] [blame] | 31 | open class AndroidXExtension(val project: Project) { |
Aurimas Liutikas | d084e36 | 2021-11-19 09:25:43 -0800 | [diff] [blame] | 32 | @JvmField |
| 33 | val LibraryVersions: Map<String, Version> |
| 34 | @JvmField |
| 35 | val LibraryGroups: Map<String, LibraryGroup> |
| 36 | |
| 37 | init { |
| 38 | val toml = project.objects.fileProperty().fileValue( |
| 39 | File(project.getSupportRootFolder(), "libraryversions.toml") |
| 40 | ) |
| 41 | val content = project.providers.fileContents(toml) |
| 42 | val composeCustomVersion = project.providers.environmentVariable("COMPOSE_CUSTOM_VERSION") |
| 43 | val composeCustomGroup = project.providers.environmentVariable("COMPOSE_CUSTOM_GROUP") |
| 44 | |
Aurimas Liutikas | d084e36 | 2021-11-19 09:25:43 -0800 | [diff] [blame] | 45 | val serviceProvider = project.gradle.sharedServices.registerIfAbsent( |
| 46 | "libraryVersionsService", |
| 47 | LibraryVersionsService::class.java |
| 48 | ) { spec -> |
Aurimas Liutikas | 9a9efd8 | 2022-02-08 15:21:48 -0800 | [diff] [blame] | 49 | spec.parameters.tomlFile = content.asText |
| 50 | spec.parameters.composeCustomVersion = composeCustomVersion |
| 51 | spec.parameters.composeCustomGroup = composeCustomGroup |
Aurimas Liutikas | d084e36 | 2021-11-19 09:25:43 -0800 | [diff] [blame] | 52 | } |
| 53 | LibraryGroups = serviceProvider.get().libraryGroups |
| 54 | LibraryVersions = serviceProvider.get().libraryVersions |
| 55 | } |
Owen Gray | 74cc259 | 2020-09-24 15:05:40 -0400 | [diff] [blame] | 56 | |
Aurimas Liutikas | 2e85edf | 2021-08-11 14:36:23 -0700 | [diff] [blame] | 57 | var name: Property<String?> = project.objects.property(String::class.java) |
| 58 | fun setName(newName: String) { name.set(newName) } |
Aurimas Liutikas | 75e93a0 | 2019-05-28 16:31:38 -0700 | [diff] [blame] | 59 | var mavenVersion: Version? = null |
| 60 | set(value) { |
Jeff Gaston | ce468a9 | 2020-01-08 12:51:16 -0500 | [diff] [blame] | 61 | field = value |
| 62 | chooseProjectVersion() |
Aurimas Liutikas | 75e93a0 | 2019-05-28 16:31:38 -0700 | [diff] [blame] | 63 | } |
Oussama Ben Abdelbaki | 34f21e0 | 2019-02-27 13:38:27 -0500 | [diff] [blame] | 64 | var mavenGroup: LibraryGroup? = null |
Jeff Gaston | ce468a9 | 2020-01-08 12:51:16 -0500 | [diff] [blame] | 65 | set(value) { |
| 66 | field = value |
| 67 | chooseProjectVersion() |
| 68 | } |
Oussama Ben Abdelbaki | f46b212 | 2020-09-18 11:55:48 -0400 | [diff] [blame] | 69 | private val ALLOWED_EXTRA_PREFIXES = listOf("-alpha", "-beta", "-rc", "-dev", "-SNAPSHOT") |
Alan Viverette | 30a7564 | 2020-02-07 13:09:18 -0500 | [diff] [blame] | 70 | |
Jeff Gaston | ce468a9 | 2020-01-08 12:51:16 -0500 | [diff] [blame] | 71 | private fun chooseProjectVersion() { |
| 72 | val version: Version |
Rahul Ravikumar | fdf66b6 | 2020-08-19 15:08:32 -0700 | [diff] [blame] | 73 | val group: String? = mavenGroup?.group |
Aurimas Liutikas | d084e36 | 2021-11-19 09:25:43 -0800 | [diff] [blame] | 74 | val groupVersion: Version? = mavenGroup?.atomicGroupVersion |
Jeff Gaston | ce468a9 | 2020-01-08 12:51:16 -0500 | [diff] [blame] | 75 | val mavenVersion: Version? = mavenVersion |
| 76 | if (mavenVersion != null) { |
Alan Viverette | 30a7564 | 2020-02-07 13:09:18 -0500 | [diff] [blame] | 77 | if (groupVersion != null && !isGroupVersionOverrideAllowed()) { |
Jeff Gaston | bc5a9b7 | 2020-09-18 14:06:14 -0400 | [diff] [blame] | 78 | throw GradleException( |
| 79 | "Cannot set mavenVersion (" + mavenVersion + |
| 80 | ") for a project (" + project + |
| 81 | ") whose mavenGroup already specifies forcedVersion (" + groupVersion + |
| 82 | ")" |
| 83 | ) |
Jeff Gaston | ce468a9 | 2020-01-08 12:51:16 -0500 | [diff] [blame] | 84 | } else { |
Oussama Ben Abdelbaki | f46b212 | 2020-09-18 11:55:48 -0400 | [diff] [blame] | 85 | verifyVersionExtraFormat(mavenVersion) |
Jeff Gaston | ce468a9 | 2020-01-08 12:51:16 -0500 | [diff] [blame] | 86 | version = mavenVersion |
| 87 | } |
| 88 | } else { |
| 89 | if (groupVersion != null) { |
Oussama Ben Abdelbaki | f46b212 | 2020-09-18 11:55:48 -0400 | [diff] [blame] | 90 | verifyVersionExtraFormat(groupVersion) |
Jeff Gaston | ce468a9 | 2020-01-08 12:51:16 -0500 | [diff] [blame] | 91 | version = groupVersion |
| 92 | } else { |
| 93 | return |
| 94 | } |
| 95 | } |
Rahul Ravikumar | fdf66b6 | 2020-08-19 15:08:32 -0700 | [diff] [blame] | 96 | if (group != null) { |
| 97 | project.group = group |
| 98 | } |
Jeff Gaston | ce468a9 | 2020-01-08 12:51:16 -0500 | [diff] [blame] | 99 | project.version = if (isSnapshotBuild()) version.copy(extra = "-SNAPSHOT") else version |
| 100 | versionIsSet = true |
| 101 | } |
Alan Viverette | 30a7564 | 2020-02-07 13:09:18 -0500 | [diff] [blame] | 102 | |
Oussama Ben Abdelbaki | f46b212 | 2020-09-18 11:55:48 -0400 | [diff] [blame] | 103 | private fun verifyVersionExtraFormat(version: Version) { |
| 104 | val extra = version.extra |
| 105 | if (extra != null) { |
Igor Demin | 0ec97c6 | 2020-10-30 14:27:41 +0300 | [diff] [blame] | 106 | if (!version.isSnapshot() && project.isVersionExtraCheckEnabled()) { |
Oussama Ben Abdelbaki | f46b212 | 2020-09-18 11:55:48 -0400 | [diff] [blame] | 107 | if (ALLOWED_EXTRA_PREFIXES.any { extra.startsWith(it) }) { |
| 108 | for (potentialPrefix in ALLOWED_EXTRA_PREFIXES) { |
| 109 | if (extra.startsWith(potentialPrefix)) { |
| 110 | val secondExtraPart = extra.removePrefix( |
Jeff Gaston | bc5a9b7 | 2020-09-18 14:06:14 -0400 | [diff] [blame] | 111 | potentialPrefix |
| 112 | ) |
Oussama Ben Abdelbaki | f46b212 | 2020-09-18 11:55:48 -0400 | [diff] [blame] | 113 | if (secondExtraPart.toIntOrNull() == null) { |
Jeff Gaston | bc5a9b7 | 2020-09-18 14:06:14 -0400 | [diff] [blame] | 114 | throw IllegalArgumentException( |
| 115 | "Version $version is not" + |
Oussama Ben Abdelbaki | f46b212 | 2020-09-18 11:55:48 -0400 | [diff] [blame] | 116 | " a properly formatted version, please ensure that " + |
Jeff Gaston | bc5a9b7 | 2020-09-18 14:06:14 -0400 | [diff] [blame] | 117 | "$potentialPrefix is followed by a number only" |
| 118 | ) |
Oussama Ben Abdelbaki | f46b212 | 2020-09-18 11:55:48 -0400 | [diff] [blame] | 119 | } |
| 120 | } |
| 121 | } |
| 122 | } else { |
Jeff Gaston | bc5a9b7 | 2020-09-18 14:06:14 -0400 | [diff] [blame] | 123 | throw IllegalArgumentException( |
| 124 | "Version $version is not a proper " + |
Oussama Ben Abdelbaki | f46b212 | 2020-09-18 11:55:48 -0400 | [diff] [blame] | 125 | "version, version suffixes following major.minor.patch should " + |
Jeff Gaston | bc5a9b7 | 2020-09-18 14:06:14 -0400 | [diff] [blame] | 126 | "be one of ${ALLOWED_EXTRA_PREFIXES.joinToString(", ")}" |
| 127 | ) |
Oussama Ben Abdelbaki | f46b212 | 2020-09-18 11:55:48 -0400 | [diff] [blame] | 128 | } |
| 129 | } |
| 130 | } |
| 131 | } |
| 132 | |
Alan Viverette | 30a7564 | 2020-02-07 13:09:18 -0500 | [diff] [blame] | 133 | private fun isGroupVersionOverrideAllowed(): Boolean { |
| 134 | // Grant an exception to the same-version-group policy for artifacts that haven't shipped a |
| 135 | // stable API surface, e.g. 1.0.0-alphaXX, to allow for rapid early-stage development. |
| 136 | val version = mavenVersion |
| 137 | return version != null && version.major == 1 && version.minor == 0 && version.patch == 0 && |
Jeff Gaston | bc5a9b7 | 2020-09-18 14:06:14 -0400 | [diff] [blame] | 138 | version.isAlpha() |
Alan Viverette | 30a7564 | 2020-02-07 13:09:18 -0500 | [diff] [blame] | 139 | } |
| 140 | |
Jeff Gaston | ce468a9 | 2020-01-08 12:51:16 -0500 | [diff] [blame] | 141 | private var versionIsSet = false |
| 142 | fun isVersionSet(): Boolean { |
| 143 | return versionIsSet |
| 144 | } |
Aurimas Liutikas | 92d9756 | 2017-11-13 13:54:27 -0800 | [diff] [blame] | 145 | var description: String? = null |
| 146 | var inceptionYear: String? = null |
Jeff Gaston | bffebcd | 2020-05-28 20:24:38 +0000 | [diff] [blame] | 147 | /** |
| 148 | * targetsJavaConsumers = true, if project is intended to be accessed from Java-language |
| 149 | * source code. |
| 150 | */ |
| 151 | var targetsJavaConsumers = true |
| 152 | get() { |
| 153 | when (project.path) { |
| 154 | // add per-project overrides here |
| 155 | // for example |
| 156 | // the following project is intended to be accessed from Java |
Louis Pullen-Freilich | 2dbfe87 | 2021-03-11 02:47:32 +0000 | [diff] [blame] | 157 | // ":compose:lint:internal-lint-checks" -> return true |
Jeff Gaston | bffebcd | 2020-05-28 20:24:38 +0000 | [diff] [blame] | 158 | // the following project is not intended to be accessed from Java |
| 159 | // ":annotation:annotation" -> return false |
| 160 | } |
Owen Gray | a7530b8 | 2020-09-22 15:07:02 -0400 | [diff] [blame] | 161 | // TODO: rework this to use LibraryType. Fork Library and KolinOnlyLibrary? |
Jeff Gaston | bffebcd | 2020-05-28 20:24:38 +0000 | [diff] [blame] | 162 | if (project.path.contains("-ktx")) return false |
Jeremy Woods | f3d1115 | 2021-05-03 17:08:16 -0700 | [diff] [blame] | 163 | if (project.path.contains("compose")) return false |
Jeff Gaston | bffebcd | 2020-05-28 20:24:38 +0000 | [diff] [blame] | 164 | if (project.path.startsWith(":ui")) return false |
| 165 | return field |
| 166 | } |
Aurimas Liutikas | 92d9756 | 2017-11-13 13:54:27 -0800 | [diff] [blame] | 167 | private var licenses: MutableCollection<License> = ArrayList() |
Alan Viverette | 6a1a0e6 | 2020-06-26 12:48:06 -0400 | [diff] [blame] | 168 | |
Owen Gray | a7530b8 | 2020-09-22 15:07:02 -0400 | [diff] [blame] | 169 | // Should only be used to override LibraryType.publish, if a library isn't ready to publish yet |
Owen Gray | 74cc259 | 2020-09-24 15:05:40 -0400 | [diff] [blame] | 170 | var publish: Publish = Publish.UNSET |
Fred Sladkey | f56f2f5 | 2022-06-13 14:27:14 +0000 | [diff] [blame] | 171 | |
| 172 | internal fun shouldPublish(): Boolean = |
| 173 | if (publish != Publish.UNSET) { |
| 174 | publish.shouldPublish() |
| 175 | } else if (type != LibraryType.UNSET) { |
Fred Sladkey | aee00da | 2022-07-11 14:38:59 -0400 | [diff] [blame] | 176 | type.publish.shouldPublish() |
Fred Sladkey | f56f2f5 | 2022-06-13 14:27:14 +0000 | [diff] [blame] | 177 | } else { |
| 178 | false |
| 179 | } |
| 180 | |
| 181 | internal fun shouldRelease(): Boolean = |
| 182 | if (publish != Publish.UNSET) { |
| 183 | publish.shouldRelease() |
| 184 | } else if (type != LibraryType.UNSET) { |
Fred Sladkey | aee00da | 2022-07-11 14:38:59 -0400 | [diff] [blame] | 185 | type.publish.shouldRelease() |
Fred Sladkey | f56f2f5 | 2022-06-13 14:27:14 +0000 | [diff] [blame] | 186 | } else { |
| 187 | false |
| 188 | } |
| 189 | |
David Saff | d6a966c | 2022-07-26 10:54:47 -0400 | [diff] [blame] | 190 | internal fun ifReleasing(action: () -> Unit) { |
| 191 | project.afterEvaluate { |
| 192 | if (shouldRelease()) { |
| 193 | action() |
| 194 | } |
| 195 | } |
| 196 | } |
| 197 | |
Fred Sladkey | f56f2f5 | 2022-06-13 14:27:14 +0000 | [diff] [blame] | 198 | internal fun isPublishConfigured(): Boolean = ( |
| 199 | publish != Publish.UNSET || |
Fred Sladkey | aee00da | 2022-07-11 14:38:59 -0400 | [diff] [blame] | 200 | type.publish != Publish.UNSET |
Fred Sladkey | f56f2f5 | 2022-06-13 14:27:14 +0000 | [diff] [blame] | 201 | ) |
| 202 | |
Alan Viverette | 6a1a0e6 | 2020-06-26 12:48:06 -0400 | [diff] [blame] | 203 | /** |
| 204 | * Whether to run API tasks such as tracking and linting. The default value is |
| 205 | * [RunApiTasks.Auto], which automatically picks based on the project's properties. |
| 206 | */ |
Owen Gray | a7530b8 | 2020-09-22 15:07:02 -0400 | [diff] [blame] | 207 | // TODO: decide whether we want to support overriding runApiTasks |
| 208 | // @Deprecated("Replaced with AndroidXExtension.type: LibraryType.runApiTasks") |
| 209 | var runApiTasks: RunApiTasks = RunApiTasks.Auto |
Owen Gray | 74cc259 | 2020-09-24 15:05:40 -0400 | [diff] [blame] | 210 | get() = if (field == RunApiTasks.Auto && type != LibraryType.UNSET) type.checkApi else field |
Owen Gray | a7530b8 | 2020-09-22 15:07:02 -0400 | [diff] [blame] | 211 | var type: LibraryType = LibraryType.UNSET |
Fred Sladkey | f56f2f5 | 2022-06-13 14:27:14 +0000 | [diff] [blame] | 212 | set(value) { |
| 213 | // don't disable multiplatform if it's already enabled, because sometimes it's enabled |
| 214 | // through flags and we don't want setting `type =` to disable it accidentally. |
Fred Sladkey | aee00da | 2022-07-11 14:38:59 -0400 | [diff] [blame] | 215 | if (value.shouldEnableMultiplatform()) { |
Fred Sladkey | f56f2f5 | 2022-06-13 14:27:14 +0000 | [diff] [blame] | 216 | multiplatform = true |
| 217 | } |
| 218 | field = value |
| 219 | } |
Alan Viverette | 6f347d7 | 2020-06-10 17:36:22 -0400 | [diff] [blame] | 220 | var failOnDeprecationWarnings = true |
Sergey Vasilinets | e8d12f2 | 2018-07-12 16:32:26 -0700 | [diff] [blame] | 221 | |
Aurimas Liutikas | c53db9a | 2020-10-08 17:22:52 -0700 | [diff] [blame] | 222 | var legacyDisableKotlinStrictApiMode = false |
| 223 | |
Sam Gilbert | 136fa47 | 2021-05-18 09:58:21 -0400 | [diff] [blame] | 224 | var benchmarkRunAlsoInterpreted = false |
| 225 | |
Fred Sladkey | ed2344f | 2022-02-01 18:25:12 -0500 | [diff] [blame] | 226 | var bypassCoordinateValidation = false |
| 227 | |
Alan Viverette | fdbce5c | 2022-03-14 17:00:52 +0000 | [diff] [blame] | 228 | /** |
Alan Viverette | fdbce5c | 2022-03-14 17:00:52 +0000 | [diff] [blame] | 229 | * Whether this project uses KMP. |
Alan Viverette | fdbce5c | 2022-03-14 17:00:52 +0000 | [diff] [blame] | 230 | */ |
Fred Sladkey | f56f2f5 | 2022-06-13 14:27:14 +0000 | [diff] [blame] | 231 | private var multiplatform: Boolean = false |
Jeff Gaston | d72edf2 | 2021-08-24 11:53:54 -0400 | [diff] [blame] | 232 | set(value) { |
| 233 | Multiplatform.setEnabledForProject(project, value) |
Alan Viverette | fdbce5c | 2022-03-14 17:00:52 +0000 | [diff] [blame] | 234 | field = value |
Jeff Gaston | d72edf2 | 2021-08-24 11:53:54 -0400 | [diff] [blame] | 235 | } |
David Saff | 9c2169a | 2021-07-01 10:40:47 -0400 | [diff] [blame] | 236 | |
Aurimas Liutikas | c53db9a | 2020-10-08 17:22:52 -0700 | [diff] [blame] | 237 | fun shouldEnforceKotlinStrictApiMode(): Boolean { |
| 238 | return !legacyDisableKotlinStrictApiMode && |
| 239 | shouldConfigureApiTasks() |
| 240 | } |
| 241 | |
Jim Sproch | b09bbc4 | 2021-01-27 13:53:54 -0800 | [diff] [blame] | 242 | fun license(closure: Closure<Any>): License { |
Aurimas Liutikas | 92d9756 | 2017-11-13 13:54:27 -0800 | [diff] [blame] | 243 | val license = project.configure(License(), closure) as License |
| 244 | licenses.add(license) |
| 245 | return license |
| 246 | } |
| 247 | |
| 248 | fun getLicenses(): Collection<License> { |
| 249 | return licenses |
| 250 | } |
| 251 | |
Ember Rose | c662e1a | 2022-09-16 14:37:50 -0400 | [diff] [blame^] | 252 | fun configureAarAsJarForConfiguration(name: String) { |
| 253 | configureAarAsJarForConfiguration(project, name) |
Aurimas Liutikas | 7d0ea332 | 2022-09-13 18:47:56 -0700 | [diff] [blame] | 254 | } |
| 255 | |
Aurimas Liutikas | 92d9756 | 2017-11-13 13:54:27 -0800 | [diff] [blame] | 256 | companion object { |
Alex Saveau | b50d500 | 2020-07-14 05:25:54 +0000 | [diff] [blame] | 257 | const val DEFAULT_UNSPECIFIED_VERSION = "unspecified" |
Aurimas Liutikas | 92d9756 | 2017-11-13 13:54:27 -0800 | [diff] [blame] | 258 | } |
| 259 | } |
| 260 | |
| 261 | class License { |
| 262 | var name: String? = null |
| 263 | var url: String? = null |
Jake Wharton | 585b8f9 | 2018-07-09 13:34:52 -0400 | [diff] [blame] | 264 | } |
Fred Sladkey | aee00da | 2022-07-11 14:38:59 -0400 | [diff] [blame] | 265 | |
| 266 | private fun LibraryType.shouldEnableMultiplatform() = this is LibraryType.KmpLibrary |