如何解决 sbt 中具有不同包装 ivy 类型的依赖项?

Posted

技术标签:

【中文标题】如何解决 sbt 中具有不同包装 ivy 类型的依赖项?【英文标题】:How can I resolve a dependency in sbt that has a different packaging ivy type? 【发布时间】:2018-06-08 07:22:34 【问题描述】:

在我的示例中,我需要解决一个依赖项,其工件没有常规的 jar 作为包装类型,而是 maven-plugin(更具体地说,我感兴趣的工件是一个 Maven 插件) .这在 Maven 领域是通过 <packaging> XML 标记指定的。

当我在 sbt 构建中添加我的项目所依赖的插件时,sbt 成功更新了项目,但解析的依赖项不在类路径中。如何让 sbt 将工件添加到我的类路径中,以便编译依赖于此类依赖项的代码?

我用来将 maven 插件添加到构建中的代码:

libraryDependencies += "net.alchim31.maven" % "scala-maven-plugin" % "3.3.1"

【问题讨论】:

【参考方案1】:

有两个原因导致 sbt 没有将所需的工件添加到类路径中,因此编译失败。

第一个原因是,默认情况下,sbt 只识别包装类型有限的工件(jarbundle 等等)。为了告诉 sbt 我们对打包类型为 maven-plugin 的工件感兴趣,我们需要明确地告诉我们想要从依赖项中获得哪些工件:

libraryDependencies += ("net.alchim31.maven" % "scala-maven-plugin" % "3.3.1")
  .withExplicitArtifacts(Vector("scala-maven-plugin", "maven-plugin", "jar"))

完成此操作后,我们可以通过在consoleProject 中运行以下代码来确认 sbt 确实获得了我们的工件:

Keys.update.in(myScope).in(myProject).eval.allFiles
  .find(_.getAbsolutePath.contains("net"))

注意myScope 必须是CompileTestRuntime(通常是Compile)并且myProject 必须是对您已在其中声明依赖项的项目的引用。上一次操作的结果,如果一切顺利的话,将会是Some(...),表示该神器确实被解析并检测到了。

但是,我们还没有完成。如果我们从 sbt shell 运行 myProject/dependencyClasspath,我们将不会在那里看到我们的工件。这是需要第二步的地方:我们需要将新的打包类型添加到classpathTypes,以便 sbt 将工件添加到我们的编译类路径中。

classpathTypes += "maven-plugin"

完成所有这些后,我们应该运行 myProject/dependencyClasspath 并查看我们的工件。

但故事还没有结束,我们进入了“bug”领域。 Sbt 不会自动将classpathTypes 中的打包类型添加到负责在 pom 文件中声明依赖关系的 pom 配置中。请注意,否则您的应用程序将失败并出现 ClassNotFoundException 或类似问题,因为并非所有相关工件都已解析并加载类。

所以为了有一个工作的应用程序,你需要自己做:

makePomConfiguration :=
  makePomConfiguration.value.withIncludeTypes(classpathTypes.value)

默认情况下没有这样做,这只是 1.x 中的一个 sbt 错误。

【讨论】:

以上是关于如何解决 sbt 中具有不同包装 ivy 类型的依赖项?的主要内容,如果未能解决你的问题,请参考以下文章

什么时候在 Scala 中使用 SBT 和 Ivy 模糊地选择了具有相同定义和类路径的两个类?

具有变量的 maven 依赖项的 Ivy/sbt 错误,是不是有修复?

手动检索 Ivy 依赖项作为 sbt 中的本地非托管库

sbt/ivy 无法解析通配符 ivy 对文件系统解析器的依赖

如何在 IntelliJ IDEA 中改变 Ivy 的家

SBT 如何为特定的 groupid 禁用 Ivy 缓存