web-dev-qa-db-fra.com

Quelles sont les principales différences entre sbt-pack et sbt-assembly?

Je suis juste tombé sur le plugin sbt-pack . Le flux de développement semble stable . C'est surprenant pour moi car je pensais que le seul plugin pour (citant le titre de sbt-pack) "créer des packages distribuables Scala." est sbt-Assembly (parmi les autres fonctionnalités).

Quelles sont les principales différences entre les plugins? Quand devrais-je utiliser l'un sur l'autre?

36
Jacek Laskowski

(Avertissement: je maintiens sbt-Assembly)

sbt-Assembly

sbt-Assembly crée un gros JAR - un seul fichier JAR contenant tous les fichiers de classe de votre code et de vos bibliothèques. Par évolution, il contient également des moyens de résoudre les conflits lorsque plusieurs fichiers JAR fournissent le même chemin de fichier (comme config ou README). Il implique la décompression de tous les fichiers JAR de la bibliothèque, donc c'est un peu lent, mais ceux-ci sont fortement mis en cache.

sbt-pack

sbt-pack conserve tous les fichiers JAR de la bibliothèque intacts, les déplace dans target/pack répertoire (par opposition à ivy cache où ils devraient normalement vivre), et crée un script Shell pour que vous puissiez les exécuter.

sbt-native-packager

sbt-native-packager est similaire à sbt-pack mais il a été démarré par un committer sbt Josh Suereth , et est maintenant maintenu par de très hautes capacités Nepomuk Seiler = (également connu sous le nom de muuki88). Le plugin prend en charge un certain nombre de formats comme le fichier msi Windows et le fichier deb Debian. L'ajout récent est un support pour images Docker .

Tous sont des moyens viables de créer des images de déploiement. Dans certains cas, comme le déploiement de votre application dans une infrastructure Web, etc., cela peut faciliter les choses si vous traitez avec un seul fichier au lieu d'une douzaine.

Mention honorable: sbt-progard et sbt-onejar .

69
Eugene Yokota

Bien que l'explication de Eugene Yokota soit complète, je voudrais expliquer les plugins mentionnés avec la commande package sous l'aspect des utilisations et comment différents résultats sont générés.

Paramètres de répertoire et build.sbt

lazy val commonSettings = Seq(
  organization := "stackOverFlow",
  scalaVersion := "2.11.12",
  version := "1.0",
)

lazy val app  = (project in file ("app")).
  enablePlugins(PackPlugin).
  settings(commonSettings)

Ci-dessus build.sbt le fichier déclare le projet appelé app et inclut tous les fichiers source dans le répertoire app. Pour activer les plugins Pack, enablePlugins (PackPlugin) doit être inclus dans le fichier sbt.

Aussi, j'ai mis la ligne ci-dessous dans le fichier project/plugins.sbt pour utiliser les plugins pack dans notre projet

addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.9.3")
addSbtPlugin("com.eed3si9n" % "sbt-Assembly" % "0.14.5")

Le paquet est déjà intégré dans le sbt par défaut, vous n'avez donc pas besoin de spécifier explicitement les plugins en utilisant addSbtPlugins. Cependant, les plugins sbt-pack et sbt-Assembly ne sont pas inclus par défaut dans le sbt, vous devez donc spécifier que vous souhaitez les utiliser. addSbtPlugin est un moyen de dire que "je veux utiliser des plugins xxx, yyy dans mon projet" à votre sbt.

J'ai également implémenté deux fichiers scala artificiels dans les fichiers ./app/src/main/scala:

AppBar.scala

class AppBar {
  def printDescription() = println(AppBar.getDescription)
}

object AppBar {
  private val getDescription: String = "Hello World, I am AppBar"

  def main (args: Array[String]): Unit = {
    val appBar = new AppBar
    appBar.printDescription()
  }
}

AppFoo.scala

class AppFoo {
  def printDescription() = println(AppFoo.getDescription)
}

object AppFoo {
  private val getDescription: String = "Hello World, I am AppFoo"

  def main (args: Array[String]): Unit = {
    val appFoo = new AppFoo
    appFoo.printDescription()
  }
}

paquet sbt

Il s'agit de la commande sbt très basique incluse dans le sbt pour vous aider à distribuer votre projet via le fichier jar. Le fichier jar généré par la commande package se trouve dans projectDirectoy/target/scala-2.11/app_2.11-1.0.jar (ici, les clés scalaVersion et de configuration de version spécifiées incluses dans le fichier build.sbt sont utilisées pour générer le jar nom de fichier).

Lorsque vous regardez à l'intérieur du pot, vous pouvez voir les fichiers de classe générés par l'outil sbt, qui est le résultat de la compilation des sources dans l'application/src/main/scala. En outre, il comprend un fichier MANIFEST.

$vi  projectDirectoy/target/scala-2.11/app_2.11-1.0.jar

META-INF/MANIFEST.MF
AppBar$.class
AppBar.class
AppFoo.class
AppFoo$.class

Notez qu'il inclut uniquement les fichiers de classe générés à partir des fichiers scala situés dans le répertoire app/src/main/scala. Le fichier jar généré par la commande package ne comprend aucun scala bibliothèques connexes telles que collection dans la bibliothèque scala (par exemple, collection.mutable.Map.class). Par conséquent, pour exécuter le programme, vous pouvez avoir besoin de scala car le fichier jar de génération ne contient que les classes minimales générées à partir des sources scala que j'ai implémentées. C'est la raison pour laquelle le fichier jar contient AppBar.class, AppBar $. classe pour objet compagnon, etc.

sbt-Assembly

Comme mentionné par Eugene Yokota, sbt-Assembly vous aide également à distribuer votre projet en générant le fichier jar; cependant, le fichier jar généré comprend non seulement les fichiers de classe générés par votre code source, mais également toutes les bibliothèques dont vous avez besoin pour exécuter le programme. Par exemple, pour exécuter la fonction principale définie dans l'objet AppFoo, vous pouvez avoir besoin des bibliothèques scala. En outre, lorsque vous ajoutez des bibliothèques externes dans votre projet, qui peuvent être incluses en ajoutant les dépendances à la clé libraryDependencies.

libraryDependencies ++= Seq("org.json4s" %% "json4s-jackson" % "3.5.3")

Par exemple, vous pouvez inclure des bibliothèques json4s dans votre projet, et les fichiers jar liés à la prise en charge de json4s dans votre projet seront également ajoutés au fichier jar final généré par sbt-Assembly. En d'autres termes, lorsque vous appelez Assembly dans votre sbt, il génère un fichier jar contenant toutes les exigences pour exécuter votre programme, de sorte que vous n'avez pas besoin d'une autre dépendance pour exécuter votre programme.

Lorsque vous invitez la commande d'assemblage dans votre shell sbt, elle génère alors un fichier jar dans votre répertoire cible. Dans ce cas, vous pouvez trouver app-Assembly-1.0.jar dans le répertoire app/target/scala-2.11. Lorsque vous regardez à l'intérieur du fichier jar, vous pouvez constater qu'il contient de nombreuses classes.

$vi  projectDirectoy/target/scala-2.11/app_2.11-1.0.jar
ETA-INF/MANIFEST.MF
scala/
scala/annotation/
scala/annotation/meta/
scala/annotation/unchecked/
scala/beans/
scala/collection/
scala/collection/concurrent/
scala/collection/convert/
scala/collection/generic/
scala/collection/immutable/
scala/collection/mutable/
scala/collection/parallel/
scala/collection/parallel/immutable/
scala/collection/parallel/mutable/
scala/collection/script/
scala/compat/
scala/concurrent/
scala/concurrent/duration/
scala/concurrent/forkjoin/
scala/concurrent/impl/
scala/concurrent/util/
scala/io/
scala/math/
scala/ref/
scala/reflect/
scala/reflect/macros/
scala/reflect/macros/internal/
scala/runtime/
scala/sys/
scala/sys/process/
scala/text/
scala/util/
scala/util/control/
scala/util/hashing/
scala/util/matching/
AppBar$.class
AppBar.class
AppFoo$.class
AppFoo.class
......

Comme mentionné précédemment, parce que le fichier jar généré par l'assembly contient toutes les dépendances telles que scala et les bibliothèques externes pour exécuter votre programme dans le jar, vous pouvez penser que vous pouvez invoquer les principales fonctions définies dans l'objet AppFoo et l'objet AppBar.

jaehyuk@ubuntu:~/work/sbt/app/target/scala-2.11$ Java -cp './*' AppFoo
Hello World, I am AppFoo
jaehyuk@ubuntu:~/work/sbt/app/target/scala-2.11$ Java -cp './*' AppBar
Hello World, I am AppBar

Ouais ~ vous pouvez exécuter la fonction principale en utilisant le fichier jar généré.

sbt-pack

sbt-pack est presque le même que sbt-Assembly; il enregistre toute la bibliothèque dont dépend votre projet sous forme de fichiers jar nécessaires à l'exécution de votre programme. Cependant, sbt-pack n'intègre pas toutes les dépendances dans un seul fichier jar, au lieu de cela, il génère plusieurs fichiers jar qui correspondent aux dépendances d'une bibliothèque et à vos classes (par exemple, AppFoo.class).

De plus, il est intéressant de noter qu'il génère automatiquement des scripts pour invoquer toutes les fonctions principales définies dans vos fichiers source scala et Makefiles pour installer le programme. Jetons un coup d'œil au répertoire pack créé après avoir lancé la commande Prompt pack sur votre shell sbt.

jaehyuk@ubuntu:~/work/sbt/app/target/pack$ ls
bin  lib  Makefile  VERSION
jaehyuk@ubuntu:~/work/sbt/app/target/pack$ ls bin/
app-bar  app-bar.bat  app-foo  app-foo.bat
jaehyuk@ubuntu:~/work/sbt/app/target/pack$ ls lib/
app_2.11-1.0.jar  sbt_2.12-0.1.0-SNAPSHOT.jar  scala-library-2.11.12.jar
jaehyuk@ubuntu:~/work/sbt/app/target/pack$ 

Comme indiqué ci-dessus, deux répertoires et deux fichiers sont créés; bin contient tous les fichiers de script pour exécuter les fonctions définies dans vos sources (chaque fichier est un script qui vous aide à exécuter la méthode principale définie dans vos fichiers scala); lib contient tous les fichiers jar requis pour exécuter votre programme, et enfin Makefile peut être utilisé pour installer votre programme et les bibliothèques dépendantes dans votre système.

Pour les détails, veuillez vous référer aux pages github de chaque plugin.

13
Jaehyuk Lee