Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SBT Crash Course

Michal Bigos
September 10, 2013

SBT Crash Course

An introduction to SBT and how it works internally.
Talk from September 2013 Slovak Scala User Group meet-up, http://www.meetup.com/slovak-scala/events/133327122/

Michal Bigos

September 10, 2013
Tweet

More Decks by Michal Bigos

Other Decks in Programming

Transcript

  1. SBT CRASH COURSE 1. Why SBT 2. How SBT works

    3. Example of simple project 4. Core concepts
  2. WHY SBT GOOD BUILD TOOL CRITERIA Reproducibility - automating build,

    gives you more time to do real stuff Conventions - using sensible defaults, no need to specify every last option and command Experience - distilation of developer wisdom, e.g. test before publish Portability - good build tool should protect you from differences betweeen systems Ecosystem - allow to extend build easily
  3. WHY SBT LITTLE HISTORY: APACHE ANT Former standard build tool

    for Java projects Pros: 1. Portability - build is defined in XML by chaining tasks 2. Experience - abillity to explicitly define dependencies between tasks Cons: 1. Conventions - no default build lifecycle, each build is piece of art 2. Ecosystem - not easy to extend, task definition distributed as jar
  4. WHY SBT LITTLE HISTORY: APACHE MAVEN Currently heavily used in

    enterprise Java projects Most opinionated build tool Pros: 1. Portability - build is defined in XML so called POM 2. Experience, Conventions - Maven introduces default lifecycle with its phases and tasks. It promotes declarative dependency management. Cons: 1. Ecosystem - not easy to extend. Maven plug-in archtecrure requires plug-in written in Java, then POMs and packaging and availability in repository.
  5. WHY SBT LITTLE HISTORY: GOOD PARTS Default project layout (Maven)

    Default project behavior (Maven) Declarative dependency management (Maven) Portability (Ant, Maven)
  6. WHY SBT FEATURES AT GLACE Uses Scala to describe build

    Can be used for Java and Scala Minimal configuration (inspired by Maven) A number of build-in tasks Declarative dependency management (using Apache Ivy) Portability Reactive development environment Allows use Scala REPL Incremental compilation Automatic re-compilation with different versions of Scala
  7. HOW SBT WORKS TASKS Task based, more like ANT, no

    phases like in Maven If you want to do something you execute a task If you want to ensure that a task runs after another, add an explicit dependency between the tasks Output of a task is value, which can be of any type and past to any another task Multiple tasks can depend upon the output of the same task By default tasks are executed in parallel Using dependency tree sbt can work out what can be run in parallel or in sequence
  8. HOW SBT WORKS DEFAULT STRUCTURE AND LAYOUT Inspired by Maven

    { p r o j e c t r o o t } p r o j e c t / b u i l d . p r o p e r t i e s p l u g i n s . s b t s r c / m a i n / s c a l a / j a v a / r e s o u r c e s / t e s t / s c a l a / j a v a / r e s o u r c e s / t a r g e t / b u i l d . s b t
  9. HOW SBT WORKS TASKS 'VS PLUGINS Appear directly in build

    definition file, shared via VCS Task can be turned into plugin and shared via repository v a l g i t H e a d C o m m i t S H A = t a s k K e y [ S t r i n g ] ( " D e t e r m i n e s t h e c u r r e n t g i t c o m m i t S H A " ) g i t H e a d C o m i t S H A : = P r o c e s s ( " g i t r e v - p a r s e H E A D " ) . l i n e s . h e a d
  10. HOW SBT WORKS PHASES 'VS TASK DEPENDENCIES In Maven, the

    order of execution tasks in phases always leads to confusion Default goals for a phase are executed before explicitly defined and those are executed in implicit order of definition in POM file Implicit order of execution can cause problems when parallelizing build, if there are dependencies between goals SBT is per default parallel, that's why explicit definition of task dependencies is needed It's similar to definition a custom lifecycle in Maven, which is not easy too
  11. HOW SBT WORKS PARALLEL EXECUTION If task A depends on

    B, and C also depends on B => SBT will run B first and then A and C in parallel
  12. HOW SBT WORKS PASSING INFORMATION BETWEEN TASKS In Maven and

    ANT it's very hard to pass an information between tasks Usually through an intermediate file In SBT, you can simply return the value from the task and use it in another dependent task This makes chaining tasks a lot easier
  13. HOW SBT WORKS WORKING WITH SCALA Cross compilation for multiple

    Scala versions => Scala is binary compatible only between minor version releases Not restricted to Scala versions either s c a l a V e r s i o n : = " 2 . 1 0 . 1 " c r o s s S c a l a V e r s i o n s : = S e q ( " 2 . 8 . 2 " , " 2 . 9 . 2 " ) l i b r a r y D e p e n d e n c i e s + = ( s c a l a B i n a r y V e r s i o n . v a l u e m a t c h { c a s e " 2 . 1 0 " = > " o r g . s p e c s 2 " % % " s p e c s 2 " % " 2 . 0 " c a s e " 2 . 9 . 1 " = > " o r g . s p e c s 2 " % % " s p e c s 2 " % " 1 . 1 2 . 4 " } )
  14. HOW SBT WORKS WORKING WITH SCALA, TAKE TWO Scala compiler

    generates lots more classes and JVM takes longer to start-up => interactive environment Scala compilation is slow (in comparision to Java) => incremental compilation Multi-module builds => parallel execution, child modules don't need to know about parent module
  15. CORE CONCEPTS BUILD FILES build.properties build.sbt Blank line is required

    between settings p r o j e c t / b u i l d . p r o p e r t i e s - d e f i n e s S B T v e r s i o n p l u g i n s . s b t - d e f i n e s S B T p l u g i n s b u i l d . s b t - d e f i n e s a c t u a l b u i l d , p r o j e c t s e t t i n g s s b t . v e r s i o n = 0 . 1 2 . 4 n a m e : = " b i g - p r o j e c t " v e r s i o n : = " 1 . 0 " s c a l a V e r s i o n : = " 2 . 1 0 . 0 " l i b r a r y D e p e n d e n c i e s + = " o r g . s c a l a t e s t " % % " s c a l a t e s t " % " 1 . 9 . 1 " % " t e s t "
  16. CORE CONCEPTS SETTINGS Mechanism to configure a build to to

    perform th ework we need to SBT reads all the settings defined in build at load time and runs their initializations n a m e : = " b i g - p r o j e c t " | | | k e y o p e r a t o r i n t i a l i z a t i o n
  17. CORE CONCEPTS SETTINGS, TAKE TWO Settings are typesafe => every

    key has only one type and any value placed into setting must match exact type Grouping of S e t t i n g K e y [ T ] with I n i t i a l i z e [ T ] creates S e t t i n g [ T ] n a m e : = " b i g - p r o j e c t " | | S e t t i n g K e y [ S t r i n g ] I n i t i a l i z e [ S t r i n g ]
  18. CORE CONCEPTS SETTINGS, TAKE THREE Operators used with settings Types

    have to match n a m e : = " b i g - p r o j e c t " | a s s i g n m e n t l i b r a r y D e p e n d e n c i e s + = " o r g . s c a l a t e s t " % % " s c a l a t e s t " % " 1 . 9 . 1 " | a p p e n d a p p e n d m u l t i p l e v a l u e s | l i b r a r y D e p e n d e n c i e s + + = S e q ( " o r g . s c a l a t e s t " % % " s c a l a t e s t " % " 1 . 9 . 1 " % " t e s t " , " o r g . s p e c s 2 " % % " s p e c s 2 " % " 2 . 0 " % " t e s t " )
  19. CORE CONCEPTS SETTINGS, TAKE FOUR Initializations are a Scala expressions

    that can produce value of desired type Intializations may use other settings via s e t t i n g . v a l u e method. v e r s i o n : = " 1 . 0 " l i b r a r y D e p e n d e n c i e s + = ( " o r g . s c a l a t e s t " % % " s c a l a t e s t " % v e r s i o n . v a l u e ) | | S e t i n g K e y [ M o d u l e I D ] I n i t i a l i z a t i o n [ M o d u l e I d ] \ / S e t t i n g [ M o d u l e I D ]
  20. CORE CONCEPTS DEFINING DEPENDENCIES Definition of exact version Cross-compiled dependency

    g r o u p I d % a r t i f a c t I d % v e r s i o n % s c o p e g r o u p I d % % a r t i f a c t I d % v e r s i o n % s c o p e | U s e a p p r o p r i a t e s c a l a v e r s i o n f r o m p r o j e c t
  21. CORE CONCEPTS CIRCULAR REFERENCES Because SBT can use values of

    one setting to instatiate another, it's possible to create circular references Build will fail to load when circular references are detected.
  22. CORE CONCEPTS CUSTOM TASKS AND SETTINGS For version 0.12.4 have

    to be defined in Scala file not sbt one From 0.13.0 they can be defined in sbt too v a l g i t H e a d C o m m i t S H A = t a s k K e y [ S t r i n g ] ( " D e t e r m i n e s t h e c u r r e n t g i t c o m m i t S H A " ) | s e t t i n g / t a s k d e f i n i t i o n g i t H e a d C o m i t S H A : = P r o c e s s ( " g i t r e v - p a r s e H E A D " ) . l i n e s . h e a d | | s e t t i n g / t a s k k e y b l o c k o f c o d e r e t u r n i n g v a l u e
  23. Definitions are compiled first and can reference another definitions Settings

    are executed after definitions, hence can refence any definition Tasks are executed every time the value is requested
  24. CORE CONCEPTS CUSTOM TASKS AND SETTINGS For version 0.12.4 have

    to be defined in Scala file not sbt one From 0.13.0 they can be defined in sbt too v a l g i t H e a d C o m m i t S H A = t a s k K e y [ S t r i n g ] ( " D e t e r m i n e s t h e c u r r e n t g i t c o m m i t S H A " ) | s e t t i n g / t a s k d e f i n i t i o n g i t H e a d C o m i t S H A : = P r o c e s s ( " g i t r e v - p a r s e H E A D " ) . l i n e s . h e a d | | s e t t i n g / t a s k k e y b l o c k o f c o d e r e t u r n i n g v a l u e
  25. Definitions are compiled first and can reference another definitions Settings

    are executed after definitions, hence can refence any definition Tasks are executed every time the value is requested