在Android项目中添加Square的Wire库以支持Protobuf之后,在编译过程中出现了以下D8异常:
D8:程序类型已存在:com.google.protobuf.DescriptorProto $ ExtensionRange $ ProtoAdapter_ExtensionRange
线路依赖项:implementation 'com.squareup.wire:wire-runtime:2.2.0'
Gradle的dependencyInsight
透露了我项目中的另一个依赖关系,该依赖关系可传递性地带来了com.google.protobuf.nano:protobuf-javanano:3.1.0
。所以我添加了一个排除项:
implementation ('com.google.vr:sdk-base:1.100.0'){
exclude group: 'com.google.protobuf.nano'
}
但这并不能解决问题。
是什么使D8感到悲伤,我又该如何使它快乐?
更新
有问题的设置是:有3个模块A
,B
,C
。 A
取决于B
和C
。 B
和C
都托管在内部Maven服务器上,它们各自依赖于wire-runtime
并带有以下POM条目:
<dependency>
<groupId>com.squareup.wire</groupId>
<artifactId>wire-runtime</artifactId>
<version>2.3.0-RC1</version>
<scope>compile</scope>
</dependency>
我尝试了Wire 2.2和2.3.0版本。当A
仅依赖于B
或仅依赖C
时,一切都是桃子的,但是当A
同时依赖于B
和C
时,D8会感到悲伤。
那么,您如何依赖可传递依赖于Wire的多个模块?
答案 0 :(得分:0)
D8难过的原因
当您运行Wire代码生成器时,它将在您的项目中创建一些Java源文件,所有其他Wire代码生成的代码都依赖该Java源文件。 com.google.protobuf.DescriptorProto
是一个这样的文件。因此,当您依赖于两个使用Wire的模块时,就有两个模块都包含一个具有相同名称和包的Java源文件,并以重复的.class文件结尾。这些.class文件是您的库模块打包输出(不是传递依赖项)的一部分,因此gradle exclude
不会有帮助(除非您知道我不知道的某些Gradle恶作剧?...)。
可能的解决方案
在库模块中设置打包选项以包括java源代码,以便您仍然可以编译,但打包aar时不包括.class文件。我试过了,但是无法使打包选项实际上排除.class文件。即使该方法可行,我也并不疯狂,因此我保住了它。
(没有尝试过,可能会起作用)将Wire产生的com.google.protobuf
源文件捆绑到您自己的单独的lib中,这样它们就成为传递依赖项。您可能希望编写一个gradle任务来处理此过程,然后再运行Wire,以免每次都手动移动这些文件。在您的应用程序中包含一个上述lib的单个副本,并使用gradle exclude
忽略传递项。
最终,这感觉太像时间同步了,我选择使用Protobuf Gradle Plugin