3
votes

I am in the process of merging several large scala projects into one. Currently they share code using cut and paste (not very much code) and I am making it so that there is a common utilities jar. Most of these projects are deployed on the amazon cloud and use the sbt-native-packager to package them

My problem is that I don't know how to configure the sbt native manager with multiple projects. I'm also not very familiar with it, having come into the project after all the initial work was done.

I have reduced the problem to the smallest I can get it. There is a git repo at https://github.com/stave-escura/multiprojectissue.git which demonstrates the problem

In the project/plugins.sbt the important lines are

addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.0.6")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.0")

The build.sbt is too long to put in here, but the rough shape of it is

import com.typesafe.sbt.SbtNativePackager
import com.typesafe.sbt.packager.archetypes.JavaServerAppPackaging

enablePlugins(SbtNativePackager)

enablePlugins(JavaServerAppPackaging)

lazy val commonSettings = Seq(
  ...
  scalaVersion := "2.11.8",
  assemblyJarName in assembly := s"${name.value}.jar",
  assemblyMergeStrategy in assembly := {
    case "BUILD" => MergeStrategy.discard
    case other => MergeStrategy.defaultMergeStrategy(other)
  }
)

lazy val project1Settings = commonSettings ++ Seq(
  rpmVendor := "someOrganisation",
  packageDescription in Rpm := "Some description1",
  rpmLicense := Some("Copyright 2016 someOrganisation. All rights reserved."),
  rpmRequirements := Seq(
    "java-1.8.0-openjdk"
  ),
  version in Rpm := "1",
  rpmRelease := version.value,
  rpmDaemonLogFile := s"${name.value}.log",
  daemonUser in Linux := "someUserName",
  daemonGroup in Linux := (daemonUser in Linux).value,
  rpmPost := Some(
    """|chkconfig --add someService1
      |chkconfig someService1 on
    """.stripMargin),
  linuxPackageMappings ++= Seq()    // <--- line 53
)


lazy val project2Settings = commonSettings ++ Seq(
  identical to project 1 settings except
  packageDescription in Rpm := "Some description2",
  rpmPost := Some(
    """|chkconfig --add someService2
      |chkconfig someService2 on
    """.stripMargin),
  linuxPackageMappings ++= Seq()   // <--- line 72
)

lazy val project1 = (project in file("components/service1")).settings(project1Settings: _*)

lazy val project2 = (project in file("components/service2")).settings(project2Settings: _*)

In the real project the linuxPackageMappings are reasonably complicated, and are my problem. They differ between the projects. When I load the build.sbt into sbt I get the error

References to undefined settings: 

  project2/*:linuxPackageMappings from project2/*:linuxPackageMappings (~/git/multiprojectissue/build.sbt:72)

  project1/*:linuxPackageMappings from project1/*:linuxPackageMappings (~/git/multiprojectissue/build.sbt:53)

    at sbt.Init$class.Uninitialized(Settings.scala:265)
    ...
    at xsbt.boot.Boot.main(Boot.scala)
[error] References to undefined settings: 
[error] 
[error]   project2/*:linuxPackageMappings from project2/*:linuxPackageMappings (/Users/ricep02/git/multiprojectissue/build.sbt:72)
[error] 
[error]   project1/*:linuxPackageMappings from project1/*:linuxPackageMappings (/Users/ricep02/git/multiprojectissue/build.sbt:53)

Lines 53 and 72 are marked in the build.sbt snippet I included above.

Things I don't know I'm not skilled enough in this to know why the project has sbt-assembly and sbt-package manager. I've commented the sbt-assembly out of the plugins.sbt and still get this issue, so I don't at the moment think it's contributory

Things I have tried I've tried putting the sub project settings into build.sbt files associated with the actual components. I get the same issue. I've also had a good look at example project such as https://github.com/muuki88/sbt-native-packager-examples/tree/master/multi-module-build, and have read the documentation at http://www.scala-sbt.org/sbt-native-packager/ quite carefully, although I'm not 'experienced' with it: just at the 'read the documentation' level. I've also looked at questions such as How to setup sbt-native-packager in a single module project with multiple mains and How to create a basic project setup using sbt-native-packager

Things that work Leaving the packageMappings in the 'main body' of the build.sbt doesn't cause a 'sbt load issue' but I don't know yet whether it will actually build the package!

Software stack

  • Operating system: MacOs
  • Java: 1.8.0_74-b02
  • Scala: 2.11.8
  • sbt: 0.13.8
  • sbt-native-packager 1.0.6
1

1 Answers

0
votes

It looks like the SbtNativePackager needs to be enabled for project1 and project2 in their settings.

Try modifying your settings by adding in enablePlugins(SbtNativePackager) :

lazy val project1Settings = commonSettings ++ Seq(
    rpmVendor := "someOrganisation",
    packageDescription in Rpm := "Some description1",
    rpmLicense := Some("Copyright 2016 someOrganisation. All rights reserved."),
    rpmRequirements := Seq(
        "java-1.8.0-openjdk"
    ),
    version in Rpm := "1",
    rpmRelease := version.value,
    rpmDaemonLogFile := s"${name.value}.log",
    daemonUser in Linux := "someUserName",
    daemonGroup in Linux := (daemonUser in Linux).value,
    rpmPost := Some(
        """|chkconfig --add someService1
           |chkconfig someService1 on
        """.stripMargin),
    enablePlugins(SbtNativePackager),
    linuxPackageMappings ++= Seq()    // <--- line 53
)

and also similarly for project 2.

I recommend getting a book like "SBT in Action" to help you get started with the "simple" build tool.