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

update to Guava 32.1.1-android: duplicate classes - not solved by advice in release notes #6618

Open
mathisdt opened this issue Jul 1, 2023 · 12 comments
Labels
P3 platform=android status=triaged type=other Miscellaneous activities not covered by other type= labels

Comments

@mathisdt
Copy link

mathisdt commented Jul 1, 2023

An Android project would not build correctly but always complain about duplicate classes:

Execution failed for task ':app:checkDebugDuplicateClasses'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
   > Duplicate class com.google.common.util.concurrent.ListenableFuture found in modules jetified-guava-32.1.1-android (com.google.guava:guava:32.1.1-android) and jetified-listenablefuture-1.0 (com.google.guava:listenablefuture:1.0)

The release notes of 32.1.0 (which are referenced in 32.1.1) said to use

configurations.all {
  resolutionStrategy.capabilitiesResolution.withCapability("com.google.collections:google-collections") {
    select("com.google.guava:guava:0")
  }
  // and/or
  resolutionStrategy.capabilitiesResolution.withCapability("com.google.guava:listenablefuture") {
    select("com.google.guava:guava:0")
  }
}

to solve this problem, but it didn't work.

What worked instead was to add:

dependencies {
    # dependency definitions here ...
    modules {
        module("com.google.guava:listenablefuture") {
            replacedBy("com.google.guava:guava", "listenablefuture is part of guava")
        }
    }
}
@mathisdt mathisdt changed the title update to Guava 32.1.1-android: duplicate classes - not solved by andvice in release notes update to Guava 32.1.1-android: duplicate classes - not solved by advice in release notes Jul 1, 2023
@cpovirk
Copy link
Member

cpovirk commented Jul 1, 2023

Thanks. @jjohannes , any advice?

@jjohannes
Copy link
Contributor

Without more information, I can only guess.

Looks like the conflict is not detected by Gradle's core systems and only checkDebugDuplicateClasses of the Android plugin is catching this later.

If the conflict is not detected, the capability resolutions strategy from the release notes has no effect.

Question is: why is the conflict not detected?

Could be that this is a bug in Gradle. There have been issues in this area in some versions and there is still one open issue I know of: gradle/gradle#22326
This is not a general problem, but a very specific configuration and combination of dependencies seems to make Gradle miss the conflict.

Would you be able to share some more information about your setup @mathisdt?

  • Which Gradle version are you using and, if it is not the latest, could you try updating?
  • Can you share a build scan or the output of the dependencies task? (if you can't share that in public, you may send me a mail.)

@mathisdt
Copy link
Author

mathisdt commented Jul 2, 2023

@jjohannes Should be no problem, the app is open source.

I'm using Gradle 8.1.1 at the moment.

When I remove the workaround I mentioned above, the following happens:

# ./gradlew build

> Task :app:processDebugMainManifest
/home/mathis/source-git/trackworktime/app/src/main/AndroidManifest.xml:36:9-42:51 Warning:
        provider#org.acra.attachment.AcraContentProvider@android:authorities was tagged at AndroidManifest.xml:36 to replace other declarations but no other declaration present

> Task :app:checkDebugDuplicateClasses FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:checkDebugDuplicateClasses'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
   > Duplicate class com.google.common.util.concurrent.ListenableFuture found in modules jetified-guava-32.1.1-android (com.google.guava:guava:32.1.1-android) and jetified-listenablefuture-1.0 (com.google.guava:listenablefuture:1.0)
     
     Go to the documentation to learn how to <a href="d.android.com/r/tools/classpath-sync-errors">Fix dependency resolution errors</a>.

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 2s
22 actionable tasks: 7 executed, 15 up-to-date

The link of the corresponding build scan is https://scans.gradle.com/s/umgfcfz2bykyy

@mathisdt
Copy link
Author

mathisdt commented Jul 2, 2023

PS: I just saw that Gradle 8.2 came out two days ago. I updated to 8.2 but the outcome was the same - fine with the workaround, "build failed" without it (also "Duplicate class ..." message).

You can try for yourself, just clone it and remove these lines. That will trigger the error.

@jjohannes
Copy link
Contributor

jjohannes commented Jul 3, 2023

Thank you @mathisdt. This is perfect to reproduce the problem. You can see in the build scan, that both guava (with the new metadata) and listenablefuture:1.0 are on the debugRuntimeClasspath. And both have the com.google.guava:listenablefuture:1.0 capability. So there should be a conflict but Gradle silently accepts it:

For me this look like the issue that I reported – gradle/gradle#22326 – but this is a better reproducer.

@chaoren
Copy link
Member

chaoren commented Jul 5, 2023

Is there anything to do here from the Guava side? Maybe we should mention the workaround in #6618 (comment) somewhere. Or just leave this issue open until the Gradle issue is resolved I guess.

@cpovirk
Copy link
Member

cpovirk commented Jul 5, 2023

Thanks, everyone.

I've added this to the release notes, and I've subscribed to the Gradle issue.

@isomeme
Copy link

isomeme commented Jul 15, 2023

I am attempting to update my Android app's guava dependency from 31.1-jre to 32.1.1-jre. Updating only that leads to the gradle listenablefuture conflict mentioned above. So I attempted to apply the "this worked" portion of this comment, like this:

dependencies {
...
    implementation 'com.google.guava:guava:32.1.1-jre'

    modules {
        module("com.google.guava:listenablefuture") {
            replacedBy("com.google.guava:guava", "listenablefuture is part of guava")
        }
    }
...
}

Gradle update now completes successfully, but building fails. Specifically, it seems that a specific subset of guava is missing, consisting of Java 8 methods and AutoValue processing.

image

Does anyone have any idea how to make this work? I have no urgent need to upgrade guava in my project, but I do like to stay up to date whenever possible, and I'm also now curious about how to resolve this issue.

@cpovirk
Copy link
Member

cpovirk commented Jul 15, 2023

Hello, stranger :)

It sounds like the problem may be that our new Gradle metadata is overriding your choice to use the -jre flavor of Guava because you're building an Android app. That means that you get a version that doesn't contain the Streams class or any Collector APIs (which also leads to errors that prevent AutoValue from running).

I guess I'm not too surprised that the -jre flavor can work on Android (for people targeting a new enough version or using desugaring), but I wouldn't necessarily have recommended it :) [edit: Update: I thought about it some more in response to another question, and I would recommend against it.]

You might be able to force the JRE flavor by following a tweaked version of the instructions under "Selecting the appropriate flavor," also in the release notes. You'd be tweaking them to replace "ANDROID" with "STANDARD_JVM" (and, if you need the second section, replacing "android" with "jre").

What would be nicer for you is if we implemented #6567 so that the APIs you need were available on the Android flavor, at which point you could presumably use that.

@joe61fa6f1awe
Copy link

Hi, I'm a university student at Australian National University. One of my current assignments requires us to finish some issues on OSS. One of the repositories is your project. May I try to take this issue? Just have a ask to make sure whether the issue is solved or not because it is still open and no assignee.

@hnljp
Copy link

hnljp commented Oct 24, 2023

When both guava and listenablefuture are in your dependency tree remember to choose the empty listenablefuture dependency, as the classes are already existing in guava.
implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
It has been that way for the last five years:
https://github.com/google/guava/blob/b49353abca20517e449b0a00f66bb5455608290a/futures/listenablefuture9999/pom.xml

@mathisdt
Copy link
Author

mathisdt commented Oct 24, 2023

@joe61fa6f1awe I don't know if this is really a Guava issue, maybe it is a Gradle problem which has only been triggered by Guava - please see above.

Maybe @cpovirk or @jjohannes can shed some light as to whether this is a good starting point for you?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P3 platform=android status=triaged type=other Miscellaneous activities not covered by other type= labels
Projects
None yet
Development

No branches or pull requests

7 participants