使用Square's Wire

时间:2018-06-28 01:35:00

标签: android protocol-buffers maven-publish android-d8 square-wire

在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个模块ABCA取决于BCBC都托管在内部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同时依赖于BC时,D8会感到悲伤。

那么,您如何依赖可传递依赖于Wire的多个模块?

1 个答案:

答案 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