IntelliJ IDEA 내에서 SBT를 사용하여 Uber JAR (Fat JAR)을 빌드하는 방법은 무엇입니까?


92

간단한 Scala 프로젝트를 빌드하기 위해 SBT (IntelliJ IDEA 내)를 사용하고 있습니다.

Uber JAR 파일 (일명 Fat JAR, Super JAR) 을 빌드하는 가장 간단한 방법 이 무엇인지 알고 싶습니다 .

현재 SBT를 사용하고 있지만 JAR 파일을 Apache Spark에 제출할 때 다음 오류가 발생합니다.

스레드 "main"java.lang.SecurityException의 예외 : Manifest 기본 속성에 대한 유효하지 않은 서명 파일 요약

또는 컴파일 시간 동안이 오류 :

java.lang.RuntimeException : 중복 제거 : 다음 위치에 다른 파일 내용이 있습니다.
PATH \ DEPENDENCY.jar : META-INF / DEPENDENCIES
PATH \ DEPENDENCY.jar : META-INF / MANIFEST.MF

그것은 처럼 보이는 내 일부 종속성이 최종 동네 짱의 JAR 파일에서 제거해야합니다 서명 파일 (META-INF)를 포함 때문입니다.

다음 과 같이 sbt-assembly 플러그인 을 사용하려고 했습니다.

/project/assembly.sbt

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

/project/plugins.sbt

logLevel := Level.Warn

/build.sbt

lazy val commonSettings = Seq(
  name := "Spark-Test"
  version := "1.0"
  scalaVersion := "2.11.4"
)

lazy val app = (project in file("app")).
  settings(commonSettings: _*).
  settings(
    libraryDependencies ++= Seq(
      "org.apache.spark" %% "spark-core" % "1.2.0",
      "org.apache.spark" %% "spark-streaming" % "1.2.0",
      "org.apache.spark" % "spark-streaming-twitter_2.10" % "1.2.0"
    )
  )

IntelliJ IDEA에서 " Build Artifact ... "를 클릭 하면 JAR 파일이 생성됩니다. 그러나 나는 같은 오류로 끝납니다 ...

저는 SBT를 처음 접했고 IntelliJ IDE를 많이 실험하지 않았습니다.

감사.


2
사물의 소리 당신은 필터링해야 할 수도 있습니다 META-INF파일 - 하나 개의 블로그 게시물을 그 힘의 도움을 : janschulte.wordpress.com/2014/03/20/...
숀 비에이라

답변:


147

마지막으로 IntelliJ IDEA 사용을 완전히 건너 뛰어 글로벌 이해에서 노이즈 생성을 방지합니다. :)

나는 공식 SBT 튜토리얼을 읽기 시작했다 .

다음 파일 구조로 프로젝트를 만들었습니다.

my-project/project/assembly.sbt
my-project/src/main/scala/myPackage/MyMainObject.scala
my-project/build.sbt

assembly.sbt 파일 에 sbt-assembly 플러그인 을 추가했습니다 . 뚱뚱한 JAR을 만들 수 있습니다.

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

내 최소한의 build.sbt 는 다음과 같습니다.

lazy val root = (project in file(".")).
  settings(
    name := "my-project",
    version := "1.0",
    scalaVersion := "2.11.4",
    mainClass in Compile := Some("myPackage.MyMainObject")        
  )

val sparkVersion = "1.2.0"

libraryDependencies ++= Seq(
  "org.apache.spark" %% "spark-core" % sparkVersion % "provided",
  "org.apache.spark" %% "spark-streaming" % sparkVersion % "provided",
  "org.apache.spark" %% "spark-streaming-twitter" % sparkVersion
)

// META-INF discarding
mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
   {
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard
    case x => MergeStrategy.first
   }
}

참고 : % "provided"최종 팻 JAR에 종속성을 포함하지 않는 수단 (이러한 라이브러리는 이미 내 작업자에 포함되어 있음)

참고 : 이 answser에서 영감을 얻은 META-INF 폐기 .

참고 : 의미 %%%

이제 내 / my-project 루트 폴더 에서 다음 명령을 실행 하여 SBT ( 설치 방법)를 사용하여 뚱뚱한 JAR을 빌드 할 수 있습니다 .

sbt assembly

내 fat JAR은 이제 새로 생성 된 / target 폴더에 있습니다.

/my-project/target/scala-2.11/my-project-assembly-1.0.jar

다른 사람에게 도움이되기를 바랍니다.


IntelliJ IDE 내에서 SBT를 횡령하려는 사람들을 위해 : IntelliJ IDEA 내에서 sbt-assembly 작업을 실행하는 방법은 무엇입니까?


2
Databricks에서 동네 짱 항아리에서 제외 불꽃의 [문제에 자바 / 메이븐 제안 databricks.gitbooks.io/databricks-spark-knowledge-base/content/...
JimLohse


1
오래된 META-INF를 폐기하는 이유는 무엇입니까?
qed

2
참고 : % "provided"는 최종 fat JAR에 종속성을 포함하지 않음을 의미합니다.
Jayasagar

심각하게는 놀라 유일한 SBT 버전에서도 작업도 공식하지,하지 않습니다 - 플러그인을 사용할 수
Abhinandan Dubey

40

IntelliJ Idea에서 Uber JAR / Fat JAR 빌드를위한 3 단계 프로세스 :

Uber JAR / Fat JAR : 모든 외부 libraray 종속성이있는 JAR 파일입니다.

  1. IntelliJ Idea에 SBT 어셈블리 플러그인 추가

    플러그인 sbt 경로

    ProjectName / project / target / plugins.sbt 파일로 이동 하여이 줄을 추가합니다.addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")

  2. build.sbt에 병합, 폐기 및 추가 안 함 전략 추가

    SBT 경로 구축

    ProjectName / build.sbt 파일로 이동하여 Uber JAR 패키징 전략을 추가합니다.

    병합 전략 : 라이브러리 버전에 대한 두 패키지에 충돌이있는 경우 Uber JAR에 패키지 할 패키지.
    폐기 전략 : Uber JAR에서 패키징하지 않으려는 라이브러리에서 일부 파일을 제거합니다.
    전략 추가 금지 : Uber JAR에 일부 패키지를 추가하지 마십시오.
    예 : spark-coreSpark Cluster에 이미 존재하므로 Uber JAR에 패키징해서는 안됩니다.

    전략 병합 및 전략 기본 코드 폐기 :

    assemblyMergeStrategy in assembly := { case PathList("META-INF", xs @ _*) => MergeStrategy.discard case x => MergeStrategy.first }

    따라서이 명령을 사용하여 META-INF 파일을 삭제하도록 요청하고 MergeStrategy.discard나머지 파일에 대해이 명령을 사용하여 충돌이있는 경우 라이브러리 파일 의 첫 번째 발생 을 가져옵니다 MergeStrategy.first.

    전략 기본 코드를 추가하지 마십시오.

    libraryDependencies += "org.apache.spark" %% "spark-core" % "1.4.1" %"provided"

    이미 클러 서에있는 Uber JAR 파일에 스파크 코어를 추가하지 않으려면 % "provided"끝에 라이브러리 종속성을 추가합니다 .

  3. 모든 종속성으로 Uber JAR 빌드

    sbtassembly

    sbt assembly패키지 구축을위한 터미널 유형


짜잔 !!! Uber JAR이 빌드되었습니다. JAR은 ProjectName / target / scala-XX에 있습니다.

JarBuilt


16

프로젝트 /plugins.sbt에 다음 줄을 추가합니다.

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

build.sbt에 다음을 추가하십시오.

mainClass in assembly := some("package.MainClass")
assemblyJarName := "desired_jar_name_after_assembly.jar"

val meta = """META.INF(.)*""".r
assemblyMergeStrategy in assembly := {
  case PathList("javax", "servlet", xs @ _*) => MergeStrategy.first
  case PathList(ps @ _*) if ps.last endsWith ".html" => MergeStrategy.first
  case n if n.startsWith("reference.conf") => MergeStrategy.concat
  case n if n.endsWith(".conf") => MergeStrategy.concat
  case meta(_) => MergeStrategy.discard
  case x => MergeStrategy.first
}

어셈블리 병합 전략은 fat jar를 만들 때 발생한 충돌을 해결하는 데 사용됩니다.


1
콘솔에서 "sbt assembly"를 실행하여 fat Jar를 만들 수 있습니다
ARMV

2
scala 버전 2.11.8 (SBT 버전 : 0.13.12)의 경우 addSbtPlugin ( "com.eed3si9n"% "sbt-assembly"% "0.12.0") in project / assembly.sbt
ARMV
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.