With Kotlin 2.1.0 new <Support for non-packed klib...
# gradle
m
With Kotlin 2.1.0 new Support for non-packed klibs feature is introduced. Since I'm using lib which hasn't migrate to latest Kotlin version, I need to revert this behavior to old one. From docs, it seems that I only need do this:
Copy code
import org.jetbrains.kotlin.gradle.plugin.attributes.KlibPackaging

val resolvableConfiguration = configurations.resolvable("resolvable") {
    attributes.attribute(KlibPackaging.ATTRIBUTE, project.objects.named(KlibPackaging.PACKED))
}
But, if I run this my issue is still here. Exactly, problem is this. For reference, I'm working on KMP project. So, my questions are: • Is this code snippet only change I need to do or I need to apply
resolvableConfiguration
somewhere? • In which gradle file I need to do it (
project
or
module
level)?
t
non-packed klibs are only used between sub-projects in the same Gradle project. So using lib which was compiled with older Kotlin version should be fine
m
If I don't set anything, I get same error https://github.com/icerockdev/moko-resources/issues/786 If I set it to
Packed
, I also get mentioned error
t
I see, so the problem is in the 3rd party Gradle plugin
cc @Alexander.Likhachev
m
I'm curious if there's some documentation about Gradle
artifactType
attribute. How did you choose between reusing the
artifactType
vs creating a new one?
It doesn't seem completely unreasonnable that
artifactType
describes the "file format" of the artifact.
At least this was my mental model before reading that thread
m
@tapchicoma so if I understood correctly, moko-resources should internally support Kotlin 2.1.0 and configure klibs correctly?
a
I'm curious if there's some documentation about Gradle
artifactType
attribute.
there are not much. But artifactType is a special attribute that used in two places: • secondary variants ◦ so one can include some artifact to outgoing variant as a secondary variant and via setting You can do it like this:
Copy code
val someAttribute = Attribute.of("some.attribute", String::class.java)

val consumableConfiguration = configurations.create("consumable") {
    isCanBeConsumed = true
    isCanBeResolved = false

    attributes {
        attribute(someAttribute, "someValue")
    }
}

consumableConfiguration.outgoing.artifact(file("artifact1.jar")) {
    type = "jar"
}

consumableConfiguration.outgoing.variants.create("secondaryVariant") {
    artifact(file("artifact2.jar")) {
        type = "secondary-jar"
    }
}
And then if you run
outgoingVariants
you'll get the following:
Copy code
> Task :lib1:outgoingVariants
--------------------------------------------------
Variant consumable
--------------------------------------------------

Capabilities
    - gradle-sample:lib1:unspecified (default capability)
Attributes
    - some.attribute = someValue
Artifacts
    - artifact1.jar (artifactType = jar)

Secondary Variants (*)

    --------------------------------------------------
    Secondary Variant secondaryVariant
    --------------------------------------------------
    
    Attributes
        - some.attribute = someValue
    Artifacts
        - artifact2.jar (artifactType = secondary-jar)
Note
artifactType = secondary-jar
If you try to consume any of the variants without specifying artifactType it will fail. So you need to either distinguish artifacts with custom attribute OR using artifactType artifactType also used with artifact transforms in this article you'll find this code:
Copy code
dependencies {
    artifactTypes.getByName("jar") {
        attributes.attribute(minified, false)    
    }
}
so here artifactType "jar" is associated with "default" attribute "minified" with value "false". But also this article has two samples, one where they use artifactType for transformations and distinguishing. Another with auxiliary attribute (minified). If I recall correctly we decided to go with an auxiliary attribute to provide more "semantics". But we could go with artifactType attribute as well. But I personally would prefer attributes as they more flexible. Alexander can provide more details.
thank you color 1
@tapchicoma so if I understood correctly, moko-resources should internally support Kotlin 2.1.0 and configure klibs correctly?
unfortunately, yes. if moko resolves KGPs configurations and consume artifacts from then. moko then should be careful with the actual artifact types.
👍 1
However there is a lesson for us anyways. as we broke someone's build. So we have to be careful in the future with changes like this and provide better diagnostics & documentation so that this change will not be a surprise.
m
@Anton Lakotka [JB] thanks for the explanation. TIL about "secondary" variant. Looks like they were designed for this (variants that are not published). The whole variant-aware resolution is pretty fragile if you ask me. Sometimes I wish we'd go back to a flat classifier list...
a
Looks like they were designed for this (variants that are not published)
Unfortunately it is not so simple 🙂 If you do the custom publication via adhoc software component (article https://docs.gradle.org/current/userguide/publishing_customization.html#sec:publishing-custom-components): like this:
Copy code
// create an adhoc component
val adhocComponent = softwareComponentFactory.adhoc("myAdhocComponent")
// add it to the list of components that this project declares
components.add(adhocComponent)
// and register a variant for publication
adhocComponent.addVariantsFromConfiguration(outgoing) {
    mapToMavenScope("runtime")
}
you can already see the plural form
addVariant*s*
here 😉 which means all your variants main + secondary will be published. to avoid that, one need to "skip" them explicitly like so:
Copy code
adhocComponent.addVariantsFromConfiguration(outgoing) {
    if (this.configurationVariant.name != configuration.name) {
        skip()
        return@addVariantsFromConfiguration
    }
    mapToMavenScope("runtime")
}
fortunately names of variants matches with configuration name. so this
if
do the trick of filtering 🙂
mind blown 1
m
OMG, I would definitely have published them by mistake... Thanks for the heads up!
a
And thus there is a rule of thumb, one should always test published artifacts (especially poms and gradle metadata) against "golden" versions. to prevent any unexpected content changes.
💯 1
m
+1000, it's not "easy" to do though...
Are you doing this in Kotlin?
a
yes, but it is not easy indeed. and we don't do it for all publications, but only for poms at the moment.
💪 1
m
Is that open source by any chance?
a
there are the golden files, and rest is hidden somewhere in build logic 🙂
m
Nice, Thanks!