Slide 1

Slide 1 text

SBT Basic Concepts @pishen

Slide 2

Slide 2 text

build.sbt

Slide 3

Slide 3 text

name := "hello_world" SettingKey[String] a function Setting[String]

Slide 4

Slide 4 text

build.sbt (*.sbt) name := "hello_world" version := "0.1.0-SNAPSHOT" scalaVersion := "2.11.8" libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.4.8" //libraryDependencies += // "com.typesafe.akka" % "akka-actor_2.11" % "2.4.8" Setting[String] Setting[Seq[ModuleID]]

Slide 5

Slide 5 text

> inspect libraryDependencies Setting: Seq[ModuleID] = List(...) > show libraryDependencies List(...)

Slide 6

Slide 6 text

build.sbt import java.util.Date def getTime() = new Date().getTime val baseVersion = "0.1.0" version := { println("Mom! I'm here!!") baseVersion + "_" + getTime() } class A() {...} object B {...}

Slide 7

Slide 7 text

Define your own Key

Slide 8

Slide 8 text

SettingKey[T] TaskKey[T] InputKey[T] name, version compile run

Slide 9

Slide 9 text

val a = settingKey[Int]("this is a") val demo = taskKey[Unit]("demo") Description, will be shown in > inspect SettingKey[Int] > show a > demo

Slide 10

Slide 10 text

Implement the Settings val demo = taskKey[Unit]("demo") name := "hello_world" demo := { println("Hello, this is project " + name.value) } dependency > demo > inspect demo build.sbt

Slide 11

Slide 11 text

Parallelization & deduplication val demo1 = taskKey[Unit]("demo1") val demo2 = taskKey[Unit]("demo2") val demo3 = taskKey[Unit]("demo3") demo1 := println("demo1") demo2 := println("demo2") demo3 := { demo1.value println("demo3") demo2.value demo1.value } demo1 demo2 demo3 demo2 demo1 demo3 build.sbt

Slide 12

Slide 12 text

SBT is recursive ``The project directory is another build inside your build, which knows how to build your build.

Slide 13

Slide 13 text

SBT is recursive ``The project directory is another build inside your build, which knows how to build your build.

Slide 14

Slide 14 text

my-project/ └ src/main/scala/.../Main.scala └ Hello.scala └ anything.sbt └ build.sbt └ target/ └ Main.class

Slide 15

Slide 15 text

my-project/ └ src/main/scala/.../Main.scala └ Hello.scala └ anything.sbt └ build.sbt └ project/ └ MyPlugin.scala └ target/ └ Main.class class A() {...} object B {...} val a = new A()

Slide 16

Slide 16 text

my-project/ └ src/main/scala/.../Main.scala └ Hello.scala └ anything.sbt └ build.sbt └ project/ └ MyPlugin.scala └ cool.sbt └ assembly.sbt └ target/ └ Main.class libraryDependencies += "joda-time" % "joda-time" % "2.9.4" addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.3") val now = DateTime.now()

Slide 17

Slide 17 text

my-project/ └ src/main/scala/.../Main.scala └ Hello.scala └ anything.sbt └ build.sbt └ project/ └ MyPlugin.scala └ cool.sbt └ assembly.sbt └ project/ └ PluginOfMyPlugin.scala └ target/ └ Main.class

Slide 18

Slide 18 text

Some examples

Slide 19

Slide 19 text

pishen/annoy4s src/main/cpp/annoyjava.cpp src/main/resource/linux-x86-64/libannoy.so win32-x86 darwin freebsd-x86 ... g++ https://github.com/pishen/annoy4s

Slide 20

Slide 20 text

pishen/annoy4s libraryDependencies += "net.java.dev.jna" % "jna" % "4.2.2" https://github.com/pishen/annoy4s project/plugins.sbt

Slide 21

Slide 21 text

pishen/annoy4s val compileNative = taskKey[Unit](...) import com.sun.jna.Platform import sys.process._ compileNative := { val lib = s"src/main/resources/${Platform.RESOURCE_PREFIX}/libannoy.so" val cpp = "src/main/cpp/annoyjava.cpp" s"g++ -o $lib -shared -fPIC $cpp".! } > compileNative https://github.com/pishen/annoy4s build.sbt

Slide 22

Slide 22 text

KKBOX/spark-deployer libraryDependencies ++= Seq( "com.typesafe" % "config" % "1.3.0", "com.amazonaws" % "aws-java-sdk-s3" % "1.10.34", "com.amazonaws" % "aws-java-sdk-ec2" % "1.10.34", "org.pacesys" % "openstack4j" % "2.0.9" ) addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.0") https://github.com/KKBOX/spark-deployer project/plugins.sbt

Slide 23

Slide 23 text

Scopes

Slide 24

Slide 24 text

compile Key

Slide 25

Slide 25 text

test:compile Key Configuration

Slide 26

Slide 26 text

test:compile::fullClasspath Key Configuration other Key

Slide 27

Slide 27 text

Configuration scope compile test * runtime staging production Global custom configurations : : : : : : name name name name name name "G" "A" "B" "C" "D" delegate

Slide 28

Slide 28 text

Configuration scope compile test * runtime staging production : : : : : : compile compile compile compile compile compile Configuration Key

Slide 29

Slide 29 text

Define Configurations lazy val Staging = config("staging") name := "G" name in Staging := "D" + name.value build.sbt > show name > show *:name > show staging:name > inspect staging:name Global

Slide 30

Slide 30 text

Question 1 lazy val Staging = config("staging") version := "1.0" version in Staging := "1.0.1" name in Staging := "D" + version.value build.sbt > show staging:name D1.0? D1.0.1?

Slide 31

Slide 31 text

Solution 1 name in Staging := "D" + (version in Staging).value inConfig(Staging)(Seq( name := "D" + version.value )) build.sbt

Slide 32

Slide 32 text

Question 2 > compile Configuration? Key?

Slide 33

Slide 33 text

Usage of Configuration lazy val Staging = config("staging") lazy val Production = config("production") val deploy = taskKey[Unit]("deploy") val servers = settingKey[Seq[String]]("servers") val baseSettings = Seq( deploy := {... servers.value ...} ) inConfig(Staging)(baseSettings) inConfig(Production)(baseSettings) deploy.sbt

Slide 34

Slide 34 text

Usage of Configuration servers in Staging := Seq("192.168.0.1") servers in Production := Seq("140.112.172.1", ...) build.sbt > staging:deploy > production:deploy sbt-codedeploy https://github.com/gilt/sbt-codedeploy

Slide 35

Slide 35 text

Task scope * :: name compile test assembly :: :: :: name name name name :: assembly Key Key

Slide 36

Slide 36 text

Question 3 val demo = taskKey[Unit]("demo") version := "1.0" version in demo := "1.0.1" demo := println("D" + version.value) build.sbt > demo D1.0? D1.0.1? demo::version

Slide 37

Slide 37 text

Usage of Task scope fullClasspath in assembly += baseDirectory.value / "production-resources" my-project/ └ src/main/ └ scala/... └ resources/application.conf └ build.sbt └ production-resources/ └ production.conf include "production.conf" build.sbt

Slide 38

Slide 38 text

Mixed scope test:compile::fullClasspath fullClasspath in (Test, compile) := {...}

Slide 39

Slide 39 text

Publishing

Slide 40

Slide 40 text

libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.4.8" ~/.ivy2/cache/ Maven Central Bintray JCenter ~/.ivy2/local/

Slide 41

Slide 41 text

libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.4.8-SNAPSHOT" ~/.ivy2/cache/ Maven Central Bintray JCenter ~/.ivy2/local/

Slide 42

Slide 42 text

organization := "net.pishen" name := "my-project" version := "0.1.0-SNAPSHOT" crossScalaVersions := Seq("2.10.6", "2.11.8") > +publishLocal ~/.ivy2/local/ Project A libraryDependencies += "net.pishen" %% "my-project" % "0.1.0-SNAPSHOT" Project B ~/.ivy2/cache/

Slide 43

Slide 43 text

Resolvers val r = "My Resolver" at "http://my-server/my-repository" val r = Resolver.sonatypeRepo("public") val r = Resolver.bintrayRepo("owner", "repo") val r = Resolver.sftp(...) val r = Resolver.... resolvers += r publishTo := Some(r) > publish

Slide 44

Slide 44 text

Publish your own library via Bintray 1. Create an account on https://bintray.com/ 2. Install bintray-sbt https://github.com/softprops/bintray-sbt 3. Share your masterpiece to the world!

Slide 45

Slide 45 text

> thanks @pishen