Sans Pareil Technologies, Inc.

Key To Your Business

Scrooge with Ant



Scrooge is a thrift code generator for generating Scala (also Java, but that is already handled by thrift) sources from thrift definitions. The scrooge project provides integration with SBT or Maven, however documentation related to performing the task with Ant is lacking. Here we will illustrate using the scrooge command line interface to perform code generation from ant using ivy for dependency management.

All we do is use the java ant task to execute the com.twitter.scrooge.Main class with the appropriate options to generate scala sources from the thrift definitions.
Dependencies 
The following ivy.xml file should provide your project all the dependencies needed for scrooge.
<ivy-module version="2.2">
  <info organisation="com.sptci" module="thrift"/>

  <configurations>
    <conf name="compile"  description="Compile the source tree"/>
    <conf name="test" extends="compile" visibility="private" description="Test application"/>
  </configurations>

  <dependencies>
    <dependency org="org.scala-lang" name="scala-library" rev="${scala.version}">
      <artifact name="scala-library" type="jar" />
    </dependency>

    <dependency org="org.scala-lang" name="scala-reflect" rev="${scala.version}">
      <artifact name="scala-reflect" type="jar" />
    </dependency>

    <dependency org="org.scala-lang" name="scala-compiler" rev="${scala.version}">
      <artifact name="scala-compiler" type="jar" />
    </dependency>

    <dependency org="com.twitter" name="scrooge-core_2.10" rev="3.16.3">
      <artifact name="scrooge-core_2.10" type="jar" />
    </dependency>

    <dependency org="com.twitter" name="scrooge_2.10" rev="3.16.3">
      <artifact name="scrooge_2.10" type="jar" />
    </dependency>

    <dependency org="com.twitter" name="scrooge-generator_2.10" rev="3.16.3">
      <artifact name="scrooge-generator_2.10" type="jar" />
    </dependency>

    <dependency org="org.apache.thrift" name="libthrift" rev="0.9.1">
      <artifact name="libthrift" type="jar" />
    </dependency>

    <exclude org="org.xerial.snappy" module="snappy-java" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="org.apache.commons" module="commons-lang3" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="javax.servlet" module="servlet-api" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="org.apache.httpcomponents" module="httpclient" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="org.apache.httpcomponents" module="httpcore" type="*" ext="*" conf="" matcher="exact" />

    <exclude org="javax.mail" module="mail" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="javax.activation" module="activation" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="javax.jms" module="jms" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="com.sun.jdmk" module="jmxtools" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="com.sun.jmx" module="jmxri" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="jline" module="jline" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="net.sf.jopt-simple" module="jopt-simple" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="org.hamcrest" module="hamcrest-core" type="*" ext="*" conf="" matcher="exact" />

    <exclude org="org.scala-lang" module="jline" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="org.fusesource.jansi" module="jansi" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="com.twitter" module="util.{0,}" type="*" ext="*" conf="" matcher="regexp" />
    <exclude org="com.google.guava" module="guava" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="com.google.code.findbugs" module="jsr305" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="io.netty" module="netty" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="com.github.spullara.mustache.java" module="compiler" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="org.codehaus.plexus" module="plexus-utils" type="*" ext="*" conf="" matcher="exact" />
    <exclude org="commons-cli" module="commons-cli" type="*" ext="*" conf="" matcher="exact" />

  </dependencies>

</ivy-module>
Properties 
The following properties file is used to configure the ant build system.
scala.version                 2.10.4

debug                              yes

ivy.home                         ${user.home}/.ivy2
ivy.jar.dir                         ${ivy.home}/lib
ivy.jar.file                        ${ivy.jar.dir}/ivy.jar
ivy.install.version          2.3.0

dir.lib                               lib

dir.src                              src
dir.src.app                      ${dir.src}/app
dir.src.test                       ${dir.src}/test
dir.config                        config
dir.build                          build
dir.deploy                       deploy

dir.src.thrift                     ${dir.src}/definitions
Build Script 
The following build script can be used to build your project. Note that we use a generate task as a dependency on the main compile task, which will ensure that the scala sources are generated from the thrift definitions prior to compiling the sources.
<?xml version="1.0"?>

<project name="ScroogeThrift" default="compile" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">

  <property environment="env" />
  <property file="ant.properties" />

  <target name="clean"
          description="Clears all generated files, including build directories, distributables, and documentation.">
    <delete dir="${dir.build}" />
    <delete dir="${dir.deploy}" />
  </target>

  <path id="compile.classpath">
    <fileset dir="${dir.lib}">
      <include name="*.jar"/>
    </fileset>
  </path>

  <target name="init" description="Initialise build system" depends="init-ivy, resolve">
    <property name="scala-library.jar"
      value="${dir.lib}/scala-library-${scala.version}.jar" />

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

  <target name="generate" depends="init">
    <fileset id="fileset" dir="${dir.src.thrift}">
      <include name="*.thrift" />
      <exclude name="common.thrift" />
    </fileset>
    <pathconvert property="files" refid="fileset" pathsep=" " />
    <java classname="com.twitter.scrooge.Main" classpathref="compile.classpath"
          fork="true" failonerror="true" maxmemory="512m">
      <arg line="-d ${dir.src.data} -s ${files}" />
    </java>
  </target>

  <target name="compile" depends="generate" description="Compile the source files for the library">
    <mkdir dir="${dir.build}" />

    <scalac destdir="${dir.build}" target="jvm-1.7"
      deprecation="yes" addparams="-feature -language:postfixOps">
      <compilerarg value="-Xlint:deprecation"/>
      <src>
        <path path="${dir.src.app}" />
      </src>
      <classpath>
        <path refid="compile.classpath"/>
      </classpath>
      <include name="**"/>
    </scalac>

  </target>

  <!-- automatically configure download and install ivy if required. -->
  <target name="download-ivy" unless="offline">
    <mkdir dir="${ivy.jar.dir}"/>
    <get src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
         dest="${ivy.jar.file}" usetimestamp="true"/>
  </target>

  <target name="init-ivy" depends="download-ivy">
    <path id="ivy.lib.path">
      <fileset dir="${ivy.jar.dir}" includes="*.jar"/>
    </path>
    <taskdef resource="org/apache/ivy/ant/antlib.xml"
                 uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
  </target>

  <target name="resolve" description="--> retrieve dependencies with ivy">
    <ivy:retrieve />
  </target>

</project>
We have illustrated how you can use scrooge to generate scala sources from thrift definitions using an ant task. In future there may be a proper ant task contributed to the scrooge project which will make the process even simpler.