如何使用不同的配置为单个模块创建 tarball 和 zip?

Posted

技术标签:

【中文标题】如何使用不同的配置为单个模块创建 tarball 和 zip?【英文标题】:How do I create a tarball and a zip for a single module using distinct configurations? 【发布时间】:2016-06-07 04:01:18 【问题描述】:

我有一个多项目构建,其中包含一个特别混乱的模块,其中包含几个 mainClass。我想为这个凌乱的模块创建几个分发包,每个分发包都使用不同的文件集并使用不同的格式。想法?

【问题讨论】:

【参考方案1】:

这是来自sbt-nativer-packager issue tracker 的答案,其中发布了相同的问题。

我也在 gitter 聊天中添加了这个:

我刚到这个聊天室,我对 sbt-native-packager 的了解几乎为零……但无论如何……在我看来,JavaAppPackaging 和其他原型实际上应该是从 Universal 扩展的配置。在这种情况下,我将创建自己的配置,从 JavaAppPackaging 扩展并根据我的需要调整必要的位。最后,如果插件只选择 mappings in ThisScope... 它会选择我自己的范围,而不是 JavaAppPackaging... 而不是 Universal。 那么,让我们一一来看看吧。

sbt-native-packager 插件总是在 Universal 中选择映射。这并不理想。它应该在概念上选择mappings in ThisScope SBT 原生打包器提供两类 AutoPlugins:FormatPluginsArchetypePluginsFormatPlugins 提供了一种新的包格式,例如UniversalPlugin(zip、tarball)或 DebianPlugins (.deb)。这些插件相互叠加,形成了一个层次结构:

          SbtNativePackager
                +
                |
                |
  +-------+  Universal  +--------+
  |                              |
  |             +                |
  |             |                |
  +             +                +
Docker    +-+ Linux +-+      Windows
          |           |
          |           |
          +           +
       Debian        RPM

定义file -> targetpath 关系的映射通过这种模式继承

mappings in ParentFormatPluginScope := (mappings in FormatPluginScope).value

所以对于 docker 来说是这样的

mappings in Docker := (mappings in Universal).value

linux 格式插件使用专门的映射来保留文件权限,但基本相同。

由于sbt-native-packager 插件总是在 Universal 中选择映射,因此我必须在每个配置中重新定义 Universal 中的映射 是的。如果您想定义自己的范围并继承映射并更改它们,您必须这样做,就像所有其他打包插件一样。我建议将此代码放入项目文件夹中的自定义 AutoPlugins 中。

例如(未测试,可能缺少导入)

import sbt._

object BuilderRSPlugin extends AutoPlugin 
   def requires = JavaAppPackaging

   object autoImport 
        val BuilderRS = config("builderrs") extend Universal
   

  import autoImport._

  override lazy val projectSettings = Seq(
     mappings in BuilderRS := (mappings in Universal).value
  )

在我看来,JavaAppPackaging 和其他原型实际上应该是从 Universal 扩展的配置 JavaAppPackaging 是一个原型,这意味着这个插件没有带来任何新的打包格式,因此没有新的范围。它会配置所有可以使用的打包格式并启用它们。

你通过指定范围来打包东西:

universal:packageBin
debian:packageBin
windows:packageBin

因此,如果您需要自定义输出格式,请在相应的范围内执行此操作。

mappings in Docker := (mappings in Docker).value.filter( /* what ever you want to filter */)

【讨论】:

【参考方案2】:

见:https://github.com/sbt/sbt-native-packager/issues/746

重要提示:这是一个“正在回答”。 还不行!

这是一个如何实现这一目标的示例。

基本思想是我们为要生成的不同包添加配置。每个配置都告诉包中将存在哪些文件。 这不按预期工作。在代码后查看我的 cmets。

lazy val BuilderRS = sbt.config("BuilderRS").extend(Compile,Universal)
lazy val BuilderRV = sbt.config("BuilderRV").extend(Compile,Universal)

addCommandAlias("buildRS", "MessyModule/BuilderRS:packageZipTarball")
addCommandAlias("buildRV", "MessyModule/BuilderRV:packageBin") // ideally should be named packageZip

lazy val Star5FunctionalTestSupport =
  project
    .in(file("MessyModule"))
    .enablePlugins(JavaAppPackaging)
    .settings((buildSettings): _*)

    .configs(Universal,BuilderRS,BuilderRV)

    .settings(inConfig(BuilderRS)(
      Defaults.configSettings ++ JavaAppPackaging.projectSettings ++
        Seq(
          executableScriptName := "rs",
          mappings in Universal :=
            (mappings in Universal).value
              .filter 
                case (file, name) =>  ! file.getAbsolutePath.endsWith("/bin/rv")
              ,
          topLevelDirectory in Universal :=
            Some(
              "ftreports-" +
                new java.text.SimpleDateFormat("yyyyMMdd_HHmmss")
                  .format(new java.util.Date())),
          mainClass in ThisScope := Option(mainClassRS))): _*)

    //TODO: SEE COMMENTS BELOW ===============================================
    // .settings(inConfig(BuilderRV)(
    //   Defaults.configSettings ++ JavaAppPackaging.projectSettings ++
    //     Seq(
    //       packageBin <<= packageBin in Universal,
    //       executableScriptName := "rv",
    //       mappings in ThisScope :=
    //         (mappings in Universal).value
    //           .filter 
    //             case (file, name) =>  ! file.getAbsolutePath.endsWith("/bin/rs")
    //           ,
    //       topLevelDirectory in Universal :=
    //         Some(
    //           "ftviewer-" +
    //             new java.text.SimpleDateFormat("yyyyMMdd_HHmmss")
    //               .format(new java.util.Date())),
    //       mainClass in ThisScope := Option(mainClassRV))): _*)

现在观察 cmets 中的配置 BuilderRV

它与配置BuilderRS 基本相同,只是我们现在在bin 文件夹中部署了不同的shell 脚本。还有一些其他的小差异,但与此论点无关。有两个问题:

    sbt-native-packager 插件总是选择mappings in Universal。这并不理想。它应该在概念上选择mappings in ThisScope

    由于sbt-native-packager 插件总是选择mappings in Universal,我必须在我的每个配置中重新定义mappings in Universal。这是一个问题,因为mappings in Universal 在所有配置中都被定义为自身的函数:结果是每次我们在每个配置中重新定义它时,我们最终都会将逻辑链接到mapppings in Universal。这在此示例中尤其会引起麻烦,因为配置BuilderRV(第二个)不仅会执行其过滤器,还会执行BuilderRS(第一个)中定义的过滤器,这不是我想要的。

【讨论】:

以上是关于如何使用不同的配置为单个模块创建 tarball 和 zip?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python 的 tarfile 创建 tarball 时保留文件权限

在重命名根目标时解压缩包含单个根目录的 tarball

如何在本地文件系统上为 tarball 创建 pip 要求文件?

Apache - 我如何将单个和/或所有模块构建为共享模块

如何使用 pip 和 PyPI 安装 Python 模块单个文件?

如何使用 pip 和 PyPI 安装 Python 模块单个文件?