Hi,
I would like to use variants to produce two versions of the same software, one targeting Java 8+ and one targeting Java 11+. I am already using the toolchains to test with multiple versions of the JDK, but I must specify:
This would be fine if I weren’t using variants. My understanding is that variants pre-generate compilation tasks; according to @Vampire (if I got it correctly), I only need to configure the compiler for these tasks.
Yes, you got me right.
The manual shenenigans @gavenkoa suggests are not needed when using proper feature variants as the feature variants already register and wire all necessary tasks.
Could I use anything supported in java when I inside registerFeature closure?
No.
Well, you can, but will probably configure the main things, not the feature variant as having things inside is just the same as having them outside.
I strongly recommend using the Kotlin DSL, because then you have amazingly better IDE support and can properly see what is available where.
Is there an example of variant redefinition for JavaCompiler version?
Hi @Vampire ,
Do you by any chance have a working example that you could share? The issue you linked seems stale and hasn’t been touched for almost 2 years?
I’m struggling to find good examples of how to use variants and toolchains together to target different java versions, and the documentation hasn’t been updated properly - as you mention in your issue, in docs just says “this is possible”, but doesn’t really tell you “how”
Basically you just need to have two feature variants with the same capability (set the one of the additional variant to the main capability) and the only difference in attributes would then be the Java version. You can list the outgoing variants with the outgoingVariants task.
No, sorry: I’ve tried a few times, and gave up in the end. It requires too much effort to get started without a template, and did not have enough time to investigate in depth.
plugins {
`java-library`
}
java {
registerFeature("java9") {
usingSourceSet(sourceSets.main.get())
capability("$group", project.name, "$version")
}
}
val java9RuntimeElements by configurations.existing {
attributes {
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 9)
}
}
val java9ApiElements by configurations.existing {
attributes {
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 9)
}
}
val java9RuntimeOnly by configurations
dependencies {
java9RuntimeOnly("a:b:1")
}
This declares a feature variant for Java 9 but with the same artifact as the main variant.
Gradle Java 9+ consumers will just get an additional dependency automatically.
Another example:
plugins {
`java-library`
}
val java9 by sourceSets.creating
java {
registerFeature("java9") {
usingSourceSet(java9)
capability("$group", project.name, "$version")
}
}
val compileJava9Java by tasks.existing(JavaCompile::class) {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(9)
}
}
This declares also a feature variant for Java 9 but in this case with separate Java sources.
And as the variant automatically uses the Java version of the main compilation task for the attribute you do not need to set the attribute explicitly in this case, as you already set it on the compilation task.
I would say the second example more answers the original question, but well, it depends on what you need. Whether you want different sources, different dependencies, or even both.
Thanks a lot for the examples @Vampire ! This really helps and it looks like I’ve just arrived at similar things myself. The confusing part for me was the usage of attributes and how they need to be declared and used. But overall it’s pretty much what I’ve arrived at myself after a day of searching and just trying things out with kotlin dsl (which helps with auto-completion and all).
I’m still getting some errors in my use-case, but they’re not related to this question per se, so I think I better make a different topic for that.