tags:

views:

58

answers:

2

How can I get the javac task to use an existing fileset? In my build.xml I have created several filesets to be used in multiple places throughout build file. Here is how they have been defined:

<fileset dir = "${src}"  
    id       = "java.source.all">  
 <include name =  "**/*.java" />  
</fileset>  

<fileset dir = "${src}"  
    id       = "java.source.examples">  
  <include name = "**/Examples/**/*.java" />  
</fileset>  

<fileset dir = "${src}"  
    id       = "java.source.tests">  
  <include name = "**/Tests/*.java" />
</fileset>

<fileset dir = "${src}"
    id       = "java.source.project">
  <include name = "**/*.java"             />
  <exclude name = "**/Examples/**/*.java" />
  <exclude name = "**/Tests/**/*.java"    />
</fileset>

I have also used macrodef to compile the java files so the javac task does not need to be repeated multiple times. The macro looks like this:

<macrodef name="compile">
  <attribute name="sourceref"/>
  <sequential>
    <javac srcdir         = "${src}"
        destdir           = "${build}"
        classpathref      = "classpath"
        includeantruntime = "no"
        debug             = "${debug}">
      <filelist dir="." files="@{sourceref}" />  <-- email is about this
   </javac>
 </sequential>

What I'm trying to do is compile only the classes that are needed for specific targets not all the targets in the source tree. And do so without having to specify the files every time. Here are how the targets are defined:

<target name = "compile-examples"
    depends  = "init">
  <compile sourceref = "${toString:java.source.examples}" />
</target>

<target name = "compile-project"
    depends  = "init">
  <compile sourceref = "${toString:java.source.project}" />
</target>

<target name = "compile-tests"
    depends  = "init">
  <compile sourceref = "${toString:java.source.tests}" />
</target>

As you can see each target specifies the java files to be compiled as a simi-colon separated list of absolute file names. The only problem with this is that javac does not support filelist. It also does not support fileset, path or pathset. I've tried using but it treats the list as a single file name. Another thing I tried is sending the reference directly (not using toString) and using but include does not have a ref attribute.

SO THE QUESTION IS: How do you get the javac task to use a reference to a fileset that was defined in another part of the build file? I'm not interested in solutions that cause me to have multiple javac tasks. Completely re-writting the macro is acceptable. Changes to the targets are also acceptable provided redundant code between targets is kept to a minimum.

p.s. Another problem is that fileset wants a comma separated list. I've only done a brief search for a way to convert semi-colons to commas and haven't found a way to do that.

p.p.s. Sorry for the yelling but some people are too quick to post responses that don't address the subject.

+1  A: 

If I understand your question correctly, then a combination of antcall and pathconvert should do the trick.

Pathconvert can be used to carry out the comma-separating in the included file list. (I don't understand what the semi-colon issue you mention in passing is, but you can probably adjust the pathconvert call to address that.) Using antcall in the macro allows you to pass a different fileset reference id on each compilation.

Here's an example that illustrates:

<fileset id="file.set1" dir="." includes="TestT*.java" />
<fileset id="file.set2" dir="." includes="TestF*.java" />

<macrodef name="compile">
  <attribute name="sourceref"/>
  <sequential>
    <antcall target="compile_inner">
      <reference refid="@{sourceref}" torefid="inner.file.set" />
    </antcall>
  </sequential>
</macrodef>

<target name="comp">
  <compile sourceref="file.set1" />
  <compile sourceref="file.set2" />
</target>

<target name="compile_inner">
  <pathconvert pathsep=" " property="file.list" refid="inner.file.set">
    <map from="${basedir}/" to="" />
  </pathconvert>
  <javac srcdir         = "${src}"
      destdir           = "${build}"
      includeantruntime = "no"
      includes          = "${file.list}"
      debug             = "${debug}"
      listfiles         = "yes">
  </javac>
</target>

Running the comp target with files

TestFive.java TestFour.java TestOne.java TestSix.java TestThree.java TestTwo.java

in the ${src} dir yields:

comp:

compile_inner:
    [javac] Compiling 2 source files to /Users/mc/stack_overflow/ant/javac
    [javac] /Users/mc/stack_overflow/ant/javac/TestThree.java
    [javac] /Users/mc/stack_overflow/ant/javac/TestTwo.java

compile_inner:
    [javac] Compiling 2 source files to /Users/mc/stack_overflow/ant/javac
    [javac] /Users/mc/stack_overflow/ant/javac/TestFive.java
    [javac] /Users/mc/stack_overflow/ant/javac/TestFour.java

BUILD SUCCESSFUL
martin clayton
Thanks, pathconvert was the solution.
Robert Menteer
A: 

Thanks! PathConvert solved the problem. Changing the macro body to this allowed the file list to be passed in:

<sequential>
  <local name = "sources" />
  <pathconvert refid = "@{sourceref}"
      property       = "sources"
      pathsep        = "," />
  <javac srcdir         = "${src}"
      destdir           = "${build}"
      classpathref      = "classpath"
      includes          = "${sources}"
      includeantruntime = "no"
      debug             = "${debug}" />
</sequential>  

With this I could also drop the toString in the macro call and pass the reference directly. Note the toString turns the reference into a semi-colon separated list.

Robert Menteer