Reusable Ant build file

Hello,

I’m back from some vacations.

The topic I want to discuss this time is the use of ant build files. I don’t like the build files generated by netbeans. Why ? Working in a professional environment, you have to master all your building chain : know what happens in the continuous integration process, know exactly what you deliver to your production team (in a professional environment developers package the release and deliver it to production team; only production authorized team deploy the package on production systems), …​.

So I don’t like the maze of ant files generated by Netbeans. Here is the reusable ant file I used. you can rapidly use it back in a new project with fex modification (mainly the project name).

This file contains targets for :

  • compilation (at least what a build file must do)

  • generate the javadocĀ  (documentation is important, don’t forget it)

  • creating the distribution jar file

  • run target to launch your application, based on the generated jar (this one is an example you’ll have to modify the command line parameters)

  • test your application (with junit), which is important to automate in the case of continuous integration

  • generation of code with jaxb : this can be suppressed (in this case, you can suppress the corresponding mkdir task in prebuild target.

<?xml version="1.0" ?>
<project name="phonebook" basedir="." default="main">
<property name="dist.dir" value="dist"/>
<property name="src.dir" value="src"/>
<property name="src-generated.dir" value="generated-src"/>
<property name="build.dir" value="build"/>
<property name="lib.dir" value="lib"/>
<property name="javadoc.dir" value="${dist.dir}/doc"/>
<property name="version" value="1.1.2"/>
<property name="MainClass" value="fr.free.banks." />
<path id="lib.path">
        <fileset dir="${lib.dir}" includes="**/*.jar"/>
    </path>
<pathconvert property="lib.classpath" pathsep=" " dirsep="/">
<path refid="lib.path"></path>
      <map from="${basedir}/lib" to="lib"/>
    </pathconvert>

<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
  <classpath>
    <fileset dir="${lib.dir}" includes="*.jar" />
  </classpath>
</taskdef>

    <target name="clean">
        <delete dir="${build.dir}"/>
        <delete dir="${dist.dir}"/>
        <delete dir="${src-generated.dir}" />
    </target>

    <target name="prebuild">
        <mkdir dir="${build.dir}" />
        <mkdir dir="${dist.dir}" />
        <mkdir dir="${src-generated.dir}" />
    </target>

    <target name="main" description="Build complet" depends="clean,create-jar">
        <copy todir="${dist.dir}/lib">
          <fileset dir="${lib.dir}">
            <include name="**/*.jar"/>
          </fileset>
        </copy>
        <copy todir="${dist.dir}">
          <fileset dir="${basedir}">
            <include name="*.xsd"/>
          </fileset>
        </copy>
        <!--copy todir="${dist.dir}/doc">
          <fileset dir="${basedir}/doc">
            <include name="**/*.doc"/>
          </fileset>
        </copy-->
        <zip destfile="${ant.project.name}.zip">
            <zipfileset dir="dist" />
        </zip>
    </target>

    <target name="compile" description="Compile classes" depends="prebuild,generate-xjc">
        <javac srcdir="${src.dir}:${src-generated.dir}" destdir="${build.dir}">
            <classpath>
                <fileset dir="${lib.dir}">
                    <include name="**/*.jar"/>
                </fileset>
            </classpath>
        </javac>
    </target>

    <target name="generate-xjc" description="Generate classes with JAXB">
        <xjc package="fr.free.banks.phonebook.xml" destdir="${src-generated.dir}" >
            <classpath>
<pathelement location="${src.dir}"/>
<pathelement path="${jaxbwiz.xjcrun.classpath}"/>
            </classpath>
            <arg value="-xmlschema"/>
            <arg value="-extension"/>
            <!--arg value="-Xinject-listener-code" /-->
            <schema file="${src.dir}/phonebook.xsd"/>
<produces dir="${src-generated.dir}"/>
        </xjc>
    </target>

    <target name="create-jar" description="Create jar file" depends="compile">
        <copy todir="${build.dir}">
          <fileset dir="${src.dir}">
            <include name="**/log4j.xml"/>
          </fileset>
        </copy>
        <jar jarfile="${dist.dir}/${ant.project.name}.jar" basedir="${build.dir}" includes="**/*.class log4j.xml" >
            <manifest>
                <section name="${ant.project.name}">
                  <attribute name="Specification-Version" value="${version}"/>
                  <attribute name="Implementation-Version" value="${version}"/>
                </section>
                <attribute name="Main-Class" value="${MainClass}"/>
                <attribute name="Class-Path" value="${lib.classpath}"/>
            </manifest>

        </jar>
    </target>

    <target name="compile.test" description="Compile test classes">
        <mkdir dir="${build.test.dir}" />
        <copy todir="${build.dir}">
            <fileset dir="${basedir}">
                <include name="k.properties" />
            </fileset>
        </copy>
        <javac srcdir="${tst.dir}" destdir="${build.test.dir}" encoding="UTF-8">
            <classpath>
<pathelement location="${junit4.dir}/junit.jar" />
<pathelement location="${build.dir}" />
            </classpath>
        </javac>
    </target>

    <target name="test" depends="compile.test">
        <junit>
            <classpath refid="classpath.test" />

            <formatter type="brief"  />
            <!--test name="com.bnpparibas.itp.qm.qos.anonymiser.test.AnonymiserTest" haltonfailure="no" outfile="result">
                <formatter type="xml"/>
            </test-->

              <batchtest fork="yes" todir="buildtest">
                <fileset dir="${tst.dir}">
                  <include name="**/*Test*.java"/>
                </fileset>
              </batchtest>

        </junit>
    </target>

    <target name="javadoc">
        <javadoc access="public" author="true" classpath="lib/log4j-1.2.15.jar;C:\Sauvegarde\eclipse-cpp-plugin\eclipse\plugins\org.junit4_4.3.1\junit.jar" destdir="${javadoc.dir}" nodeprecated="false" nodeprecatedlist="false" noindex="false" nonavbar="false" notree="false" source="1.5" sourcepath="${src.dir}" splitindex="true" use="true" version="true"/>
    </target>

    <target name="run">
        <java classname="fr.free.banks.phonebook.App"
               fork="true"
               failonerror="true"
               maxmemory="128m" >
            <classpath>
<pathelement location="${dist.dir}/${ant.project.name}.jar" />

            </classpath>
            <arg value="-f" />

        </java>
    </target>

</project>

You can had dependances from other projects in the prebuild target, for example add this :

<copy todir="${lib.dir}">
    <fileset dir="${basedir}/../otherproject/dist">
    <include name="otherproject.jar"/> </fileset>
 </copy>

Hopes this can help you. And don’t hesitate to report possible errors.

comments powered by Disqus