What does settings(inThisBuild(...)) mean in sbt?

Viewed 946

I just generated an sbt project using scalaxb template:

sbt new eed3si9n/scalaxb.g8

I got this build.sbt file:

lazy val root = (project in file(".")).
  enablePlugins(ScalaxbPlugin).
  settings(inThisBuild(List(
    organization  := "com.example",
    scalaVersion  := "2.13.2",
    crossScalaVersions := Seq("2.13.2", "2.12.12")
  ))).
  settings(
    name          := "test-scalaxb",
    libraryDependencies ++= Seq(dispatch, scalaXml, scalaParser)
  ).
  settings(
    scalaxbDispatchVersion in (Compile, scalaxb) := dispatchV,
    scalaxbPackageName in (Compile, scalaxb)     := "generated"
  )

What does the inThisBuild within settings mean (Line 3)? I usually see it at the root level of the build.sbt file, not under settings. How is it different from not having inThisBuild at all (e.g. name and libraryDependencies in above file)?

2 Answers

What does the inThisBuild within settings mean?

Semantically it means identical to:

ThisBuild / organization  := "com.example"
ThisBuild / scalaVersion  := "2.13.2"
ThisBuild / crossScalaVersions := Seq("2.13.2", "2.12.12")

Today, I recommend using ThisBuild / organization. I should probably update my old Giter8 template.

Meta details

sbt has a helper function called inConfig(Compile)(List(setting1, ...)) to map over the settings sequence to scope them to Compile configuration, which is useful for defining a setting sequence once and reusing it in Compile, Test, etc.

In 2015, Dale contributed another helper function called inThisBuild(List(setting1, ...)), which similar to inConfig(Compile)(...) scopes the list to ThisBuild scope. This is due to sbt 0.13 where scoping was written as organization in ThisBuild instead of the slash syntax introduced in 2018.

I usually see it at the root level of the build.sbt file, not under settings.

Writing at the root level of the build.sbt is called bare style build.sbt. Semantically writing setting sequence (including inThisBuild(...)) using bare style is identical to putting them in .settings(...) in the root subproject (the subproject at file(".")) of the build. In 2016 when I added that line to eed3si9n/scalaxb.g8 I guess I was more committed to getting away from the bare style build.sbt than I am today, so I refused to write inThisBuild(...) directly on build.sbt and put it in .settings(...) instead.

As mentioned above, I introduced slash syntax in 2018, which warmed me up to using ThisBuild / scalaVersion using bare style (and only for ThisBuild / ... and Global / ... settings) so it would be the same as the shell syntax.

Build-wide setting

How is it different from not having inThisBuild at all (e.g. name and libraryDependencies in above file)?

See Build-wide settings:

To factor out common settings across multiple projects, define the settings scoped to ThisBuild. The limitation is that the right-hand side needs to be a pure value or settings scoped to Global or ThisBuild, and there are no default settings scoped to subprojects.

ThisBuild is basically a special subproject name that is provided so you can define default settings for your build. When you define one or more subprojects, and when the subproject doesn't define scalaVersion it would fallback to ThisBuild / scalaVersion.

From the sbt docs:

The project axis can also be set to ThisBuild, which means the “entire build”, so a setting applies to the entire build rather than a single project. Build-level settings are often used as a fallback when a project doesn’t define a project-specific setting.

the first settings applies to all the subprojects in the entire project , whereas the second one applies only to the root project

Related