====================== Setting Initialization ====================== This page outlines the mechanisms by which sbt loads settings for a particular build, including the hooks where users can control the ordering of everything. As stated elsewhere, sbt constructs its initialization graph and task graph via ``Setting[_]`` objects. A setting is something which can take the values stored at other Keys in the build state, and generates a new value for a particular build key. Sbt converts all registered ``Setting[_]`` objects into a giant linear sequence and *compiles* them into the a task graph. This task graph is then used to execute your build. All of sbt's loading semantics are contained within the `Load.scala <../../sxr/sbt/Load.scala.html>` file. It is approximately the following: .. Note: This image comes from a google drawing: https://docs.google.com/a/typesafe.com/drawings/d/1Aj_IkOaJpRXJNhrVtVJaS8m-YRcKsympVOj3M2sUz7E/edit .. Feel free to request access to modify as appropriate. .. image:: settings-initialization-load-ordering.png The blue circles represent actions happening when sbt loads a project. We can see that sbt performs the following actions in load: 1. Compile the user-level project (``~/.sbt//``) a. Load any plugins defined by this project (``~/.sbt//plugins/*.sbt`` and ``~/.sbt//plugins/project/*.scala``) b. Load all settings defined (``~/.sbt//*.sbt`` and ``~/.sbt//plugins/*.scala``) 2. Compile the current project (``/*.sbt``) 4. All local configurations (``build.sbt``) Controlling Initialization ========================== The order which sbt uses to load settings is configurable at a *project* level. This means that we can't control the order of settings added to Build/Global namespace, but we can control how each project loads, e.g. plugins and ``.sbt`` files. To do so, use the ``AddSettings`` class :: import sbt._ import Keys._ import AddSettings._ object MyOwnOrder extends Build { // here we load config from a txt file. lazy val root = project.in(file(".")).settingSets( autoPlugins, buildScalaFiles, sbtFiles(file("silly.txt")) ) } In the above project, we've modified the order of settings to be: 1. All AutoPlugin settings. 2. All settings defined in the ``project/Build.scala`` file (shown above). 3. All settings found in the ``silly.txt`` file. What we've excluded: * All settings from the user directory (``~/.sbt/``) * All ``*.sbt`` settings. The AddSettings object provides the following "groups" of settings you can use for ordering: ``autoPlugins`` All the ordered settings of plugins after they've gone through dependency resolution ``buildScalaFiles`` The full sequence of settings defined directly in ``project/*.scala`` builds. ``sbtFiles(*)`` Specifies the exact setting DSL files to include (files must use the ``.sbt`` file format) ``userSettings`` All the settings defined in the user directory ``~/.sbt//``. ``defaultSbtFiles`` Include all local ``*.sbt`` file settings. *Note: Be very careful when reordering settings. It's easy to accidentally remove core functionality.* For example, let's see what happens if we move the ``build.sbt`` files *before* the ``buildScalaFile``. Let's create an example project the following defintiion: `project/build.scala` :: object MyTestBuild extends Build { val testProject = project.in(file(".")).settingSets(autoPlugins, defaultSbtFiles, buildScalaFile).settings( version := scalaBinaryVersion.value match { case "2.10" => "1.0-SNAPSHOT" case v => "1.0-for-${v}-SNAPSHOT" } ) } This build defines a version string which appends the scala version if the current scala version is not the in the ``2.10.x`` series. Now, when issuing a release we want to lock down the version. Most tools assume this can happen by writing a ``version.sbt`` file: `version.sbt` :: version := "1.0.0" However, when we load this new build, we find that the ``version`` in ``version.sbt`` has been **overriden** by the one defined in ``project/Build.scala`` because of the order we defined for settings, so the new ``version.sbt`` file has no effect.