首页 > 解决方案 > 使用 Square 的 Wire 时出现 D8 异常

问题描述

在 Android 项目中添加 Square 的Wire库以支持 Protobuf 后,我在编译期间收到以下 D8 异常:

D8:程序类型已经存在:com.google.protobuf.DescriptorProto$ExtensionRange$ProtoAdapter_ExtensionRange

电线依赖:implementation 'com.squareup.wire:wire-runtime:2.2.0'

GradledependencyInsight在我的项目中揭示了另一个依赖项,即传递引入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取决于BCB并且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时,D8 会变得悲伤。ABC

那么你如何依赖于传递依赖于 Wire 的多个模块呢?

标签: androidprotocol-buffersmaven-publishandroid-d8square-wire

解决方案


D8伤心的原因

当您运行 Wire 代码生成时,它会在您的项目中创建一些 Java 源文件,所有其他 Wire 代码生成的代码都依赖这些文件。com.google.protobuf.DescriptorProto就是这样一个文件。因此,当您依赖两个使用 Wire 的模块时,您将拥有两个模块,它们都包含具有相同名称和包的 Java 源文件,并最终得到重复的 .class 文件。这些 .class 文件是您的库模块打包输出的一部分(不是传递依赖项),因此没有任何gradle exclude帮助(除非您知道一些我不知道的 Gradle 恶作剧?...)。

可能的解决方案

在库模块中设置打包选项以包含 java 源代码,以便您仍然可以编译,但在打包 aar 时排除 .class 文件。我试过这个,但无法使打包选项实际上排除 .class 文件。即使它有效,我也不喜欢这种方法,所以我放弃了它。

(没有尝试,可能有效)com.google.protobuf将 Wire 生成的源文件捆绑到您自己的单独库中,以便它们成为传递依赖项。您可能希望在运行 Wire 后编写一个处理此过程的 gradle 任务,以免每次都手动移动这些文件。在您的应用程序中包含所述库的单个副本并用于gradle exclude忽略传递。

最终这感觉时间同步太多了,我选择使用Protobuf Gradle 插件


推荐阅读