About this book

Build tools are a boon to developers working on large projects. With the configuration to run/execute the project moved out, developers can focus more on the project. SBT is a build tool designed for Scala and Java projects. It provides developers with a high productivity work environment hence it comes in really handy when dealing with large projects.

Getting Started with SBT for Scala gets you going with using SBT and also introduces its advanced concepts. SBT is a build tool that uses a Scala-based DSL. Additionally, SBT has some interesting features that come in handy during development, such as starting a Scala REPL with project classes and dependencies on the classpath, continuous compilation and testing with triggered execution, and much more.

Getting Started with SBT for Scala introduces SBT and its various features. It shows how to set up the build definition for a Scala project using sample code to explain different scenarios and use cases. It explains the basic configuration required to compile, test, and run a project using SBT. We will take a look at the additional configuration and settings that can be set to suit the project requirements. You will also learn how to handle project dependencies in SBT and use Scala files to define the build. It shows how to fork the JVM in SBT for different processes and specific configurations. It also explains the intricacies of the build definition, parallel execution.

This book will make you familiar with SBT so that you can use it for different kinds of projects like simple, and multiple modules which can be dependent or independent.

Publication date:
September 2013
Publisher
Packt
Pages
86
ISBN
9781783282678

 

Chapter 1. Hello World with SBT

In the stone age of programming, a project team comprised several programmers and a person whose job was to build and deploy the software developed by others. To compile the project, this person would have to compile each file individually. If compilation for all of the files was successful, they went on to deploy the project. There were no means to check for errors while integration. One had to come up with a method to have logs for each process. Deploying was equally complex as it required modules to be placed manually in the right location.

Thankfully, this is not the case anymore.

Building projects involves compiling your code and assembling the binaries with the required dependencies and resources. Build tools are programs that assist in managing and maintaining programs. Initial build tools had support for compiling and linking modules in the required order. Gradually, other features were included.

Some key advantages of automating the build process are as follows:

  • Reduces time taken for compiling and linking

  • Reduces scope of errors by humans

  • Consistency

  • Cost efficient

Make was one of the earliest build tools. It is also the most widespread tool. Make was originally created by Stuart Feldman in 1977 at Bell Labs to ease the process of building and deploying. Prior to Make, the program source was accompanied by OS dependent "make" and "install" shell scripts in the Unix build system. With Make, it became possible to combine the commands for different targets into a single file and abstract out dependency tracking and archive handling. Hence, Make was an important milestone on the path to modern build environments.

In the late 1990s, James Duncan Davidson, a software architect at Sun Microsystems, conceived the idea of Another Neat Tool (ANT) while turning Tomcat into an open source product. ANT is similar to Make, but it is implemented using Java. ANT uses an XML file to describe the build process and its dependencies. Today, ANT is the most widely used build tool for Java development projects.

In 2002, Jason van Zyl felt the need for a standardized project structure, and it led to the creation of Maven. Maven projects are configured using a Project Object Model in an XML file by describing the software project being built, its dependencies on other external modules and components, the build order, directories, and the required plugins.

In September 2004, Jayasoft came up with a transitive relation dependency manager called Ivy. It provides a way to resolve project dependencies in ANT projects.

In 2009, Gradleware built another build tool which used a Groovy-based DSL. Gradle utilizes a directed acyclic graph to determine the order in which tasks can be run.

Leiningen started off as a project with the aim of simplifying Apache Maven for Clojure projects by using Clojure to describe the build requirements. It uses a Clojure-based DSL for writing the build scripts.

Inspired by its predecessors, Simple Build Tool (SBT) was created by Typesafe Engineer, Mark Harrah. It is written in Scala and can be used to compile both Java and Scala code. SBT is not just a build tool, but also provides the basic framework for a development environment. Its integrated Scala console, the continuous compile mechanism, and the fast compile server, make it a necessary tool in any Scala developer's toolkit.

 

Why SBT?


Apart from being the build tool of choice for most Scala projects, SBT provides some very interesting features besides the ones provided by a conventional build tool.

To begin with, SBT can be configured using a simple Scala-based DSL and extended to use a full-fledged configuration with Scala as the project demands.

SBT uses incremental recompilation to reduce the compilation time of the Scala code. An incremental compiler will only compile what needs to be recompiled after changes. It also keeps the compiler's JVM up and running with the project's compiled code to prevent the load time.

SBT commands can be run in a triggered execution mode. That is, if opted by the user, specific tasks will be run whenever the user makes a change in any of the source code. This was originally meant for continuous compilation, but has now been extended for various other tasks. It is also possible to run multiple commands in this mode.

SBT provides support for testing with ScalaCheck, specs, and ScalaTest. Additionally, JUnit tests can also be run by using a plugin (junit-interface). SBT allows the user to run tests selectively or run all the tests. It also allows running only those tests that failed earlier or were excluded earlier or have a dependency on the recompiled code that is run.

SBT can start the Scala REPL with the project loaded in the classpath. One could call the methods defined in the project code within the REPL.

SBT can be configured to have subprojects. This provides better means for achieving modularity. Dependent modules can be clubbed using a single build and desired modules can be made completely independent of others.

SBT allows inclusion of external projects using their path or URL. This means it's also possible to include Git repositories as a dependency for the project. This makes the developer's life a lot simpler as he/she can easily have a project that depends on another project.

SBT runs tasks in parallel. Task parallelism refers to running one or more independent tasks concurrently. Task parallelism ensures efficient and scaleable use of resource systems. This is really useful for running tests in parallel.

SBT supports the inclusion of libraries as unmanaged or managed dependencies; that is, libraries can simply be included by adding the corresponding JAR in the lib directory or by specifying the dependencies in the build definition. SBT uses Apache Ivy to implement managed dependencies.

There are plugins to support SBT in Sublime Text, IntelliJ Idea, Eclipse, and Netbeans IDE. This makes it easier and simpler to adopt SBT.

 

Installing SBT


SBT can either be installed from a package or manually.

Installing from a package

SBT can be installed directly using MSI for Windows, RPM, or DEB packages downloaded from the SBT website.

You could also use the zip/tgz package, but after extracting from the zip/tgz package, you need to add the sbt/bin folder to PATH.

Installing on Mac

SBT can be installed on Mac using either Macports, as follows:

$ port install sbt 

Or, by using Homebrew, as follows:

$ brew install sbt 

Installing SBT manually

Download sbt-launch.jar (available at http://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch//0.12.3/sbt-launch.jar) and write a script. The script and the JAR file should be in the same folder.

On Windows, create an sbt.bat file and add it to PATH. The contents of the file should be as follows:

$ set SCRIPT_DIR=%~dp0 
$ java -Xmx512M -jar "%SCRIPT_DIR%sbt-launch.jar" %*

On Unix, save the JAR file and script in your ~/bin directory. Name the script sbt. The contents of the script should be as follows:

java -Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=384M -jar `dirname $0`/sbt-launch.jar "[email protected]"

Make the script executable:

$ chmod u+x ~/bin/sbt

To check if the installation was successful, use the about or the version command:

$ sbt --version
sbt launcher version 0.12.1
 

Creating a new project


The following diagram shows the basic directory structure of a Scala SBT:

SBT recommends, and uses, the standard Maven project directory structure by default.

The files generated by SBT are written in the target directory within the project folder by default.

Let's write a program that checks for palindromes. Create Introduction.scala:

package Chapter1 

object Introduction extends App { 

  def isPalindrome(word: String) = { 
    val modifiedWord = word.toLowerCase.replaceAll("[^a-z0-9]", "") 
    val reversed = modifiedWord.reverse 
    modifiedWord == reversed 
  } 

  println("Is 'Herculaneum' a palindrome? " + isPalindrome("Herculaneum")) 
}

The IntroSpec.scala file is as follows:

import Chapter1.Introduction 
import org.specs2.mutable._ 

class IntroSpec extends Specification{ 
  "The phrase 'Never odd or even'" should{ 
    "be a palindrome" in { 
      Introduction.isPalindrome("Never odd or even") must beTrue 
    } 
  } 

  "The phrase 'Mr. Owl ate my metal worm'" should{ 
    "be a palindrome" in { 
      Introduction.isPalindrome("Mr. Owl ate my metal worm") must beTrue 
    } 
  } 

  "The date '20:02 02/20 2002'" should{ 
    "be a palindrome" in{ 
      Introduction.isPalindrome("20:02 02/20 2002") must beTrue 
    } 
  } 

}

The build file is used to specify the basic build settings and manage dependencies. We will see the build file in detail in the next chapter. It should be similar to the following:

name := "Introduction"

version := "1.0"

scalaVersion := "2.9.1"

resolvers ++= Seq("snapshots" at "http://oss.sonatype.org/content/repositories/snapshots",
  "releases" at "http://oss.sonatype.org/content/repositories/releases")

libraryDependencies ++= Seq(  "org.specs2" %% "specs2" % "1.12.3" % "test")

Note

The blank lines between each item are required to separate them and are not there just for clarity in reading.

 

Compiling, testing, and running your project


From the terminal/command prompt, go to the project directory:

$ cd introduction

To compile the project, use the following command:

$ sbt compile

The result will be as follows:

[info] Loading project definition from /home/introduction/project 
[info] Set current project to Introduction (in build file:/home/introduction/) 
[success] Total time: 0 s, completed 

To run the tests, use the following command:

$ sbt test

The result will be as follows:

[info] Loading project definition from /home/introduction/project 
[info] Set current project to Introduction (in build file:/home/introduction/) 
[info] IntroSpec 
… 
[info] Passed: : Total 3, Failed 0, Errors 0, Passed 3, Skipped 0 
[success] Total time: 5 s, completed 

To run the project, use the following command:

$ sbt run

The result will be as follows:

[info] Loading project definition from /home/introduction/project 
[info] Set current project to Introduction (in build file:/home/introduction/) 
[info] Running Chapter1.Introduction 
Is 'Herculaneum' a palindrome? false 
[success] Total time: 0 s, completed

It is also possible to run sbt in batch mode, that is, multiple commands separated by spaces. Execution will happen in the given order. Commands that take arguments must be enclosed in quotes.

The clean command is used to delete all the generated files in the target folder:

$ sbt clean compile test

The result will be as follows:

[info] Loading project definition from /home/introduction/project 
… 
[info] Passed: : Total 3, Failed 0, Errors 0, Passed 3, Skipped 0 
[success] Total time: 7 s, completed
 

Going interactive with the SBT shell


While you are still in your project folder, type sbt in the terminal/command prompt:

$ sbt

It will load the required JAR files, and finally, result in an SBT shell that looks like the following:

[info] Loading project definition from /home/introduction/project 
[info] Set current project to Introduction (in build file:/home/introduction/) 
> 

Once the shell has started, you can compile, test, or run the project with compile, test, and run commands respectively:

>compile
[success] Total time: 0 s, completed

> test 
[info] IntroSpec 
.....................................
[info] Passed: : Total 3, Failed 0, Errors 0, Passed 3, Skipped 0 
[success] Total time: 2 s, completed

>run 
[info] Running Chapter1.Introduction 
Is 'Herculaneum' a palindrome? false 
[success] Total time: 0 s, completed

Typing console at the command prompt will open Scala REPL with the project's classpath, where you can try out live Scala examples based on your project's code. For example, consider the following:

> console 
[info] Starting scala interpreter... 
…
scala>

Let's run our palindrome function here:

scala> Chapter1.Introduction.isPalindrome("hello") 
res0: Boolean = false 

You could try running other functions as an exercise.

Triggering SBT commands on saves

Passing a ~ character before a command tells SBT to keep looking for changes and run the same command if there are any changes in any of the source files.

This is possible in both interactive and batch modes.

> ~run 
[info] Running Chapter1.Introduction 
Is 'Herculaneum' a palindrome? false 
[success] Total time: 0 s, completed Apr 11, 2013 4:04:08 PM 
1. Waiting for source changes... (press enter to interrupt) 

After changes are saved, it resumes on its own.

[info] Compiling 1 Scala source to /home/introduction/target/scala-2.9.1/classes... 
[info] Running Chapter1.Introduction 
Is 'HelloWorld' a palindrome? false 
[success] Total time: 1 s, completed Apr 11, 2013 4:04:51 PM 
2. Waiting for source changes... (press enter to interrupt) 
[info] Compiling 1 Scala source to /home/introduction/target/scala-2.9.1/classes... 
[info] Running Chapter1.Introduction 
Is 'Herculaneum' a palindrome? false 
[success] Total time: 1 s, completed Apr 11, 2013 4:05:11 PM 
3. Waiting for source changes... (press enter to interrupt) 
 

Summary


In this chapter, we saw how to build a simple Scala project in SBT and execute basic operations, such as compile, test, and run. In the following chapters, we will see how we can customize the build for our project based on various settings.

About the Author

  • Shiti Saxena

    Shiti Saxena is a software engineer with around 4 years of work experience. She is currently working with Imaginea (a business unit of Pramati). She has previously worked with Tata Consultancy Services Ltd. and Genpact.

    A true polyglot, she's had exposure to various languages, including Scala, JavaScript, Java, Python, Perl, and C. She likes to work with Play Scala and AngularJS.

    She blogs at http://eraoferrors.blogspot.in and maintains open source projects on GitHub.

    She loves to travel, is a movie buff, and likes to spend time playing her piano whenever she is not programming.

    She has authored Getting Started with SBT for Scala (https://www.packtpub.com/application-development/getting-started-sbt-scala).

    Browse publications by this author

Latest Reviews

(2 reviews total)
A very helpful guide for those with little exposure to SBT
The content of the book is NOT about SBT, it is WebRTC book!