sbt by aform research, saulius valatka
TRANSCRIPT
Building scala/Java projects
• Option #1: scalac/javac
scalac HelloWorld.scala // outputs .class files
• Option #2: build system• Ant (old and lame)
• Maven (too much XML)
• Ivy (limited)
• sbt (powerful)
End result
• .class files contain bytecode (directory structure <-> packages)
• .jar files are zipped up .class files
• MANIFEST files can specify the main class in a .jar
• run with java jar yourfile.jar
Maven – the good parts
• Source code structure:
• src
• main• java
• com/adform/dspr
• Processor.Java• test
• java
• com/adform/dsrp• ProcessorTest.Java
• target
• pom.xml• README.md
Ivy/Maven – the good parts
• Dependency management
<dependency>
<groupId>com.twitter</groupId>
<artifactId>scalding-core_2.9.2</artifactId>
<version>0.8.4</version>
</dependency>
• Libraries make graphs of dependencies
• JARs are published to repositories ( http://search.maven.org/ )
• Maven resolves/downloads everything!
sbt
• Simple (haha!) Build Tool
• Can compile both Java and Scala projects
• Build definitions are scala programs
• Uses Ivy dependency management
sbt – project layout
• src• main
• scala• com/adform/dspr
• Processor.scala• test
• scala• com/adform/dsrp
• ProcessorTest.scala
• target
• project• target• Build.scala• plugins.sbt• build.properties
• build.sbt
• version.sbt
• README.md
Minimal build.sbt
organization := "com.adform.dspr"
name := "vertica-udfs"
scalaVersion := "2.11.2"
resolvers ++= Seq(
"Concurrent Maven Repo" at "http://conjars.org/repo",
)
libraryDependencies ++= Seq(
"io.argonaut" % "argonaut_2.10" % "6.0.4"
)
Some (very simplified) Theory
• A build is a Seq[Setting[T]]
• A Setting[T] is either a property or a Task
• e.g. name = SettingKey[String]("name", "Project name.")
• e.g. compile = TaskKey[Analysis]("compile", "Compiles sources.")
• A build definition transforms the Settings
• e.g. name := "vertica-udfs” [def :=(v: T): Setting[T]]
Some (very simplified) Theory
• You can define your own tasks/settings
• e.g. • lazy val hello = taskKey[Unit]("An example task")
• hello := { println("Hello!") }
• sbt hello
• Settings/Tasks have scopes
• e.g. name in Compile := "hello"
Some (very simplified) Theory
• Settings can also be modified with other operators:• libraryDependencies ++= Seq(…)
• resolvers += “Repository” at “http://repo.lt/”
• publishTo <<= version { v => “repository/” + v }
More details
• A build consists of project/*.scala + *.sbt files
• Sample project/Build.scala:
import sbt._
import Keys._
object HelloBuild extends Build {
val sampleKeyB = settingKey[String]("demo key B")
lazy val root = Project(id = "hello",
base = file("."),
settings = Seq(
sampleKeyB := "B: in the root project settings in Build.scala"
))
}
More details
• .scala builds useful for multi-project builds
• Also useful for shared code across .sbt files
• .sbt take precedence over project/.scala!
• project/build.properties used to specify sbt version
Plot twist!
• How do you build the build project ?
• With sbt!
• project is the root folder of the build application
• plugins.sbt is the definition of the build of the build!
Plugins
• They are just library dependencies for the build project!
• Useful plugins: assembly, dependency-graph
• http://www.scala-sbt.org/0.13/docs/Community-Plugins.html
Library dependencies
libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % "2.2.2" % "test“
)
%% === % “scalatest_2.10”
% “test” === use only in test scope
Library dependencies
resolvers ++= Seq(
"Twitter Maven" at "http://maven.twttr.com",
"Adform Repo" at "http://ec2-54-74-8-112.eu-west-1.compute.amazonaws.com/repository/releases“
)
Dependencies are also cached in ~/.ivy2 – clear cache if something is off!