Используя 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
.
Наслаждайтесь!