ant-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Mathew Delong" <Mathew.Del...@embarcadero.com>
Subject RE: AW: dynamic targets
Date Wed, 25 Oct 2006 13:53:58 GMT
Like others said, failonerror="false" (someone mistyped this and said "true" but meant false)
is a bad idea for the same reason that was already mentioned: you only want it to not fail
if the target doesn't exist in a file, but want it to still fail for everything else.

One very easy solution I see is in every "individual" build file include a line like:

<import file="${this.property.might.not.resolve}" optional="true"/>

This fulfills your requirement that if you run the build independently, it won't know about
the "skeleton" targets and also the build doesn't need to know anything about a "master" build,
because the property which decides which file is imported isn't resolved unless it is passed
in from another build. Just use subant to pass the desired property to all the build files
it is executing on.

Mat

-----Original Message-----
From: Jacob Kjome [mailto:hoju@visi.com] 
Sent: Tuesday, October 24, 2006 10:58 PM
To: Ant Users List
Subject: Re: AW: dynamic targets

At 08:05 AM 10/24/2006, you wrote:
 >same - write a common buildfile (maybe with 
empty implementation) and all the
 >projects have all needed targets. Web project could overwrite the
 >target implementation.
 >
 >Jan
 >

Yep, <import> is powerful and extremely useful 
and I use it all the time.  I tried to keep my 
example specific and concrete so as not to 
complicate the question.  But it seems to have 
caused the original point of this exercise to be entirely missed.

Think of this in an OOP way.   You let other 
classes know what you are capable of by 
implementing interfaces.  There are a million 
things that you might be capable of doing, all 
represented by methods you might implement.  Do 
you implement all possible methods and, for 99% 
of the ones you aren't really capable of doing, 
you just report that you aren't capable of the 
method (by returning null, logging a message, or 
throwing an exception, etc...)?  Or do you 
implement only the interfaces having the methods 
representing the capabilities you do have?  If 
you said "the former", please stop here.  No need 
to keep reading.  If you said "the latter", then 
you're still with me.  Read on....


In other words, please don't focus on the "war" 
target.  That's an implementation 
detail.  Although I have a master build file, 
each individual build is entirely independent and 
need not have any knowledge that the master or 
any other builds exists.   It might be a very 
unique build that implements a "blahblah" 
target.  What those of you who have commented are 
telling me is that I should have every build 
implement a "blahblah" target simply because one 
unique build does.  Yes, I could have all builds 
import a common build with the "blahblah" target 
and the build that cares about it could override 
it, but that's conceptually ugly.

Let me put it this way.   When I run the 
individual build with "ant -projecthelp", I want 
to see *ONLY* the targets that are actually 
implemented in the build.  Not 10,000 other dummy 
targets imported from some common dummy build 
file.  If the only capabilities I have in a build 
are "clean" and "compile", then all I want is...

C:\dev>ant -projecthelp
Buildfile: build.xml

Main targets:

  clean
  compile

Other targets:

Default target: compile


I do *NOT* want...

C:\dev>ant -projecthelp
Buildfile: build.xml

Main targets:

  clean
  compile

Other targets:

  blahblah
  war
  sometargetyoudontcareabout
  yetanothertargetyoudontcareabout
  isthisgettingoldyet
  amidrivingthepointhome
  maybeacouplemore
  icouldkeepgoing
  youthinkicant
  doyoudoubledogdareme
  okyougotitmister
  imstillgoing
  youaskedforitandyougotit
  onemorejustforoldtimesake
  wowthisisstartingtogetannoyingnow
  yepreallyannoying
  butforsomereasonijustcantstop
  okillstop
  justforyou
  hehgotchastillgoing
  okimsickofwriting
  illstop

Default target: compile


Does that make it a bit more clear?

The dynamic targets would be generated only if 
the target is called on the build and it doesn't 
exist.  And the use-case for this would be mass 
target calling using <subant> to tell all build 
files to run a particular target.  Rather than 
having individual build files have to implement a 
target only to tell the caller that they don't 
really perform the task, I want a target to by 
generated on the fly just to satisfy Ant in order 
to continue on without build failure.  And, 
again, this would allow my master build file to 
be really stupid and generic because it wouldn't 
have to know which builds implement a "war" 
target or a "blahblah" target.  It would just 
mass call the target on the individual 
projects.  And the individual projects wouldn't 
have to worry about being the one that bombed out 
the mass build by not implementing dummy targets, 
nor would they be forced to report that they 
perform tasks that they don't really perform.

Dynamic target functionality could also make it 
so that I could have a really short master build 
file that takes whatever target is called on it 
and pass it on to all the other build files 
without the master target having to implement 
each mass build target, but have a common 
infrastructure for doing so.  For instance...

<project name="Build_master">

     Dynamic target gets generated based on what 
the user entered.  The dynamic target calls 
<m-iter/> with the target provided to Ant on the command line

     <macrodef name="m-iter">
         <attribute name="target"/>
         <attribute name="patternsetref"/>
         <sequential>
             <subant target="@{target}" inheritAll="false">
                 <fileset dir=".">
                     <patternset refid="@{patternsetref}"/>
                 </fileset>
             </subant>
         </sequential>
     </macrodef>

     The alternative to the description above 
using the dynamic targets is, for instance....

     <target name="jar">
         <m-iter target="jar" patternsetref="subant.build.patternset"/>
     </target>

     <target name="test">
         <m-iter target="test" patternsetref="subant.build.patternset"/>
     </target>

     <target name="war">
         <m-iter target="war" patternsetref="subant.war.patternset"/>
     </target>

      etc.... for every possible top-level target 
implemented by all builds in question, as well as 
taking pains to define the patternsets for the 
different types of build types which perform 
certain tasks that others might not implement.

</project>


I can't explain it any better than that.  I hope my point was made more clear.


Jake


 >>-----Urspr√ľngliche Nachricht-----
 >>Von: Markus M. May [mailto:mmay@gmx.net]
 >>Gesendet: Dienstag, 24. Oktober 2006 09:13
 >>An: Ant Users List
 >>Betreff: Re: dynamic targets
 >>
 >>Hello Jacob,
 >>
 >>why don't you just import a common build file and define the
 >>common target there. Only when the target is not defined in
 >>the build file, the common target gets executed.
 >>
 >>R,
 >>
 >>Markus M. May
 >>-------- Original-Nachricht --------
 >>Datum: Mon, 23 Oct 2006 22:28:35 -0500
 >>Von: Jacob Kjome <hoju@visi.com>
 >>An: user@ant.apache.org
 >>Betreff: dynamic targets
 >>
 >>>
 >>> Along the lines of....
 >>> http://marc.theaimsgroup.com/?l=ant-user&m=107429941032345&w=2
 >>>
 >>> Is it possible to create targets dynamically, deferring
 >>creation until
 >>> such time as it is found that the project doesn't have the target
 >>> already defined?  My use-case is using <subant> to iterate over
 >>> sub-builds calling a target on each one.  My current strategy is to
 >>> define <patternset>s for each type of project.  For instance, I add
 >>> all web projects to a particular patternset and then reference that
 >>> patternset when calling <subant>....
 >>>
 >>>              <subant target="war" inheritAll="false">
 >>>                  <fileset dir=".">
 >>>                      <patternset refid="war.patternset"/>
 >>>                  </fileset>
 >>>              </subant>
 >>>
 >>>
 >>> As further fallback, individual builds may implement empty targets
 >>> just so that they don't fail, just in case...
 >>>
 >>> <target name="war">
 >>>      <echo message="Unimplemented target"/> </target>
 >>>
 >>>
 >>> However, ideally, I'd like to be able to create the above target
 >>> dynamically in the case that it isn't implemented already by the
 >>> build.   This would have 2 benefits:
 >>>
 >>> 1.  I wouldn't have to bother creating the patternsets.  I'd
 >>just call
 >>> all the build files and let them either build the war file
 >>or echo the
 >>> "Unimplemented target" message.
 >>>
 >>> 2.  Individual builds that aren't web projects wouldn't have to have
 >>> to know what a web project is.  If the only artifact generated is a
 >>> simple jar library, it seems odd to have to implement a dummy "war"
 >>> target simply because some external master build file might
 >>call "war"
 >>> on it.
 >>>
 >>>
 >>> Instead of Ant failing with the following message...
 >>>
 >>> BUILD FAILED
 >>> Target `war' does not exist in this project.
 >>>
 >>>
 >>> ...I'd like Ant to just run the above dynamically created
 >>target (not
 >>> just the "war" target, but any target that might not exist), report
 >>> the "Unimplemented target" message, and continue on.
 >>>
 >>> So, is this possible?  Where/how do I hook into Ant to know
 >>the target
 >>> isn't implemented and create it myself via a scriptdef before Ant
 >>> gives me the build failure?
 >>>
 >>>
 >>> Jake
 >>>
 >>>
 >>> ---------------------------------------------------------------------
 >>> To unsubscribe, e-mail: user-unsubscribe@ant.apache.org For
 >>additional
 >>> commands, e-mail: user-help@ant.apache.org
 >>
 >>---------------------------------------------------------------------
 >>To unsubscribe, e-mail: user-unsubscribe@ant.apache.org For
 >>additional commands, e-mail: user-help@ant.apache.org
 >>
 >>
 >
 >---------------------------------------------------------------------
 >To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
 >For additional commands, e-mail: user-help@ant.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
For additional commands, e-mail: user-help@ant.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
For additional commands, e-mail: user-help@ant.apache.org


Mime
View raw message