Building paths in SBT for the packageMappings of the sbt-native-packager

1.6k views Asked by At

I am very new to SBT and need to create a RPM package for one of my project. The RPM contains only 1 file, which is a one-jar created by the sbt-onejar plugin). I want to use sbt-native-packager plugin and have created a Packagin.scala file under the /project directory like this:

object Packaging {
  val settings: Seq[Setting[_]] = packagerSettings ++ deploymentSettings ++ mapGenericFilesToLinux ++ Seq(

    maintainer := "Team",
    packageSummary := "Summary",
    packageDescription := """Description""",

    mappings in Universal += {
      file("target/scala-2.10/projectname_2.10-0.1-one-jar.jar") -> "/opt/projectname/projectname-0.1.jar"
    },

    linuxPackageMappings in Rpm <+= (baseDirectory) map { _:File =>
      (packageMapping(file("target/scala-2.10/projectname_2.10-0.1-one-jar.jar") -> "/opt/projectname/projectname-0.1.jar")
        withUser "someusr" withGroup "somegroup" withPerms "0755")
    },

    name in Rpm := "projectname",
    version in Rpm <<= version apply { sv => sv split "[^\\d]" filterNot (_.isEmpty) mkString "." },
    rpmRelease := "1",
    rpmVendor := "Vendor",
    rpmUrl := Some("url"),
    rpmGroup := Some("group"),
    rpmLicense := Some("BSD")
  )
}

1) I don't want to hardcode the file names. Instead of having "target/scala-2.10/projectname_2.10-0.1-one-jar.jar" I need a way to use existing SettingKey's, i.e. target + "scala-" + scalaVersion + "/" + name + "_" + scalaVersion + "-" + version + "-one-jar.jar" - how do you do this=

2) For the value rpmRelease := "1" I want to use a System property, i.e. in Maven I would do ${rpm.buildNumber}, how does that work in SBT?

3) Is there anything I should do better in regards to the sbt-native-packager plugin?

1

There are 1 answers

2
jsuereth On BEST ANSWER

1) You should always use task output in sbt rather than raw filesystem lookups. Because sbt has parallel execution, if you don't put an explicit dependency on the output of a task, then you have no guarantee that a file will be created before you run your task.

In that vein you want to change your package mappings line to be something like this:

mappings in Universal += {
  oneJar.value -> "/opt/projectname/projectname-0.1.jar"
},

Where the oneJar key is defined in the onejar plugin.

2) Sbt just uses scala for the build language, so you can grab system properties similarly (but please also provide a default):

rpmRelease := Option(sys.props("rpm.buildNumber")) getOrElse "1"

3) Right now you're defining a generic package and redefining the same file in the Rpm with a different user. The mapGenericFilesToLinux settings still lack a few customizations, but if you're not creating universal distributions, you should be able to drop that bit of settings and instead directly configure your linux package:

linuxPackageMappings in Rpm <+= (oneJar) map { jar:File =>
  (packageMapping(jar -> "/opt/projectname/projectname-0.1.jar")
    withUser "someusr" withGroup "somegroup" withPerms "0755")
},