Simple Build Tool (sbt) is an open source build tool , It is a best choice for Scala projects that aims to do the basics well. It requires Java 1.6 or later.
2. AGENDA
What is Simple Build Tool (SBT)
Installation Of SBT
Features of SBT
Creating a simple project with SBT
Multi project build with SBT
3. What is SBT
Simple Build Tool (sbt) is an open source build tool , It is a
best choice for Scala projects that aims to do the basics well. It
requires Java 1.6 or later.
➢ SBT uses a small number of concepts to support flexible and
powerful build definitions.
➢ An sbt build definition can contain files ending in .sbt.
4. Installation of SBT
➢
Sbt comes pre-built with several available packages for different
operating systems.
➢
Mac : Use below command to install Sbt.
$ port install sbt
➢
Linux : Download sbt-launch.jar and place it in ~/bin and create a
script for run above jar.
java -Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled
-XX:MaxPermSize=384M -jar `dirname $0`/sbt-launch.jar "$@“
Windows : Create a batch file sbt.bat which contains following script
$ set SCRIPT_DIR=%~dp0 $ java -Xmx512M -jar "%SCRIPT_DIR
%sbt-launch.jar" %*
5. Features Of SBT
Native support for compiling Scala code and integrating with many
Scala test frameworks .
Build descriptions written in Scala using a DSL (Domain Specific
Language).
Support for mixed Java/Scala projects .
Multi project build support
Does dependency management
Interactive shell
6. Creating SBT Project
Projects will need some manual setup. Basic build settings go in a file
called build.sbt, located in the project's base directory.
For example, my project is in the directory sbtDemo, in
sbtDemo/build.sbt I have to write:
D:>mkdir sbtDemo
D:>cd sbtDemo
D:sbtDemo>sbt
[info] Set current project to default-d0025a (in build
file:/D:/sbtDemo/)
>
7. Build Defnition
Basic build setting giving as below on sbt console :
D:sbtDemo>sbt
[info] Set current project to default-d0025a (in build file:/D:/sbtDemo/)
> set name :="hello"
[info] Reapplying settings...
[info] Set current project to hello (in build file:/D:/sbtDemo/)
> set version :="1.0"
[info] Reapplying settings...
[info] Set current project to hello (in build file:/D:/sbtDemo/)
> set scalaVersion :="2.9.2"
[info] Reapplying settings...
[info] Set current project to hello (in build file:/D:/sbtDemo/)
> session save
[info] Reapplying settings...
[info] Set current project to hello (in build file:/D:/sbtDemo/)
> exit
D:sbtDemo>
8. ….....continue
In previous setting, On the left, name, version, and scalaVersion are
keys. A key is an instance of SettingKey[T], TaskKey[T], or InputKey[T]
where T is the expected value type.
Note : we should also be add resolver in build.sbt file .
resolvers += "Typesafe Repo" at "http://repo.typesafe.com/typesafe/releases/"
Settings are separated by blank lines
If we open build.sbt file then we noticed the blank line between every
item. This isn't just for show; they're actually required in order to
separate each item.
sbt needs some kind of delimiter to tell where one expression stops
and the next begins.
Settings are key initialization pair ,
for ex. name := “sbtDemo”
Key Initialization
9. Types Of Keys
The built-in keys are just fields in an object called Keys.
A build.sbt implicitly has an import sbt.Keys._, so sbt.Keys.name can be
referred to as name.
There are three flavors of key:
Setting Key[T]: a key with a value computed once (the value is computed
one time when loading the project, and kept around).
Task Key[T]: a key with a value that has to be recomputed each time,
potentially creating side effects and its said to define a task.
Input Key[T]: a task key which has command line arguments as input.
10. Adding library dependencies
To depend on third-party libraries, there are two options. The first is to
drop jars in lib/ (unmanaged dependencies) and the other is to add managed
dependencies, which will look like this in build.sbt :
// Add a single dependency,
libraryDependencies += "junit" % "junit" % "4.8" % "test"
// Add multiple dependencies.
libraryDependencies ++= Seq( "net.databinder" %% "dispatch-google" %
"0.7.8", "net.databinder" %% "dispatch-meetup" % "0.7.8"
11. Adding Plugins
A plugin extends the build definition, most commonly by adding new
settings. The new settings could be new tasks.
My project is in directory sbtDemo, add a plugins.sbt file under
sbtDemo/project/plugins.sbt and add the plugin location as a resolver,
then call addSbtPlugin
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.0.0")
Note : If the plugin isn’t located in one of the default repositories, we
would have to add a resolver ,For ex.
resolvers += Classpaths.typesafeResolver
12. .....continue
We add plugin for eclipse, now execute command :
> sbt eclipse
[info] Loading project definition from D:sbtDemoproject
[info] Updating {file:/D:/sbtDemo/project/}default-8bffc2...
[info] Resolving com.typesafe.sbteclipse#sbteclipse-plugin;2.0.0 ...
[info] Resolving com.typesafe.sbteclipse#sbteclipse-core;2.0.0 ...
[info] Resolving org.scalaz#scalaz-core_2.9.1;6.0.3 ...
[info] Resolving org.scala-lang#scala-library;2.9.1 ………
All eclipse dependencies are resolved , now my project is ready to
import on eclipse.
13. Directory Structure of Sbt Project
Base Directory : In sbt's terminology, the "base directory" is the directory containing the
project. So if we created a project sbtDemo , its containing sbtDemo/build.sbt file and
other directories.
Source code : Source code can be placed in the project's base directory as
with sbtDemo/hello.scala.
14. Multi Project Build
It can be useful to keep multiple related projects in a single build,
especially if they depend on one another and you tend to modify them
together.
Each sub-project in a build has its own src/main/scala, generates its own
jar file when you run package, and in general works like any other
project.
15. Defining projects in a .scala file
To have multiple projects, you must declare each project and how they relate
in a Build.scala file; there's no way to do it in a .sbt file. However, you can
define settings for each project in .sbt files. Here's an example of a
Build.scala file which defines a root project parent, where the root project
aggregates two sub-projects, child1 and child2 :
import sbt._
import Keys._
object SbtMultiBuild extends Build {
lazy val parent = Project(id = "sbtmDemo",
base = file(".")) aggregate(ch1, ch2)
lazy val ch1 = Project(id = "c1",
base = file("child1"))
lazy val ch2 = Project(id = "c2",
base = file("child2"))
}
16. …. continue
sbt finds the list of Project objects using reflection, looking for fields with
type Project in the Build object.
For Ex. : I have a main project parent and two sub-project child1 and child2.
Lets quickly started with creating parent. In order to create project execute the
following commands in the sbt session.
D:parent>sbt
>set name :="parent“
>set scalaVersion :="2.9.2“
>Set version :="4.0“
>session save
> exit
17. ………Continue
Projects in the build can be completely independent of one another. For Multi
Project Builds we call a method aggregate(child1, child2).
Note : If we execute sbt clean compile command on console then it create two
sub-directory child1 and child2 by default.It is not contain any project specific
setting.
If we want project specific setting then executing following commands in the
sbt session for sub-project.
D:parentchild1>sbt
>set name :="child1”
>set version :=“1.0”
>set scalaVersion :="2.9.2”
> session save
> exit
19. …… Continue
If we compile our project from root then we can see with main project, sub-
project also compile parallely, It is help full for large project which takes
more time in compilation. So for resolving this problem we can develop our
project under Multi Project Builds. By executing sbt compile command on
console we can see updating all projects at a time.
D:parent>sbt clean compile eclipse
[info] Loading project definition from D:parentproject
[info] Done updating.
[info] Set current project to parent (in build file:/D:/parent/)
[success] Total time: 0 s, completed Jan 25, 2013 2:26:59 PM
[info] Updating {file:/D:/parent/}child2...
[info] Updating {file:/D:/parent/}child1...
[info] Done updating.
[success] Total time: 0 s, completed Jan 25, 2013 2:26:59 PM
[info] About to create Eclipse project files for your project(s).
[info] Successfully created Eclipse project files for project(s): child2, parent
-child1
20. ……Continue
My whole project is in parent and I defined different version in
parentbuild.sbt ,parentchild1build.sbt and parentchild2build.sbt. Now
we can check project version by executing show version command on sbt
session :
D:sbtmDemo>sbt
[info] Loading project definition from D:sbtmDemoproject
[info] Set current project to parent (in build file:/D:/sbtmDemo/)
> show version
[info] c1/*:version
[info] 1.0
[info] c2/*:version
[info] 2.0
[info] sbtmDemo/*:version
[info] 4.0
>
21. Aggregation
Aggregation means that running a task on the aggregate project ,
aggregation will run the aggregated tasks in parallel and with no defined
ordering. Start up sbt with two subprojects as in the example, and
try compile. We can see that all three projects are compiled at same
time.
In the previous example, we can see the method
call aggregate(ch1,ch2). This aggregates ch1 and ch2 underneath the
parent project.
aggregation will run the aggregated tasks in parallel and with no defined
ordering.
22. Classpath dependencies
A project may depend on code in another project. This is done by adding
a dependsOn method call. For example, if child1 needed child3 on its
classpath, then we would write in Build.scala:
lazy val ch1 = Project(id = “c1", base = file(“child1"))
dependsOn(child3)