Version 8, last updated by dmclean62 at May 05, 2011 12:56 UTC

We will start with an outline and fill it in on an “as I have time” basis.

Managing libraries without Maven or SBT

One thing that Maven and SBT do that Ant does not is to automatically download the correct version of any needed library from the appropriate Maven repository. Due to the prevalence of Maven and SBT within the Scala community, there is no traditional Lift download and installation package – you have to go to the Maven repository and download it all yourself. Unfortunately, this has to be done on a component by component basis.

Within the repository, there are a collection of sub-directories of the form component name_scala version. Under these directories are sub-directories by Lift release number that contain the source and binary jars for a specific version of a specific component. I am currently using the following components:

  • lift-actor_2.8.1-2.2.jar
  • lift-common_2.8.1-2.2.jar
  • lift-json_2.8.1-2.2.jar
  • lift-mapper_2.8.1-2.2.jar
  • lift-util_2.8.1-2.2.jar
  • lift-webkit_2.8.1-2.2.jar

Other libraries

Manually managing dependencies is not exactly my favorite thing but using Ant makes it necessary.

One favorite tactic is to copy the jars into a central place with a standard file name, such as just “hibernate.jar”, with no version information. Often the jars are dumped into the VCS to make it really easy to build everything. This can be a very convenient setup, but of course, you have no idea from looking at the file what version is being used (and putting binaries into most VCS systems can cause bloating).

The approach that I favor is to set aside a directory where all of the libraries go. It doesn’t matter what the name of this directory is, in our Ant build file we will refer to it with a property (extHome) that will be defined outside the build file. For the most part I just dump the entire distribution package there without change. This is easy to setup and, since most Java library packages have the version number in the directory name, it becomes transparent which version of each library is being used. I then add property definitions for each Jar to the Ant build.xml file. If I have a bunch of Jar definitions from the same package, I’ll use a “libHome” variable, like so:


    <!-- Location of Liftweb files -->
    <property name="liftHome" value="${extHome}/lift-2.1/lib"/>
    <property name="lift-actor.jar" value="${liftHome}/lift-actor_2.8.1-2.2.jar"/>
    <property name="lift-common.jar" value="${liftHome}/lift-common_2.8.1-2.2.jar"/>
    <property name="lift-json.jar" value="${liftHome}/lift-json_2.8.1-2.2.jar"/>
    <property name="lift-mapper.jar" value="${liftHome}/lift-mapper_2.8.1-2.2.jar"/>
    <property name="lift-util.jar" value="${liftHome}/lift-util_2.8.1-2.2.jar"/>
    <property name="lift-webkit.jar" value="${liftHome}/lift-webkit_2.8.1-2.2.jar"/>

Some libraries put the version number of the library in the name of the Jar (in addition to the directory) which makes upgrading libraries a pain.

Creating the Ant build file

I’m a big fan or a well organized Ant build file. To me, that means breaking the build up into discrete steps, with pretty much only one thing taking place in each step (compile, test, etc). In Ant, a step is implemented with a “target”. The build file for the WAR of my application contains the following targets (in order):

  • init – sets up Ant variables used in later steps
  • clean – deletes previous artifacts to insure that they won’t interfere with the build
  • mkdirs – creates empty target directories to replace the ones deleted in clean
  • copyresources – copies all non-compiled files that at bundled into the application JAR file
  • compile – compiles all source files
  • deliver – creates the application JAR file
  • war – creates the WAR file from the application JAR, bundled JARs, HTML files, etc

It could be argued that executing a clean with every build is unnecessary paranoia. On the flip side, paranoid people are generally the ones that are best prepared when something goes wrong.

Compiling Scala sources

In my init section, there are two pieces that tell Ant how to run the scalac and scaladoc tasks:


        <path id="scala.classpath">
            <pathelement location="${scala-compiler.jar}"/>
            <pathelement location="${scala-library.jar}"/>
        </path>

        <taskdef resource="scala/tools/ant/antlib.xml">
            <classpath refid="scala.classpath"/>
        </taskdef>

With scalac defined, compiling code is reasonably straightforward. Here’s the section from the compile target to compile the production code (test is separate):


        <scalac logging="verbose"
                srcdir="${src.dir}"
                destdir="${class.dir}"
                addparams="-g:vars"
                classpathref="compile.classpath"
                force="changed"
                deprecation="on"
                >
            <include name="**/*.scala"/>
        </scalac>

Mixed Java and Scala environments

Building a WAR file