This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 18.18, “Building a Scala Project with Apache Ant.”
Problem
You want to use Apache Ant to build your Scala project.
Solution
Assuming you have a Maven- and SBT-like project directory structure as described in Recipe 18.1, create the following Ant build.xml file in the root directory of your project:
<project name="AntCompileTest" default="compile" basedir=".">
<!-- mostly from: http://www.scala-lang.org/node/98 -->
<property name="sources.dir" value="src" />
<property name="scala-source.dir" value="main/scala" />
<property name="scala-test.dir" value="main/test" />
<property name="build.dir" value="classes" />
<!-- set scala.home -->
<property environment="env" />
<property name="scala.home" value="${env.SCALA_HOME}" />
<target name="init">
<property name="scala-library.jar"
value="${scala.home}/lib/scala-library.jar" />
<property name="scala-compiler.jar"
value="${scala.home}/lib/scala-compiler.jar" />
<property name="scala.reflect"
value="${scala.home}/lib/scala-reflect.jar"/>
<path id="build.classpath">
<pathelement location="${scala-library.jar}" />
<pathelement location="${build.dir}" />
</path>
<taskdef resource="scala/tools/ant/antlib.xml">
<classpath>
<pathelement location="${scala-compiler.jar}" />
<pathelement location="${scala-library.jar}" />
<pathelement location="${scala.reflect}"/>
</classpath>
</taskdef>
</target>
<target name="compile" depends="init">
<mkdir dir="${build.dir}" />
<scalac srcdir="${sources.dir}"
destdir="${build.dir}"
classpathref="build.classpath"
deprecation="on">
<include name="${scala-source.dir}/**/*.scala" />
<exclude name="${scala-test.dir}/**/*.scala" />
</scalac>
</target>
</project>
You can then run the usual ant
command, which by default will compile your files to a new classes folder under the root directory of your project. Running ant
on a small project produces output like this:
$ ant
Buildfile: /Users/Al/Projects/AntExample/build.xml
init:
compile:
[scalac] Compiling 1 source file to /Users/Al/Projects/AntExample/classes
BUILD SUCCESSFUL
Total time: 5 seconds
Discussion
In general, when learning a new technology it’s best to learn the tools of that technology, and in this case the preferred build tool for Scala projects is SBT. (As a friend once said, when we went from C to Java we didn’t attempt to bring make
along with us.) Once you grasp the SBT concepts, you’ll find that it’s both a simple and powerful tool, especially for basic projects, and you can find a lot of support in the Scala community.
That being said, you’re also hit with a lot of changes when first learning a new technology, and at the beginning it can be helpful to use the tools you’re already comfortable with, so this recipe demonstrates how to use Ant to compile a Scala project to help you get into Scala in a comfortable way.
Recommendation: If someone brought me into their organization to help them adopt Scala, SBT is one of the first things I’d teach. In this case I think you’re better off just diving into the water, so to speak. It doesn’t take that long to grasp the SBT basics.
The build.xml code
The secret sauce to this Ant recipe is the init
target, whose source code can be found on the official Scala website at www.scala-lang.org/node/98. This target does the work necessary to make the scalac Ant task available to you.
As you can see from the code, the build
target depends on the init
target, and uses scalac
to compile all the files in the source directory, while skipping the files in the test directory. Of course that approach is completely optional, and you can adjust it to meet your needs.
The antlib.xml file referred to in the taskdef
tag is shipped with the Scala distribution. You can demonstrate this on a Unix system with the following command:
$ jar tvf ${SCALA_HOME}/lib/scala-compiler.jar | grep -i antlib
The build.xml file shown here is slightly different than the file shown on the Scala website. Specifically, I found that the scala.home
property needed to be set manually, and with Scala 2.10 it’s also necessary to add the scala.reflect
lines to the build file. The compilation process worked fine with Ant 1.8.4 once I made those changes.
In addition to this scalac
Ant task, there are also fsc
and scaladoc
tasks. See the Scala Ant Tasks page on the official Scala website for more information.
Creating a JAR file with Ant
Once you’ve compiled your Scala classes, you can treat them as normal Java class files. For instance, you can create a JAR file from them using the following simplified Ant task. This task shows how to create a JAR file named hello.jar from the compiled classes in the classes directory, and a simple manifest in a Manifest.txt file. Here’s the create-jar
task, which you can add to the earlier build.xml file:
<target name="create-jar" depends="compile">
<jar basedir="classes"
jarfile="hello.jar"
manifest="Manifest.txt"/>
</target>
Assuming the Hello
class in the hello package has the main
method for your application (or extends the App
trait), place this line in the Manifest.txt file:
Main-Class: hello.Hello
After adding this task to your build.xml file, you can run it as follows from the root directory of your project:
$ ant create-jar
That command creates a JAR file named hello.jar in the root directory. You can then run the JAR file with this scala
command:
$ scala hello.jar
This is similar to running java -jar
on a JAR file created by a Java application, but because a Scala application has dependencies on its own JAR files, such as $SCALA_HOME/lib/scala-library.jar, you need to run the JAR file with the scala
interpreter, as shown. You can run the JAR file with the Java interpreter, but this takes a bit more work. See Recipe 18.14, “Deploy a Single, Executable JAR File,” for details on that process.
See Also
The Scala Cookbook
This tutorial is sponsored by the Scala Cookbook, which I wrote for O’Reilly:
You can find the Scala Cookbook at these locations: