Ant multiple source directories with copied resources

Consider the minimal build.xml fragment that builds jar from sources and includes all resources other than java:

<property name="src.dir" value="src" /> <target name="build"> <javac destdir="bin"> <src path="${src.dir}" /> </javac> <copy includeemptydirs="false" todir="bin"> <fileset dir="${src.dir}"> <exclude name="**/*.java" /> </fileset> </copy> <jar destfile="dist/foo.jar" basedir="bin"/> </target> 

Now imagine that I need to maintain a list of source directories:

 <property name="src.dirs" value="src;src-gen" /> 

How can I modify the above script to make this happen? javac will happily take a list of directories, but for copying I need to convert the string to a list of file sets with exceptions or find another way.

+8
ant
source share
4 answers

I'm not sure if I can do this with Ant's built-in tasks, but you can use the ant -contrib <for> task

 <path id="src.path"> <pathelement location="src" /> <pathelement location="src-gen" /> </path> <target name="build"> <javac destdir="bin"> <src refid="src.path" /> </javac> <for param="dir"> <path refid="src.path" /> <sequential> <copy includeemptydirs="false" todir="bin"> <fileset dir="@{dir}"> <exclude name="**/*.java" /> </fileset> </copy> </sequential> </for> <jar destfile="dist/foo.jar" basedir="bin"/> </target> 
+3
source share

Usually you just list them all together:

 <javac destdir="bin"> <src path="${src.dir}"/> <src path="${src2.dir}"/> <src path="${src3.dir}"/> </javac> 

You can try the <sourcepath/> attribute. I have never used it, but I believe that you can use it to determine the path to various source files and use it:

 <path id="source.path"> <pathelement path="${src.dir}"/> <pathelement path="${src2.dir}"/> <pathelement path="${src4.dir}"/> </path> <javac destdir="bin"> srcpathref="source.path"/> 

The first will work, but not 100% sure about the second.

+8
source share

A simple solution is to simply specify multiple sets of files in the same way that a javac task supports multiple src attributes:

  <target name="build" depends="init" description="Create the package"> <javac destdir="${classes.dir}" includeantruntime="false"> <src path="src/main1/java"/> <src path="src/main2/java"/> </javac> <copy todir="${classes.dir}" includeemptydirs="false"> <fileset dir="src/main1" excludes="**/*.java"/> <fileset dir="src/main2" excludes="**/*.java"/> <flattenmapper/> </copy> </target> 

This, of course, assumes that the number of places in the source code is fixed, which is not unreasonable to expect.

If you want to manage this using a list property, you must resort to embedding a script in your assembly to process this list (I cannot approve ant -contrib):

 <project name="demo" default="build"> <property name="src.dirs" value="src/main1,src/main2"/> <property name="build.dir" location="build"/> <property name="classes.dir" location="${build.dir}/classes"/> <target name="bootstrap"> <mkdir dir="${user.home}/.ant/lib"/> <get dest="${user.home}/.ant/lib/groovy-all.jar" src="http://search.maven.org/remotecontent?filepath=org/codehaus/groovy/groovy-all/2.1.6/groovy-all-2.1.6.jar"/> </target> <target name="init"> <mkdir dir="${classes.dir}"/> </target> <target name="build" depends="init" description="Create the package"> <taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/> <groovy> def srcDirs = properties["src.dirs"].split(",") ant.javac(destdir:properties["classes.dir"], includeantruntime:false) { srcDirs.each { src(path:"${it}/java") } } ant.copy(todir:properties["classes.dir"], includeemptydirs:false) { srcDirs.each { fileset(dir:it, excludes:"**/*.java") } flattenmapper() } </groovy> </target> <target name="clean" description="Cleanup build dirs"> <delete dir="${build.dir}"/> </target> </project> 

Notes:

  • Compare build goals. You will notice that the groovy solution invokes ANT in the same way. That's why I really like groovy integration with ANT.
  • The example also includes the goal of "bootstrap" to download jar groovy dependency on Maven Central . You can also use ivy to manage build dependencies.
+4
source share

As a simple solution without antisocial tasks or built-in scripts:

 <property name="src.dirs" value="src,src-gen" /> <path id="src.path"> <multirootfileset type="dir" basedirs="${src.dirs}"/> </path> <target name="build"> <javac destdir="bin"> <src refid="src.path"/> </javac> <copy todir="bin"> <multirootfileset type="file" basedirs="${src.dirs}"> <exclude name="**/*.java"/> </multirootfileset> </copy> <jar destfile="dist/foo.jar" basedir="bin"/> </target> 

Multirootfileset to the rescue! ;-) Requires Ant 1.9.4 or higher.

0
source share

All Articles