복붙노트

[SCALA] 스칼라 파일에서 jar 파일 만들기

SCALA

스칼라 파일에서 jar 파일 만들기

나는 스칼라에 새로 온 사람과 자바를 모른다. 나는 간단한 스칼라 파일에서 jar 파일을 만들려고합니다. 내 HelloWorld.scala을하며,이 례 HelloWorld.jar를 생성합니다.

MANIFEST.MF :

Main-Class: HelloWorld

콘솔에서 나는 실행 :

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)

해결법

  1. ==============================

    1.샘플 디렉토리 구조 :

    샘플 디렉토리 구조 :

    X:\scala\bin
    X:\scala\build.bat
    X:\scala\MANIFEST.MF
    X:\scala\src
    X:\scala\src\foo
    X:\scala\src\foo\HelloWorld.scala
    

    HelloWorld.scala :

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

    MANIFEST.MF :

    Main-Class: foo.HelloWorld
    Class-Path: scala-library.jar
    

    경우 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
    

    성공적으로 -jar 스위치를 사용하려면, 당신은 META-INF / MANIFEST.MF 파일에 두 개의 항목이 필요합니다 주요 클래스; 종속성에 대한 상대 URL. 문서 참고 사항 :

    (참고 : JAR 파일은 대부분의 우편 응용 프로그램과 함께 검사 할 수 있으며, 아마 방치 배치 스크립트에서 디렉토리 이름에 공백을 처리, 스칼라 코드 주자 버전 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
    
  2. ==============================

    2.스칼라 스크립트는 스칼라가 설치 될 도서관 필요하기 때문에, 당신은 당신의 JAR와 함께 스칼라 런타임을 포함해야합니다.

    스칼라 스크립트는 스칼라가 설치 될 도서관 필요하기 때문에, 당신은 당신의 JAR와 함께 스칼라 런타임을 포함해야합니다.

    이 같은 항아리 항아리로이 작업을 수행하기위한 많은 전략은,하지만 궁극적으로 문제가 당신이있는 거 보는 당신이 시작했습니다 자바 프로세스가 스칼라 JAR 파일을 찾을 수 있다는 것입니다.

    간단한 독립형 스크립트, 난 그렇지 않으면 종속성 관리 도구보고 시작하거나 JDK에 스칼라를 설치하도록 요구해야한다, 항아리 항아리를 사용하는 것이 좋습니다 것입니다.

  3. ==============================

    3.나는 그것이 정말 사용하기 간단하고, 조립 SBT를 사용하여 끝났다. 나는 하나의 라이너 (변경해야 할 수도 버전을 참고)와 함께 프로젝트의 루트에있는 프로젝트 / 디렉토리에 assembly.sbt라는 파일을 추가했습니다.

    나는 그것이 정말 사용하기 간단하고, 조립 SBT를 사용하여 끝났다. 나는 하나의 라이너 (변경해야 할 수도 버전을 참고)와 함께 프로젝트의 루트에있는 프로젝트 / 디렉토리에 assembly.sbt라는 파일을 추가했습니다.

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

    그럼 그냥 SBT의 조립 작업을 실행 :

    > assembly
    

    아니면 그냥 프로젝트의 루트 디렉토리에 '조립 SBT'

    $ sbt assembly
    

    그것은 먼저 테스트를 실행 한 후 대상 / 디렉토리에 새 항아리를 생성합니다 (내 build.sbt 이미 내 모든 종속성을 나열 주어진).

    내 경우에는, 난 그냥 그 .jar 파일의 실행을 확장을 제거하기 위해 이름을 변경하고 그것을 제공 할 준비가되어 있습니다!

    당신이 명령 줄 도구를하고있는 경우에도, 사람 페이지를 (심지어 당신을 위해 호출기로 파이프되지 않은 적절한 맨없이 또는 여러 페이지 일반 텍스트 문서와 스크립트를 싫어)을 추가하는 것을 잊지 마세요.

  4. ==============================

    4.또한 받는다는과 받는다는 - 스칼라 - 플러그인을 사용할 수 있습니다. 당신이 받는다는 설정하면, 당신은 단지 MVN 패키지를 할 수 있으며, 그것은 당신을 위해 단지를 만들 것입니다.

    또한 받는다는과 받는다는 - 스칼라 - 플러그인을 사용할 수 있습니다. 당신이 받는다는 설정하면, 당신은 단지 MVN 패키지를 할 수 있으며, 그것은 당신을 위해 단지를 만들 것입니다.

  5. ==============================

    5.나는 MyDowell의 방법을 재현 해 보았습니다. 마지막으로 나는 그것이 작동되도록 할 수있다. 그러나 나는 올바른 비트가 너무 초보자 복잡하지만 대답 (특정 디렉토리 구조에서 불필요하게 복잡) 것을 찾을 수 있습니다.

    나는 MyDowell의 방법을 재현 해 보았습니다. 마지막으로 나는 그것이 작동되도록 할 수있다. 그러나 나는 올바른 비트가 너무 초보자 복잡하지만 대답 (특정 디렉토리 구조에서 불필요하게 복잡) 것을 찾을 수 있습니다.

    나는 매우 단순한 수단이 결과를 재현 할 수 있습니다. 세 개의 파일이 들어있는 하나의 디렉토리가 시작하려면 :

    helloworld.scala
    MANIFEST.MF
    scala-library.jar
    

    helloworld.scala

    object HelloWorld
    {
      def main(args: Array[String])
      {
        println("Hello, world!")
      }
    }
    

    MANIFEST.MF :

    Main-Class: HelloWorld
    Class-Path: scala-library.jar
    

    첫 번째 컴파일 helloworld.scala :

    scalac helloworld.scala
    

    다음 항아리를 만들 :

    \progra~1\java\jdk18~1.0_4\bin\jar -cfm helloworld.jar MANIFEST.MF .
    

    지금 당신은 그것을 실행할 수 있습니다 :

    java -jar helloworld.jar
    

    원래는 작동하지 않았다 때문에 나는이 간단한 해결책을 발견. 내가 줄 바꿈과의 긴밀한 MANIFEST.MF에서 두 번째 줄을하지 않으면,이 라인은 무시됩니다 나중에 내가 잘못 때문이 아니라 사소한 오류입니다 때문이 아니라 사실을 발견했다. 이 알아 나에게 시간을했고 나는이 아주 간단한 해결책을 찾는 과정에서, 이전에 다른 모든 것을 시도했다.

  6. ==============================

    6.그 이유의를 작성하지 않을 방법이 아니라 단지 (우분투 리눅스 명령 줄을 통해) 내 경우에는 근무 솔루션을 보여줄 것 :

    그 이유의를 작성하지 않을 방법이 아니라 단지 (우분투 리눅스 명령 줄을 통해) 내 경우에는 근무 솔루션을 보여줄 것 :

    1)

    mkdir scala-jar-example
    cd scala-jar-example
    

    2)

    nano Hello.scala
    object Hello extends App   {  println("Hello, world")   }
    

    3)

    nano build.sbt
    import AssemblyKeys._
    
    assemblySettings
    
    name := "MyProject"
    
    version := "1.0"
    
    scalaVersion := "2.11.0"
    

    3)

    mkdir project
    cd project 
    nano plugins.sbt
    addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.9.1")
    

    4)

    cd ../   
    sbt assembly
    

    5)

    java -jar target/target/scala-2.11/MyProject-assembly-1.0.jar
    >> Hello, world
    
  7. ==============================

    7.나는 자동 매니페스트 생성 등 일부 정보를 추가 bash는 스크립트를 수정했습니다.

    나는 자동 매니페스트 생성 등 일부 정보를 추가 bash는 스크립트를 수정했습니다.

    이 스크립트는 기본 개체가가에있는 파일 (대소 문자 구분)과 동일한라는 것으로 가정합니다. 또한, 하나의 현재 디렉토리 이름은 메인 오브젝트 이름과 동일해야하며 메인 오브젝트 이름은 커맨드 라인 파라미터로서 제공한다. 프로젝트의 루트 디렉토리에서이 스크립트를 실행합니다. 필요에 따라 상단에있는 변수를 수정합니다.

    스크립트가 빈과의 dist 폴더를 생성하고 빈에있는 기존 내용을 삭제된다는 점에 유의하십시오.

    
    #!/bin/bash
    
    SC_DIST_PATH=dist
    SC_SRC_PATH=src
    SC_BIN_PATH=bin
    SC_INCLUDE_LIB_JAR=scala-library.jar
    SC_MANIFEST_PATH=MANIFEST.MF
    SC_STARTING_PATH=$(pwd)
    
    if [[ ! $SCALA_HOME ]] ; then
        echo "ERROR: set a SCALA_HOME environment variable"
        exit 1
    fi
    
    if [[ ! -f $SCALA_HOME/lib/$SC_INCLUDE_LIB_JAR ]] ; then
        echo "ERROR: Cannot find Scala Libraries!"
        exit 1
    fi
    
    if [[ -z "$1" ]] ; then
        SC_APP=$(basename $SC_STARTING_PATH)
    else
        SC_APP=$1
    fi
    
    [[ ! -d $SC_DIST_PATH ]] && mkdir $SC_DIST_PATH
    
    if [[ ! -d $SC_BIN_PATH ]] ; then
        mkdir "$SC_BIN_PATH"
    else
        rm -r "$SC_BIN_PATH"
        if [[ -d $SC_BIN_PATH ]] ; then
            echo "ERROR:  Cannot remove temp compile directory:  $SC_BIN_PATH"
            exit 1
        fi
        mkdir "$SC_BIN_PATH"
    fi
    
    if [[ ! -d $SC_SRC_PATH ]] || [[ ! -d $SC_DIST_PATH ]] || [[ ! -d $SC_BIN_PATH ]] ; then
        echo "ERROR: Directory not found!:  $SC_SRC_PATH or $SC_DIST_PATH or $SC_BIN_PATH"
        exit 1
    fi
    
    if [[ ! -f $SC_DIST_PATH/$SC_INCLUDE_LIB_JAR ]] ; then
        cp "$SCALA_HOME/lib/$SC_INCLUDE_LIB_JAR" "$SC_DIST_PATH"
    fi
    
    SCALA_MAIN=$(find ./$SC_SRC_PATH -name "$SC_APP.scala")
    COMPILE_STATUS=$?
    SCALA_MAIN_COUNT=$(echo "$SCALA_MAIN" | wc -l)
    
    if [[ $SCALA_MAIN_COUNT != "1" ]] || [[ ! $COMPILE_STATUS == 0 ]] ; then
        echo "Main source file not found or too many exist!:  $SC_APP.scala"
        exit 1
    fi
    
    if [[ -f $SC_DIST_PATH/$SC_APP.jar ]] ; then
        rm "$SC_DIST_PATH/$SC_APP.jar"  
        if [[ -f $SC_DIST_PATH/$SC_APP.jar ]] ; then
            echo "Unable to remove existing distribution!:  $SC_DIST_PATH/$SC_APP.jar"
            exit 1
        fi
    fi
    
    if [[ ! -f $SC_MANIFEST_PATH ]] ; then
        LEN_BASE=$(echo $(( $(echo "./$SC_SRC_PATH" |wc -c) - 0 )))
        SC_MAIN_CLASS=$(echo $SCALA_MAIN |cut --complement -c1-$LEN_BASE)
        SC_MAIN_CLASS=${SC_MAIN_CLASS%%.*}
        SC_MAIN_CLASS=$(echo $SC_MAIN_CLASS |awk '{gsub( "/", "'"."'"); print}')
    
        echo $(echo "Main-Class: "$SC_MAIN_CLASS) > $SC_MANIFEST_PATH
        echo $(echo "Class-Path: "$SC_INCLUDE_LIB_JAR) >> $SC_MANIFEST_PATH
    fi
    
    scalac -sourcepath $SC_SRC_PATH -d $SC_BIN_PATH $SCALA_MAIN
    COMPILE_STATUS=$?
    
    if [[ $COMPILE_STATUS != "0" ]] ; then
        echo "Compile Failed!"
        exit 1
    fi
    
    cd "$SC_BIN_PATH"
    jar -cfm ../$SC_DIST_PATH/$SC_APP.jar ../$SC_MANIFEST_PATH *
    COMPILE_STATUS=$?
    cd "$SC_STARTING_PATH"
    
    if  [[ $COMPILE_STATUS != "0" ]] || [[ ! -f $SC_DIST_PATH/$SC_APP.jar ]] ; then
        echo "JAR Build Failed!"
        exit 1
    fi
    
    echo " "
    echo "BUILD COMPLETE!... TO LAUNCH:  java -jar $SC_DIST_PATH/$SC_APP.jar"
    echo " "
    
  8. ==============================

    8.(이것은 초기 질문 위의 문제가 아니다 있지만) 유사한 문제가 발생할 수 있습니다 한가지는 Java VM이 주요 방법은 무효 반환 요구 보인다는 것이다. 스칼라에서 우리는 같은 (메인의 정의에 = -sign을 관찰)을 쓸 수 있습니다 :

    (이것은 초기 질문 위의 문제가 아니다 있지만) 유사한 문제가 발생할 수 있습니다 한가지는 Java VM이 주요 방법은 무효 반환 요구 보인다는 것이다. 스칼라에서 우리는 같은 (메인의 정의에 = -sign을 관찰)을 쓸 수 있습니다 :

    object MainProgram {
    
      def main(args: Array[String]) = {
        new GUI(args)
      }
    }
    

    주요 실제로 GUI 객체를 반환 경우 (즉, 그것은 무효 아니다),하지만 우리는 스칼라 명령을 사용하여 시작할 때 프로그램이 잘 실행됩니다.

    우리는 메인 클래스로 메인 프로 그램과 항아리 파일에이 코드를 패키지 경우 Java VM이 우리의 주요의 반환 형식이 무효가 아니므로 아무 주요 기능은 없다 불평한다 (I은 다소 이상이 불만을 찾을 이후 반환 형식은 서명의 일부)이 아니다.

    우리가 명시 적으로 단위로 선언 된 경우, 우리는 우리가 주요의 헤더에 = -sign에서 제외하면 아무런 문제가, 또는 것입니다.

  9. ==============================

    9.당신은 SBT 기능을 사용하지 않으려면 나는 메이크의 사용을 권장합니다.

    당신은 SBT 기능을 사용하지 않으려면 나는 메이크의 사용을 권장합니다.

    여기에 foo는 패키지가 완성도 foo.bar.myApp로 대체하는 예이다.

    메이크

    NAME=HelloWorld
    JARNAME=helloworld
    
    PACKAGE=foo.bar.myApp
    PATHPACK=$(subst .,/,$(PACKAGE))
    
    .DUMMY: default
    default: $(NAME)
    
    .DUMMY: help
    help:
        @echo "make [$(NAME)]"
        @echo "make [jar|runJar]"
        @echo "make [clean|distClean|cleanAllJars|cleanScalaJar|cleanAppJar]"
    
    .PRECIOUS: bin/$(PATHPACK)/%.class
    
    bin/$(PATHPACK)/%.class: src/$(PATHPACK)/%.scala
        scalac -sourcepath src -d bin $<
    
    scala-library.jar:
        cp $(SCALA_HOME)/lib/scala-library.jar .
    
    .DUMMY: runjar
    runJar: jar
        java -jar $(JARNAME).jar
    
    .DUMMY: jar
    jar: $(JARNAME).jar
    
    MANIFEST.MF:
        @echo "Main-Class: $(PACKAGE).$(NAME)" > $@
        @echo "Class-Path: scala-library.jar" >> $@
    
    $(JARNAME).jar: scala-library.jar bin/$(PATHPACK)/$(NAME).class \
                                    MANIFEST.MF
        (cd bin && jar -cfm ../$(JARNAME).jar ../MANIFEST.MF *)
    
    %: bin/$(PATHPACK)/%.class
        scala -cp bin $(PACKAGE).$@
    
    .DUMMY: clean
    clean:
        rm -R -f bin/* MANIFEST.MF
    
    cleanAppJar:
        rm -f $(JARNAME).jar
    
    cleanScalaJar:
        rm -f scala-library.jar
    
    cleanAllJars: cleanAppJar cleanScalaJar
    
    distClean cleanDist: clean cleanAllJars
    
  10. from https://stackoverflow.com/questions/809138/creating-a-jar-file-from-a-scala-file by cc-by-sa and MIT license