我有一个应用程序,我想通过定义组件将其作为一组ZIP或RPM(甚至胖JAR)归档文件提供。
例如,我想要一个为我的应用程序构建一个ZIP存档的任务,其中包含所有内置的jar和另一个具有所有依赖项的存档。
该怎么做?
我有一个应用程序,我想通过定义组件将其作为一组ZIP或RPM(甚至胖JAR)归档文件提供。
例如,我想要一个为我的应用程序构建一个ZIP存档的任务,其中包含所有内置的jar和另一个具有所有依赖项的存档。
该怎么做?
使用sbt-1.2
和sbt-native-packager-1.x
,您可以实现这一目标。
在多项目构建中,sbt-native-packager
添加了一个任务Universal / packageBin
,该任务为您的应用程序构建了一个ZIP存档,并带有一个漂亮的Shell脚本来定义其类路径。它像一种魅力:
// 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归档文件:一个用于您的 jars(sbt构建的jar),另一个用于其 jars。 (已下载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
。
享受!