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

Document the plugin usage #1

Closed
bric3 opened this issue Sep 24, 2020 · 4 comments
Closed

Document the plugin usage #1

bric3 opened this issue Sep 24, 2020 · 4 comments

Comments

@bric3
Copy link

bric3 commented Sep 24, 2020

This plugin is mentionned in several blogs and presentations, but declaring it is not enough.

E.g. suppose a project like this, with a transitive dependency to guava 28.1-android, how to use the plugin to select the jre variant, knowing this project will run on the JVM.

plugins {
    id 'java'
    id "de.jjohannes.missing-metadata-guava" version "0.1"
}

repositories {
    mavenCentral()
}

dependencies {
    implementation "com.google.cloud:google-cloud-bigtable:1.5.0"
}

compileJava {
    options.release.set(11)
}
dep insight
$  gradle dependencyInsight --dependency guava --configuration compileClasspath

> Task :dependencyInsight
com.google.guava:failureaccess:1.0.1
   variant "compile" [
      org.gradle.status              = release (not requested)
      org.gradle.usage               = java-api
      org.gradle.libraryelements     = jar (compatible with: classes)
      org.gradle.category            = library

      Requested attributes not found in the selected variant:
         org.gradle.dependency.bundling = external
         org.gradle.jvm.version         = 11
   ]

com.google.guava:failureaccess:1.0.1
\--- com.google.guava:guava:28.1-android
     +--- com.google.cloud:google-cloud-bigtable:1.5.0
     |    \--- compileClasspath
     +--- com.google.cloud:google-cloud-core-grpc:1.91.2
     |    \--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     +--- com.google.api:gax-grpc:1.49.0
     |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |    \--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
     +--- com.google.cloud:google-cloud-core:1.91.2
     |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |    \--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
     +--- com.google.api:gax:1.49.0
     |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |    +--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
     |    +--- com.google.api:gax-grpc:1.49.0 (*)
     |    \--- com.google.cloud:google-cloud-core:1.91.2 (*)
     +--- com.google.api:api-common:1.8.1 (requested com.google.guava:guava:26.0-android)
     |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |    +--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
     |    +--- com.google.api:gax-grpc:1.49.0 (*)
     |    +--- com.google.cloud:google-cloud-core:1.91.2 (*)
     |    +--- com.google.api:gax:1.49.0 (*)
     |    +--- com.google.api.grpc:proto-google-cloud-bigtable-v2:0.81.0
     |    |    \--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |    +--- com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:0.81.0
     |    |    \--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |    \--- com.google.api.grpc:proto-google-iam-v1:0.13.0
     |         +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |         +--- com.google.cloud:google-cloud-core:1.91.2 (*)
     |         \--- com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:0.81.0 (*)
     +--- io.grpc:grpc-protobuf:1.24.0 (requested com.google.guava:guava:26.0-android)
     |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |    +--- com.google.api:gax-grpc:1.49.0 (requested io.grpc:grpc-protobuf:1.23.0) (*)
     |    +--- io.grpc:grpc-alts:1.23.0 (requested io.grpc:grpc-protobuf:1.23.0)
     |    |    \--- com.google.api:gax-grpc:1.49.0 (*)
     |    \--- io.grpc:grpc-grpclb:1.23.0 (requested io.grpc:grpc-protobuf:1.23.0)
     |         \--- io.grpc:grpc-alts:1.23.0 (*)
     +--- com.google.auth:google-auth-library-oauth2-http:0.17.2 (requested com.google.guava:guava:28.0-android)
     |    +--- com.google.api:gax-grpc:1.49.0 (*)
     |    +--- com.google.cloud:google-cloud-core:1.91.2 (*)
     |    +--- com.google.api:gax:1.49.0 (*)
     |    \--- io.grpc:grpc-alts:1.23.0 (requested com.google.auth:google-auth-library-oauth2-http:0.13.0) (*)
     +--- com.google.protobuf:protobuf-java-util:3.10.0 (requested com.google.guava:guava:28.0-android)
     |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |    +--- com.google.cloud:google-cloud-core:1.91.2 (*)
     |    \--- io.grpc:grpc-grpclb:1.23.0 (requested com.google.protobuf:protobuf-java-util:3.9.0) (*)
     +--- io.grpc:grpc-protobuf-lite:1.24.0 (requested com.google.guava:guava:26.0-android)
     |    \--- io.grpc:grpc-protobuf:1.24.0 (*)
     +--- io.grpc:grpc-api:1.24.0 (requested com.google.guava:guava:26.0-android)
     |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |    +--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
     |    +--- io.grpc:grpc-protobuf:1.24.0 (*)
     |    +--- io.grpc:grpc-auth:1.24.0
     |    |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |    |    +--- com.google.api:gax-grpc:1.49.0 (requested io.grpc:grpc-auth:1.23.0) (*)
     |    |    \--- io.grpc:grpc-alts:1.23.0 (requested io.grpc:grpc-auth:1.23.0) (*)
     |    +--- io.grpc:grpc-core:1.24.0
     |    |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |    |    +--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
     |    |    +--- io.grpc:grpc-alts:1.23.0 (requested io.grpc:grpc-core:1.23.0) (*)
     |    |    +--- io.grpc:grpc-grpclb:1.23.0 (requested io.grpc:grpc-core:1.23.0) (*)
     |    |    \--- io.grpc:grpc-netty-shaded:1.24.0
     |    |         +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     |    |         +--- com.google.api:gax-grpc:1.49.0 (requested io.grpc:grpc-netty-shaded:1.23.0) (*)
     |    |         \--- io.grpc:grpc-alts:1.23.0 (requested io.grpc:grpc-netty-shaded:1.23.0) (*)
     |    +--- io.grpc:grpc-stub:1.23.0 (requested io.grpc:grpc-api:1.23.0)
     |    |    +--- com.google.api:gax-grpc:1.49.0 (*)
     |    |    +--- io.grpc:grpc-alts:1.23.0 (*)
     |    |    \--- io.grpc:grpc-grpclb:1.23.0 (*)
     |    \--- io.grpc:grpc-protobuf-lite:1.24.0 (*)
     +--- com.google.http-client:google-http-client:1.32.1
     |    +--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
     |    +--- com.google.cloud:google-cloud-core:1.91.2 (*)
     |    +--- com.google.auth:google-auth-library-oauth2-http:0.17.2 (*)
     |    \--- com.google.http-client:google-http-client-jackson2:1.32.1
     |         +--- com.google.cloud:google-cloud-core:1.91.2 (*)
     |         \--- com.google.auth:google-auth-library-oauth2-http:0.17.2 (*)
     \--- io.opencensus:opencensus-contrib-http-util:0.24.0 (requested com.google.guava:guava:26.0-android)
          \--- com.google.http-client:google-http-client:1.32.1 (*)

com.google.guava:guava:28.1-android
   variant "jdk8Compile" [
      org.gradle.jvm.version         = 8 (compatible with: 11)
      org.gradle.status              = release (not requested)
      org.gradle.usage               = java-api
      org.gradle.libraryelements     = jar (compatible with: classes)
      org.gradle.category            = library

      Requested attributes not found in the selected variant:
         org.gradle.dependency.bundling = external
   ]
   Selection reasons:
      - By conflict resolution : between versions 28.1-android, 26.0-android and 28.0-android

com.google.guava:guava:28.1-android
+--- com.google.api:gax:1.49.0
|    +--- com.google.cloud:google-cloud-bigtable:1.5.0
|    |    \--- compileClasspath
|    +--- com.google.cloud:google-cloud-core-grpc:1.91.2
|    |    \--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    +--- com.google.api:gax-grpc:1.49.0
|    |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    |    \--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
|    \--- com.google.cloud:google-cloud-core:1.91.2
|         +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|         \--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
+--- com.google.api:gax-grpc:1.49.0 (*)
+--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
+--- com.google.cloud:google-cloud-core:1.91.2 (*)
+--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
\--- com.google.http-client:google-http-client:1.32.1
     +--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
     +--- com.google.cloud:google-cloud-core:1.91.2 (*)
     +--- com.google.auth:google-auth-library-oauth2-http:0.17.2
     |    +--- com.google.api:gax-grpc:1.49.0 (*)
     |    +--- com.google.cloud:google-cloud-core:1.91.2 (*)
     |    +--- com.google.api:gax:1.49.0 (*)
     |    \--- io.grpc:grpc-alts:1.23.0 (requested com.google.auth:google-auth-library-oauth2-http:0.13.0)
     |         \--- com.google.api:gax-grpc:1.49.0 (*)
     \--- com.google.http-client:google-http-client-jackson2:1.32.1
          +--- com.google.cloud:google-cloud-core:1.91.2 (*)
          \--- com.google.auth:google-auth-library-oauth2-http:0.17.2 (*)

com.google.guava:guava:26.0-android -> 28.1-android
+--- com.google.api:api-common:1.8.1
|    +--- com.google.cloud:google-cloud-bigtable:1.5.0
|    |    \--- compileClasspath
|    +--- com.google.cloud:google-cloud-core-grpc:1.91.2
|    |    \--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    +--- com.google.api:gax-grpc:1.49.0
|    |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    |    \--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
|    +--- com.google.cloud:google-cloud-core:1.91.2
|    |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    |    \--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
|    +--- com.google.api:gax:1.49.0
|    |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    |    +--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
|    |    +--- com.google.api:gax-grpc:1.49.0 (*)
|    |    \--- com.google.cloud:google-cloud-core:1.91.2 (*)
|    +--- com.google.api.grpc:proto-google-cloud-bigtable-v2:0.81.0
|    |    \--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    +--- com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:0.81.0
|    |    \--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    \--- com.google.api.grpc:proto-google-iam-v1:0.13.0
|         +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|         +--- com.google.cloud:google-cloud-core:1.91.2 (*)
|         \--- com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:0.81.0 (*)
+--- io.grpc:grpc-api:1.24.0
|    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    +--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
|    +--- io.grpc:grpc-protobuf:1.24.0
|    |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    |    +--- com.google.api:gax-grpc:1.49.0 (requested io.grpc:grpc-protobuf:1.23.0) (*)
|    |    +--- io.grpc:grpc-alts:1.23.0 (requested io.grpc:grpc-protobuf:1.23.0)
|    |    |    \--- com.google.api:gax-grpc:1.49.0 (*)
|    |    \--- io.grpc:grpc-grpclb:1.23.0 (requested io.grpc:grpc-protobuf:1.23.0)
|    |         \--- io.grpc:grpc-alts:1.23.0 (*)
|    +--- io.grpc:grpc-auth:1.24.0
|    |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    |    +--- com.google.api:gax-grpc:1.49.0 (requested io.grpc:grpc-auth:1.23.0) (*)
|    |    \--- io.grpc:grpc-alts:1.23.0 (requested io.grpc:grpc-auth:1.23.0) (*)
|    +--- io.grpc:grpc-core:1.24.0
|    |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    |    +--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
|    |    +--- io.grpc:grpc-alts:1.23.0 (requested io.grpc:grpc-core:1.23.0) (*)
|    |    +--- io.grpc:grpc-grpclb:1.23.0 (requested io.grpc:grpc-core:1.23.0) (*)
|    |    \--- io.grpc:grpc-netty-shaded:1.24.0
|    |         +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    |         +--- com.google.api:gax-grpc:1.49.0 (requested io.grpc:grpc-netty-shaded:1.23.0) (*)
|    |         \--- io.grpc:grpc-alts:1.23.0 (requested io.grpc:grpc-netty-shaded:1.23.0) (*)
|    +--- io.grpc:grpc-stub:1.23.0 (requested io.grpc:grpc-api:1.23.0)
|    |    +--- com.google.api:gax-grpc:1.49.0 (*)
|    |    +--- io.grpc:grpc-alts:1.23.0 (*)
|    |    \--- io.grpc:grpc-grpclb:1.23.0 (*)
|    \--- io.grpc:grpc-protobuf-lite:1.24.0
|         \--- io.grpc:grpc-protobuf:1.24.0 (*)
+--- io.grpc:grpc-protobuf:1.24.0 (*)
+--- io.grpc:grpc-protobuf-lite:1.24.0 (*)
\--- io.opencensus:opencensus-contrib-http-util:0.24.0
     \--- com.google.http-client:google-http-client:1.32.1
          +--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
          +--- com.google.cloud:google-cloud-core:1.91.2 (*)
          +--- com.google.auth:google-auth-library-oauth2-http:0.17.2
          |    +--- com.google.api:gax-grpc:1.49.0 (*)
          |    +--- com.google.cloud:google-cloud-core:1.91.2 (*)
          |    +--- com.google.api:gax:1.49.0 (*)
          |    \--- io.grpc:grpc-alts:1.23.0 (requested com.google.auth:google-auth-library-oauth2-http:0.13.0) (*)
          \--- com.google.http-client:google-http-client-jackson2:1.32.1
               +--- com.google.cloud:google-cloud-core:1.91.2 (*)
               \--- com.google.auth:google-auth-library-oauth2-http:0.17.2 (*)

com.google.guava:guava:28.0-android -> 28.1-android
+--- com.google.auth:google-auth-library-oauth2-http:0.17.2
|    +--- com.google.api:gax-grpc:1.49.0
|    |    +--- com.google.cloud:google-cloud-bigtable:1.5.0
|    |    |    \--- compileClasspath
|    |    \--- com.google.cloud:google-cloud-core-grpc:1.91.2
|    |         \--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    +--- com.google.cloud:google-cloud-core:1.91.2
|    |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    |    \--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
|    +--- com.google.api:gax:1.49.0
|    |    +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
|    |    +--- com.google.cloud:google-cloud-core-grpc:1.91.2 (*)
|    |    +--- com.google.api:gax-grpc:1.49.0 (*)
|    |    \--- com.google.cloud:google-cloud-core:1.91.2 (*)
|    \--- io.grpc:grpc-alts:1.23.0 (requested com.google.auth:google-auth-library-oauth2-http:0.13.0)
|         \--- com.google.api:gax-grpc:1.49.0 (*)
\--- com.google.protobuf:protobuf-java-util:3.10.0
     +--- com.google.cloud:google-cloud-bigtable:1.5.0 (*)
     +--- com.google.cloud:google-cloud-core:1.91.2 (*)
     \--- io.grpc:grpc-grpclb:1.23.0 (requested com.google.protobuf:protobuf-java-util:3.9.0)
          \--- io.grpc:grpc-alts:1.23.0 (*)

(*) - dependencies omitted (listed previously)

A web-based, searchable dependency report is available by adding the --scan option.

BUILD SUCCESSFUL in 662ms
1 actionable task: 1 executed

For now the simpliest solution is to declare the dependency itself.

    implementation "com.google.guava:guava:29.0-jre"

But then it requires more manual intervention to align the version with the transitive one. E.g. if trnasitive is bumped to 30, this require to bump this dependency as well.

I've seen the substution DSL, but this requires more lines, and suffer from the same drawback, I need to set the version.

configurations.all {
    resolutionStrategy.dependencySubstitution {
        substitute module('com.google.guava:guava') using module('com.google.guava:guava:29.0-jre') withoutClassifier()
    }
}
@jjohannes
Copy link
Owner

@bric3 It is working, but the dependency insight report does not show which jar is selected. As you see, here the "Java 8" compatible variant was picked.

com.google.guava:guava:28.1-android
   variant "jdk8Compile" [
      org.gradle.jvm.version         = 8 (compatible with: 11)
      org.gradle.status              = release (not requested)
      org.gradle.usage               = java-api
      org.gradle.libraryelements     = jar (compatible with: classes)
      org.gradle.category            = library

      Requested attributes not found in the selected variant:
         org.gradle.dependency.bundling = external
   ]
   Selection reasons:
      - By conflict resolution : between versions 28.1-android, 26.0-android and 28.0-android

In particular: org.gradle.jvm.version = 8 (compatible with: 11)

The module GAV itself is still com.google.guava:guava:28.1-android because we cannot change that anymore during variant selection. But it does not matter as with this plugin, 28.1-android and 28.1-jre are identical (except for the version String itself). Both 28.1-android and 28.1-jre provide both Guava variants. So first Gradle selects one of these Guava "versions" by version conflict resolution. For Gradle, these just look like different versions, because the variant is encoded in the version number - which is a "hack" Guava does as there is no variant concept in pom.

In a stage after that, Gradle chooses one of the variants. In your example it chooses the Java 8 variant as expected.

It would be nice, if Gradle has a reporting task built-in to show you the actual artifacts (jars) that are resolved. Unfortunately, it does not have it at the moment. You can write your own simple task for it, to verify that it is working as expected:

tasks.register("printJars") {
  doLast {
    configurations.compileClasspath.get().files.forEach { println(it.name) }
  }
}

Note: Version 0.1 of the plugin does not support the latest release (Guava 29.0). I plan to publish a new plugin version later today.

I will also attempt to add a readme to the repository explaining what I wrote here to avoid confusion for other users.

@jjohannes
Copy link
Owner

A new version of the plugin (0.2) has been released and the readme was updated.

@bric3
Copy link
Author

bric3 commented Oct 12, 2020

@jjohannes Thank you for your insight. I might have built upon a wrong expectation from the plugin, that it will choose / substitute jre variant over the android one if the consumer is targetting a JDK. Thank you for rectifying this and explaing it to me !

Also I'm not sure about this though as both only ship one jar. What do you mean (ABI compatibility) ?

Both 28.1-android and 28.1-jre provide both Guava variants.

@jjohannes
Copy link
Owner

@bric3 I probably need to explain this a bit better. What the plugin does is effectively merging two versions of Guava (e.g. 28.1-android and 28.1-jre) into one. It assumes that these versions are always released together. 28.1-android and 28.1-jre are then identical versions from Gradle's point of view. And it does not matter which one you select.

Each version then has both jars in different variants. And Gradle selects one of them based on which JDK you are targeting.

If this information where published with Gradle Module Metadata, it would look like this:

  ...
  "variants": [
    {
      "name": "jdk8RuntimeElements",
      "attributes": {
        "org.gradle.category": "library",
        "org.gradle.jvm.version": 8,
        "org.gradle.libraryelements": "jar",
        "org.gradle.usage": "java-runtime"
      },
      "dependencies": [
        ...
      ],
      "files": [
        {
          "name": "guava-28.1-jre.jar",
          "url": "guava-28.1-jre.jar"
        }
      ]
    },
    {
      "name": "jdk6RuntimeElements",
      "attributes": {
        "org.gradle.category": "library",
        "org.gradle.jvm.version": 6,
        "org.gradle.libraryelements": "jar",
        "org.gradle.usage": "java-runtime"
      },
      "dependencies": [
        ...
      ],
      "files": [
        {
          "name": "guava-28.1-android.jar",
          "url": "../28.1-android/guava-28.1-android.jar"
        }
      ],
    }
  ]
}

(Guava will most likely publish this in the the next release - google/guava#3683 - and then this plugin would no longer be needed)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants