Каков идиоматический способ развертывания двоичного файла scala с зависимостями без использования sbt-assembly? - PullRequest
0 голосов
/ 18 апреля 2019

После создания полезного приложения в Scala с зависимостями, как мне развернуть (создать двоичный файл) для него?

Я хотел бы знать самый идиоматический способ, который, надеюсь, является самым простым.

Для меня это было бы обычным sbt compile, тогда ищи основной класс:

./target/scala-2.12/classes/scala_pandoc/Main.class

Затем выполните его:

$ CLASSPATH="$CLASSPATH:./target/scala-2.12/classes/" scala scala_pandoc.Main --unwrap-explain
Picked up _JAVA_OPTIONS: -Xms256m -Xmx300m
java.lang.ClassNotFoundException: ujson.Value
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at scala_pandoc.Main$.main(Main.scala:51)
    at scala_pandoc.Main.main(Main.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at scala.reflect.internal.util.ScalaClassLoader.$anonfun$run$2(ScalaClassLoader.scala:106)
    at scala.reflect.internal.util.ScalaClassLoader.asContext(ScalaClassLoader.scala:41)
    at scala.reflect.internal.util.ScalaClassLoader.asContext$(ScalaClassLoader.scala:37)
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:132)
    at scala.reflect.internal.util.ScalaClassLoader.run(ScalaClassLoader.scala:106)
    at scala.reflect.internal.util.ScalaClassLoader.run$(ScalaClassLoader.scala:98)
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:132)
    at scala.tools.nsc.CommonRunner.run(ObjectRunner.scala:28)
    at scala.tools.nsc.CommonRunner.run$(ObjectRunner.scala:27)
    at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:45)
    at scala.tools.nsc.CommonRunner.runAndCatch(ObjectRunner.scala:35)
    at scala.tools.nsc.CommonRunner.runAndCatch$(ObjectRunner.scala:34)
    at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:45)
    at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:73)
    at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:92)
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:103)
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:108)
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

Но, как мы видим, это как-то не находит зависимости. Когда я компилирую проект, куча файлов загружается / создается в ~/.sbt/ и ~/.ivy2, но ни добавление этих (или всех подпапок к CLASSPATH) не решает проблему.

Вышеупомянутая процедура работает для проектов без внешних зависимостей.

Обход

Используйте https://github.com/sbt/sbt-assembly, что замечательно (создает исполняемый файл .jar), который я могу запустить с java -jar myjar.jar, но чувствует себя хакерским / неофициальным / хрупким и, кроме того, это также накладывает больше зависимостей на мой проект.


  • build.sbt

    lazy val scalatest = "org.scalatest" %% "scalatest" % "3.0.5"
    lazy val ujson = "com.lihaoyi" %% "ujson" % "0.7.1"
    
    name := "scala_pandoc"
    
    organization := "org.fmv1992"
    
    licenses += "GPLv2" -> url("https://www.gnu.org/licenses/gpl-2.0.html")
    
    lazy val commonSettings = Seq(
        version := "0.0.1-SNAPSHOT",
        scalaVersion := "2.12.8",
        pollInterval := scala.concurrent.duration.FiniteDuration(50L, "ms"),
        maxErrors := 10,
    
        // This final part makes test artifacts being only importable by the test files
        // libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % Test,
        //                                                                   ↑↑↑↑↑
        // Removed on commit 'cd9d482' to enable 'trait ScalaInitiativesTest' define
        // 'namedTest'.
        libraryDependencies ++= Seq(scalatest, ujson),
    
        scalacOptions ++= Seq("-feature", "-deprecation", "-Xfatal-warnings")
        )
    
    lazy val root = (project in file(".")).settings(commonSettings).settings(assemblyJarName in assembly := "scala_pandoc.jar")
    
  • project/build.properties

    sbt.version=1.2.8
    
  • project/plugins.sbt:

    addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.9")
    

Смежный вопрос: Развертывание бинарных файлов Scala без зависимостей

1 Ответ

2 голосов
/ 18 апреля 2019

sbt-сборка не хакерская - она ​​поддерживается одним из создателей sbt (Юджин Йокота) и живет в официальной организации sbt, поэтому это официальный способ развертывания JAR-файлов Scala в sbt.

Ну, один из нескольких официальных способов.Вы можете взглянуть на sbt-native-packager .Дело в том, что существует так много возможных целей sbt build, что авторы решили, что даже сборка uberjar не должна быть специальной снежинкой, и это должно быть сделано с помощью плагина.

Так что просто используйте sbt-assembly и donне чувствую себя виноватым по этому поводу. То, что - идиоматический путь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...