openjfx / javafx-gradle-plugin

Gradle plugin that makes it easy to work with JavaFX 11+
https://openjfx.io/
BSD 3-Clause "New" or "Revised" License
354 stars 62 forks source link

Cannot choose between the following variants of org.openjfx:javafx-fxml:21 #164

Open vcvitaly opened 6 months ago

vcvitaly commented 6 months ago

After updating to '0.1.0' I cannot download sources for javafx with the following error:

Execution failed for task ':ijDownloadSourcescab4df0e-539'.
> Could not resolve all files for configuration ':downloadSources_125583eb-3adb-477f-be75-e96ee19535fa'.
   > Could not resolve org.openjfx:javafx-fxml:21.
     Required by:
         project :
      > Cannot choose between the following variants of org.openjfx:javafx-fxml:21:
          - linux-aarch64Runtime
          - linuxRuntime
          - mac-aarch64Runtime
          - macRuntime
          - runtime
          - winRuntime
        All of them match the consumer attributes:
          - Variant 'linux-aarch64Runtime' capability org.openjfx:javafx-fxml:21:
              - Unmatched attributes:
                  - Provides org.gradle.category 'library' but the consumer didn't ask for it
                  - Provides org.gradle.libraryelements 'jar' but the consumer didn't ask for it
                  - Provides org.gradle.native.architecture 'aarch64' but the consumer didn't ask for it
                  - Provides org.gradle.native.operatingSystem 'linux' but the consumer didn't ask for it
                  - Provides org.gradle.status 'release' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it
          - Variant 'linuxRuntime' capability org.openjfx:javafx-fxml:21:
              - Unmatched attributes:
                  - Provides org.gradle.category 'library' but the consumer didn't ask for it
                  - Provides org.gradle.libraryelements 'jar' but the consumer didn't ask for it
                  - Provides org.gradle.native.architecture 'x86-64' but the consumer didn't ask for it
                  - Provides org.gradle.native.operatingSystem 'linux' but the consumer didn't ask for it
                  - Provides org.gradle.status 'release' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it
          - Variant 'mac-aarch64Runtime' capability org.openjfx:javafx-fxml:21:
              - Unmatched attributes:
                  - Provides org.gradle.category 'library' but the consumer didn't ask for it
                  - Provides org.gradle.libraryelements 'jar' but the consumer didn't ask for it
                  - Provides org.gradle.native.architecture 'aarch64' but the consumer didn't ask for it
                  - Provides org.gradle.native.operatingSystem 'macos' but the consumer didn't ask for it
                  - Provides org.gradle.status 'release' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it
          - Variant 'macRuntime' capability org.openjfx:javafx-fxml:21:
              - Unmatched attributes:
                  - Provides org.gradle.category 'library' but the consumer didn't ask for it
                  - Provides org.gradle.libraryelements 'jar' but the consumer didn't ask for it
                  - Provides org.gradle.native.architecture 'x86-64' but the consumer didn't ask for it
                  - Provides org.gradle.native.operatingSystem 'macos' but the consumer didn't ask for it
                  - Provides org.gradle.status 'release' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it
          - Variant 'runtime' capability org.openjfx:javafx-fxml:21:
              - Unmatched attributes:
                  - Provides org.gradle.category 'library' but the consumer didn't ask for it
                  - Provides org.gradle.libraryelements 'jar' but the consumer didn't ask for it
                  - Provides org.gradle.status 'release' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it
          - Variant 'winRuntime' capability org.openjfx:javafx-fxml:21:
              - Unmatched attributes:
                  - Provides org.gradle.category 'library' but the consumer didn't ask for it
                  - Provides org.gradle.libraryelements 'jar' but the consumer didn't ask for it
                  - Provides org.gradle.native.architecture 'x86-64' but the consumer didn't ask for it
                  - Provides org.gradle.native.operatingSystem 'windows' but the consumer didn't ask for it
                  - Provides org.gradle.status 'release' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it

At the same time dependency itself is downloaded without issues, I tried adding:

ext {
    ...
    platform = getPlatform()
    ...
}

configurations.implementation {
    attributes {
        attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
        attribute(OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTE, objects.named(OperatingSystemFamily, platform.osFamily))
        attribute(MachineArchitecture.ARCHITECTURE_ATTRIBUTE, objects.named(MachineArchitecture, platform.arch))
    }
}

def getPlatform() {
    return JavaFXPlatform.detect(osdetector);
}

But it didn't help. Could you advice what could be done to fix that? I'm ready to take that issue and contribute if you point me in the right direction.

vcvitaly commented 6 months ago

So far resolved it the following way:

configurations
        .matching(it -> it.name.contains("downloadSources"))
        .configureEach {
    attributes {
        attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
        attribute(OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTE, objects.named(OperatingSystemFamily, platform.osFamily))
        attribute(MachineArchitecture.ARCHITECTURE_ATTRIBUTE, objects.named(MachineArchitecture, platform.arch))
    }
}
jjohannes commented 6 months ago

@vcvitaly thanks for bringing this up. It's an unfortunate interaction between Gradle and IntelliJ and I wonder if this would better be fixed on the IntelliJ side (although I am not sure how).

The underlying issue is that there are no so-called Disambiguation Rules for OperatingSystemFamily and MachineArchitecture in Gradle. For Usage for example, there is such a rule that chooses the runtime over the api if no clear selection has been made. That's why it works for other libraries that do not have the additional attributes for OperatingSystem and Architecture.

But, I also think there is no good way to define a Disambiguation Rule here (which OS should be the primary?). Although, in the case of sources download for JavaFX it won't matter. The sources are the same for each variation (I think).

Bottom line: the solution you found is the best I can think of as well. Matching based on the name (downloadSources) is not super nice, but I can't think of another way. I would reduce it to the minimum and only set the OPERATING_SYSTEM_ATTRIBUTE and ARCHITECTURE_ATTRIBUTE attributes, which we already have in the source code here: setClasspathAttributes

I think this can be added to the plugin. In Java it would look like this:

private void setClasspathAttributesForSourcesDownload() {
  getConfigurationContainer().matching(c -> c.getName().startsWith("downloadSources")).configureEach(this::setClasspathAttributes);
}

...as an additional method in JavaFXOptions that is called in setPlatform.

@vcvitaly if you would like to do a PR for this, I am happy to review and maybe we can get someone from the maintainers to integrate it. 🙂 We could probably also add a test in JavaFXPluginSmokeTest by manually re-creating the setup IntelliJ does (with a ijDownloadSources... task and a downloadSources... configuration).