从Scala文件创建jar文件

nur*_*ion 49 java scala jar

我是Scala的新手,不懂Java.我想用简单的Scala文件创建一个jar文件.所以我有我的HelloWorld.scala,生成一个HelloWorld.jar.

MANIFEST.MF:

Main-Class: HelloWorld
Run Code Online (Sandbox Code Playgroud)

在我运行的控制台中:

fsc HelloWorld.scala
jar -cvfm HelloWorld.jar Manifest.mf HelloWorld\$.class HelloWorld.class
java -jar HelloWorld.jar 
  => "Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld/jar"

java -cp HelloWorld.jar HelloWorld 
  => Exception in thread "main" java.lang.NoClassDefFoundError: scala/ScalaObject
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:675)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:316)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:280)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:374)
    at hoppity.main(HelloWorld.scala)
Run Code Online (Sandbox Code Playgroud)

McD*_*ell 54

示例目录结构:

X:\scala\bin
X:\scala\build.bat
X:\scala\MANIFEST.MF
X:\scala\src
X:\scala\src\foo
X:\scala\src\foo\HelloWorld.scala
Run Code Online (Sandbox Code Playgroud)

HelloWorld.scala:

//file: foo/HelloWorld.scala
package foo {
  object HelloWorld {
    def main(args: Array[String]) {
      println("Hello, world!")
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

MANIFEST.MF:

Main-Class: foo.HelloWorld
Class-Path: scala-library.jar
Run Code Online (Sandbox Code Playgroud)

运行build.bat:

@ECHO OFF

IF EXIST hellow.jar DEL hellow.jar
IF NOT EXIST scala-library.jar COPY %SCALA_HOME%\lib\scala-library.jar .

CALL scalac -sourcepath src -d bin src\foo\HelloWorld.scala

CD bin
jar -cfm ..\hellow.jar ..\MANIFEST.MF *.*
CD ..

java -jar hellow.jar
Run Code Online (Sandbox Code Playgroud)

为了成功使用-jar开关,您需要在META-INF/MANIFEST.MF文件中有两个条目:主类; 任何依赖项的相对URL.文档说明:

-罐

执行封装在JAR文件中的程序.第一个参数是JAR文件的名称而不是启动类名称.为了使此选项起作用,JAR文件的清单必须包含Main-Class:classname形式的一行.这里,classname标识具有public static void main(String [] args)方法的类,该方法充当应用程序的起点.有关使用Jar文件和Jar文件清单的信息,请参阅Jar工具参考页面和Java Tutorial的Jar跟踪.

使用此选项时,JAR文件是所有用户类的源, 并忽略其他用户类路径设置.

(注意:大多数ZIP应用程序都可以检查JAR文件;我可能忽略了批处理脚本中目录名中的处理空格; Scala代码运行器版本2.7.4.final.)


为了完整性,一个等效的bash脚本:

#!/bin/bash

if [ ! $SCALA_HOME ]
then
    echo ERROR: set a SCALA_HOME environment variable
    exit
fi

if [ ! -f scala-library.jar ]
then
    cp $SCALA_HOME/lib/scala-library.jar .
fi

scalac -sourcepath src -d bin src/foo/HelloWorld.scala

cd bin
jar -cfm ../hellow.jar ../MANIFEST.MF *
cd ..

java -jar hellow.jar
Run Code Online (Sandbox Code Playgroud)

  • @JohnNicholas我认为这个答案比sbt更早. (2认同)

小智 10

由于Scala脚本需要安装Scala库,因此您必须将Scala运行时与JAR一起包含在内.

有很多策略可以做到这一点,例如jar jar,但最终你看到的问题是你启动的Java进程无法找到Scala JAR.

对于一个简单的独立脚本,我建议使用jar jar,否则你应该开始查看依赖管理工具,或者要求用户在JDK中安装Scala .


Dav*_*idG 5

我最终使用了sbt程序集,使用起来非常简单.我添加了一个名为assembly.sbt进入project/目录的项目的根用一个衬垫(注意你的版本可能需要改变).

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
Run Code Online (Sandbox Code Playgroud)

然后只需运行以下assembly任务sbt:

> assembly
Run Code Online (Sandbox Code Playgroud)

或者只是在项目根目录中'sbt assembly'

$ sbt assembly
Run Code Online (Sandbox Code Playgroud)

它将首先运行您的测试,然后它将生成新的jar到target/目录中(假设我build.sbt已经列出了所有的依赖项).

在我的情况下,我只是使该.jar文件可执行,重命名删除扩展名,它已准备好发货!

此外,如果您正在使用命令行工具,请不要忘记添加手册页(我讨厌脚本没有正确的联机帮助页或多页纯文本文档,甚至没有通过管道传输到您的寻呼机).