首页 > 解决方案 > 在 gradle 依赖中,为什么 API 配置会丢弃所有传递依赖?

问题描述

我有一个包含 2 个子项目的 gradle 项目:common 和 demo。

公共项目依赖于一个已发布的库:

dependencies {

    implementation("eu.timepit:singleton-ops_${vs.scalaBinaryV}:0.5.0")
...

演示项目依赖于 common 作为其 API 的一部分:

dependencies {

    api(project(":common")) {
        isTransitive =true
    }
}

当我编译两者时,我观察到共同的正确依赖关系:

compileClasspath - Compile classpath for source set 'main'.
+--- org.scala-lang:scala-compiler:2.12.11
|    +--- org.scala-lang:scala-library:2.12.11
|    +--- org.scala-lang:scala-reflect:2.12.11
|    |    \--- org.scala-lang:scala-library:2.12.11
|    \--- org.scala-lang.modules:scala-xml_2.12:1.0.6
+--- org.scala-lang:scala-library:2.12.11
+--- org.scala-lang:scala-reflect:2.12.11 (*)
\--- eu.timepit:singleton-ops_2.12:0.5.0
     +--- org.scala-lang:scala-compiler:2.12.8 -> 2.12.11 (*)
     +--- org.scala-lang:scala-library:2.12.8 -> 2.12.11
     \--- com.chuusai:shapeless_2.12:2.3.3
          +--- org.scala-lang:scala-library:2.12.4 -> 2.12.11
          \--- org.typelevel:macro-compat_2.12:1.1.1
               \--- org.scala-lang:scala-library:2.12.0 -> 2.12.11

但是在demo中,common下的传递依赖是空的!

compileClasspath - Compile classpath for source set 'main'.
+--- project :common
+--- org.scala-lang:scala-compiler:2.12.11
...

这会导致非常常见的类路径丢失错误,例如:

[Error] /xxx/DoubleVectorDemo.scala:9: Symbol 'type shapeless.ProductArgs' is missing from the classpath.
This symbol is required by 'object edu.umontreal.kotlingrad.shapesafe.tensor.DoubleVector'.
Make sure that type ProductArgs is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
A full rebuild may help if 'DoubleVector.class' was compiled against an incompatible version of shapeless.

那么为您的 API 的一部分删除库有什么意义呢?以及如何在所有项目中覆盖这种行为?

标签: gradlegradle-kotlin-dsltransitive-dependency

解决方案


从 gradle java-plugin文档,

api 配置应该用于声明库 API 导出的依赖项,而 implementation 配置应该用于声明组件内部的依赖项。出现在 api 配置中的依赖项将传递给库的使用者,因此将出现在使用者的编译类路径中。另一方面,在实现配置中找到的依赖项不会暴露给消费者,因此不会泄漏到消费者的编译类路径中

假设您想要公开eu.timepit:singleton-ops_${vs.scalaBinaryV}:0.5.0所有公共库,那么您需要将其添加为api公共模块 build.gradle.kts 中的依赖项。

dependencies {

api("eu.timepit:singleton-ops_${vs.scalaBinaryV}:0.5.0")

推荐阅读