when declaring a dependency from a version catalog...
# dependency-management
n
when declaring a dependency from a version catalog that requires a classifier, you can use the following syntax:
Copy code
implementation(variantOf(libs.myLib) { classifier("myClassifier") })
How can I do the same inside the dependencies block of a
JvmTestSuite
?
βœ… 1
v
I didn't try it, but if that dependency block does not have something for that built-in, you probably can do the usual work-around and report as missing feature:
Copy code
implementation(project.dependencies.variantOf(libs.myLib) { classifier("myClassifier") })
But isn't it simply
Copy code
implementation(libs.myLib) {
    artifact {
        classifier = "myClassifier"
    }
}
?
In both blocks
n
I referenced this blogpost: https://melix.github.io/blog/2021/03/version-catalogs-faq.html#_why_cant_i_use_excludes_or_classifiers but that artifact selector seems to do the trick πŸ‘ thanks as ever
πŸ‘Œ 1
v
Hm, maybe @melix can enlighten us what the difference is, when you should use either, and whether it is a shortcoming of the new dependencies blocks the you cannot use
variantOf
conveniently in there.
j
variantOf works by mapping off of a provider retuned by the version catalog. The artifacts block (and the whole new dependencies block) eagerly realizes those providers from the version catalog We do not currently have plans to support variantOf in the new block to avoid having multiple ways of doing things
v
Thanks for the clarification. Would this eager realization be a problem in any case? The value coming from the version catalog should not be able to change, should it? Maybe the
variantOf
should be deprecated then? Or is it able to do other things you cannot achieve otherwise right now? If the latter, then how would you do those things in the new
dependencies
blocks?
j
I may have jumped the gun. In the new dependencies block it seems we map the provider passed into the block and then apply the configure closure to it. However at that time if the value comes from a version catalog we copy it as a mutable version first
The value from the version catalog is immutable, which is why we need to copy first before allowing you to mutate it
variantOf and similar apis should not be able to perform anything that existing apis cannot
v
So that's a "yes" for deprecating it? πŸ™‚
j
It’s probably a good idea to deprecate it. I’d have to look into it a little further to be sure but I’d avoid using it
It adds a lot of complexity internally to support so I’d like to see it go
n
So, my takeaway from this discussion is that I should always prefer the following syntax:
Copy code
implementation(libs.myLib) {
    artifact {
        classifier = "myClassifier"
    }
}
correct?
v
If you really want only that artifact with that classifier, yes. Actually, you should always prefer to use feature variants if they are available. Or if they are not, use a component metadata rule to ad-hoc define the missing feature variant for that classified artifact. One of the problem with classified artifacts - if they represent a feature variant - is, that you loose dependency information as you are telling Gradle "just give me the artifact with that classifier. In some situations like
org.wildfly:wildfly-dist
this might be what you want (besides that there it is the extension you need to change not the classifier, but principle stays the same). But if it really is a feature variant that is represented by that classified artifact it would be cleaner to model it as feature variant, either in the original project, or ad-hoc.
n
https://repo1.maven.org/maven2/org/apache/shiro/shiro-core/2.0.1/ <-- so as an example, we use the jakarta variant of shiro. It would be better to model it ad-hoc? I suppose I could follow this example: https://docs.gradle.org/current/userguide/component_metadata_rules.html#making_variants_published_as_classified_jars_explicit and potentially model many libraries with a jakarta variant?
v
Yes, exactly. That is a typical feature variant. Main variant is for working with
javax
, that variant is for working with
jakarta
. Best would be to make the library properly publish their feature variants, but for that you need to make them publish Gradle Module Metadata. (Does not necessarily mean building with Gradle, that's just the easiest). But while not having that, yes, imho modeling the feature variant ad-hoc is the cleaner solution where you then also do not loose dependency information. Actually, you could also create some plugin that does it, so that everyone using
jakarta
can just apply that plugin and get all the feature variants defined for all libraries the plugin already supports, much like the https://github.com/gradlex-org/jvm-dependency-conflict-resolution plugin does it for adding capabilities to detect and fix conflicting libraries.
πŸ‘ 1
Ah, sorry, I spread a little desinformation. Using a classifier does not loose dependency information. Even using
artifact { extension = "..." }
does not loose dependency information. Just the
@...
suffix looses dependency information like
"org.apache.shiro:shiro-core:2.0.1@jar"
.
But still imho modeling as feature variant is cleaner and semantically better. Besides that often with a different feature variant you also need changed dependencies at least.
m
Sorry I didn't have time to read the whole thread, but
variantOf
exists for a reason, it seems weird to deprecate it when it was created to solve a problem
that said I tend to be annoyed with the new APIs which do not support what the old ones did, so let me shut up πŸ™‚
v
Better not shut up, but tell what it can do what the other API cannot. Then maybe it also gets supported by the new dependencies block, or the ability added to the other API. Or at least it does not get deprecated. @Justin Van Dort might just not be aware of what it can do, that the other API cannot. For sure it was created for a reason, but maybe the reason is obsolete and the other API can do the same now?