What is the difference between ThisBuild and Global scopes?
This would probably be used in a plugin:
resolvers in Global ++= appResolvers
Whereas this could appear in your build definition:
resolvers in ThisBuild ++= appResolvers
thereby letting you override global default offered by plugin.
Within the same build definition, using either one will most likely have equivalent effect, because they are the bottom two in the delegates list.
Read Scopes for the full explanation.
I'll quote relevant parts:
There are three scope axes:
- The subproject axis
- The dependency configuration axis
- The task axis
Scoping by project axis
If you put multiple projects in a single build, each project needs its own settings. That is, keys can be scoped according to the project.
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.Zero scope component
Each scope axis can be filled in with an instance of the axis type (analogous to
Some(_)
), or the axis can be filled in with the special valueZero
. So we can think ofZero
asNone
.
Zero
is a universal fallback for all scope axes, but its direct use should be reserved to sbt and plugin authors in most cases.
Global
is a scope that setsZero
to all axes:Zero / Zero / Zero
. In other words,Global / someKey
is a shorthand forZero / Zero / Zero / someKey
.Referring to scopes in a build definition
Global / concurrentRestrictions := Seq( Tags.limitAll(1) )
(
Global / concurrentRestrictions
implicitly converts toZero / Zero / Zero / concurrentRestrictions
, setting all axes toZero
scope component; the task and configuration are alreadyZero
by default, so here the effect is to make the projectZero
, that is, defineZero / Zero / Zero / concurrentRestrictions
rather thanProjectRef(uri("file:/tmp/hello/"), "root") / Zero / Zero / concurrentRestrictions
)
So as written above, Global
sets all three axes to Zero
whereas ThisBuild
sets only the subproject axis to ThisBuild
. This might make sense if you combine ThisBuild
with other axis like configuration:
> set ThisBuild / Test / name := "test-name"
[info] Defining ThisBuild / Test / name
Update February 2020: As Stefan K noted in the comment scope delegation rule is a key fact that I didn't include in the above explanation.
Rule 4: Given a scope, delegate scopes are searched by substituting the subproject axis in the following order: the given subproject,
ThisBuild
, and thenZero
.
For example, if publishing configuration refers to projFoo / version
, it would look in the order of:
projFoo / version
ThisBuild / version
Global / version
If the default setting is scoped to Global
, like in the case of version
setting (see inspect version
), using either ThisBuild / version
or Global / version
would be able to set a version number for all projects in the build. The choice of ThisBuild
here is almost by convention.
There are times where one might want to distinguish the two scoping. First is for source dependencies. sbt has a built-in support to depend on subprojects across multiple builds. In these cases, using ThisBuild
would prevent one setting from spilling over to other builds.
There are also cases where some feature specifically refers to a globally scoped setting, often to configure the behavior of a command and/or the behavior of sbt itself. Global / concurrentRestrictions
is an example of that. In this case, one must use Global / concurrentRestrictions
.