Setting up an Ant build script for your Scala project

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-reflect.jar" location="${scala.dir}/lib/scala-reflect.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-reflect.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>

References

2 Replies to “Setting up an Ant build script for your Scala project”

  1. Strange, my system’s installation of Scala doesn’t have a “scala/tools/ant/antlib.xml” anywhere. Where are we supposed to find that?

  2. The “scala/tools/ant/antlib.xml” is located within the scala-compiler.jar, which itself is located at %SCALA_HOME%/lib/. Might be related to a problem with the script. I updated the check in init to reference env.SCALA_HOME and env.JAVA_HOME properly, and verified it that it ran when everything is configured correctly.

Leave a Reply

Your email address will not be published. Required fields are marked *