scalasbtsbt-native-packager

SBT: Override setting in multi-build dependsOn/aggregate project


How do I override a sub-project setting/task in a multi-build SBT project? For example, here are two very simple SBT projects:

~/projects/backend/build.sbt

name := "backend"

// old version of scala
scalaVersion := "2.9.1"

~/mycode/docker_builder/build.sbt

lazy val backend = RootProject(file("~/projects/backend"))

lazy val root = (project in file(".")).
settings(
  // Doesn't work because sub-project already defines name
  name in backend := "sub-overriden",

  // Doesn't override {backend/}backend/*:scalaVersion since backend already defines scalaVersion in Global config
  scalaVersion in backend := "2.10.1",

  // Does define new setting in sub-project: {backend/}backend/test:scalaVersion (because backend did not define scalaVersion in test config)
  scalaVersion in (backend, Test) := "2.10.2"
).
aggregate(sub1)
// dependsOn(sub1)

In the sample above, I'm trying to override both name and scalaVersion, but as noted in the comments, the root project is not able to override any setting/task explicitly defined explicitly in the backend project. Now I'm assuming this is expected behavior, since RootProject and it's parent ProjectReference point to a completely different SBT build, but if this is the case, why are we allowed to introduce new settings into the build, e.g: scalaVersion in (backend, Test)?

Any workarounds or other solutions?

The sample backend project above is a gross oversimplification--our actual backend project in our team is based on the multi-project format with about a dozen or two sub-projects and sbt-plugins--however, fortunately I'm able to reproduce the issue with the listing above.

Related:
How to define build-scoped settings in multi-project .sbt builds?
Setting javac options for SBT dependencies
Use common settings in SBT `RootProject`


Solution

  • Very old question, but I could not find any good solution and this question pointed me to a acceptable solution with the following features in sbt:

    Define the property in both, the child and the parent:

    lazy val testProperty = settingKey[String]("Test Prop")
    

    In the child project you set the property value conditionally like:

    testProperty := testProperty.?.value.getOrElse("~ child default! ~")
    

    In the parent project you set the property value normally:

    childProject / testProperty := "# parent override! "