2013-02-09 15 views
23

Ich versuche, ein Scala-Projekt in ein einsetzbares Fettglas mit sbt-assembly konvertieren. Wenn ich meine Montageaufgabe in sbt laufen erhalte ich folgende Fehlermeldung:Assembly-Merge-Strategie Probleme mit 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 

Und von der SBT-Montagedokumentation:

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

dieses ich mein Setup build.sbt gehen Sie wie folgt vor:

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 

In der letzten Zeile des build.sbt, ich habe:

mergeStrategy in assembly := mergeStrategy.first 
Jetzt

, wenn ich SBT laufen lasse, erhalte ich folgende Fehlermeldung:

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

Kann jemand darauf hinweisen, was ich hier falsch sein könnte tun?

Dank

Antwort

7

ich denke, es M, so mergeStrategy in assembly := MergeStrategy.firstMergeStrategy.first mit einem Kapital sein sollte.

+0

Ohrfeigen mein Kopf. Das war so ein Versehen. Danke, dass du es aufgezeigt hast. –

+1

nicht für mich arbeiten, heißt es: build.sbt: 27: Fehler: nicht gefunden: Wert mergeStrategy mergeStrategy in der Montage: = MergeStrategy.first ^ [Fehler] Typ Fehler in Ausdruck – stantonk

+0

@stantonk: Können Sie um es zu lösen? – gjain

11

Wie bei der aktuellen Version 0.11.2 (2014-03-25) ist die Definition der Zusammenführungsstrategie anders.

Diese here dokumentiert ist, der relevante Teil ist:

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

mergeStrategy in assembly := MergeStrategy.first 

Der neue Weg (aus der gleichen Quelle kopiert) wird:

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

, dies auch zu früheren Versionen möglicherweise anwendbar ist, Ich weiß nicht genau wann es sich geändert hat.

+2

Das letzte Beispiel (das offiziell ist) funktioniert nicht auf scala 10, zeigt Typ Mismatch – tribbloid

+0

@tribbloid Ich habe das Schnipsel in einer 'assembly.sbt' getestet, und es funktioniert (Scala 2.10.3, sbt 0.13.2). – Beryllium

8

Ich habe gerade Setup ein wenig sbt Projekt, das einige mergeStrategies neu verkabeln muss und fand die Antwort ein wenig veraltet, lassen Sie mich für Versionen meine Arbeits Code hinzufügen (Stand 4-7-2015)

  • SBT 0.13.8
  • scala 2.11.6
  • Montage 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' ist jetzt veraltet, verwenden Sie stattdessen' assemblyMergeStrategy'. –

3

Für die neue sbt-Version (sbt-Version: 0.13.11) bekam ich den Fehler für slf4j; für die Zeit genommen wird, den einfachen Weg: Bitte auch hier die Antwort Scala SBT Assembly cannot merge due to de-duplication error in StaticLoggerBinder.class wo sbt-dependency-graph Werkzeug erwähnt wird, die ziemlich cool ist dies manuell

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

ist dies die richtige Art und Weise zu tun, die meisten gängigen Java zu fusionieren/Scala-Projekte. es kümmert sich um META-INF und Klassen.

auch die Service-Registrierung in META-INF ist erledigt.

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}