在具有依赖关系的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")
答案 0 :(得分:2)
sbt程序集不是不是 hacky-它是由sbt创建者之一(Eugene Yokota)维护的,并且居住在官方sbt组织中,因此这是在sbt中部署Scala JAR的官方方式。 / p>
好吧,几种官方方式之一。您可以查看sbt-native-packager。事实是:sbt构建有很多可能的目标,以至于作者决定即使构建uberjar也不应该是一种特殊的雪花,而应该通过插件完成。
所以只需使用sbt-assembly,不要对此感到内。 那是惯用的方式。