I plan on looking next at the utility of the *.compiled & *.uptodate property passing scheme - you mentioned on #lucene IRC that it didn't seem to be having any effect on the build.
The properties were being passed in as intended, but the <uptodate> tasks were still running, since their execution was not dependent on the already-defined values of *.uptodate output properties.
The attached version of the patch, which includes Robert's latest patch, wraps the <uptodate> tasks in check-*-uptodate targets, and makes the compile-* targets depend on them, so that the <uptodate> tasks only run when the corresponding *.update property value has not previously been set.
The only problem with this approach is that the *.jar properties aren't constructed properly, since the property passing scheme only works one-way (properties are passed into <ant> invocations, but not back out of them). I worked around this problem by defining the *.jar properties statically.
My build times now:
||patch w/property passing optimizations
|ant example (clean checkout)
|ant example (already compiled)
This shaves a few more seconds off my build time.