Date post: | 15-Jul-2015 |
Category: |
Technology |
Upload: | renat-bekbolatov |
View: | 146 times |
Download: | 0 times |
Installation
• Pre-reqs: java and scala installed
• http://www.scala-sbt.org/release/tutorial/Setup.html
• sbt runs as a java program: sbt-launch.jar
2
Let’s create an SBT project
• mkdir my_project
• cd my_project
• mkdir -p project src/{main,test}/{scala,java,resources}
• echo “sbt.version=0.13.7” > project/build.properties
3
Directory Structure• “src” contains source and resource
files
• “project” directory contains build
code for this project
• “build.properties” is a key-value
properties file for sbt
• “build.sbt” also contains build
information for this project
• “target” directory (not shown)
contains build products
Image source: http://just-thor.com/2013/11/getting-started-with-a-simple-sbt-project/
build.sbt——————— build.sbt —————————————————————
—————————
name := "MyProj"
version := "1.0"
scalaVersion := “2.11.6”
libraryDependencies += "com.google.guava" % "guava" % "18.0"
—————————————————————————————————
———————————————
Remember from part 1, we are setting values to keys:
KEY := VALUE <——- SETTING
KEY[T] := VALUE <——- SETTING[T] - type of value
5
sbt REPL
% sbt
[info] Loading project definition from my_project/project
[info] Updating {file: my_project/project/}my_project-build...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Set current project to MyProj (in build file:my_project/)
(Now we are in sbt REPL)
> name
[info] MyProj
> version
[info] 1.0
>
6
show & inspect
> show name
[info] MyProj
>
> inspect name
[info] Setting: java.lang.String = MyProj <— Type and Value
[info] Description:
[info] Project name.
[info] Provided by:
[info] {file: my_project/}my_project/*:name
[info] Defined at:
[info] my_project/build.sbt:1 <——— Key “name” that
[info] Reverse dependencies: we set in build.sbt
[info] *:projectInfo
[info] *:normalizedName
[info] *:onLoadMessage
[info] *:description
[info] Delegates: <——— Delegates (more on this later)
[info] *:name
[info] {.}/*:name
[info] */*:name
>
7
src/main/scala/StringSplit.scala————————————————————————————————-
StringSplit.sbt ———————————
package example
import com.google.common.base.Splitter
import scala.collection.JavaConversions._
object StringSplit extends App {
println("hello")
val parts = Splitter.on(',')
.trimResults()
.omitEmptyStrings()
.split("foo,bar,, baz")
parts.foreach { part => println(s"Part: $part")}
}————————————————————————————————————
————————————————-———————8
compile & run% sbt[info] Loading project definition from my_project/project
[info] Set current project to MyProj (in build file:my_project/)
> compile[info] Updating {file:my_project/}my_project...
[info] [SUCCESSFUL ] com.google.guava#guava;18.0!guava.jar(bundle) (28ms)
[info] Done updating.
[info] Compiling 1 Scala source to my_project/target/scala-2.11/classes...
[info] 'compiler-interface' not yet compiled for Scala 2.11.6. Compiling...
[info] Compilation completed in 12.713 s
[success] Total time: 48 s, completed Apr 1, 2015 2:41:55 PM
> run[info] Updating {file:my_project/}my_project...
[info] Resolving jline#jline;2.12.1 ...
[info] Done updating.
[info] Compiling 1 Scala source to my_project/target/scala-2.11/classes...
[info] Running example.StringSplit
hello
Part: foo
Part: bar
Part: baz
[success] Total time: 5 s, completed Apr 1, 2015 3:04:05 PM
>
9
package
> package
[info] Compiling 1 Scala source to my_project/target/scala-2.11/classes...
[info] Packaging my_project/target/scala-2.11/myproj_2.11-1.0.jar ...
[info] Done packaging.
[success] Total time: 1 s, completed Apr 1, 2015 3:21:59 PM
> exit
(Now we are in shell)
% ls -lh target/scala-2.11
drwxr-xr-x 3 renat renat 102B Apr 1 15:21 classes
-rw-r--r-- 1 renat renat 4.2K Apr 1 15:21 myproj_2.11-1.0.jar
10
List available tasks
(Now we are in sbt REPL)
> tasks
This is a list of tasks defined for the current project.
It does not list the scopes the tasks are defined in; use the 'inspect' command for that.
Tasks produce values. Use the 'show' command to run the task and print the resulting value.
clean Deletes files produced by the build, such as generated sources, comp…
compile Compiles sources.
console Starts the Scala interpreter with the project classes on the classpath.
… [truncated]
11
console> console
[info] Starting scala interpreter...
[info]
Welcome to Scala version 2.11.6 (Java HotSpot(TM)
64-Bit Server VM, Java 1.7.0_60).
Type in expressions to have them evaluated.
Type :help for more information.
(Now we are in Scala console - with main classpath)
scala> import com.google.common.base.Splitter
import com.google.common.base.Splitter
scala> Splitter.on(' ').split("one two three”)
res0: Iterable[String] = [one, two, three]
scala> example.StringSplit.main(Array[String]())
hello
Part: foo
Part: bar
Part: baz
12
More on sbt commands…
• Can issue command directly in shell: “sbt run”
• Can combine commands: “sbt test package”
• clean, publish, publish-local, update, reload
• Plugins can add new keys
13
Build script
So far we have been running only with one file
build.sbt in project’s root directory.
Behind the scenes, sbt created a Project object
and appended the contents of project’s
build.sbt to its settings.
Manually creating a project by creating a Scala
file in project directory…
Build script——————— project/MyBuild.scala ———————————————————————————
import sbt._
import sbt.Keys._
object MyBuild extends Build {
lazy val root = (project in file("."))
.settings(
name := "MyProj",
version := "1.0",
scalaVersion := "2.11.6",
libraryDependencies += "com.google.guava" % "guava" % "18.0"
)
}
—————————————————————————————————————————————————
—————————————
Same definition as before with build.sbt file.
Settings in build.sbt will be applied on top of this.
In fact, any .sbt files in a project, will be merged with the build definition for the entire build, but scoped to that
project.
15
Scopeslazy val commonSettings = Seq(
organization := "com.example",
version := "0.1.0",
scalaVersion := "2.11.4"
)
lazy val core = (project in file("core"))
.dependsOn(util)
.settings(commonSettings: _*)
.settings(
name := "projCore"
// other settings
)
lazy val util = (project in file("util"))
.settings(commonSettings: _*)
.settings(
name := "projUtil"
// other settings
)
Then in sbt:
> util/name
[info] projUtil
> core/name <— {<build-uri>}<project-id>/config:inkey::key
[info] projCore
> util/name
[info] projUtil
>
16
ConfigurationsA configuration defines a flavor of build, potentially with its own classpath, sources, generated
packages, etc.
The configuration concept comes from Ivy, which sbt uses for managed dependencies Library
Dependencies, and from MavenScopes.
Some configurations you’ll see in sbt:
Compile which defines the main build (src/main/scala).
Test which defines how to build tests (src/test/scala).
Runtime which defines the classpath for the run task.
By default, all the keys associated with compiling, packaging, and running are scoped to a
configuration and therefore may work differently in each configuration.
The most obvious examples are the task keys compile, package, and run; but all the keys
which affect those keys (such as sourceDirectories or scalacOptions or fullClasspath) are
also scoped to the configuration.
17
Source: http://www.scala-sbt.org/0.13/tutorial/Scopes.html
Scopes again
In build definition:
scalacOptions in Test ++= Seq(“-unchecked")
In REPL:
Test:scalacOptions
General for in REPL is {<build-uri>}<project-id>/config:intask::key
18
PluginsA plugin extends the build definition, most commonly by adding new settings, possibly new tasks.
For example - if you want to create fat jars, there is a plugin for that: plugin “sbt-assembly”.
In project directory create file “assembly.sbt” with the following:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % “0.11.2”)
This particular plugin brings in new keys, such as:
assembly, assemblyJarName, assemblyMergeStrategy, …
Now in sbt, you can run “assembly”:
> assembly[info] Including: guava-18.0.jar
[info] Including: scala-library-2.11.6.jar
[info] Checking every *.class/*.jar file's SHA-1.
[info] Merging files...
[warn] Merging 'META-INF/MANIFEST.MF' with strategy 'discard'
[warn] Merging 'META-INF/maven/com.google.guava/guava/pom.properties' with strategy 'discard'
[warn] Merging 'META-INF/maven/com.google.guava/guava/pom.xml' with strategy 'discard'
[warn] Strategy 'discard' was applied to 3 files
[info] SHA-1: db72fdf182c7c5332a145aa4c018466840f9c554
[info] Packaging /Users/renatb/tmp/sm/my_project/target/scala-2.11/MyProj-assembly-1.0.jar ...
[info] Done packaging.
[success] Total time: 5 s, completed Apr 1, 2015 11:51:57 PM
>
19
DelegatesA setting has a key and a scope.
A request for a key in a scope A may be delegated to another scope if A doesn't define a
value for the key.
The delegation chain is well-defined and is displayed in the Delegates section of the inspect
command.
The Delegates section shows the order in which scopes are searched when a value is not
defined for the requested key.
> inspect console::initialCommands
...
[info] Delegates:
[info] *:console::initialCommands
[info] *:initialCommands
[info] {.}/*:console::initialCommands
[info] {.}/*:initialCommands
[info] */*:console::initialCommands
[info] */*:initialCommands
...
20
Useful links
• http://www.scala-sbt.org/0.13/tutorial/index.html
• http://just-thor.com/2013/11/getting-started-with-a-
simple-sbt-project/
• http://www.scala-sbt.org/0.13/tutorial/Full-Def.html
• http://www.scala-sbt.org/0.13.2/docs/Detailed-
Topics/Inspecting-Settings.html
21
Upcoming Meetups
Seattle Spark Meetup
Sparkly Notebook: Interactive Analysis and Visualization with Spark
Wednesday, April 15, 2015 - Avvo - 705 5th Ave South #600, Seattle, WA
Scala at the Sea
Discuss Scala Akka and Related Technologies
Tuesday, April 14, 2015 - Whitepages - 1301 5th Avenue #1600, Seattle, WA
22