2013-02-09 1 views
23

Sto provando a convertire un progetto scala in un contenitore di grassi deployable utilizzando sbt-assembly. Quando eseguo il mio compito di assemblaggio in SBT Sto ottenendo il seguente errore:problemi di assembly-merge-strategy con 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 

Ora dalla documentazione SBT-assemblaggio:

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

Andando da questa configurazione ho il mio build.sbt come segue:

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 

nell'ultima riga del build.sbt, ho:

mergeStrategy in assembly := mergeStrategy.first 

Ora, quando corro SBT, ottengo il seguente errore:

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

Qualcuno può sottolineare quello che potrebbe essere sbagliato qui?

Grazie

risposta

7

penso che dovrebbe essere MergeStrategy.first con un capitale M, così mergeStrategy in assembly := MergeStrategy.first.

+0

Schiaffegiando la testa. Era una tale svista. Grazie per segnalarlo. –

+1

non funziona per me, che dice: build.sbt: 27: errore: non trovato: il valore mergeStrategy mergeStrategy in assemblea: = MergeStrategy.first ^ [errore] Errore nell'espressione – stantonk

+0

@stantonk Tipo: Sei riuscito per risolverlo? – gjain

11

Per quanto riguarda la versione corrente 0.11.2 (2014-03-25), il modo per definire la strategia di unione è diverso.

Questo è documentato here, la parte rilevante è:

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

mergeStrategy in assembly := MergeStrategy.first 

Il nuovo modo è (copiato dalla stessa fonte):

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

Questa è forse applicabile alle versioni precedenti, nonché, Non so esattamente quando è cambiato.

+2

L'ultimo esempio (che è ufficiale) non funziona su scala 10, che mostra la mancata corrispondenza di Tipo – tribbloid

+0

@tribbloid Ho testato lo snippet in un 'assembly.sbt', e funziona (Scala 2.10.3, sbt 0.13.2). – Beryllium

8

ho appena messa a punto di un progetto SBT po 'che ha bisogno di ricablare alcuni mergeStrategies, e ha trovato la risposta un po' datata, mi permetta di aggiungere il mio codice di lavoro per le versioni (a partire dal 4-7-2015)

  • SBT 0.13.8
  • scala 2.11.6
  • montaggio 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' è ora deprecato, usa invece' assemblyMergeStrategy'. –

3

Per la nuova versione di sbt (sbt-version: 0.13.11), ricevevo l'errore per slf4j; per il momento ha preso la strada più facile: Si prega di controllare anche la risposta qui Scala SBT Assembly cannot merge due to de-duplication error in StaticLoggerBinder.class in cui è menzionato sbt-dependency-graph strumento che è abbastanza freddo per farlo manualmente

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

questo è il modo corretto per unire la maggior parte del Java comuni/scala progetti. si occupa di META-INF e classi.

anche la registrazione del servizio in META-INF è curata.

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}