diff --git a/src/sphinx/Architecture/Command-Engine.rst b/src/sphinx/Architecture/Command-Engine.rst new file mode 100644 index 000000000..5388dbbae --- /dev/null +++ b/src/sphinx/Architecture/Command-Engine.rst @@ -0,0 +1,5 @@ +================= + Command Engine +================= + +Placeholder for command engine details. \ No newline at end of file diff --git a/src/sphinx/Architecture/Core-Principles.rst b/src/sphinx/Architecture/Core-Principles.rst new file mode 100644 index 000000000..2f101c6ee --- /dev/null +++ b/src/sphinx/Architecture/Core-Principles.rst @@ -0,0 +1,70 @@ +================= + Core Principles +================= + +This document details the core principles overarching sbt's design and code style. Sbt's core principles can +be stated quite simply: + +1. Everything should have a ``Type``, enforced as much as is practical. +2. Dependencies should be **explicit**. +3. Once learned, a concept should hold throughout **all** parts of sbt. +4. Parallel is the default. + +With these principles in mind, let's walk through the core design of sbt. + + +Introduction to build state +=========================== +This is the first piece you hit when starting sbt. Sbt's command engine is the means by which +it processes user requests using the build state. The command engine is essentially a means of applying +**state transformations** on the build state, to execute user requests. + +In sbt, commands are functions that take the current build state (``sbt.State``) and produce the next state. In +other words, they are essentially functions of ``sbt.State => sbt.State``. However, in reality, Commands are +actually string processors which take some string input and act on it, returning the next build state. + +The details of the command engine are covered in :doc:`the command engine section `. + +So, the entirety of sbt is driven off the ``sbt.State`` class. Since this class needs to be resilient in the +face of custom code and plugins, it needs a mechanism to store the state from any potential client. In +dynamic languages, this can be done directly on objects. + +A naive approach in Scala is to use a ``Map``. However, this vioaltes tennant #1: Everythign should have a `Type`. +So, sbt defines a new type of map called an ``AttributeMap``. An ``AttributeMap`` is a key-value storage mechanism where +keys are both strings *and* expected `Type`s for their value. + +Here is what the typesafe ``AttributeKey`` key looks like :: + + sealed trait AttributeKey[T] { + /** The label is the identifier for the key and is camelCase by convention. */ + def label: String + /** The runtime evidence for `T` */ + def manifest: Manifest[T] + } + +These keys store both a `label` (``string``) and some runtime type information (``manifest``). To put or get something on +the AttributeMap, we first need to construct one of these keys. Let's look at the basic definition of the ``AttributeMap`` :: + + trait AttributeMap { + /** Gets the value of type `T` associated with the key `k` or `None` if no value is associated. + * If a key with the same label but a different type is defined, this method will return `None`. */ + def get[T](k: AttributeKey[T]): Option[T] + + + /** Adds the mapping `k -> value` to this map, replacing any existing mapping for `k`. + * Any mappings for keys with the same label but different types are unaffected. */ + def put[T](k: AttributeKey[T], value: T): AttributeMap + } + + +Now that there's a definition of what build state is, there needs to be a way to dynamically construct it. In sbt, this is +done through the ``Setting[_]`` sequence. + +Introduction to Settings +======================== + +TODO - Discuss ``Setting[_]`` + +TODO - Transition into ``Task[_]`` + +TODO - Transition into ``InputTask[_]`` \ No newline at end of file diff --git a/src/sphinx/Architecture/Setting-Initialization.rst b/src/sphinx/Architecture/Setting-Initialization.rst index d636e598c..e2e54fd47 100644 --- a/src/sphinx/Architecture/Setting-Initialization.rst +++ b/src/sphinx/Architecture/Setting-Initialization.rst @@ -12,6 +12,9 @@ a particular build key. Sbt converts all registered ``Setting[_]`` objects into 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: @@ -26,14 +29,19 @@ The blue circles represent actions happening when sbt loads a project. We can s Each of these loads defines several sequences of settings. The diagram shows the two most important: -* ``buildSettings`` - These are settings defined to be ``in ThisBuild``. They are initialized *once* for the build. +* ``buildSettings`` - These are settings defined to be ``in ThisBuild`` or directly against the ``Build`` object. They are initialized *once* for the build. You can add these, e.g. in ``project/build.scala`` :: object MyBuild extends Build { - override val settings = ... + override val settings = Seq(foo := "hi") } -* ``projectSettings`` - These are settings specific to a project. They are specific to a *particular submodule* in the build. A + or in a ``build.sbt`` file :: + + foo in ThisBuild := "hi" + + +* ``projectSettings`` - These are settings specific to a project. They are specific to a *particular sub project* in the build. A plugin may be contributing its settings to more than on project, in which case the values are duplicated for each project. You add project specific settings, eg. in ``project/build.scala`` :: @@ -94,4 +102,30 @@ The AddSettings object provides the following "groups" of settings you can use f Include all local ``*.sbt`` file settings. -*Note: Be very careful when reordering settings. It's easy to accidentally remove core functionality.* \ No newline at end of file +*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 ``projectSettings``. + +Let's create an example project the following defintiion: + +`project/build.scala` :: + + object MyTestBuild extends Build { + + val testProject = project.in(file(".")).autoSettings(autoPlugins, defaultSbtFiles, projectSettings).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. \ No newline at end of file diff --git a/src/sphinx/Architecture/Task-Engine.rst b/src/sphinx/Architecture/Task-Engine.rst new file mode 100644 index 000000000..9d7be5da0 --- /dev/null +++ b/src/sphinx/Architecture/Task-Engine.rst @@ -0,0 +1,5 @@ +================= + Task Engine +================= + +Placeholder for task engine design details. \ No newline at end of file diff --git a/src/sphinx/Architecture/index.rst b/src/sphinx/Architecture/index.rst index d20bce232..ea16cae7a 100644 --- a/src/sphinx/Architecture/index.rst +++ b/src/sphinx/Architecture/index.rst @@ -2,7 +2,7 @@ Architecture ============== -This is the fledgeling set of documentation about the Architecture of sbt. This will cover all the core components of +This is the set of documentation about the Architecture of sbt. This covers all the core components of sbt as well as the general notion of how they all work together. This documentation is suitable for those who wish to have a deeper understanding of sbt's core, but already understand the fundamentals of ``Setting[_]``, ``Task[_]`` and constructing builds. @@ -10,4 +10,7 @@ constructing builds. .. toctree:: :maxdepth: 2 - Setting-Initialization \ No newline at end of file + Core-Principles + Setting-Initialization + Task-Engine + Command-Engine