Как упаковать мое приложение в несколько архивов? - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть приложение, и я хочу доставить его в виде набора ZIP или RPM-архивов, определив компоненты.

Например, мне нужна задача, которая создает ZIP-архив длямое приложение, содержащее все встроенные файлы jar и другой архив со всеми зависимостями.

Как это сделать?

1 Ответ

0 голосов
/ 06 ноября 2019

Используя sbt-1.2 и sbt-native-packager-1.x, вы можете достичь этого.

В многопроектной сборке sbt-native-packager добавляет задачу Universal / packageBin, которая создаетZIP-архив для вашего приложения, с хорошим сценарием оболочки для определения его пути к классам. Он работает как шарм:

// in your (sub)project definition (a .sbt file, anyone)
lazy val MySubProject1 = (project in file("MySubProject1"))
  .enablePlugins(JavaAppPackaging)

Это позволяет вам:

sbt:MyProject> project MySubProject1
sbt:MySubProject1> universal:packageBin
[...]
  adding: lib/
  adding: lib/MySubProject2-0.1.0.jar
  adding: lib/MySubProject1-0.1.0.jar
  adding: lib/org.apache.kafka.kafka_2.11-0.10.0.1.jar
[...]
  adding: bin/
  adding: bin/MySubProject1
  adding: bin/MySubProject1.bat
[success] [...]
^D
$ unzip -l target/universal/MySubProject1.zip # list archive content :)
[...]

Хорошо, теперь мы хотим вывести два ZIP-архива: одиндля ваших банок (собранные sbt) и один для их банок (загруженные sbt). Это не так просто, но достижимо.

Чтобы упорядочить вещи, мы определим часть кода в файлах scala. Предположим следующую иерархию проекта:

MyProject              |
├── build.sbt          | Define all that is not defined in modules.sbt
├── modules.sbt        | Defile all (sub)projects
├── project/           |
│   ├── Settings.scala | Define settings to apply to (sub)projects
│   └── Deps.scala     | Define dependencies
├── MySubProject1/     | This is the subproject you will package
│   └── src/           |
├── ...                | Some of those subprojects are dependencies to MuSubProject1
└── MySubProjectn/     | 
    └── src/           |

modules.sbt: применить наши настройки упаковки к MySubProject1

lazy val MySubProject1 = (project in file("MySubProject1"))
  .settings(
    name := "AwesomeApp",
    Settings.Common ++ Settings.Package, // this is here (Settings.Package) that magic operates
    libraryDependencies ++= Deps.Spark,
  )
  .dependsOn(MySubProject2)
  .enablePlugins(JavaAppPackaging) // This is still needed

project/Settings.scala: определить настройки, необходимые для упаковки

Из простого объекта scala мы расширим нашу стратегию упаковки

import sbt._
import Keys._

// additional imports (0/)

object Settings {
  lazy val Common = Seq(
    version := "0.1.0",
    scalaVersion := "2.11.8",
    // other settings
  )

  // <packaging strategy> (1/, 2/ & 3/)
}

0 / добавим несколько импортов

import com.typesafe.sbt.SbtNativePackager.autoImport._
import com.typesafe.sbt.packager.universal.UniversalPlugin.autoImport._
import com.typesafe.sbt.packager.universal.Archives.makeNativeZip

1 / добавим одну конфигурацию для целевого архива

  val Application  = config("application")
  val Dependencies = config("dependencies")

2 / Определить наше разбиение (какой файл входит в какую конфигурацию)

  //! @brief Return the configuration this file is into.
  private[this] def configOf(mapping: (File, String)): Configuration = mapping match {
    case (file, _) =>
      if (file.getPath() contains "/cache/") Dependencies // this depends on **your** context and should be improved
      else Application
  }

  //! @brief Return a file filter for this configuration to apply with @c filter on a file mapping.
  private[this] def filterOf(conf: Configuration): ((File, String)) => Boolean = {
    mapping: (File, String) => configOf(mapping) == conf
  }

3 / Создать ZIP-архив для каждой конфигурации

  //! @brief Define the task packageBin for this configuration.
  private[this] def packageDefinition(conf: Configuration): Setting[Task[File]] = {
    conf / packageBin := {
      // TODO add JavaAppPackaging plugin to the project here, but how? See `thisProject.value.autoPlugins`?
      val targets = (Universal / mappings).value filter filterOf(conf)
      makeNativeZip(target.value, s"${packageName.value}-${conf.name}", targets, None, Nil)
    }
  }

   /**
    * @brief Add packaging configuration to a project.
    *
    * Apply with:
    * @code
        lazy val subproject = (project in file ("directory")).settings(
          name := "MyAwesomeSubProject",
          Settings.Package,
        ).enablePlugins(JavaAppPackaging)
    * @endcode
    */
  def Package = Seq(
    maintainer := "YSC@example.com",
    packageName := s"${name.value}",

    packageDefinition(Application),
    packageDefinition(Dependencies),
  )

Вот и все! Теперь вы можете применить application:packageBin и dependencies:packageBin к вашему подпроекту для генерации соответственно AwesomeApp-application.zip и AwesomeApp-dependencies.zip.

Наслаждайтесь!

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