D8 exception when using Square's Wire

266 views Asked by At

After adding Square's Wire library for Protobuf support in an Android project, I'm getting the following D8 exception during compilation:

D8: Program type already present: com.google.protobuf.DescriptorProto$ExtensionRange$ProtoAdapter_ExtensionRange

wire dependency: implementation 'com.squareup.wire:wire-runtime:2.2.0'

Gradle's dependencyInsight revealed one other dependency in my project that was transitively bringing in com.google.protobuf.nano:protobuf-javanano:3.1.0. So I added an exclude with:

implementation ('com.google.vr:sdk-base:1.100.0'){
  exclude group: 'com.google.protobuf.nano'
}

but that didn't fix the problem.

What's making D8 sad, and how can I make it happy again?

Update

The problematic setup is: have 3 modules A, B, C. A depends on B and C. B and C are both hosted on an internal maven server, they each depend on wire-runtime with the following POM entry:

<dependency>
  <groupId>com.squareup.wire</groupId>
  <artifactId>wire-runtime</artifactId>
  <version>2.3.0-RC1</version>
  <scope>compile</scope>
</dependency>

I've tried Wire version 2.2 and 2.3.0. Everything is peachy when A depends on only B or only C, but D8 gets sad when A depends on both B and C.

So how do you depend on mutliple modules that transitively depend on Wire?

1

There are 1 answers

0
Splash On

The reason D8 is sad

When you run the Wire code gen, it creates a few Java source files in your project that all of the other Wire-code-genned code depends on. com.google.protobuf.DescriptorProtois one such file. So when you depend on two modules that are using Wire, you have two modules which both contain a Java source file with the same name and package, and end up with duplicate .class files. These .class files are part of your library modules packaged output (not a transitive dependency) so no amount of gradle exclude will help (unless you know some Gradle shenanigans that I don't?...).

Possible solutions

Set up the packaging options in your library module to include the java sources so you can still compile, but exclude the .class files when packaging the aar. I tried this, but wasn't able to make the packaging options actually exclude the .class files. I wasn't wild about the approach even if it worked so I bailed on it.

(didn't try, might work) Bundle the com.google.protobuf source files that Wire produces into your own separate lib so that they do become a transitive dependency. You'd probably want to write a gradle task that handles this process after you run Wire as not to manually move those files around every time. Include a single copy of said lib in your application and use gradle exclude to ignore the transitives.

Ultimately this felt like too much of a time-sync, and I opted to use the Protobuf Gradle Plugin