I agree that it would be nice if subant would be modified to include this 
functionality. In the meantime, if you, as you said, prefer not to create 
custom Ant tasks, and you don't like my previous suggestion that requires you 
to have a "template" build file containing all of the skeleton targets, just do 
something like this:

<project name="skeleton-target">
    <target name="##TOKEN##">
        <echo>##TOKEN## target not implemented in ${ant.project}</echo>
    </target>
</project>

Then, right before you call subant on all of the builds, do something like this:

<replace file="skeleton-target.xml" token="##TOKEN##" value="${target.name}"/>

Then after subant, you will need to change it back like:

<replace file="skeleton-target.xml" token="${target.name}" value="##TOKEN##"/>

Note that although I used a property for the value of target name, replace does 
not directly support the dereferencing of properties, you would need to use a 
replacefilter and a properties file if you don't want to hardcode the target 
name in.

Well, hope that helps.

Mat

-----Original Message-----
From: Jacob Kjome [mailto:[EMAIL PROTECTED] 
Sent: Wednesday, October 25, 2006 11:49 AM
To: Ant Users List
Subject: RE: AW: dynamic targets


Thanks to you all for your comments.  I guess I finally did get my point across
and you all came up with interesting options.  I try to avoid writing custom
tasks and such if I can do them using a macrodef or scriptdef, but this one
might require a custom file selector, such as DD suggested (along with many
other good points).

Jan's suggestion of using failonerror="false" is definitely a possible solution,
but, as others have pointed out, probably more problematic than useful, since it
masks true build failures that I want to know about, not just missing targets.

Actually, this could be an enhancement that could be added to <subant> and/or
<ant>.  That is, providing a new option to say failonmissingtarget="false"
(assuming a missing target failure can be differentiated from other failures). 
That would provide almost everything I want, other than the ability to run
arbitrary targets without exhaustively defining them in my master build file. 
Then again, as DD mentioned, that would break "ant -projecthelp" for the master
build file.  However, with failonmissingtarget="false" implemented, I wouldn't
much care in this context since all the master build file does is proxy calls
to other build files, not actually implement the targets themselves.  With a
predictable naming scheme of top-level targets, "ant -p" becomes must less
important, at least for the master build file.

Matt, I think you came up with the most practical solution.  Curiously enough, I
already employ this technique for imports that provide optional functionality. 
I guess I was so focused on figuring out how to implementing dynamic targets
that I missed the relevant application here.  It still requires me to
exhaustively specify every possible top-level target that might be used by any
build file to avoid any other one that doesn't actually implement the target
from failing, but it is a pretty good option; especially since it solves the
"ant -projecthelp" problem for individual builds.

My builds all do share the same build framework, so this is easy to implement
without touching any one of the individual project build files.

thanks!

Jake

Quoting Mathew Delong <[EMAIL PROTECTED]>:

> 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:[EMAIL PROTECTED]
> 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:[EMAIL PROTECTED]
>  >>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 <[EMAIL PROTECTED]>
>  >>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: [EMAIL PROTECTED] For
>  >>additional
>  >>> commands, e-mail: [EMAIL PROTECTED]
>  >>
>  >>---------------------------------------------------------------------
>  >>To unsubscribe, e-mail: [EMAIL PROTECTED] For
>  >>additional commands, e-mail: [EMAIL PROTECTED]
>  >>
>  >>
>  >
>  >---------------------------------------------------------------------
>  >To unsubscribe, e-mail: [EMAIL PROTECTED]
>  >For additional commands, e-mail: [EMAIL PROTECTED]
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to