Introduction
This is a small writeup which gives one way of setting up a build system for your Scala project. Here Apache Ant is used for managing this process, where the whole configuration is contained within a single build.xml file placed in the project’s root directory. Execution is done from command line or within your IDE environment.
Prerequisites
Install and configure Scala:
- Define and set the
SCALA_HOME variable in the OS environment
- Update the
PATH variable in the OS environment to include SCALA_HOME\bin directory
Install and configure Ant:
- Define and set the
ANT_HOME variable in the OS environment
- Update the
PATH variable in the OS environment to include ANT_HOME\bin directory
- Optional: If you encounter memory problems, define and set
ANT_OPTS=-Xmx500M with JVM memory configuration in the OS environment
Install and configure Java:
- Define and set the
JAVA_HOME variable in the OS environment
- Update the
PATH variable in the OS environment to include JAVA_HOME\bin directory
Find a suitable file structure for the project:
project-name/
build/
lib/
src/
test/
build.xml
The Ant build script
Order of Ant targets:
build <- package <- doc <- compile <- init
clean <- init
Configure project-name/build.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project name="ProjectName" default="build" basedir=".">
<description>Project Build Script</description>
<!-- targets -->
<target name="build" depends="package" description="Build whole project"/>
<target name="clean" depends="init" description="Remove previous build files">
<delete dir="${build.dir}" includeemptydirs="true" quiet="true"/>
</target>
<target name="init">
<property environment="env"/>
<!-- check for required tools -->
<fail message="Missing SCALA_HOME variable in OS environment">
<condition><isset property="${env.SCALA_HOME}"/></condition>
</fail>
<fail message="Missing JAVA_HOME variable in OS environment">
<condition><isset property="${env.JAVA_HOME}"/></condition>
</fail>
<!-- variables for paths and files -->
<property name="src.dir" location="${basedir}/src"/>
<property name="lib.dir" location="${basedir}/lib"/>
<property name="build.dir" location="${basedir}/build"/>
<property name="build-classes.dir" location="${build.dir}/classes"/>
<property name="build-lib.dir" location="${build.dir}/lib"/>
<property name="build-doc.dir" location="${build.dir}/doc"/>
<property name="java.dir" location="${env.JAVA_HOME}"/>
<property name="scala.dir" location="${env.SCALA_HOME}"/>
<property name="scala-library.jar" location="${scala.dir}/lib/scala-library.jar"/>
<property name="scala-compiler.jar" location="${scala.dir}/lib/scala-compiler.jar"/>
<path id="project.classpath">
<pathelement location="${scala-library.jar}"/>
<pathelement location="${build-classes.dir}"/> <!-- used during recompilation -->
</path>
<path id="scala.classpath">
<pathelement location="${scala-compiler.jar}"/>
<pathelement location="${scala-library.jar}"/>
</path>
<!-- load scala's ant tasks -->
<taskdef resource="scala/tools/ant/antlib.xml" classpathref="scala.classpath"/>
<!-- print where this project will get scala and java from -->
<echo message="Init project"/>
<echo message=" with scala.dir = ${scala.dir}"/>
<echo message=" with java.dir = ${java.dir}"/>
<!-- check if any files has been modified since last build -->
<uptodate property="build.uptodate" targetfile="${build.dir}/build.done">
<srcfiles dir= "${src.dir}" includes="**"/>
<srcfiles dir= "${lib.dir}" includes="**"/>
</uptodate>
</target>
<target name="compile" depends="init" unless="build.uptodate">
<mkdir dir="${build-classes.dir}"/>
<scalac
destdir="${build-classes.dir}"
classpathref="project.classpath">
<include name="**/*.scala"/>
<src><pathelement location="${src.dir}"/></src>
</scalac>
</target>
<target name="doc" depends="compile" unless="build.uptodate">
<mkdir dir="${build-doc.dir}"/>
<scaladoc
srcdir="${src.dir}"
destdir="${build-doc.dir}"
doctitle="Project API documentation"
classpathref="project.classpath">
<include name="**/*.scala"/>
</scaladoc>
</target>
<target name="package" depends="doc" unless="build.uptodate">
<mkdir dir="${build-lib.dir}"/>
<jar destfile="${build-lib.dir}/project.jar">
<fileset dir="${build-classes.dir}"/>
</jar>
<jar destfile="${build-lib.dir}/project-src.jar">
<fileset dir="${src.dir}" includes="**/*.scala"/>
</jar>
<jar destfile="${build-lib.dir}/project-doc.jar">
<fileset dir="${build-doc.dir}"/>
</jar>
<touch file="${build.dir}/build.done"/> <!-- mark build as up-to-date -->
</target>
</project>
Reference for Scalac Ant task
Arguments: srcdir, srcref, destdir, classpath, classpathref, sourcepath, sourcepathref, bootclasspath, bootclasspathref, extdirs, extdirsref, encoding, target={jvm-1.5,msil}, deprecation={yes,no}, optimise={yes,no}, unchecked={yes,no}, force={yes,no}, fork={yes,no}, logging={none,verbose,debug}, logphase={namer,typer,pickler,uncurry, tailcalls,explicitouter,erasure, lambdalift,flatten,constructors, mixin,icode,jvm,terminal}, debuginfo={none,source,line,vars,notailcalls}, addparams, scalacdebugging, failonerror={yes,no}, assemname='msil-specific', assemrefs='msil-specific'
Nested arguments: src,classpath,sourcepath,bootclasspath,extdirs
Reference for Scaladoc Ant task
Arguments: srcdir, srcref, destdir, classpath, classpathref, sourcepath, sourcepathref, bootclasspath, bootclasspathref, extdirs, extdirsref, encoding, docgenerator, doctitle, docsourceurl, docversion, header, footer, top, bottom, addparams, deprecation, unchecked
Nested arguments: src, classpath, sourcepath, extdirs
Alternative build systems
Simple Build Tool (SBT) - a Scala-centric build system with support for continuous compilation
Testing frameworks
ScalaTest - supports various testing methodologies
ScalaCheck - specification verified using automatic test-case generation
Specs2 - supports various testing methodologies
References