blob: 7ad1d67fc093087cfa8ca4dcd0900e6865ef11e1 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.build.api.variant.impl
import com.android.build.api.artifact.impl.ArtifactsImpl
import com.android.build.api.attributes.ProductFlavorAttr
import com.android.build.api.component.UnitTest
import com.android.build.api.component.impl.ComponentImpl
import com.android.build.api.component.impl.features.BuildConfigCreationConfigImpl
import com.android.build.api.component.impl.features.NativeBuildCreationConfigImpl
import com.android.build.api.component.impl.features.OptimizationCreationConfigImpl
import com.android.build.api.component.impl.features.RenderscriptCreationConfigImpl
import com.android.build.api.component.impl.features.ShadersCreationConfigImpl
import com.android.build.api.component.impl.warnAboutAccessingVariantApiValueForDisabledFeature
import com.android.build.api.variant.AndroidVersion
import com.android.build.api.variant.BuildConfigField
import com.android.build.api.variant.CanMinifyAndroidResourcesBuilder
import com.android.build.api.variant.CanMinifyCodeBuilder
import com.android.build.api.variant.Component
import com.android.build.api.variant.ExternalNativeBuild
import com.android.build.api.variant.HasDeviceTests
import com.android.build.api.variant.HasHostTestsBuilder
import com.android.build.api.variant.ResValue
import com.android.build.api.variant.Variant
import com.android.build.gradle.internal.DependencyConfigurator
import com.android.build.gradle.internal.component.ApkCreationConfig
import com.android.build.gradle.internal.component.VariantCreationConfig
import com.android.build.gradle.internal.component.features.BuildConfigCreationConfig
import com.android.build.gradle.internal.component.features.FeatureNames
import com.android.build.gradle.internal.component.features.ManifestPlaceholdersCreationConfig
import com.android.build.gradle.internal.component.features.NativeBuildCreationConfig
import com.android.build.gradle.internal.component.features.OptimizationCreationConfig
import com.android.build.gradle.internal.component.features.RenderscriptCreationConfig
import com.android.build.gradle.internal.component.features.ShadersCreationConfig
import com.android.build.gradle.internal.core.VariantSources
import com.android.build.gradle.internal.core.dsl.VariantDslInfo
import com.android.build.gradle.internal.dependency.VariantDependencies
import com.android.build.gradle.internal.scope.BuildFeatureValues
import com.android.build.gradle.internal.scope.MutableTaskContainer
import com.android.build.gradle.internal.services.TaskCreationServices
import com.android.build.gradle.internal.services.VariantServices
import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfig
import com.android.build.gradle.internal.variant.BaseVariantData
import com.android.build.gradle.internal.variant.VariantPathHelper
import com.android.builder.core.ComponentTypeImpl
import com.android.utils.appendCapitalized
import com.android.utils.capitalizeAndAppend
import com.google.common.collect.ImmutableMap
import org.gradle.api.file.RegularFile
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Property
import java.io.Serializable
abstract class VariantImpl<DslInfoT: VariantDslInfo>(
open val variantBuilder: VariantBuilderImpl,
buildFeatureValues: BuildFeatureValues,
dslInfo: DslInfoT,
variantDependencies: VariantDependencies,
variantSources: VariantSources,
paths: VariantPathHelper,
artifacts: ArtifactsImpl,
variantData: BaseVariantData,
taskContainer: MutableTaskContainer,
variantServices: VariantServices,
taskCreationServices: TaskCreationServices,
global: GlobalTaskCreationConfig
) : ComponentImpl<DslInfoT>(
variantBuilder,
buildFeatureValues,
dslInfo,
variantDependencies,
variantSources,
paths,
artifacts,
variantData,
taskContainer,
variantServices,
taskCreationServices,
global
), Variant, VariantCreationConfig {
override val description: String
get() = if (componentIdentity.productFlavors.isNotEmpty()) {
val sb = StringBuilder(50)
componentIdentity.buildType?.let { sb.appendCapitalized(it) }
sb.append(" build for flavor ")
componentIdentity.flavorName?.let { sb.appendCapitalized(it) }
sb.toString()
} else {
componentIdentity.buildType!!.capitalizeAndAppend(" build")
}
// ---------------------------------------------------------------------------------------------
// PUBLIC API
// ---------------------------------------------------------------------------------------------
override val minSdk: AndroidVersion by lazy {
variantBuilder.minSdkVersion
}
override val minSdkVersion: AndroidVersion
get() = minSdk
override val maxSdk: Int?
get() = variantBuilder.maxSdk
override val maxSdkVersion: Int?
get() = variantBuilder.maxSdk
override val buildConfigFields: MapProperty<String, BuildConfigField<out Serializable>> by lazy {
buildConfigCreationConfig?.buildConfigFields
?: warnAboutAccessingVariantApiValueForDisabledFeature(
featureName = FeatureNames.BUILD_CONFIG,
apiName = "buildConfigFields",
value = internalServices.mapPropertyOf(
String::class.java,
BuildConfigField::class.java,
dslInfo.buildConfigDslInfo!!.getBuildConfigFields()
)
)
}
override val externalNativeBuild: ExternalNativeBuild?
get() = nativeBuildCreationConfig.externalNativeBuild
override fun <T> getExtension(type: Class<T>): T? =
type.cast(externalExtensions?.get(type))
override val proguardFiles: ListProperty<RegularFile>
get() = optimizationCreationConfig.proguardFiles
/**
* Do Not Use
*
* This API is for backward compatibility, if you need to do work with host tests, iterate
* over all of them using the [hostTests] API. If you only need to have access to unit tests,
* use [hostTests] using [HasHostTestsBuilder.UNIT_TEST_TYPE]
*/
@Deprecated("Use hostTests or getByTestComponentType APIs", ReplaceWith(
"hostTests[HasHostTestsBuilder.UNIT_TEST_TYPE) as? UnitTestImpl",
"com.android.build.api.component.impl.UnitTestImpl"
)
)
@Suppress("DEPRECATION")
override val unitTest: UnitTest?
get() = hostTests().firstOrNull() {
it.componentType == ComponentTypeImpl.UNIT_TEST
} as? UnitTest
// ---------------------------------------------------------------------------------------------
// INTERNAL API
// ---------------------------------------------------------------------------------------------
override val buildConfigCreationConfig: BuildConfigCreationConfig? by lazy(LazyThreadSafetyMode.NONE) {
if (buildFeatures.buildConfig) {
BuildConfigCreationConfigImpl(
this,
dslInfo.buildConfigDslInfo!!,
internalServices
)
} else {
null
}
}
override val renderscriptCreationConfig: RenderscriptCreationConfig? by lazy(LazyThreadSafetyMode.NONE) {
if (buildFeatures.renderScript) {
RenderscriptCreationConfigImpl(
dslInfo.renderscriptDslInfo!!,
internalServices,
renderscriptTargetApi = variantBuilder.renderscriptTargetApi
)
} else {
null
}
}
override val shadersCreationConfig: ShadersCreationConfig by lazy(LazyThreadSafetyMode.NONE) {
ShadersCreationConfigImpl(
dslInfo.shadersDslInfo!!
)
}
override val optimizationCreationConfig: OptimizationCreationConfig by lazy(LazyThreadSafetyMode.NONE) {
OptimizationCreationConfigImpl(
this,
dslInfo.optimizationDslInfo,
variantBuilder as? CanMinifyCodeBuilder,
variantBuilder as? CanMinifyAndroidResourcesBuilder,
internalServices
)
}
override val nativeBuildCreationConfig: NativeBuildCreationConfig by lazy(LazyThreadSafetyMode.NONE) {
NativeBuildCreationConfigImpl(
this,
dslInfo.nativeBuildDslInfo!!,
internalServices
)
}
private val externalExtensions: Map<Class<*>, Any>? by lazy {
variantBuilder.getRegisteredExtensions()
}
override val resValues: MapProperty<ResValue.Key, ResValue> by lazy {
resValuesCreationConfig?.resValues
?: warnAboutAccessingVariantApiValueForDisabledFeature(
featureName = FeatureNames.RES_VALUES,
apiName = "resValues",
value = internalServices.mapPropertyOf(
ResValue.Key::class.java,
ResValue::class.java,
dslInfo.androidResourcesDsl!!.getResValues()
)
)
}
override fun makeResValueKey(type: String, name: String): ResValue.Key = ResValueKeyImpl(type, name)
override val pseudoLocalesEnabled: Property<Boolean> by lazy {
androidResourcesCreationConfig?.pseudoLocalesEnabled
?: warnAboutAccessingVariantApiValueForDisabledFeature(
featureName = FeatureNames.ANDROID_RESOURCES,
apiName = "pseudoLocalesEnabled",
value = internalServices.newPropertyBackingDeprecatedApi(
Boolean::class.java,
dslInfo.androidResourcesDsl!!.isPseudoLocalesEnabled
)
)
}
override val experimentalProperties: MapProperty<String, Any> =
internalServices.mapPropertyOf(
String::class.java,
Any::class.java,
dslInfo.experimentalProperties,
disallowUnsafeRead = false
)
override val nestedComponents: List<ComponentImpl<*>>
get() = mutableListOf<ComponentImpl<*>>().also { list ->
(this as? HasTestFixtures)?.testFixtures?.let {
list.add(it)
}
list.addAll(deviceTests())
list.addAll(hostTests())
}
override val components: List<Component>
get() = mutableListOf<Component>(
this,
).also {
it.addAll(nestedComponents)
}
override val manifestPlaceholders: MapProperty<String, String>
get() = manifestPlaceholdersCreationConfig.placeholders
override val manifestPlaceholdersCreationConfig: ManifestPlaceholdersCreationConfig by lazy(LazyThreadSafetyMode.NONE) {
createManifestPlaceholdersCreationConfig(
dslInfo.manifestPlaceholdersDslInfo?.placeholders)
}
override val codeCoverageEnabled: Boolean
get() = (this as? HasDeviceTests)?.deviceTests?.any { it.codeCoverageEnabled } ?: false
override val isCoreLibraryDesugaringEnabledLintCheck: Boolean
get() = if (this is ApkCreationConfig) {
dexing.isCoreLibraryDesugaringEnabled
} else {
// We don't dex library variants, but we still need to check if core library desugaring
// for lint checks.
global.compileOptions.isCoreLibraryDesugaringEnabled
}
override fun missingDimensionStrategy(dimension: String, vararg requestedValues: String) {
val attributeKey = ProductFlavorAttr.of(dimension)
val attributeValue: ProductFlavorAttr = services.named(
ProductFlavorAttr::class.java, name
)
variantDependencies.compileClasspath.attributes.attribute(attributeKey, attributeValue)
variantDependencies.runtimeClasspath.attributes.attribute(attributeKey, attributeValue)
variantDependencies
.annotationProcessorConfiguration
?.attributes
?.attribute(attributeKey, attributeValue)
// then add the fallbacks which contain the actual requested value
DependencyConfigurator.addFlavorStrategy(
services.dependencies.attributesSchema,
dimension,
ImmutableMap.of(name, requestedValues.toList())
)
}
private fun deviceTests(): List<ComponentImpl<*>> =
(this as? HasDeviceTests)?.deviceTests?.map { it as ComponentImpl<*> }
?: listOf()
private fun hostTests(): List<ComponentImpl<*>> =
(this as? HasHostTestsCreationConfig)?.hostTests?.values?.map { it as ComponentImpl<*> }
?: listOf()
}