bash-in-XML
September 9, 2010 5:38 PM   Subscribe

Apache ant build file help. What's the ant equivalent of the makefile I have in mind?

This is not a question about insects.

One particular subsystem of my java project is implemented differently in three different source directories, and three different jar targets can be created by changing CLASSPATH to include the one "main" class and the desired subsystem path, along with the paths for the common classes before running javac/jar. This isn't negotiable, and from what I hear isn't that unusual.

I'd like to make a build.xml that can javac and jar up all three targets, but I'm having trouble figuring out how to do it efficiently. If this were a makefile, I'd simply define the three target names, have each target depend on a distinct list of source files, and provide the build/tar command statements to transform them.

How can I do this in ant? I've tried something like this approach:
    <target name="setup1" >
        <set filelist="first list"/>
    </target>
    <target name="setup2" >
        <set filelist="second list"/>
    </target>
    <target name="setup3" >
        <set filelist="third list"/>
    </target>

    <target name="compile" >
        <javac src="${filelist}" />
    </target>

    <target name="jar1" depends="setup1, compile"/>
    <target name="jar2" depends="setup2, compile"/>
    <target name="jar3" depends="setup3, compile"/>

    <target name="all" depends="jar1, jar2, jar3"/>
But when I try to build, ant evaluates/executes setup1, then compile, then setup2, then setup3, then exits. Does anyone know how to do this without resorting to one target with three pairs of javac, jar commands in it? I spent a good chunk of the afternoon googling for insight but only found dozens of "my first build.xml" tutorials.
posted by ceribus peribus to Computers & Internet (5 answers total)
 
I'm not entirely sure I follow, but usually I have a separate build.xml for each subsystem. I have a "dist" target in each where the JAR is copied to a variable directory, say "distdir". Then building is a simple ant call to each subunit:
<target name="buildall">
  <ant dir="${user.prjroot}/subsys1" target="dist" inheritall="false">
    <reference refid="distdir"/>
  </ant>
  <ant dir="${user.prjroot}/subsys2" target="dist" inheritall="false">
    <reference refid="distdir"/>
  </ant>
  etc...
</target>
In each case, the refid for "distdir" is passed to each subsystem so their output goes to the same place.
posted by Civil_Disobedient at 6:00 PM on September 9, 2010


Response by poster: Well, subsystem is probably being generous. Without getting into proprietary details, consider each jar a different kind of data connection manager, with the directories being reimplementations of some underlying routines using different transport protocols. Almost like middleware alternatives. It's static compile time polymorphism though, not runtime. (We're not going to redesign the project to accomodate a build tool!)

Instead of exhaustively building everything in each of these subdirectories, we've been setting the appropriate $CLASSPATH for each target and letting the main project pull in the routines it needs from this layer as it compiles.

Using multiple build.xml's and multiple <ant... > tags that way - isn't that resorting to iteration by repetition? Ideally, I'd like to have the rest of the command attributes (java target version, optflags, debug switches, etc) and such all specified in one place so that they won't fall out of sync with each other in several places during the months ahead. This doesn't seem to be How It's Done in the ant world, however.

The problem I think I'm having is that there's no way to convey to ant that the source files used are different with a different $CLASSPATH value. Given a target name and the main class name, it merrily compiles the first case, and considers that class up to date when building the second target even when the $CLASSPATH changes? I think the main class itself has to be different (and thus come from different .java files... sigh) for each .jar.
posted by ceribus peribus at 7:28 PM on September 9, 2010


use Ant tp copy the source file ${filelist} into a temp build directory... Compile and jar that...

Rinse and repeat as required..
posted by nielm at 1:58 AM on September 10, 2010


I haven't used ant in a while, but you don't seem to be getting much help here, so here are a couple inexpert comments:

Looking at the javac task, it looks like you might be able to fix your specific problem by adding the includeDestClasses="false" attribute. Alternately, you could use the destdir attribute and compile each version into a different directory and jar from there.

Another related approach would be to delete the classfiles you want to force a recompile on after doing the jar.

But I think the best solution is to get yourself straightened out on the best way to do multiple tasks. I think all you need to know is about the antcall task (which lets you call another task in the same file and pass some parameters), but if you want to get more complicated you might want to look at this page about import and macros (also helpful if you want to take Civil_Disobedient's advice and make a build.xml for each directory, since those can all import from a common one).
posted by inkyz at 6:44 PM on September 10, 2010


I've done this using property files, treating each build profile as a separate environment configuration.

The build file was written to compile/test/package the main implementation with paths and compile specific flags set in default property values. Alternative implementations were built by using the -D flag to load different extra property files that overrode properties as needed.

Only works if you're just changing implementation details and swapping out source directories.
posted by tksh at 9:58 AM on September 12, 2010


« Older UBUNTU! no, seriously.   |   The Quintessential _____ Album Is... Newer »
This thread is closed to new comments.