2. Playing with/Debugging SBT
● > settings -V <regex>
● > tasks -V <regex>
● > inspect <setting/task>
○ good to get the type of a setting/task
○ inspect tree <setting/task>
● > show <setting/task>
● > project <project>
● > ~reload
● Keys.scala
3. Basics
● An SBT build is an immutable map of key-
value pairs describing the build
○ e.g. version = "0.0.1"
● When loading the *.sbt and *.scala files SBT
builds a (long, huge) list of Setting[T] objects
that describe a transformation to the map
○ e.g. name := "My Project"
● The list is then first sorted and the each
Setting[T] is applied to the map
4. Basics (cont.)
● A Setting[T] can be build/expressed as ...
○ Key := Value where Key is one of ...
■ SettingKey[T], TaskKey[T], InputKey[T]
● There are lots of predefined Keys
○ Look at Keys.scala
● The operator describes the transformation
○ e.g. := replaces a key-value with another one, +=
would add a value to a list
■ e.g. given an existing Setting[List[String]]
identified by a SettingKey[List[String]] called
example, you can add a value to the setting
with ...
● example += "another string"
5. Basics - Keys
● SettingKey[T] are computed once when the
project is loaded and kept around
● TaskKey[T] are computed every time they
are evaluated
○ val showTime = TaskKey[Unit]("show-time", "...")
○ showTime := {println <Time>}
○ This will result in a Setting[Task[Unit]] that can be
added to the list of settings
● InputKey[T] to be discussed later
6. Basics - Scopes
● Actually ...
○ ... there is not one Key, but lots of them, because ...
○ ... they are Scoped, means ...
○ ... e.g. name can have a different value in different
scopes
● Scopes have 3 axis: Project, Configuration
and Task
○ Project should be clear/obvious
○ Configurations are e.g. Compile, Test, RunTime
○ Tasks are e.g. package-bin, package-src
■ scoping is used to give SettingKeys a different
value for a task (e.g. artifactName)
7. Basics - Scopes (cont.)
● Special scopes are ...
○ There is a global scope for Configuration and Tasks
called "Global"
■ <key> in (Global, Global) := ...
○ There is an "entire-build" scope called "ThisBuild"
■ <key> in ThisBuild := ...
● same as <key> := ...
● Project scoping happens by putting the setting
into the right scope (as opposed to using the
"in" operator)
● Last but not least ... <key> in (Compile,
compile) := ... make total sense, right?
8. Basic - Scopes (cont.)
● Use inspect to explore scoping
○ Learn how to read Provided-by, Delegates and
Related
● Use show to display (Task)Keys
● Make inspect tree <key> work
9. Setting settings :)
● (Re)Set - := [T]
● Append value (to Seq) - += [T]
● Append seq (to Seq) - ++= Seq[T]
● Apply function to previous value(s) - ~= {T=>T}
● Make a setting depend on another - <<=
10. SBT builds are SBT projects :)
● Look at ../project/project/Build.scala
○ Every project loads all *.sbt files from the root plus
all *.scala files from the project/ directory
○ Explore the difference between version.sbt and
plugins.sbt
11. Wrap up ...
... continue to play on ...
https://github.com/rolandtritsch/scala-sbt-tutorial
13. Using sbt-assembly ... right
● Initially it "just" adds a new task: assembly
● Question is ... how does this task relate and
integrate with the rest of the build process, e.
g. package and publish?
● Conceptually ... you first compile, then you
package and then you publish
○ Package has multiple sub-tasks (package-bin,
package-src, package-doc)
○ Each sub-task produces an Artifact that can then get
published
14. Using sbt-assembly ... right (cont.)
● Proposal is ...
○ ... to introduce a new task package-assembly
○ ... and to run this task when package runs
○ ... and have it produce a new Artifact
○ ... and publish this Artifact as part of the publish task
(or the publish-to or the publish-local) and a name
that is different from the name that is used to
package/publish the bin)
○ ... and make that work as part of the Compile
configuration (should not be available in the Test
configuration)
○ ... and get rid of running the tests as part of
packaging it