Skip to content

Instantly share code, notes, and snippets.

@gmazzo
Last active October 15, 2021 12:35
Show Gist options
  • Save gmazzo/426f861660d4ae6d7ee072fa5bc21e07 to your computer and use it in GitHub Desktop.
Save gmazzo/426f861660d4ae6d7ee072fa5bc21e07 to your computer and use it in GitHub Desktop.
Android Library Variant-Aware Publication (with sources)
import org.gradle.api.attributes.LibraryElements
import org.gradle.api.component.ConfigurationVariantDetails
import org.gradle.api.plugins.JavaPlugin.SOURCES_ELEMENTS_CONFIGURATION_NAME
import org.gradle.jvm.tasks.Jar
import java.util.Locale
plugins {
id("com.android.library")
`maven-publish`
}
publishing {
val publication = publications.create<MavenPublication>("default")
val componentFactory = the<SoftwareComponentFactory>()
val mainComponent = componentFactory.adhoc("all-multi-artifact").apply {
publication.from(this)
}
android.libraryVariants.all {
val variantName = name
val variantComponent = componentFactory.adhoc("$variantName-multi-artifact")
val sourcesJarTask = tasks.register<Jar>("${variantName}SourcesJar") {
group = BasePlugin.BUILD_GROUP
description =
"Assembles a jar archive containing the $variantName ${DocsType.SOURCES}."
from(sourceSets.map { it.kotlinDirectories + it.javaDirectories + it.resourcesDirectories })
archiveAppendix.set(variantName)
archiveClassifier.set("sources")
duplicatesStrategy = DuplicatesStrategy.WARN
}
assembleProvider.configure { dependsOn(sourcesJarTask) }
// we transform AGP default variant-aware publication into a new variant-artifact by changing its maven coordinates
val variantPublication = publications.create<MavenPublication>(variantName) {
from(variantComponent)
groupId += ".$artifactId"
artifactId = variantName
(this as PublicationInternal<*>).isAlias = true
}
fun createConfiguration(type: String, mavenScope: String) = with(configurations) {
// the AGP default variant-aware publication (or new variant-artifact)
val base = getByName("${variantName}All${type}Publication")
// `all` artifacts have classifiers by default, we need to remove them
afterEvaluate {
base.outgoing.artifacts.configureEach {
(this as ConfigurablePublishArtifact).classifier = null
}
}
// our intermediate POM publication that will depend on the variant-artifact
val configuration = create("${variantName}Variant${type}Publication") {
isVisible = false
isCanBeConsumed = false
isCanBeResolved = false
// makes a dependency on the variant-artifact
project.dependencies.add(name, provider {
variantPublication.run { "$groupId:$artifactId:$version" }
})
// clones the attributes
attributes.from(base.attributes, LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE)
}
val sourcesConfiguration = configurations.create(
"$variantName$type${SOURCES_ELEMENTS_CONFIGURATION_NAME.capitalize(Locale.ROOT)}"
) {
isVisible = false
isCanBeConsumed = false
isCanBeResolved = false
outgoing.artifact(sourcesJarTask)
attributes {
from(base.attributes, LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE)
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType.SOURCES))
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
}
}
val mapAction = Action<ConfigurationVariantDetails> {
mapToMavenScope(mavenScope)
mapToOptional()
}
variantComponent.addVariantsFromConfiguration(base, mapAction)
variantComponent.addVariantsFromConfiguration(sourcesConfiguration, mapAction)
mainComponent.addVariantsFromConfiguration(configuration, mapAction)
}
createConfiguration("Api", "compile")
createConfiguration("Runtime", "runtime")
}
}
fun AttributeContainer.from(other: AttributeContainer, vararg excluding: Attribute<*>) {
(other.attributes.keySet() - excluding).forEach {
@Suppress("UNCHECKED_CAST")
attribute(it as Attribute<Any>, other.attributes.getAttribute(it)!!)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment