Hello,
I question myself regarding gradle way of handling variants and artifacts. Is it possible to generate a BOM featuring 2 dependencies, the foo
and bar
variants produced by a subproject?
So far I was not able to achieve this…
Given a multi-project initialized with:
allprojects {
apply plugin: 'base' // for clean, assemble tasks
}
subprojects {
apply plugin: 'maven-publish'
group = 'org.example'
version = '3.1415'
publishing {
repositories {
maven {
name = 'temp'
url rootProject.layout.buildDirectory.dir("repo")
}
}
}
}
And a subproject that generate several outgoing artifacts (think of each one being a zip file containing configuration files for specific target environments) with:
// producer/build.gradle
// This is a truncated binary plugin copied in a quick and dirty way to
// highlight its main features (and because SoftwareComponentFactory cannot be
// used directly from scripts)
class MultipleArtifactsPlugin implements Plugin<Project> {
def component
@javax.inject.Inject MultipleArtifactsPlugin(SoftwareComponentFactory factory) {
component = factory.adhoc("outgoing");
}
@Override void apply(Project p) {
p.components.add component
def conf = p.configurations.create("outgoingElements") {
canBeResolved = false
canBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, p.objects.named(Usage, Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, p.objects.named(Category, Category.LIBRARY))
}
}
component.addVariantsFromConfiguration(conf) { mapToMavenScope("runtime") }
}
}
apply plugin: MultipleArtifactsPlugin
def foo = tasks.register("foo", Zip) {
from("foo")
archiveFileName = "${project.name}-${project.version}-foo.zip"
archiveClassifier = "foo"
destinationDirectory = layout.buildDirectory.dir("outgoing")
}
def bar = tasks.register("bar", Zip) {
from("bar")
archiveFileName = "${project.name}-${project.version}-bar.zip"
archiveClassifier = "bar"
destinationDirectory = layout.buildDirectory.dir("outgoing")
}
configurations.outgoingElements {
outgoing {
artifact(foo)
artifact(bar)
}
}
tasks.named("assemble").configure {
dependsOn(foo, bar)
}
publishing {
publications {
maven(MavenPublication) {
afterEvaluate {
from(components["outgoing"])
}
}
}
}
When I want to publish a BOM listing all the generated artifacts with:
plugins {
id 'java-platform'
}
javaPlatform {
allowDependencies()
}
dependencies {
runtime project(':producer')
}
publishing {
publications {
maven(MavenPublication) {
from(components["javaPlatform"])
}
}
}
tasks.register("listArtifacts") {
inputs.files configurations.classpath
doLast {
inputs.files.collect { it.absolutePath }.each { println it }
}
}
And the command gradle clean [listArtifacts] publish
Then:
foo and bar artifacts from producer are published on the maven repository
foo and bar artifacts from producer can be consumed in consumer (listArtifacts shows them)
the BOM for the consumer project is published on the maven repository
the BOM lacks dependencies on the producer foo and bar artifacts which is desired, instead I have a useless dependency on the project consumer
Use of maven-publish plugin and maven BOM is required because clients of this BOM are almost exclusively maven builds.
Thanks for your inputs.