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:
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.
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
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
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
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
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
This thread is closed to new comments.
posted by Civil_Disobedient at 6:00 PM on September 9, 2010