This week's giveaway is in the EJB and other Java EE Technologies forum. We're giving away four copies of EJB 3 in Action and have Debu Panda, Reza Rahman, Ryan Cuprak, and Michael Remijan on-line! See this thread for details.
I have an issue with managing a multiple project build. Allow me to provide some context first.
I have a system of projects managed by an Ant build process consisting of multiple levels of Ant projects (Ant build scripts). A root Ant script invokes the subproject Ant scripts in the proper dependency order, down through multiple levels of subprojects.
As Ant is reinvoked for each subproject (via the subant task), the same target is invoked as for the calling project, all the way across and down the project tree.
Here is an example of a typical system file structure: Root Build.xml - invokes B/Build.xml, C/Build.xml, A/Build.xml A Build.xml src *.java B Build.xml - invokes B2/Build.xml, B1/Build.xml, B3/Build.xml B1 Build.xml src *.java B2 Build.xml src *.java B3 Build.xml src *.java C Build.xml src *.java
I have a Windows script Ant.cmd that allows me to invoke Ant on the current directory, such that Ant executes the Build.xml script in that directory, which invokes the Build.xml scripts in the subdirectories as appropriate. So a typical invocation in a Windows command shell would be:
Ant clean build doc
Now, Ant's famous and desirable behavior is to evaluate the dependencies among the targets invoked on the command line, assemble an ordered list of targets to execute (including referenced dependencies but without duplicates), and then execute them in that order, WITHIN THAT SINGLE INVOCATION OF ANT.
But, when I invoke Ant on a Build.xml that invokes subprojects, my current Ant scripts result in A SEPARATE INVOCATION OF ANT FOR EACH TARGET ON EACH SUBPROJECT. This is due to the target dependencies being evaluated for the initial parent project (the one in the current directory), but the delegation occurs separately for each executed target (via subant). As a consequence, the subprojects are invoked repeatedly and many of their targets get executed repeatedly. The net effect is, for each subproject, as if I had instead entered the following into the Windows command shell: Ant clean Ant build Ant doc
The problem with this behavior, of course, is that I do not get the same result from invoking a multi-target (e.g., clean build doc) build directly on a subproject as I do by invoking it on a parent project. In particular, the result is far less efficient since there are extra invocations of Ant on the subprojects and there are extra invocations of subproject targets.
However, the really big problem is that any property dependencies between subproject targets fail completely.
Consider a common practice for implementing debug versus release builds. The build target is typically implemented to default (via properties) to a debug compile. But, if you invoke the release target first, then those properties configure the compile for release mode instead. So Ant build gives you a debug compile, but Ant release build gives you a release compile since the release target sets the appropriate properties for release before the build target can set them for debug.
When invoking a subproject directly (in the current directory), this technique works as expected. But invoking a subproject through a parent project does not work because the release and build targets get executed IN SEPARATE INVOCATIONS OF ANT.
So, the solution is to get Ant to invoke a subproject with multiple targets ALL AT ONCE IN THE SAME INVOCATION OF ANT. But, it appears, none of the typical ways to invoke a subproject do this. The ant and subant tasks appear to only allow a single target in their target attributes, though I still need to do more thorough testing to be certain of this.
This results in my request: has anyone tackled this challenge of invoking multiple targets consistently down through a series of subprojects???
Thanks for your patience! ;^)
Joined: Jul 22, 2005
Oops, my file structure was not preserved in my initial post. Here it is again:
First up, I haven't tackled this problem before, but here are my thoughts.
First, I'm somewhat amazed that you can't specify multiple targets like this:
...but you're right, it doesn't work. Perhaps you could define a meta-target in each build file:
On a side note, one of the examples in the subant task documentation describes a problem very similar to yours. I also found this article useful, though chances are you know this stuff already.
On property dependencies, does use of 'inheritall' and/or 'inheritrefs' not solve your problem?
Joined: Jul 22, 2005
Thanks for the reply. Yes, I am familiar with Ant's capabilities as documented at the links you provided. As the article says, doing a complex build such as mine is very much easier with the new capabilities of Ant 1.6.
I did indeed try creating composite targets such as rebuild = clean build, etc. Of course, this works in simple cases, but it does not scale. I don't want to have to create composite targets for every combination of my base targets and, if I did, I would encounter a combinatorial explosion of possiblities.
Ideally, I just want subant to handle multiple targets in a single invocation, just as though I were invoking Ant from the command line. Perhaps I need to post a request to their feature list.
Otherwise, it seems that my only solution is to reinvoke Ant via the exec task. Yuch!
Joined: Jul 22, 2005
I forgot to address the inheritall and inheritrefs of the subant task. Yes, they could help to resolve part of my problem, and they may be able to be leveraged to solve all of it.
However, doing so would potentially involve a lot of extra properties with a lot of VERY careful management. The complexity seems prohibitive, and I think I would rather live with the inefficiencies instead. However, I have not yet tackled the integration of a release build into my new Ant infrastructure, or similarly complex processes that demand more property management.