【问题标题】:assembly-merge-strategy issues using sbt-assembly使用 sbt-assembly 的程序集合并策略问题
【发布时间】:2013-01-25 08:42:58
【问题描述】:

我正在尝试使用 sbt-assembly 将 scala 项目转换为可部署的 fat jar。当我在 sbt 中运行我的组装任务时,我收到以下错误:

Merging 'org/apache/commons/logging/impl/SimpleLog.class' with strategy 'deduplicate'
    :assembly: deduplicate: different file contents found in the following:
    [error] /Users/home/.ivy2/cache/commons-logging/commons-logging/jars/commons-logging-1.1.1.jar:org/apache/commons/logging/impl/SimpleLog.class
    [error] /Users/home/.ivy2/cache/org.slf4j/jcl-over-slf4j/jars/jcl-over-slf4j-1.6.4.jar:org/apache/commons/logging/impl/SimpleLog.class

现在来自 sbt-assembly 文档:

如果多个文件共享相同的相对路径(例如,一个名为 application.conf 在多个依赖 JAR 中),默认策略是 验证所有候选人具有相同的内容和错误 否则。可以使用基于每个路径配置此行为 以下内置策略之一或编写自定义策略:

  • MergeStrategy.deduplicate 是上述默认值
  • MergeStrategy.first 按类路径顺序选择第一个匹配的文件
  • MergeStrategy.last 选择最后一个
  • MergeStrategy.singleOrError 退出并显示冲突错误消息
  • MergeStrategy.concat 只是连接所有匹配的文件并包含结果
  • MergeStrategy.filterDistinctLines 也可以连接,但会沿途省略重复项
  • MergeStrategy.rename 重命名来自 jar 文件的文件
  • MergeStrategy.discard 只是丢弃匹配的文件

通过这个,我将 build.sbt 设置如下:

import sbt._
import Keys._
import sbtassembly.Plugin._
import AssemblyKeys._
name := "my-project"
version := "0.1"
scalaVersion := "2.9.2"
crossScalaVersions := Seq("2.9.1","2.9.2")

//assemblySettings
seq(assemblySettings: _*)

resolvers ++= Seq(
    "Typesafe Releases Repository" at "http://repo.typesafe.com/typesafe/releases/",
    "Typesafe Snapshots Repository" at "http://repo.typesafe.com/typesafe/snapshots/",
    "Sonatype Repository" at "http://oss.sonatype.org/content/repositories/releases/"
)

libraryDependencies ++= Seq(
    "org.scalatest" %% "scalatest" % "1.6.1" % "test",
    "org.clapper" %% "grizzled-slf4j" % "0.6.10",
    "org.scalaz" % "scalaz-core_2.9.2" % "7.0.0-M7",
    "net.databinder.dispatch" %% "dispatch-core" % "0.9.5"
)

scalacOptions += "-deprecation"
mainClass in assembly := Some("com.my.main.class")
test in assembly := {}
mergeStrategy in assembly := mergeStrategy.first

在 build.sbt 的最后一行,我有:

mergeStrategy in assembly := mergeStrategy.first

现在,当我运行 SBT 时,我收到以下错误:

error: value first is not a member of sbt.SettingKey[String => sbtassembly.Plugin.MergeStrategy]
    mergeStrategy in assembly := mergeStrategy.first

有人能指出我在这里做错了什么吗?

谢谢

【问题讨论】:

  • mergeStrategy 现在已弃用。请改用assemblyMergeStrategy。我正在使用汇编版本0.14.10

标签: scala deployment sbt executable-jar sbt-assembly


【解决方案1】:

对于当前版本0.11.2(2014-03-25),定义合并策略的方式不同。

这是记录在here,相关部分是:

注意: 汇编中的mergeStrategy需要一个函数,你不能这样做

mergeStrategy in assembly := MergeStrategy.first

新方法是(从同一来源复制):

mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
  {
    case PathList("javax", "servlet", xs @ _*)         => MergeStrategy.first
    case PathList(ps @ _*) if ps.last endsWith ".html" => MergeStrategy.first
    case "application.conf" => MergeStrategy.concat
    case "unwanted.txt"     => MergeStrategy.discard
    case x => old(x)
  }
}

这可能也适用于早期版本,我不知道它是什么时候改变的。

【讨论】:

  • 最后一个例子(这是官方的)在 scala 10 上不起作用,显示类型不匹配
  • @tribbloid 我已经在assembly.sbt 中测试了 sn-p,它可以工作(Scala 2.10.3,sbt 0.13.2)。
【解决方案2】:

我认为应该是MergeStrategy.first,大写M,所以mergeStrategy in assembly := MergeStrategy.first

【讨论】:

  • 拍我的头。那是一种疏忽。感谢您指出。
  • 对我不起作用,它说:build.sbt:27: error: not found: value mergeStrategy mergeStrategy in assembly := MergeStrategy.first ^ [error] Type error in expression
  • @gjain 不,我必须基本上复制整个代码并更改 mergeStrategy 通过接受第一个版本而不是失败来解决冲突的方式(也就是 maven 所做的):gist.github.com/stantonk/5303b7ec84b782a58628 我没有知道为什么 sbt 不这样做...
  • 这是不正确的。根据文档。你不能做mergeStrategy in assembly := MergeStrategy.first 因为mergeStrategy in assembly 需要一个函数,你会得到一个type mismatch error
【解决方案3】:

这是合并大多数常见 java/scala 项目的正确方法。 它负责 META-INF 和类。

还负责 META-INF 中的服务注册。

assemblyMergeStrategy in assembly := {
case x if Assembly.isConfigFile(x) =>
  MergeStrategy.concat
case PathList(ps @ _*) if Assembly.isReadme(ps.last) || Assembly.isLicenseFile(ps.last) =>
  MergeStrategy.rename
case PathList("META-INF", xs @ _*) =>
  (xs map {_.toLowerCase}) match {
    case ("manifest.mf" :: Nil) | ("index.list" :: Nil) | ("dependencies" :: Nil) =>
      MergeStrategy.discard
    case ps @ (x :: xs) if ps.last.endsWith(".sf") || ps.last.endsWith(".dsa") =>
      MergeStrategy.discard
    case "plexus" :: xs =>
      MergeStrategy.discard
    case "services" :: xs =>
      MergeStrategy.filterDistinctLines
    case ("spring.schemas" :: Nil) | ("spring.handlers" :: Nil) =>
      MergeStrategy.filterDistinctLines
    case _ => MergeStrategy.first
  }
case _ => MergeStrategy.first}

【讨论】:

  • +1 表示 META-INF 规则。这帮助我解决了将 jpmml-spark 与其他库一起打包到一个 jar 中的问题。
【解决方案4】:

我刚刚设置了一个需要重新连接一些 mergeStrategies 的小 sbt 项目,发现答案有点过时,让我添加版本的工作代码(截至 2015 年 4 月 7 日)

  • sbt 0.13.8
  • scala 2.11.6
  • 程序集 0.13.0

    mergeStrategy in assembly := {
      case x if x.startsWith("META-INF") => MergeStrategy.discard // Bumf
      case x if x.endsWith(".html") => MergeStrategy.discard // More bumf
      case x if x.contains("slf4j-api") => MergeStrategy.last
      case x if x.contains("org/cyberneko/html") => MergeStrategy.first
      case PathList("com", "esotericsoftware", xs@_ *) => MergeStrategy.last // For Log$Logger.class
      case x =>
         val oldStrategy = (mergeStrategy in assembly).value
         oldStrategy(x)
    }
    

【讨论】:

  • mergeStrategy 现在已弃用,请改用assemblyMergeStrategy
【解决方案5】:

对于新的 sbt 版本(sbt-version :0.13.11),我收到了 slf4j 的错误;暂时采取简单的方法:也请在此处查看答案Scala SBT Assembly cannot merge due to de-duplication error in StaticLoggerBinder.class,其中提到了sbt-dependency-graph 工具,手动执行此操作非常酷

assemblyMergeStrategy in assembly <<= (assemblyMergeStrategy in assembly) {
  (old) => {
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard
    case x => MergeStrategy.first
  }
}

【讨论】:

    【解决方案6】:

    快速更新:mergeStrategy 已弃用。使用 assemblyMergeStrategy。除此之外,早期的反应仍然是可靠的

    【讨论】:

      【解决方案7】:

      将以下内容添加到 build.sbt 以将 kafka 添加为源或目标

       assemblyMergeStrategy in assembly := {
       case PathList("META-INF", xs @ _*) => MergeStrategy.discard
       //To add Kafka as source
       case "META-INF/services/org.apache.spark.sql.sources.DataSourceRegister" => 
       MergeStrategy.concat
       case x => MergeStrategy.first
       }
      

      【讨论】:

        猜你喜欢
        • 2014-12-06
        • 2018-08-31
        • 2019-01-31
        • 2014-11-01
        • 2015-12-27
        • 2017-01-15
        • 2019-05-03
        • 2016-06-29
        • 2013-09-19
        相关资源
        最近更新 更多