Search code examples
scalasbtsbt-native-packager

How do I create a tarball and a zip for a single module using distinct configurations?


I have a multi-project build with a particularly messy module which contain several mainClasses. I would like to create several distribution packages for this messy module, each distribution package employing distinct file sets and employing different formats. Ideas?


Solution

  • This is the answer from the sbt-nativer-packager issue tracker where the same question was posted.

    I'm adding this from the gitter chat as well:

    I'm just arriving in this chat room and my knowledge of sbt-native-packager is virtually zero... but anyway... looks to me that JavaAppPackaging and other archetypes should actually be configurations extended from Universal. In this scenario, I would just create my own configuration extended from JavaAppPackaging and tweak the necessary bits according to my needs. And, finally, if the plugin just picks mappings in ThisScope... it would pick my own scope, and not JavaAppPackaging... and not Universal. So, let's go through this one by one.

    The sbt-native-packager plugin always pick mappings in Universal. This is not ideal. It should conceptually pick mappings in ThisScope SBT native packager provides two categories of AutoPlugins: FormatPlugins and ArchetypePlugins. FormatPlugins provide a new package format, e.g. UniversalPlugin (zip, tarball) or DebianPlugins (.deb). These plugins form a a hierarchy as they are build on top of each other:

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

    mappings, which define a file -> targetpath relation, are inherited with this pattern

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

    So for docker it looks like this

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

    The linux format plugins use specialized mappings to preserve file permissions, but are basically the same.

    Since sbt-native-packager plugin always pick mappings in Universal, I have to redefine mappings in Universal in each of my configurations Yes. If you want to define your own scope and inherit the mappings and change them you have to do this, like all other packaging plugins, too. I recommend putting this code into custom AutoPlugins in your project folder.

    For example (not tested, imports may be missing )

    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
      )
    }
    

    looks to me that JavaAppPackaging and other archetypes should actually be configurations extended from Universal JavaAppPackaging is an archetype, which means this plugin doesn't bring any new packaging formats, thus no new scopes. It configures all the packaging formats it can and enables them.

    You package stuff by specifying the scope:

    universal:packageBin
    debian:packageBin
    windows:packageBin
    

    So if you need to customize your output format you are doing this in the respecting scope.

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