Search code examples
sbtsbt-assemblysbt-plugin

Sbt what is the difference placing settings in the file or in commonSettings in multi project


Beginners question, I have a multi project sbt file is there a difference if I put general settings at the beginning of the file? e.g :

organization := "com.example"
  version := "0.0.1-SNAPSHOT"
  scalaVersion := "2.11.12"
resolvers ++= Seq(
    "Apache Development Snapshot Repository" at "https://repository.apache.org/content/repositories/snapshots/",
    "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/",

    Resolver.mavenLocal
  )
assemblyMergeStrategy in assembly := {
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard
    case x => MergeStrategy.first
  }
lazy val commonSettings  = Seq(  libraryDependencies ++= commonDependencies ++ testingDependencies)
lazy val sharedProject = (project in file(...))
.settings(commonSettings: _*)
val projectA = .....dependsOn(sharedPorject)
val projectB = .....dependsOn(sharedPorject)

Or if I put it in the common settings

lazy val commonSettings  = Seq(  
organization := "com.example",
  version := "0.0.1-SNAPSHOT",
  scalaVersion := "2.11.12",
resolvers ++= Seq(
    "Apache Development Snapshot Repository" at "https://repository.apache.org/content/repositories/snapshots/",
    "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/",
    Resolver.mavenLocal
  ),
assemblyMergeStrategy in assembly := {
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard
    case x => MergeStrategy.first
  },
libraryDependencies ++= commonDependencies ++ testingDependencies)
lazy val sharedProject = (project in file(...))
.settings(commonSettings: _*)
val projectA = .....dependsOn(sharedPorject)
val projectB = .....dependsOn(sharedPorject)

what is the difference ?


Solution

  • Any settings defined without attaching it to a specific project's settings, ie .settings(), are attached to root project.

    Thus code like this

    organization := "foo"
    

    is same as

    lazy val root = (project in file(".")).settings(organization := "foo")
    

    Now, if you defined a new sub-project like common and add organization to it

    lazy val common = (project in file("common")).settings(organization := "bar")
    

    It and only it will have value organization set to bar.

    This will hold in the example when root project has its own organization defined too.

    lazy val root = (project in file(".")).settings(organization := "foo")
    
    lazy val common = (project in file("common")).settings(organization := "bar")
    

    This is easy to test with commands sbt "show organization" and sbt "show common/organization". It will print foo and bar respectively.

    Finally, if you'd like to have same value defined for all sub-projects, add settings in root project for scope ThisBuild like in this example:

    organization in ThisBuild := "foo"
    
    lazy val common = (project in file("common")).settings(???)
    

    Or store settings in a Seq and apply it to all sub-projects and root. This will have similar effect as in scope ThisBuild but it's a bit more explicit:

    val commonSettings = Seq(organization := "foo")
    
    lazy val root = (project in file(".")).settings(commonSettings)
    lazy val common = (project in file("common")).settings(commonSettings)