--On Tuesday, September 13, 2005 1:30 PM +0200 Christoph Lofi <[EMAIL PROTECTED]> wrote:

Well, I don't know. I think generating the build file is the easiest and least
dangerous way to go.
I also think that the debugugging problem isn't that severe as long as the 
build file
generation is transparent (which is the case when using template languages like
velocity).

Hi Christoph,

I've just spent some time researching this issue. I've discovered one very 
useful article:

<http://www.oracle.com/technology/pub/articles/bodewig_ant1.6.html>

In a nutshell, this article shows:

- how to use <macrodef> to simplify tasks that used to call <antcall>
- how to use <import> to simplify splitting up a large build.xml into smaller 
ones.
- how to use <subant> to invoke a task that may be present in multiple 
build.xml files.

There is an extremely intriguing reference at the very end of the article to an (as yet unimplemented) task called <buildlist>, which would accept a set of build.xml files and return a path that orders them according to their dependencies. They say this "might be available" in a future release of Ant, but I did some searching and all I could find was an implementation for a system called Ivy:

<http://www.jayasoft.org/node/223>

I'm pretty sure we don't want to import Ivy just to get this one task, but Ivy is open source so its implementation is accessable and might be interesting to look at.

But Aarons Option 2 also sounds cool too me.
Determining the module build order should not be too hard (isn't that some kind 
of
stupid standard graph theory problem? "serialization of a paralell tree" or 
something
like that?). The implementation of that isn't not too different from the 
generating
alternative (crawaling for the module definition files, checking if all 
dependencies
are there and then generating eitther a build file or some kind of build order
description file.)

The first thing to note is that there is a misconception about the "generating alternative": just like our current implementation is structured so that Ant takes care of the dependency analysis, the generating alternative would similarly not require any dependency analysis. It would simply use as data the various local.module.definition.xml files, such as:

<hackystat-module>
 <name>hackyFoo</name>
 <available>on</available>
 <dependent-modules>
   <module>hackyKernel</module>
   <module>hackyStdExt</module>
 </dependent-modules>
</hackystat-module>

to produce (among other things) task definitions such as this doInternal_hackyFoo in the generated build XML file:

<target name="doInternal_hackyFoo"
       depends="doInternal_hackyKernel, doInternal_hackyStdExt"
       if="hackyStdFoo.available">
<echo message="(${ant.project.name}) Invoking ${target} in hackyFoo." />
<fail message="hackyFoo requires module hackyKernel." 
unless="hackyKernel.available" />
<fail message="hackyFoo requires module hackyStdExt." 
unless="hackyStdExt.available" />
<ant dir="../hackyFoo" antfile="local.build.xml" target="${target}" />
</target>

The second thing to note is that Ant already implements a solution to the "stupid standard graph theory problem" :-), so if we were to go down the route of implementing our own <buildlist>, one would presumably be able to leverage the already implemented dependency analysis code in Ant.

However, as I look more closely at the problem, I am less sanguine about the possibility of <buildlist> solving all our problems, at least in a way that doesn't produce more complexity rather than less.

To provide some insight into the complexity, what you need to see is that for each module in Hackystat, there are over a dozen targets we want to implement, including: clean, compile, checkstyle, javadoc, java2html, bcml, install, junit, cvsUpdate, cvsCommit, cvsChangeLog, cvsDiff, and dependency. It turns out that some of these targets (like compile) have to be written in a custom manner for each module, while other targets (such as cvsUpdate) are written exactly the same way (modulo some property values) for each module. Our current system solves this problem by providing "generic" implementations for the tasks that are written the same way in the build.utils.xml file, and requiring each module to provide its own implementation of the custom tasks in its own local.build.xml file.

So, that's one issue that our current build system solves reasonably nicely, which is the custom vs. generic task implementation. Overlaid on top of this is a second issue, the module dependency issue, which involves doInternal_<module> and so forth to figure out the order in which the generic (or custom) task for the set of modules should be invoked. (By the way, I forgot that there's a whole other set of tasks in the build.utils.xml file called doUtil_<module> that are there to facilitate the implementation of the generic tasks.)

So, in summary, it seems to me that the direction that is simplest is the 
following:

- remodularize our current build.xml and build.util.xml into a set of new build 
files,

 (1) new.build.xml
 the master build.xml, which <import>'s the following build files.

 (2) new.modules.build.xml
the auto-generated build file containing all tasks referring to specific modules, including:
   doUtil_<module>
   doUtilAll
   doInternal_<module>
   doAll
   checkModuleAvailability
   modules

 (3) new.cruisecontrol.build.xml
 contains all of the cruise control related targets

 (4) new.cm.build.xml
 contains the CVS targets (and will be updated to SVN targets eventually)

The first goal is to successfully be able to invoke all of our current functionality using:

ant -f new.build.xml <target>

Once we get to here, the next step is to autogenerate the contents of the new.modules.build.xml file by reading in the individual local.module.definition.xml files. For simplicity's sake, I would prefer to avoid introducing another huge and complex package (i.e. velocity) if something simpler (such as Ant's built-in XSLT task) would work epsilon-distance as well. On the other hand, a small improvement to the built-in XSLT task like the <styler> task might be worth checking out, particularly because it supports file merging:
<http://www.langdale.com.au/styler/>

By creating brand new files (i.e. with the "new." suffix), this allows us to work on the revised build system in parallel with the current one, and only cut-over when we're convinced it's working right.

So, Christoph, are you still up for fooling around with this?

Cheers,
Philip

Reply via email to