Configure publication variants

Publication variants let you create a more customized experience for your users. Configuring publication variants lets you publish different build variants, each with its own attributes.

Publishing multiple build variants of your library lets your user choose the appropriate features for their needs. For example, you can publish different artifacts for the debug versus release build types. The debug publication artifact might have extra logging code and different dependencies to enable this extra logging.

Before you proceed, make sure you prepare your library for release.

Use Gradle Module Metadata

In order to publish variants of your library, you must use Gradle Module Metadata (GMM). GMM describes your publication and maintains variant-aware dependency management. GMM is published with your library by default.

The benefits of using GMM include:

  • If you use GMM with Gradle 6.0 or higher, you can publish multiple publication variants or multiple artifacts—each with its own attributes and dependencies. If you use Maven's POM file instead of GMM, you can only publish one artifact. If you use a POM file, you can publish additional artifacts using classifiers, but the additional artifacts can't have their own dependencies.
  • Gradle automatically creates one variant for compilation and one for runtime, each with its own dependencies. You might publish one variant for compilation and one for runtime, so the consumer can choose based on when they are using your library. GMM lets consumers see different dependencies for compile and runtime, based on the published library's usage of api, implementation, or compileOnly/runtimeOnly. See Dependency configurations for a full list of dependencies. This is available even if you publish a single publication variant.
  • When using test fixtures, you can publish an additional variant with special metadata or capabilities that let the consumer select it. This is available even if you publish a single publication variant.

Understand publication variants

To understand how publication variants work, it is helpful to be familiar with Gradle's basic publishing steps. Here are some publication key concepts:

  • Build variant: The configuration Gradle uses to build your library, which is the cross product of build type and product flavor. To learn more, see the Android build glossary.
  • Artifact: A file or directory that a build produces. In the context of library publishing, an artifact is usually a JAR or AAR file.
  • Publication variant: An artifact with its associated attributes, features, and dependencies. Note that Gradle calls publication variants variants. However, they are called publication variants in these docs to distinguish them from build variants.
  • Attribute: Gradle uses attributes to identify and select publication variants when there are multiple options. For example, org.gradle.usage=java-api and org.gradle.jvm.version=11 are variant attributes.
  • Software component: A Gradle object that can hold one or more publication variants and is published to a single set of Maven coordinates (groupdId:artifactId:version). It is exposed in Gradle's DSL through Project.getComponents().
  • Publication: What gets published to the repository and consumers use. Publications consist of one software component and its metadata-for instance, its identity (groupId:artifactId:version).

The Android Gradle plugin (AGP) 7.1 introduces a domain-specific language (DSL) to control which build variants are used during publication and which are ignored. The DSL lets you create instances of SoftwareComponent that contain either of the following:

  • One publication variant from one build variant
  • Several publication variants from several build variants

When creating a software component with multiple publication variants, AGP sets up attributes on each variant that let the consumer select the appropriate variant they need. These attributes come directly from the build type and flavors used to create the build variant. Creating a component with a single publication variant doesn't require attributes because there's no need to distinguish.

Create a software component with a single publication variant

The following snippet configures a software component with a single publication variant created from the release build variant and adds the source JAR as a secondary artifact:

Kotlin

android {
  publishing {
    singleVariant("release") {
        withSourcesJar()
    }
  }
}

Groovy

android {
  publishing {
    singleVariant('release') {
        withSourcesJar()
    }
  }
}

You can create several components, each with a single publication variant, and distribute them under different Maven coordinates. In this case, attributes aren't set on the publication variant. You can't tell that this publication variant is from the release build variant by looking at the publication metadata. Since there's only one publication variant involved, there's no need for disambiguation.

Create a software component with multiple publication variants

You can select all or a subset of build variants to put in a single software component. AGP automatically uses the build type names, product flavor names, and product flavor dimension names to create attributes so that the consuming project can distinguish between them.

To publish all build variants in a single component, specify allVariants() in the multipleVariants{} block in the module-level build.gradle file:

Kotlin

android {
  publishing {
    multipleVariants {
      allVariants()
      withJavadocJar()
    }
  }
}

Groovy

android {
  publishing {
    multipleVariants {
      allVariants()
      withJavadocJar()
    }
  }
}

This creates a single component called default. To name your component something else, use multipleVariants({name}). In this case, all build type and product flavor dimensions are used as attributes.

You can also select which variants are published by using includeBuildTypeValues() and includeFlavorDimensionAndValues():

Kotlin

android {
  publishing {
    multipleVariants("custom") {
      includeBuildTypeValues("debug", "release")
      includeFlavorDimensionAndValues(
        dimension = "color",
        values = arrayOf("blue", "pink")
      )
        includeFlavorDimensionAndValues(
          dimension = "shape",
          values = arrayOf("square")
      )
    }
  }
}

Groovy

android {
  publishing {
    multipleVariants('custom') {
      includeBuildTypeValues('debug', 'release')
      includeFlavorDimensionAndValues(
        /*dimension =*/ 'color',
        /*values =*/ 'blue', 'pink'
      )
      includeFlavorDimensionAndValues(
        /*dimension =*/ 'shape',
        /*values =*/ 'square'
      )
    }
  }
}

In this example, the custom component contains all the combinations of (debug, release) for build type, (blue, pink) for the dimension color, and (square) for the dimension shape .

All flavor dimensions must be listed, even if you are only publishing one value from a dimension, so AGP knows which value to use for every dimension.

The following table lists the resulting publication variants and their associated attributes.

Variant Attributes
blueSquareDebug com.android.build.api.attributes.BuildTypeAttr="debug" com.android.build.api.attributes.ProductFlavorAttr:color="blue"
blueSquareRelease com.android.build.api.attributes.BuildTypeAttr="release"
com.android.build.api.attributes.ProductFlavorAttr:color="blue"
pinkSquareDebug com.android.build.api.attributes.BuildTypeAttr="debug"
com.android.build.api.attributes.ProductFlavorAttr:color="pink"
pinkSquareRelease com.android.build.api.attributes.BuildTypeAttr="release"
com.android.build.api.attributes.ProductFlavorAttr:color="pink"

In practice, more variants get published. For instance, each of the above variants is published twice, once for compilation and once for runtime, with different dependencies (based on whether the declared dependencies use implementation or api) and with a different value for the attribute org.gradle.Usage. However, the artifacts (AAR file) for these two variants are the same.

For more information, see the publishing API documentation.

Compatibility issue for publishing multi-flavor libraries

A project using AGP 7.0 or below cannot consume multi-flavor libraries published with AGP 7.1 or above. This is a known issue caused by a change to the attribute name for product flavor dimension from dimensionName to com.android.build.api.attributes.ProductFlavor:dimensionName in AGP 7.1. Depending on your project setup, you can use missingDimensionStrategy in the old variant API to work around this issue.

For example, suppose your application project only has a version product flavor dimension:

Kotlin

android {
    applicationVariants.forEach { variant ->
        val flavor = variant.productFlavors[0].name
        val attributePrefix = "com.android.build.api.attributes.ProductFlavor"
        val dimensionName = "version"
        variant.missingDimensionStrategy("$attributePrefix:$dimensionName", flavor)
    }
}

Groovy

android {
    applicationVariants.forEach { variant ->
        def flavor = variant.getProductFlavors()[0].name
        def attributePrefix = "com.android.build.api.attributes.ProductFlavor"
        def dimensionName = "version"
        variant.missingDimensionStrategy("$attributePrefix:$dimensionName", flavor)
    }
}