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
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
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.
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
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
{ 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
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
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
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
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 " } )
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
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 "
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
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 ]
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 " )
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 ]
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
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
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