如何将我的应用程序打包为多个存档? [英] How to package my application as multiple archives?

查看:60
本文介绍了如何将我的应用程序打包为多个存档?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,我想通过定义组件将它作为一组 ZIP 或 RPM(甚至是胖 JAR)档案交付.

I've got an application and I'd like to deliver it as a set of ZIP or RPM (or even fat JAR) archives by defining components.

例如,我想要一个任务,为我的应用程序构建一个 ZIP 存档,其中包含所有构建的 jar,以及另一个包含所有依赖项的存档.

For instance, I'd like a task that builds a ZIP archive for my application containing all built jars, and another archive with all dependencies.

怎么做?

推荐答案

使用 sbt-1.2sbt-native-packager-1.x,你可以做到这一点.

Using sbt-1.2 and sbt-native-packager-1.x, you can achieve that.

在多项目构建中,sbt-native-packager 添加一个任务,Universal/packageBin,它为您的应用程序构建一个 ZIP 存档,带有一个漂亮的外壳脚本来定义它的类路径.它就像一个魅力:

In a multi-project build, sbt-native-packager adds a task, Universal / packageBin, which builds a ZIP archive for your application, with a nice shell script to define its classpath. It works like a charm:

// 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 的那些).这并不容易,但可以实现.


Ok, now we want to output two ZIP archives: one for your jars (the ones sbt built) and one for their jars (the ones sbt downloaded). It's not as easy, but achievable.

为了组织起来,我们将在 Scala 文件中定义一些代码.假设以下项目层次结构:

In order to organize things, we'll define some of the code in scala files. Assume the following project hierarchy:

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

modules.sbt: apply our packaging settings to 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 对象,我们将扩展我们的打包策略

project/Settings.scala: define the settings needed for packaging

From a simple scala object, we'll expand our packaging strategy

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/为每个目标存档添加一个配置

1/ Add one configuration per target archive

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

2/定义我们的分区(哪个文件在哪个配置中)

2/ Define our partitioning (which file goes in which configuration)

  //! @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 存档

3/ Create the ZIP archive for each configuration

  //! @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:packageBindependencies:packageBin 以分别生成 AwesomeApp-application.zipAwesomeApp-依赖项.zip.

This is it! You can now apply the application:packageBin and dependencies:packageBin on your subproject to generate respectively AwesomeApp-application.zip and AwesomeApp-dependencies.zip.

享受吧!

这篇关于如何将我的应用程序打包为多个存档?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆