What is the difference between ThisBuild and Global scopes?

sbt

Solution

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 value `Zero`. So we can think of `Zero` as `None`.

`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 sets `Zero` to all axes: `Zero / Zero / Zero`. In other words, `Global / someKey` is a shorthand for `Zero / Zero / Zero / someKey`.

Referring to scopes in a build definition

Global / concurrentRestrictions := Seq(
  Tags.limitAll(1)
)

(`Global / concurrentRestrictions` implicitly converts to `Zero / Zero / Zero / concurrentRestrictions`, setting all axes to `Zero` scope component; the task and configuration are already `Zero` by default, so here the effect is to make the project `Zero`, that is, define `Zero / Zero / Zero / concurrentRestrictions` rather than `ProjectRef(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 then `Zero`.

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`.

Problem

Can someone explain me the difference between writing these 2 lines: ``` resolvers in ThisBuild ++= appResolvers resolvers in Global ++= appResolvers ```

Original source