I started using Maven at a company where we had 60+ Java projects all with their own individual Ant build file. Each build file was different and each project was structured completely differently. Porting the most active projects to Maven made this situation a lot saner, test code was always in the same location, the same commands achieved the same things on different projects and we could start to manage our library dependencies sensibly. However, some things just always seemed crazy about Maven - having to explain that Maven really did need to ‘download the whole internet’ just to clean compiled code out of its target directory soon gets painful!
Since I started working on some Scala projects at LShift I experienced further annoyances with Maven so I thought I would examine an alternative to Maven written in Scala – the simple build tool (sbt) http://code.google.com/p/simple-build-tool.
The first thing it did nicely was new project creation, this is much simpler than Maven, no multiple command line options or selections from very long lists, just a simple interactive script with questions that are easy to answer.
[bert] things%sbt Project does not exist, create new project? (y/N/s) : y Name: parsnip Organization []: lshift Version [1.0]: Scala version [2.7.5]: sbt version [0.5.5]: :: retrieving :: sbt#boot confs: [default] 2 artifacts copied, 0 already retrieved (9831kB/619ms) :: retrieving :: sbt#boot confs: [default] 3 artifacts copied, 0 already retrieved (3395kB/39ms) [success] Successfully initialized directory structure. [info] Building project parsnip 1.0 using sbt.DefaultProject [info] with sbt 0.5.5 and Scala 2.7.5 [info] No actions specified, interactive session started. Execute 'help' for more information.
This creates a project structure for you that is closely modelled on the standard directory layout used by Maven. There are two additional directories lib and project. The lib directory provides a standard place to keep any dependencies that aren’t available in a Maven repository. The project directory is where the project configuration is kept.
Secondly, there is no XML required to configure the project, the configuration is carried out by a properties file and a Scala file. Dependencies are managed by adding the values to the Scala file that defines the project configuration; for example:
import sbt._ class ParsnipProject(info: ProjectInfo) extends DefaultProject(info) { val derby = "org.apache.derby" % "derby" % "10.4.1.3" val scalatest = "org.scala-tools.testing" % "scalatest" % "0.9.5" % "test" }
This uses a simple DSL to replace your Maven or Ivy configuration file.
Thirdly, testing is easy! Maven can be a bit hit or miss running the three major Scala testing frameworks and it doesn’t report the actual error when a test fails – you need to dig through the test output. If a test fails with sbt the standard output you would get from the test runner is displayed in the console. Additionally, you can make sbt monitor your project continuously and re-test as code changes so you are informed of broken tests as soon as they break.
Fourthly, it won’t ‘download the internet’ unless you explicitly tell it. The command, sbt update, downloads dependencies but you can do sbt clean without having to download the internet.
[bert] things%sbt clean [info] Building project parsnip 1.0 using sbt.DefaultProject [info] with sbt 0.5.5 and Scala 2.7.5 [info] [info] == clean == [info] Deleting directory /Users/timc/tmp/things/target [info] == clean == [success] Successful. [info] [info] Total time: 0 s [success] Build completed successfully. [info] [info] Total build time: 1 s
So for Scala development sbt seems to be as good if not better than Maven. Extending sbt is also simpler, custom tasks and plugins are simple Scala functions or classes with no additional XML required.