I am using artifactView withVariantReselection and...
# plugin-development
j
I am using artifactView withVariantReselection and it is working when I publish and resolve via maven. But I am having trouble making it work via project dependencies. my
outgoingVariants
has this (which is the one I am trying to resolve to)
Copy code
Secondary Variants (*)

    --------------------------------------------------
    Secondary Variant archRulesElements
    --------------------------------------------------
    
    Attributes
        - org.gradle.category            = library
        - org.gradle.dependency.bundling = external
        - org.gradle.jvm.version         = 21
        - org.gradle.libraryelements     = jar
        - org.gradle.usage               = arch-rules
    Artifacts
build/libs/library-with-rules-archrules.jar (artifactType = jar, classifier = archrules)
but when I select
Copy code
attributes {
                                            attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named<Category>(Category.LIBRARY))
                                            attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named<Bundling>( Bundling.EXTERNAL))
                                            attribute(Usage.USAGE_ATTRIBUTE, project.objects.named<Usage>( "arch-rules"))
                                        }
it matches no artifacts. any ideas? maybe there is a common gotcha I am missing?
this variant is created from runtimeElements
does a project dependency use apiElements?
v
Whether
apiElements
or
runtimeElements
is used is defined by the attributes the resolved configuration or artifact view is requesting. What is the error message you get on trying to resolve. Here indeed a screenshot might be beneficial to see the colors in the message.
j
well, there is no error. the artifactView just comes out empty
v
And if you try to request the variant directly using the configuration, not an artifact view? Artifact views are by default lenient in a way that not found variants are fine and ignored.
j
so basically do this?
Copy code
project.configurations.getByName(sourceSet.runtimeClasspathConfigurationName).attributes {
                                attribute(Usage.USAGE_ATTRIBUTE, project.objects.named<Usage>( "arch-rules"))
                            }
then resolve the configuration?
Copy code
Could not determine the dependencies of task ':code-to-check:checkArchRulesMain'.
> Could not resolve all dependencies for configuration ':code-to-check:runtimeClasspath'.
   > Could not resolve project :library-with-rules.
     Required by:
         project ':code-to-check'
      > No matching variant of project :library-with-rules was found. The consumer was configured to find a library for use during 'arch-rules', compatible with Java 21, packaged as a jar, preferably optimized for standard JVMs, and its dependencies declared externally but:
          - Variant 'apiElements' declares a library, compatible with Java 21, packaged as a jar, and its dependencies declared externally:
              - Incompatible because this component declares a component for use during compile-time and the consumer needed a component for use during 'arch-rules'
              - Other compatible attribute:
                  - Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
          - Variant 'mainSourceElements' declares a component, and its dependencies declared externally:
              - Incompatible because this component declares a component of category 'verification' and the consumer needed a library
              - Other compatible attributes:
                  - Doesn't say anything about its elements (required them packaged as a jar)
                  - Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
                  - Doesn't say anything about its target Java version (required compatibility with Java 21)
                  - Doesn't say anything about its usage (required 'arch-rules')
          - Variant 'runtimeElements' declares a library, compatible with Java 21, packaged as a jar, and its dependencies declared externally:
              - Incompatible because this component declares a component for use during runtime and the consumer needed a component for use during 'arch-rules'
              - Other compatible attribute:
                  - Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
          - Variant 'testResultsElementsForArchRulesTest':
              - Incompatible because this component declares a component of category 'verification' and the consumer needed a library
              - Other compatible attributes:
                  - Doesn't say anything about how its dependencies are found (required its dependencies declared externally)
                  - Doesn't say anything about its elements (required them packaged as a jar)
                  - Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
                  - Doesn't say anything about its target Java version (required compatibility with Java 21)
                  - Doesn't say anything about its usage (required 'arch-rules')
          - Variant 'testResultsElementsForTest':
              - Incompatible because this component declares a component of category 'verification' and the consumer needed a library
              - Other compatible attributes:
                  - Doesn't say anything about how its dependencies are found (required its dependencies declared externally)
                  - Doesn't say anything about its elements (required them packaged as a jar)
                  - Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
                  - Doesn't say anything about its target Java version (required compatibility with Java 21)
                  - Doesn't say anything about its usage (required 'arch-rules')
v
Ok, and now with color please 🙂
In this error the color is very helpful
j
this is happening in a testkit integration test so I don't have color unfortunately lol
v
ok, no problem
j
so i dont see my variant in there at all
v
Yes
j
is it because it is a secondary variant?
v
That sounds like it is the problem 😕
I'm not sure
Did not play too much with creating own secondary variants so far
But why is is a secondary variant actually? Secondary variants do not get published, do they? So how does it then work when published?
j
for reference, my full outgoing variants:
Copy code
--------------------------------------------------
Variant apiElements
--------------------------------------------------
API elements for the 'main' feature.

Capabilities
    - junit-10007194369204690871:library-with-rules:unspecified (default capability)
Attributes
    - org.gradle.category            = library
    - org.gradle.dependency.bundling = external
    - org.gradle.jvm.version         = 21
    - org.gradle.libraryelements     = jar
    - org.gradle.usage               = java-api
Artifacts
    - build/libs/library-with-rules.jar (artifactType = jar)

Secondary Variants (*)

    --------------------------------------------------
    Secondary Variant classes
    --------------------------------------------------
    Directories containing compiled class files for main.

    Attributes
        - org.gradle.category            = library
        - org.gradle.dependency.bundling = external
        - org.gradle.jvm.version         = 21
        - org.gradle.libraryelements     = classes
        - org.gradle.usage               = java-api
    Artifacts
        - build/classes/java/main (artifactType = java-classes-directory)

--------------------------------------------------
Variant archives
--------------------------------------------------
Configuration for archive artifacts.

Capabilities
    - junit-10007194369204690871:library-with-rules:unspecified (default capability)
Artifacts
    - build/libs/library-with-rules.jar (artifactType = jar)

--------------------------------------------------
Variant default
--------------------------------------------------
Configuration for default artifacts.

Capabilities
    - junit-10007194369204690871:library-with-rules:unspecified (default capability)
Artifacts
    - build/libs/library-with-rules.jar (artifactType = jar)

--------------------------------------------------
Variant mainSourceElements (i)
--------------------------------------------------
List of source directories contained in the Main SourceSet.

Capabilities
    - junit-10007194369204690871:library-with-rules:unspecified (default capability)
Attributes
    - org.gradle.category            = verification
    - org.gradle.dependency.bundling = external
    - org.gradle.verificationtype    = main-sources
Artifacts
    - src/main/java (artifactType = directory)
    - src/main/resources (artifactType = directory)

--------------------------------------------------
Variant runtimeElements
--------------------------------------------------
Runtime elements for the 'main' feature.

Capabilities
    - junit-10007194369204690871:library-with-rules:unspecified (default capability)
Attributes
    - org.gradle.category            = library
    - org.gradle.dependency.bundling = external
    - org.gradle.jvm.version         = 21
    - org.gradle.libraryelements     = jar
    - org.gradle.usage               = java-runtime
Artifacts
    - build/libs/library-with-rules.jar (artifactType = jar)

Secondary Variants (*)

    --------------------------------------------------
    Secondary Variant archRulesElements
    --------------------------------------------------
    
    Attributes
        - org.gradle.category            = library
        - org.gradle.dependency.bundling = external
        - org.gradle.jvm.version         = 21
        - org.gradle.libraryelements     = jar
        - org.gradle.usage               = arch-rules
    Artifacts
        - build/libs/library-with-rules-archrules.jar (artifactType = jar, classifier = archrules)

    --------------------------------------------------
    Secondary Variant classes
    --------------------------------------------------
    Directories containing compiled class files for main.

    Attributes
        - org.gradle.category            = library
        - org.gradle.dependency.bundling = external
        - org.gradle.jvm.version         = 21
        - org.gradle.libraryelements     = classes
        - org.gradle.usage               = java-runtime
    Artifacts
        - build/classes/java/main (artifactType = java-classes-directory)

    --------------------------------------------------
    Secondary Variant resources
    --------------------------------------------------
    Directories containing assembled resource files for main.

    Attributes
        - org.gradle.category            = library
        - org.gradle.dependency.bundling = external
        - org.gradle.jvm.version         = 21
        - org.gradle.libraryelements     = resources
        - org.gradle.usage               = java-runtime
    Artifacts
        - build/resources/main (artifactType = java-resources-directory)

--------------------------------------------------
Variant testResultsElementsForArchRulesTest (i)
--------------------------------------------------
Binary results obtained from running all targets in the 'archRulesTest' Test Suite.

Capabilities
    - junit-10007194369204690871:library-with-rules:unspecified (default capability)
Attributes
    - org.gradle.category         = verification
    - org.gradle.testsuite.name   = archRulesTest
    - org.gradle.verificationtype = test-results
Artifacts
    - build/test-results/archRulesTest/binary (artifactType = directory)

--------------------------------------------------
Variant testResultsElementsForTest (i)
--------------------------------------------------
Binary results obtained from running all targets in the 'test' Test Suite.

Capabilities
    - junit-10007194369204690871:library-with-rules:unspecified (default capability)
Attributes
    - org.gradle.category         = verification
    - org.gradle.testsuite.name   = test
    - org.gradle.verificationtype = test-results
Artifacts
    - build/test-results/test/binary (artifactType = directory)

(i) Configuration uses incubating attributes such as Category.VERIFICATION.
(*) Secondary variants are variants created via the Configuration#getOutgoing(): ConfigurationPublications API which also participate in selection, in addition to the configuration itself.
I am doing this to create the variant
Copy code
project.plugins.withId("java") {
            val ext = project.extensions.getByType<JavaPluginExtension>()
            val archRulesSourceSet = ext.sourceSets.create("archRules")

            val jarTask = project.tasks.register<Jar>("archRulesJar") {
                archiveClassifier.set("archrules")
                from(archRulesSourceSet.output)
            }

            val runtimeElements = project.configurations.getByName("runtimeElements")
            runtimeElements.outgoing.variants.create("archRulesElements") {
                attributes {
                    attribute(Usage.USAGE_ATTRIBUTE, project.objects.named("arch-rules"))
                }
                artifact(jarTask)
            }
}
and it ends up published
v
And why do you do it that manual? If you create a source set, you should automatically get a jar task for it. And when you have a source set, you can just use
registerFeature
with it to get a feature variant set up. Then you just set the capability to the main capability if you don't want to select by capability but attributes, and I think it should work
j
I thought I needed a custom jar task for the classifier but if one exists already I can look into reusing that one
v
Btw.
.plugins
you should not use, see its JavaDoc. You should use
.pluginManager.withPlugin
instead. 🙂
👍 1
j
if i make a separate top-level configuration then it works for project dependency, but it isnt published 😕
i was not able to find any auto-generated jar tasks
is it possible to create a consumable configuration from the output of a sourceSet (not a jar)?
i could use that for project dependencies, and the secondary variant for publicaiton, and call it a day
v
i was not able to find any auto-generated jar tasks
Ah right, it is not created for the source set per se, but when you register it as feature variant.
if i make a separate top-level configuration
I did not say make a configuration, but register a feature.
Something like
Copy code
val archRules by sourceSets.registering
java {
    registerFeature("archRules") {
        usingSourceSet(archRules.get())
        capability("$group", name, "$version")
    }
}
configurations.named("archRulesRuntimeElements") {
    attributes {
        attribute(Usage.USAGE_ATTRIBUTE, objects.named("arch-rules"))
    }
}
j
oh so invoking capability that way makes it not a capability feature really and allows me to just set an attribute
v
Yes, as I said above. 🙂 By default it has a unique capability to select it manually like "give me the Oracle DB integration" or "give me the MSSQL Server integration". But if you set it to the main capability, it can be selected purely by attributes. This way you can for example make variants that get selected automatically by the Java version the consumer uses. Or to automatically select a Gradle plugin variant matching the Gradle version the consumer uses.
j
hm, i think the problem with this is that I am overloading the usage attribute. so if i create api and runtime elements for my source set, ill end up with multiple variants with the same set of attributes
this does look like a lot better of a solution overall though
if there are 2 variants, one has an attribute and the other does not, and it is being resolved in a configuration without the attribute, will it always prefer the variant without the attribute?
v
j
ah ok yeah i think that will work then
👌 1
Thanks for all your help. This plugin will be OSS once it is ready, so Ill share it here so you can see it
👌 1