Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

productionRuntimeClasspath fails to resolve multiplatform dependency variants #21549

Closed
vlsi opened this issue May 24, 2020 · 5 comments
Closed
Labels
type: regression A regression from a previous release
Milestone

Comments

@vlsi
Copy link

vlsi commented May 24, 2020

productionRuntimeClasspath resolution fails for Kotlin-multiplatform project dependencies.

Note: ./gradlew jar works, and bootJar works with Spring Boot 2.2.6.RELEASE

Environment:
Gradle 6.3
Spring Boot 2.3.0.RELEASE (fails)
Kotlin 1.3.72

Execution failed for task ':parser:bootJar'.
> Could not resolve all files for configuration ':parser:productionRuntimeClasspath'.
   > Could not resolve project :common.
     Required by:
         project :parser
      > Cannot choose between the following variants of project :common:
          - jsApiElements
          - jsCompile
          - jsCompileOnly
          - jsDefault
          - jsRuntime
          - jsRuntimeElements
          - jsTestCompile
          - jsTestRuntime
          - jvmApiElements
          - jvmCompile
          - jvmCompileOnly
          - jvmDefault
          - jvmRuntime
          - jvmRuntimeElements
          - jvmTestCompile
          - jvmTestRuntime
          - metadataApiElements
          - metadataCompile
          - metadataCompileOnly
          - metadataDefault
        All of them match the consumer attributes:
          - Variant 'jsApiElements' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.gradle.usage 'kotlin-api' but wasn't required.
                  - Found org.jetbrains.kotlin.localToProject 'public' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'js' but wasn't required.
          - Variant 'jsCompile' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.jetbrains.kotlin.localToProject 'local to :common' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'js' but wasn't required.
          - Variant 'jsCompileOnly' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.jetbrains.kotlin.localToProject 'local to :common' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'js' but wasn't required.
          - Variant 'jsDefault' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.jetbrains.kotlin.localToProject 'local to :common' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'js' but wasn't required.
          - Variant 'jsRuntime' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.jetbrains.kotlin.localToProject 'local to :common' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'js' but wasn't required.
          - Variant 'jsRuntimeElements' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.gradle.usage 'kotlin-runtime' but wasn't required.
                  - Found org.jetbrains.kotlin.localToProject 'public' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'js' but wasn't required.
          - Variant 'jsTestCompile' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.jetbrains.kotlin.localToProject 'local to :common' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'js' but wasn't required.
          - Variant 'jsTestRuntime' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.jetbrains.kotlin.localToProject 'local to :common' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'js' but wasn't required.
          - Variant 'jvmApiElements' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.gradle.libraryelements 'jar' but wasn't required.
                  - Found org.gradle.usage 'java-api' but wasn't required.
                  - Found org.jetbrains.kotlin.localToProject 'public' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'jvm' but wasn't required.
          - Variant 'jvmCompile' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.jetbrains.kotlin.localToProject 'local to :common' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'jvm' but wasn't required.
          - Variant 'jvmCompileOnly' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.jetbrains.kotlin.localToProject 'local to :common' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'jvm' but wasn't required.
          - Variant 'jvmDefault' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.jetbrains.kotlin.localToProject 'local to :common' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'jvm' but wasn't required.
          - Variant 'jvmRuntime' capability com.example:common:1.0.0:
              - Unmatched attributes:
                  - Found org.jetbrains.kotlin.localToProject 'local to :common' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'jvm' but wasn't required.
...
@wilkinsona
Copy link
Member

Thanks for the report. It looks like a change in Boot 2.3 may have shaken loose another example of a problem that Kotlin's Gradle support has had in the past. While we may be able to copy attributes from an existing configuration to the productionRuntimeClasspath configuration that we create, that feels rather brittle. IMO, Kotlin's Gradle support should handle this itself rather than relying on the rest of the ecosystem understanding and adding Kotlin-specific attributes to any configurations that they may create.

@wilkinsona
Copy link
Member

@vlsi Can you please try the workaround mentioned in the issue I linked to above. Without a sample it's hard to tell exactly how it should look for you, but I think it should be something like the following:

api project(path: ':common', configuration: 'jvmRuntimeElements')

Also, to help us to investigate further and decide if there's anything we can do in Spring Boot or if the problem needs to be addressed entirely on the Kotlin side, can you please provide a minimal sample that reproduces the failure you're seeing? You can do so by zipping something up and attaching it to this issue or by pushing it to a separate repository on GitHub.

@wilkinsona wilkinsona added the status: waiting-for-feedback We need additional information before we can continue label May 26, 2020
@vlsi
Copy link
Author

vlsi commented May 26, 2020

can you please provide a minimal sample that reproduces the failure you're seeing?

I feel your pain, however, the project is not open, and that is the only Kotlin multiplatform + Spring Boot project I have. It would take me time to share a reproducer.

Kotlin's Gradle support should handle this itself rather than relying on the rest of the ecosystem understanding and adding Kotlin-specific attributes to any configurations

I believe the issue is NOT Kotlin-specific.
It provides regular Gradle attributes:

          - Variant 'jvmRuntimeElements' capability com.nitok:common:1.0.0:
              - Unmatched attributes:
                  - Found org.gradle.libraryelements 'jar' but wasn't required.
                  - Found org.gradle.usage 'java-runtime' but wasn't required.
                  - Found org.jetbrains.kotlin.localToProject 'public' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'jvm' but wasn't required.

org.gradle.libraryelements=jar and org.gradle.usage=java-runtime has nothing to do with Kotlin. They are regular attributes for a Java project.

However, productionRuntimeClasspath does not request the attributes, that is why Gradle can't choose between the variants.


The following workaround works: implementation(project(":common", "jvmRuntimeElements")), however, I believe it is a workaround.


The following workaround works as well:

configurations {
    productionRuntimeClasspath {
        attributes {
            attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
        }
    }
}

However, I don't quite follow the following code in SpringBoot productionRuntimeClasspath.setExtendsFrom(runtimeClasspath.getExtendsFrom());

What was the purpose there?

Did you mean productionRuntimeClasspath.setExtendsFrom(runtimeClasspath)?

I don't think it is safe to assume that runtimeClasspath.getExtendsFrom() resolves to something meaningful and stable. It is likely Gradle's implementation detail.

@vlsi
Copy link
Author

vlsi commented May 26, 2020

TL;DR: please use Gradle-provided configurations (e.g. runtimeClasspath) or request the proper attributes in your configurations (see example 8 in https://docs.gradle.org/current/userguide/cross_project_publications.html )

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels May 26, 2020
@wilkinsona
Copy link
Member

wilkinsona commented May 26, 2020

Setting the usage attribute makes sense. Thanks for the suggestion.

What was the purpose there?

To create a configuration that extends from the same configurations as runtimeClasspath. Ultimately, the goal is to create a configuration that contains everything in runtimeClasspath other than dependencies that are unique to Boot's developmentOnly configuration.

Did you mean productionRuntimeClasspath.setExtendsFrom(runtimeClasspath)

No. If productionRuntimeClasspath extends from runtimeClasspath, then it will end up including the dependencies in developmentOnly.

@wilkinsona wilkinsona changed the title 2.3.0 regression: productionRuntimeClasspath fails to resolve multiplatform dependency variants productionRuntimeClasspath fails to resolve multiplatform dependency variants May 26, 2020
@wilkinsona wilkinsona added type: regression A regression from a previous release and removed status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged labels May 26, 2020
@wilkinsona wilkinsona added this to the 2.3.1 milestone May 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

3 participants