web-dev-qa-db-fra.com

assemblage-fusion-strategie questions utilisant sbt-assembly

J'essaye de convertir un projet Scala en un gros pot déployable en utilisant sbt-Assembly . Lorsque j'exécute ma tâche d'assemblage dans sbt, l'erreur suivante apparaît:

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

Maintenant de la documentation sbt-Assembly:

Si plusieurs fichiers partagent le même chemin relatif (une ressource nommée Application.conf dans plusieurs fichiers JAR de dépendance, par exemple), la stratégie par défaut est vérifier que tous les candidats ont le même contenu et la même erreur de sortie autrement. Ce comportement peut être configuré chemin par chemin à l’aide de soit l'une des stratégies intégrées suivantes, soit une stratégie personnalisée:

  • MergeStrategy.deduplicate est la valeur par défaut décrite ci-dessus
  • MergeStrategy.first choisit le premier des fichiers correspondants dans l'ordre des classpath
  • MergeStrategy.last choisit le dernier
  • MergeStrategy.singleOrError abandonne avec un message d'erreur sur le conflit 
  • MergeStrategy.concat concatène simplement tous les fichiers correspondants et inclut le résultat 
  • MergeStrategy.filterDistinctLines concatène également, mais omet les doublons en cours de route
  • MergeStrategy.rename renomme les fichiers provenant des fichiers jar
  • MergeStrategy.discard supprime simplement les fichiers correspondants

En passant par ceci j'ai configuré mon build.sbt comme suit:

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

Dans la dernière ligne du build.sbt, j'ai:

mergeStrategy in Assembly := mergeStrategy.first

Maintenant, quand j'exécute SBT, j'obtiens l'erreur suivante:

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

Quelqu'un peut-il indiquer ce que je pourrais faire de mal ici?

Merci

25
sc_ray

Je pense que cela devrait être MergeStrategy.first avec une majuscule M, donc mergeStrategy in Assembly := MergeStrategy.first.

7
user500592

En ce qui concerne la version actuelle 0.11.2 (2014-03-25), la façon de définir la stratégie de fusion est différente.

Ceci est documenté ici , la partie pertinente est:

REMARQUE: mergeStrategy dans Assembly attend une fonction, vous ne pouvez pas le faire 

mergeStrategy in Assembly := MergeStrategy.first

La nouvelle manière est (copiée à partir de la même source):

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

Cela s’applique peut-être aussi aux versions précédentes, je ne sais pas exactement quand cela a changé.

11
Beryllium

Je viens de configurer un petit projet sbt qui doit modifier certaines stratégies de fusion et trouve la réponse un peu dépassée. Laissez-moi ajouter mon code de travail pour les versions (à partir du 4-7-2015).

  • sbt 0,13.8
  • note 2.11.6
  • Assemblée 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)
    }
    
8
mrArias

Pour la nouvelle version de sbt (sbt-version: 0.13.11), je rencontrais l’erreur pour slf4j; pour le moment, prenez la solution de facilité: vérifiez également la réponse ici Scala SBT Assembly ne peut pas fusionner en raison d’une erreur de déduplication dans StaticLoggerBinder.classsbt-dependency-graph est mentionné plutôt cool de le faire manuellement

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

Mise à jour rapide: mergeStrategy est obsolète. Utilisez assemblyMergeStrategy. En dehors de cela, les réponses précédentes sont encore solides

0
Jake

c’est le bon moyen de fusionner la plupart des projets Java/scala courants . Il s’occupe de META-INF et des classes.

l'enregistrement des services dans META-INF est également pris en charge.

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}
0
linehrr