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.

<?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=”xjc-typedef-target” >
<typedef classname=”com.sun.tools.xjc.XJCTask” name=”xjc” xmlns:s=”http://xml.netbeans.org/schema/JAXBWizConfig”&gt;
<classpath>
<pathelement path=”${jaxbwiz.xjcdef.classpath}” />
<pathelement location=”lib/proplistinjector-0.1.1.jar” />
</classpath>
</typedef>
</target–>

<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>

Advertisements

About this entry