【问题标题】:How to package my application as multiple archives?如何将我的应用程序打包为多个档案?
【发布时间】:2020-03-03 01:44:22
【问题描述】:

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

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

怎么做?

【问题讨论】:

    标签: scala sbt


    【解决方案1】:

    使用sbt-1.2sbt-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 构建的),一个用于他们的 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:packageBindependencies:packageBin 以分别生成AwesomeApp-application.zipAwesomeApp-dependencies.zip

    享受吧!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      • 2021-03-03
      • 2016-09-13
      • 1970-01-01
      • 2011-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多