1 /* <lambda>null2 * Copyright 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 package androidx.baselineprofile.gradle.consumer 18 19 import androidx.baselineprofile.gradle.configuration.ConfigurationManager 20 import androidx.baselineprofile.gradle.consumer.task.GenerateBaselineProfileTask 21 import androidx.baselineprofile.gradle.consumer.task.MainGenerateBaselineProfileTaskForAgp80Only 22 import androidx.baselineprofile.gradle.consumer.task.MergeBaselineProfileTask 23 import androidx.baselineprofile.gradle.consumer.task.PrintConfigurationForVariantTask 24 import androidx.baselineprofile.gradle.consumer.task.PrintMapPropertiesForVariantTask 25 import androidx.baselineprofile.gradle.utils.AgpFeature 26 import androidx.baselineprofile.gradle.utils.AgpPlugin 27 import androidx.baselineprofile.gradle.utils.AgpPluginId 28 import androidx.baselineprofile.gradle.utils.BUILD_TYPE_BASELINE_PROFILE_PREFIX 29 import androidx.baselineprofile.gradle.utils.BUILD_TYPE_BENCHMARK_PREFIX 30 import androidx.baselineprofile.gradle.utils.CONFIGURATION_NAME_BASELINE_PROFILES 31 import androidx.baselineprofile.gradle.utils.INTERMEDIATES_BASE_FOLDER 32 import androidx.baselineprofile.gradle.utils.KOTLIN_MULTIPLATFORM_PLUGIN_ID 33 import androidx.baselineprofile.gradle.utils.KotlinMultiPlatformUtils 34 import androidx.baselineprofile.gradle.utils.MAX_AGP_VERSION_RECOMMENDED_EXCLUSIVE 35 import androidx.baselineprofile.gradle.utils.MIN_AGP_VERSION_REQUIRED_INCLUSIVE 36 import androidx.baselineprofile.gradle.utils.R8Utils 37 import androidx.baselineprofile.gradle.utils.RELEASE 38 import androidx.baselineprofile.gradle.utils.camelCase 39 import androidx.baselineprofile.gradle.utils.namedOrNull 40 import com.android.build.api.dsl.ApplicationExtension 41 import com.android.build.api.dsl.LibraryExtension 42 import com.android.build.api.variant.ApplicationVariant 43 import com.android.build.api.variant.ApplicationVariantBuilder 44 import com.android.build.api.variant.Variant 45 import org.gradle.api.GradleException 46 import org.gradle.api.Plugin 47 import org.gradle.api.Project 48 import org.gradle.api.Task 49 import org.gradle.api.artifacts.Configuration 50 import org.gradle.api.tasks.TaskContainer 51 52 /** 53 * This is the consumer plugin for baseline profile generation. In order to generate baseline 54 * profiles three plugins are needed: one is applied to the app or the library that should consume 55 * the baseline profile when building (consumer), one is applied to the module that should supply 56 * the under test app (app target) and the last one is applied to a test module containing the ui 57 * test that generate the baseline profile on the device (producer). 58 */ 59 class BaselineProfileConsumerPlugin : Plugin<Project> { 60 override fun apply(project: Project) = BaselineProfileConsumerAgpPlugin(project).onApply() 61 } 62 63 private class BaselineProfileConsumerAgpPlugin(private val project: Project) : 64 AgpPlugin( 65 project = project, 66 supportedAgpPlugins = 67 setOf(AgpPluginId.ID_ANDROID_APPLICATION_PLUGIN, AgpPluginId.ID_ANDROID_LIBRARY_PLUGIN), 68 minAgpVersionInclusive = MIN_AGP_VERSION_REQUIRED_INCLUSIVE, 69 maxAgpVersionExclusive = MAX_AGP_VERSION_RECOMMENDED_EXCLUSIVE 70 ) { 71 72 // List of the non debuggable build types 73 private val nonDebuggableBuildTypes = mutableListOf<String>() 74 75 // The baseline profile consumer extension to access non-variant specific configuration options 76 private val baselineProfileExtension = BaselineProfileConsumerExtension.register(project) 77 78 // Offers quick access to configuration extension, hiding the property override and merge logic 79 private val perVariantBaselineProfileExtensionManager = 80 PerVariantConsumerExtensionManager(baselineProfileExtension) 81 82 // Manages creation of configurations 83 private val configurationManager = ConfigurationManager(project) 84 85 // Manages r8 properties 86 private val r8Utils = R8Utils(project) 87 88 // Global baseline profile configuration. Note that created here it can be directly consumed 89 // in the dependencies block. 90 private val mainBaselineProfileConfiguration = 91 configurationManager.maybeCreate( 92 nameParts = listOf(CONFIGURATION_NAME_BASELINE_PROFILES), 93 canBeConsumed = false, 94 canBeResolved = true, 95 buildType = null, 96 productFlavors = null 97 ) 98 99 private val Variant.benchmarkVariantName: String 100 get() { 101 val parts = <lambda>null102 listOfNotNull(flavorName, BUILD_TYPE_BENCHMARK_PREFIX, buildType).filter { 103 it.isNotBlank() 104 } 105 return camelCase(*parts.toTypedArray()) 106 } 107 onAgpPluginNotFoundnull108 override fun onAgpPluginNotFound(pluginIds: Set<AgpPluginId>) { 109 throw IllegalStateException( 110 """ 111 The module ${project.name} does not have the `com.android.application` or 112 `com.android.library` plugin applied. The `androidx.baselineprofile.consumer` 113 plugin supports only android application and library modules. Please review 114 your build.gradle to ensure this plugin is applied to the correct module. 115 """ 116 .trimIndent() 117 ) 118 } 119 onAgpPluginFoundnull120 override fun onAgpPluginFound(pluginIds: Set<AgpPluginId>) { 121 project.logger.debug( 122 """ 123 [BaselineProfileConsumerPlugin] afterEvaluate check: app or library plugin was applied 124 """ 125 .trimIndent() 126 ) 127 } 128 onApplicationFinalizeDslnull129 override fun onApplicationFinalizeDsl(extension: ApplicationExtension) { 130 131 // Here we select the build types we want to process if this is an application, 132 // i.e. non debuggable build types that have not been created by the app target plugin. 133 // Also exclude the build types starting with baseline profile prefix, in case the app 134 // target plugin is also applied. 135 136 nonDebuggableBuildTypes.addAll( 137 extension.buildTypes 138 .filter { 139 !it.isDebuggable && 140 !it.name.startsWith(BUILD_TYPE_BASELINE_PROFILE_PREFIX) && 141 !it.name.startsWith(BUILD_TYPE_BENCHMARK_PREFIX) 142 } 143 .map { it.name } 144 ) 145 } 146 onLibraryFinalizeDslnull147 override fun onLibraryFinalizeDsl(extension: LibraryExtension) { 148 149 // Here we select the build types we want to process if this is a library. 150 // Libraries don't have a `debuggable` flag. Also we don't need to exclude build types 151 // prefixed with the baseline profile prefix. Ideally on the `debug` type should be 152 // excluded. 153 154 nonDebuggableBuildTypes.addAll( 155 extension.buildTypes.filter { it.name != "debug" }.map { it.name } 156 ) 157 } 158 getWarningsnull159 override fun getWarnings() = baselineProfileExtension.warnings 160 161 override fun onApplicationBeforeVariants(variantBuilder: ApplicationVariantBuilder) { 162 163 // Note that the lifecycle is for each variant `beforeVariant`, `onVariant`. This means 164 // that the `onVariant` for the base variants of the module (for example `release`) will 165 // run before `beforeVariant` of `benchmarkRelease` and `nonMinifiedRelease`. 166 // Since we schedule some callbacks in for benchmark and nonMinified variants in the 167 // onVariant callback for the base variants, this is the place where we can remove them, 168 // in case the benchmark and nonMinified variants have been disabled. 169 170 val isBaselineProfilePluginCreatedBuildType = 171 isBaselineProfilePluginCreatedBuildType(variantBuilder.buildType) 172 173 // Note that the callback should be remove at the end, after all the variants 174 // have been processed. This is because the benchmark and nonMinified variants can be 175 // disabled at any point AFTER the plugin has been applied. So checking immediately here 176 // would tell us that the variant is enabled, while it could be disabled later. 177 afterVariants { 178 if (!variantBuilder.enable && isBaselineProfilePluginCreatedBuildType) { 179 removeOnVariantCallback(variantBuilder.name) 180 logger.warn( 181 property = { disabledVariants }, 182 propertyName = "disabledVariants", 183 message = 184 "Variant `${variantBuilder.name}` is disabled. If this " + 185 "is not intentional, please check your gradle configuration " + 186 "for beforeVariants blocks. For more information on variant " + 187 "filters checkout the docs at https://developer.android.com/" + 188 "build/build-variants#filter-variants." 189 ) 190 } 191 } 192 } 193 194 @Suppress("UnstableApiUsage") onVariantsnull195 override fun onVariants(variant: Variant) { 196 197 // For test only: this registers a print task with the experimental properties of the 198 // variant. This task is hidden from the `tasks` command. 199 PrintMapPropertiesForVariantTask.registerForVariant(project = project, variant = variant) 200 201 // Controls whether Android Studio should see this variant. Variants created by the 202 // baseline profile gradle plugin are hidden by default. 203 if ( 204 baselineProfileExtension.hideSyntheticBuildTypesInAndroidStudio && 205 isBaselineProfilePluginCreatedBuildType(variant.buildType) 206 ) { 207 variant.experimentalProperties.put("androidx.baselineProfile.hideInStudio", true) 208 } 209 210 // From here on, process only the non debuggable build types we previously selected. 211 if (variant.buildType !in nonDebuggableBuildTypes) return 212 213 // This allows quick access to this variant configuration according to the override 214 // and merge rules implemented in the PerVariantConsumerExtensionManager. 215 val variantConfiguration = perVariantBaselineProfileExtensionManager.variant(variant) 216 217 // For test only: this registers a print task with the configuration of the variant. 218 // This task is hidden from the `tasks` command. 219 PrintConfigurationForVariantTask.registerForVariant( 220 project = project, 221 variant = variant, 222 variantConfig = variantConfiguration 223 ) 224 225 // Sets the r8 rewrite baseline profile for the non debuggable variant. 226 variantConfiguration.baselineProfileRulesRewrite?.let { 227 r8Utils.setRulesRewriteForVariantEnabled(variant, it) 228 } 229 230 // Sets the r8 startup dex optimization profile for the non debuggable variant. 231 variantConfiguration.dexLayoutOptimization?.let { 232 r8Utils.setDexLayoutOptimizationEnabled(variant, it) 233 } 234 235 // Check if this variant has any direct dependency 236 val variantDependencies = variantConfiguration.dependencies 237 238 // Creates the configuration to carry the specific variant artifact 239 val baselineProfileConfiguration = 240 createConfigurationForVariant( 241 variant = variant, 242 mainConfiguration = mainBaselineProfileConfiguration 243 ) 244 245 // Adds the custom dependencies for baseline profiles. Note that dependencies 246 // for global, build type, flavor and variant specific are all merged. 247 variantDependencies.forEach { 248 val targetProjectDependency = project.dependencyFactory.create(it) 249 baselineProfileConfiguration.dependencies.add(targetProjectDependency) 250 } 251 252 // There are 2 different ways in which the output task can merge the baseline 253 // profile rules, according to [BaselineProfileConsumerExtension#mergeIntoMain]. 254 // When mergeIntoMain is `true` the first variant will create a task shared across 255 // all the variants to merge, while the next variants will simply add the additional 256 // baseline profile artifacts, modifying the existing task. 257 // When mergeIntoMain is `false` each variants has its own task with a single 258 // artifact per task, specific for that variant. 259 // When mergeIntoMain is not specified, it's by default true for libraries and false 260 // for apps. 261 262 // Warning: support for baseline profile source sets in library module was added with 263 // agp 8.3.0 alpha 15 (b/309858620). Therefore, before then, we can only always merge into 264 // main and always output only in src/main/baseline-prof.txt. 265 val forceOutputInSrcMain = 266 isLibraryModule() && 267 !supportsFeature(AgpFeature.LIBRARY_MODULE_SUPPORTS_BASELINE_PROFILE_SOURCE_SETS) 268 269 val mergeIntoMain = 270 if (forceOutputInSrcMain) { 271 true 272 } else { 273 variantConfiguration.mergeIntoMain ?: isLibraryModule() 274 } 275 276 // Determines the target name for the Android target in kotlin multiplatform projects. 277 // Note that KotlinMultiPlatformUtils references the kmp extension that exists only if the 278 // multiplatform plugin has been applied. 279 val androidTargetName = 280 if (project.plugins.hasPlugin(KOTLIN_MULTIPLATFORM_PLUGIN_ID)) { 281 KotlinMultiPlatformUtils.androidTargetName(project) 282 } else { 283 "" 284 } 285 286 // This part changes according to the AGP version of the module. `mergeIntoMain` merges 287 // the profile of the generated profile for this variant into the main one. This can be 288 // applied to the `main` configuration or to single variants. On Agp 8.0, since it's not 289 // possible to run tests on multiple build types in the same run, when `mergeIntoMain` is 290 // true only variants of the specific build type invoked are merged. This means that on 291 // AGP 8.0 the `main` baseline profile is generated by only the build type `release` when 292 // calling `generateReleaseBaselineProfiles`. On Agp 8.1 instead, it works as intended and 293 // we can merge all the variants with `mergeIntoMain` true, independently from the build 294 // type. 295 data class TaskAndFolderName(val taskVariantName: String, val folderVariantName: String) 296 val (mergeAwareTaskName, mergeAwareVariantOutput) = 297 if (mergeIntoMain) { 298 if (supportsFeature(AgpFeature.TEST_MODULE_SUPPORTS_MULTIPLE_BUILD_TYPES)) { 299 TaskAndFolderName( 300 taskVariantName = "", 301 folderVariantName = camelCase(androidTargetName, "main") 302 ) 303 } else { 304 // Note that the exception here cannot happen because all the variants have a 305 // build 306 // type in Android. 307 TaskAndFolderName( 308 taskVariantName = 309 variant.buildType 310 ?: throw IllegalStateException("Found variant without build type."), 311 folderVariantName = camelCase(androidTargetName, "main") 312 ) 313 } 314 } else { 315 TaskAndFolderName( 316 taskVariantName = variant.name, 317 folderVariantName = camelCase(androidTargetName, variant.name) 318 ) 319 } 320 321 // Creates the task to merge the baseline profile artifacts coming from 322 // different configurations. 323 val mergedTaskOutputDir = 324 project.layout.buildDirectory.dir( 325 "$INTERMEDIATES_BASE_FOLDER/$mergeAwareVariantOutput/merged" 326 ) 327 328 val mergeTaskProvider = 329 MergeBaselineProfileTask.maybeRegisterForMerge( 330 project = project, 331 variantName = variant.name, 332 mergeAwareTaskName = mergeAwareTaskName, 333 hasDependencies = baselineProfileConfiguration.allDependencies.isNotEmpty(), 334 sourceProfilesFileCollection = baselineProfileConfiguration, 335 outputDir = mergedTaskOutputDir, 336 filterRules = variantConfiguration.filterRules, 337 library = isLibraryModule(), 338 warnings = baselineProfileExtension.warnings, 339 340 // Note that the merge task is the last task only if saveInSrc is disabled. When 341 // saveInSrc is enabled an additional task is created to copy the profile in the 342 // sources 343 // folder. 344 isLastTask = !variantConfiguration.saveInSrc 345 ) 346 347 // If `saveInSrc` is true, we create an additional task to copy the output 348 // of the merge task in the src folder. 349 val lastTaskProvider = 350 if (variantConfiguration.saveInSrc) { 351 352 // Here we determine where the final baseline profile file should be placed. 353 // Before AGP 8.3.0 alpha 15, libraries don't support source sets so we can only 354 // output in src/main/baseline-prof.txt. Variable `shouldOutputInSrcMain` defined 355 // above, controls this behavior. Note that `mergeAwareVariantOutput` is always 356 // `main` 357 // when `shouldOutputInSrcMain` is true 358 var srcOutputDir = 359 project.layout.projectDirectory.dir("src/$mergeAwareVariantOutput/") 360 if (!forceOutputInSrcMain) { 361 val baselineProfileOutputDir = 362 perVariantBaselineProfileExtensionManager 363 .variant(variant) 364 .baselineProfileOutputDir 365 srcOutputDir = srcOutputDir.dir("$baselineProfileOutputDir/") 366 } 367 368 // This task copies the baseline profile generated from the merge task. 369 // Note that we're reutilizing the [MergeBaselineProfileTask] because 370 // if the flag `mergeIntoMain` is true tasks will have the same name 371 // and we just want to add more file to copy to the same output. This is 372 // already handled in the MergeBaselineProfileTask. 373 val copyTaskProvider = 374 MergeBaselineProfileTask.maybeRegisterForCopy( 375 project = project, 376 variantName = variant.name, 377 mergeAwareTaskName = mergeAwareTaskName, 378 library = isLibraryModule(), 379 sourceDir = mergeTaskProvider.flatMap { it.baselineProfileDir }, 380 outputDir = project.provider { srcOutputDir }, 381 hasDependencies = baselineProfileConfiguration.allDependencies.isNotEmpty(), 382 isLastTask = true, 383 warnings = baselineProfileExtension.warnings 384 ) 385 386 // Applies the source path for this variant. Note that this doesn't apply when the 387 // output is src/main/baseline-prof.txt. 388 if (!forceOutputInSrcMain) { 389 390 val srcOutputDirPath = srcOutputDir.asFile.apply { mkdirs() }.absolutePath 391 fun applySourceSets(variant: Variant) { 392 variant.sources.baselineProfiles?.addStaticSourceDirectory(srcOutputDirPath) 393 } 394 applySourceSets(variant) 395 396 // For apps the source set needs to be applied to both the current variant 397 // (for example `release`) and its benchmark version. 398 if ( 399 isApplicationModule() && 400 supportsFeature(AgpFeature.TEST_MODULE_SUPPORTS_MULTIPLE_BUILD_TYPES) 401 ) { 402 onVariant(variant.benchmarkVariantName) { v: ApplicationVariant -> 403 applySourceSets(v) 404 } 405 } 406 } 407 408 // If this is an application, we need to ensure that: 409 // If `automaticGenerationDuringBuild` is true, building a release build 410 // should trigger the generation of the profile. This is done through a 411 // dependsOn rule. 412 // If `automaticGenerationDuringBuild` is false and the user calls both 413 // tasks to generate and assemble, assembling the release should wait of the 414 // generation to be completed. This is done through a `mustRunAfter` rule. 415 // Depending on whether the flag `automaticGenerationDuringBuild` is enabled 416 // Note that we cannot use the variant src set api 417 // `addGeneratedSourceDirectory` since that overwrites the outputDir, 418 // that would be re-set in the build dir. 419 // Also this is specific for applications: doing this for a library would 420 // trigger a circular task dependency since the library would require 421 // the profile in order to build the aar for the sample app and generate 422 // the profile. 423 424 val automaticGeneration = 425 perVariantBaselineProfileExtensionManager 426 .variant(variant) 427 .automaticGenerationDuringBuild 428 429 if (automaticGeneration && isLibraryModule() && !isGradleSyncRunning()) { 430 throw IllegalStateException( 431 "The flag `automaticGenerationDuringBuild` is not compatible with library " + 432 "modules. Please remove the flag `automaticGenerationDuringBuild` in " + 433 "your com.android.library module ${project.name}." 434 ) 435 } 436 437 if (isApplicationModule()) { 438 // Defines a function to apply the baseline profile source sets to a variant. 439 fun applySourceSets(variantName: String) { 440 441 // These dependencies causes a circular task dependency when the producer 442 // points to a consumer that does not have the appTarget plugin. 443 // Note that on old versions of AGP these tasks may not exist. 444 listOfNotNull( 445 project.tasks.taskMergeArtProfile(variantName), 446 project.tasks.taskMergeStartupProfile(variantName) 447 ) 448 .forEach { 449 it.configure { t -> 450 if (automaticGeneration) { 451 t.dependsOn(copyTaskProvider) 452 } else { 453 t.mustRunAfter(copyTaskProvider) 454 } 455 } 456 } 457 } 458 459 afterVariants { 460 461 // Apply the source sets to the variant. 462 applySourceSets(variant.name) 463 464 // Apply the source sets to the benchmark variant if supported. 465 if (supportsFeature(AgpFeature.TEST_MODULE_SUPPORTS_MULTIPLE_BUILD_TYPES)) { 466 applySourceSets(variant.benchmarkVariantName) 467 } 468 } 469 } 470 471 // In this case the last task is the copy task. 472 copyTaskProvider 473 } else { 474 475 if (variantConfiguration.automaticGenerationDuringBuild) { 476 477 // If the flag `automaticGenerationDuringBuild` is true, we can set the 478 // merge task to provide generated sources for the variant, using the 479 // src set variant api. This means that we don't need to manually depend 480 // on the merge or prepare art profile task. 481 482 // Defines a function to apply the baseline profile source sets to a variant. 483 fun applySourceSets(v: Variant) { 484 v.sources.baselineProfiles?.addGeneratedSourceDirectory( 485 taskProvider = mergeTaskProvider, 486 wiredWith = MergeBaselineProfileTask::baselineProfileDir 487 ) 488 } 489 490 // Apply the source sets to the variant. 491 applySourceSets(variant) 492 493 // Apply the source sets to the benchmark variant if supported and this the 494 // consumer is an app (libraries don't have benchmark type). 495 if ( 496 isApplicationModule() && 497 supportsFeature(AgpFeature.TEST_MODULE_SUPPORTS_MULTIPLE_BUILD_TYPES) 498 ) { 499 500 // Note that there is no way to access directly a specific variant, so we 501 // schedule a callback for later, when the variant is processed. Note that 502 // because the benchmark build type is created after the baseline profile 503 // build type, its variants will also come after the ones for baseline 504 // profile. 505 onVariant(variant.benchmarkVariantName) { v: ApplicationVariant -> 506 applySourceSets(v) 507 } 508 } 509 } else { 510 511 // This is the case of `saveInSrc` and `automaticGenerationDuringBuild` 512 // both false, that is unsupported. In this case we simply throw an 513 // error. 514 if (!isGradleSyncRunning()) { 515 throw GradleException( 516 """ 517 The current configuration of flags `saveInSrc` and `automaticGenerationDuringBuild` 518 is not supported. At least one of these should be set to `true`. Please review your 519 baseline profile plugin configuration in your build.gradle. 520 """ 521 .trimIndent() 522 ) 523 } 524 } 525 526 // In this case the last task is the merge task. 527 mergeTaskProvider 528 } 529 530 // Here we create the final generate task that triggers the whole generation for this 531 // variant and all the parent tasks. For this one the child task is either copy or merge, 532 // depending on the configuration. 533 GenerateBaselineProfileTask.maybeCreate( 534 project = project, 535 variantName = mergeAwareTaskName, 536 lastTaskProvider = lastTaskProvider 537 ) 538 539 // Create the build type task. For example `generateReleaseBaselineProfile` 540 // The variant name is equal to the build type name if there are no flavors. 541 // Note that if `mergeIntoMain` is `true` the build type task already exists. 542 if ( 543 !mergeIntoMain && 544 !variant.buildType.isNullOrBlank() && 545 variant.buildType != variant.name 546 ) { 547 GenerateBaselineProfileTask.maybeCreate( 548 project = project, 549 variantName = variant.buildType!!, 550 lastTaskProvider = lastTaskProvider 551 ) 552 } 553 554 if (supportsFeature(AgpFeature.TEST_MODULE_SUPPORTS_MULTIPLE_BUILD_TYPES)) { 555 556 // Generate a flavor task for the assembled flavor name and each flavor dimension. 557 // For example for variant `freeRelease` (build type `release`, flavor `free`): 558 // `generateFreeBaselineProfile`. 559 // For example for variant `freeRedRelease` (build type `release`, flavor dimensions 560 // `free` and `red`): `generateFreeBaselineProfile`, `generateRedBaselineProfile` and 561 // `generateFreeRedBaselineProfile`. 562 if (!mergeIntoMain) { 563 listOfNotNull( 564 variant.flavorName, 565 *variant.productFlavors.map { it.second }.toTypedArray() 566 ) 567 .filter { it != variant.name && it.isNotBlank() } 568 .toSet() 569 .forEach { 570 GenerateBaselineProfileTask.maybeCreate( 571 project = project, 572 variantName = it, 573 lastTaskProvider = lastTaskProvider 574 ) 575 } 576 } 577 578 // Generate the main global tasks `generateBaselineProfile 579 GenerateBaselineProfileTask.maybeCreate( 580 project = project, 581 variantName = "", 582 lastTaskProvider = lastTaskProvider 583 ) 584 } else { 585 // Due to b/265438201 we cannot have a global task `generateBaselineProfile` that 586 // triggers generation for all the variants when there are multiple build types. 587 // So for version of AGP that don't support that, invoking `generateBaselineProfile` 588 // will run generation for `release` build type only, that is the same behavior of 589 // `generateReleaseBaselineProfile`. For this same reason we cannot have a flavor 590 // task, such as `generateFreeBaselineProfile` because that would run generation for 591 // all the build types with flavor free, that is not as well supported. 592 if (variant.buildType == RELEASE) { 593 MainGenerateBaselineProfileTaskForAgp80Only.maybeCreate( 594 project = project, 595 variantName = "", 596 lastTaskProvider = lastTaskProvider, 597 warnings = baselineProfileExtension.warnings 598 ) 599 } 600 } 601 } 602 TaskContainernull603 fun TaskContainer.taskMergeArtProfile(variantName: String) = 604 project.tasks.namedOrNull<Task>("merge", variantName, "artProfile") 605 606 fun TaskContainer.taskMergeStartupProfile(variantName: String) = 607 project.tasks.namedOrNull<Task>("merge", variantName, "startupProfile") 608 609 private fun createConfigurationForVariant(variant: Variant, mainConfiguration: Configuration) = 610 configurationManager.maybeCreate( 611 nameParts = listOf(variant.name, CONFIGURATION_NAME_BASELINE_PROFILES), 612 canBeResolved = true, 613 canBeConsumed = false, 614 extendFromConfigurations = listOf(mainConfiguration), 615 buildType = variant.buildType ?: "", 616 productFlavors = variant.productFlavors 617 ) 618 619 private fun isBaselineProfilePluginCreatedBuildType(buildType: String?) = 620 buildType?.let { 621 it.startsWith(BUILD_TYPE_BASELINE_PROFILE_PREFIX) || 622 it.startsWith(BUILD_TYPE_BENCHMARK_PREFIX) 623 } ?: false 624 } 625