2013-02-09 4 views
23

Я пытаюсь преобразовать проект scala в развернутую флягу с использованием sbt-assembly. Когда я запускаю мою сборочную задачу в SBT я получаю следующее сообщение об ошибке:Проблемы сборки-слияния-стратегии с использованием sbt-assembly

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 сборки:

If multiple files share the same relative path (e.g. a resource named application.conf in multiple dependency JARs), the default strategy is to verify that all candidates have the same contents and error out otherwise. This behavior can be configured on a per-path basis using either one of the following built-in strategies or writing a custom one:

  • MergeStrategy.deduplicate is the default described above
  • MergeStrategy.first picks the first of the matching files in classpath order
  • MergeStrategy.last picks the last one
  • MergeStrategy.singleOrError bails out with an error message on conflict
  • MergeStrategy.concat simply concatenates all matching files and includes the result
  • MergeStrategy.filterDistinctLines also concatenates, but leaves out duplicates along the way
  • MergeStrategy.rename renames the files originating from jar files
  • MergeStrategy.discard simply discards matching files

Идя по этой установке I моего 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 

Может кто-нибудь указать на то, что я могу делать неправильно здесь?

Благодаря

ответ

7

Я думаю, что это должно быть MergeStrategy.first с капиталом M, так mergeStrategy in assembly := MergeStrategy.first.

+0

Похлопывая головой. Это был такой надзор. Спасибо, что указали это. –

+1

не работает для меня, он говорит: build.sbt: 27: ошибка: не найден: значение mergeStrategy mergeStrategy в сборе: = MergeStrategy.first ^ [ошибка] Тип ошибки в выражение – stantonk

+0

@stantonk: Вы были в состоянии разрешить его? – gjain

11

Что касается текущей версии 0.11.2 (2014-03-25), то способ определения стратегии слияния отличается.

Это документально here, соответствующая часть:

NOTE: mergeStrategy in assembly expects a function, you can't do

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) 
    } 
} 

Это, возможно, применима к более ранним версиям, а также, Я не знаю точно, когда он изменился.

+2

Последний пример (который является официальным) не работает на scala 10, показывая несоответствие типа – tribbloid

+0

@tribbloid Я проверил фрагмент в 'assembly.sbt', и он работает (Scala 2.10.3, sbt 0.13.2). – Beryllium

8

У меня есть только установка немного SBT проект, который необходимо перемонтировать некоторые mergeStrategies, и нашел ответ немного устаревший, позвольте мне добавить мой рабочий код для версий (от 4-7-2015)

  • SBT 0.13.8
  • 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", [email protected]_ *) => MergeStrategy.last // For Log$Logger.class 
        case x => 
        val oldStrategy = (mergeStrategy in assembly).value 
        oldStrategy(x) 
    } 
    
+8

'mergeStrategy' устарел сейчас, вместо этого используйте' assemblyMergeStrategy'. –

3

Для новой версии sbt (sbt-версия: 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 
    } 
} 
0

это правильный способ объединить большую часть общего 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}