How to check a condition once when using multiple "depends"? - ant

I want to have a 'master' ant target which depends on multiple "worker targets", (each of which does "one thing well")
However, I want to conditionally execute the "master" target, i.e. and not execute the "worker' subtargets if the condition is not met
(specficially, the master target creates and populates the database. The subtarget creates schema, populates tables, etc. The final step in the master target leaves a marker file to indicate "database created once." On subsequent runs, the process should not try to create the database.
The question
How can I implement this in a manner both "antish" (i.e. without "antcall) and DRY (dont' repeat yourself).
Example
<target name="check-db-created">
<available file="db.created.marker.txt" property="db.already.created"/>
</target>
<target name="create-new-db"
unless="db.already.created"
depends="check-db-created,create-db-mssql,create-tables,compile-sp,disable-constraints.....">
</target>
<target name="create-db-mssql" >
..do stufff
</target>
Comments
The issue is that the 'sub-targets' ('create-db-mssql', create-tables', etc) execute even though the "master" target does not need to run. Ant documentation clearly discusses this.
Important: the if and unless attributes only enable or disable the
target to which they are attached. They do not control whether or not
targets that a conditional target depends upon get executed. In fact,
they do not even get evaluated until the target is about to be
executed, and all its predecessors have already run.
I can code around the rpoblem by adding "unless" clauses to all the 'worker targets', but would like to avoid repeating.
Additionally, I use antcall as follows, but would prefer to avoid the "GOTO" of the ant world.
<target name="create-new-db" depends="check-db-created"
unless="db.already.created">
<antcall target="create-new-db-internal"/>
</target>
<target name="create-new-db-internal"
depends="create-db,create-tables,compile-sp,disable-constraints,insert-base-data,insert-installer-generated-sql,insert-kb-data"
>
</target>
thanks

Related

How to pass nested arguments from one ant target to another

How to pass nested arguments from one ant target to another?
I need to pass a variable number of nested elements from one target to another.
I have a common file with all of my standard build tasks that's included in all of my projects.
I am adding a new custom task that takes a variable number of nested arguments
As a standard, all ant calls are made through the common file to ensure consistency of build style and logging.
Thus the new custom task and its nested child will be defined in the common script.
The project build script looks like this
<target name="projectBuild">
...
<ant target="_newFooTaskWrapper" antfile="commonFile">
<property name="_arg1" value="hello"/>
<property name="_arg2" value="world"/>
<nestedArg value="qux"/>
<nestedArg value="baaz"/>
...
<nestedArg value="AAAAA"/>
</ant>
...
</target>
The common script looks like this:
<target name ="_newFooTaskWrapper">
<echo message="Target _newFooTaskWrapper in project ${ant.project.name} from base directory ${basedir}"/>
<echo message="arg1 = ${_arg1}"/>
<echo message="arg2 = ${_arg2}"/>
<taskdef name="newFooTask" classname="org.foo.NewFooTask"/>
<typedef name="nestedArg" classname="org.foo.NewFooTask$NestedArg"/>
<newFooTask arg1="${_arg1}" arg2="${_arg2}">
<nestedArg value="qux"/>
<nestedArg value="baaz"/>
...
<nestedArg value="AAAAA"/>
</newFooTask>
Obviously, this isn't right. My question is, what's the right way to do this?
I need to pass a variable number of nested elements from one target to another.
For "varible", I assume you mean you don't know the exact number of the nested elements you want to pass to the task, so what you want is something like method(Object param...) in java, is it?
It's not a good idea to try such a way. Ant is not a scripting language but a build tool. It provides limited "scripting" possibilities.
However, you can try it in the following two ways:
1, If your nested element is just in the form of <elementName value="xx" />, you don't need anything complicated. Just pass another property containing a comma seperated list of the values, and process the list in your custom ant task. It's easy for Java to split the property into a list and process it.
2, If your nested element may be more complicated... maybe you can try reference:
Make a type fooTaskParams which can be referenced via an id:
<fooTaskParams id="_foo_task_params">
<nestedArg value="qux"/>
<nestedArg value="baaz"/>
...
<nestedArg value="AAAAA"/>
</fooTaskParams>
and pass the reference to the other build file:
<ant target="_newFooTaskWrapper" antfile="commonFile">
<property name="_arg1" value="hello"/>
<property name="_arg2" value="world"/>
<reference refid="_foo_task_params"/>
</ant>
and then make your task to be able to process the reference:
<newFooTask arg1="${_arg1}" arg2="${_arg2}" paramRefId="_foo_task_params" />
You may need to take care of reference override, or make your task able to process the ref as well as taking nested elements.
Read ant's manual about <ant> and <typedef> for more about this approach, and refer to SO Q&As like this when you encount any problem.

ANT Scenario Conditional Depend Targets

Is it possible in ANT to have the same target which depends on set of different targets depending on the condition in this target.
EXAMPLE:
<target name=my_target depends="target2,target3,target4" if="my_property1">
and
<target name=my_target depends="target2,target5,target6" if="my_property2">
Where "target2" evaluates properties my_property1 or my_property2.
Is something like this possible, or is there another way to assign to the same target different "depends" based on condition?
Thanks.
You cannot have duplicate targets. I'm not quite clear on what you're goign for... what does target2 do with your properties? To replicate the behavior you have you could setup
<target name="my_target" depends="target2,target3,target4,target5,target6">
and then setup if and/or unless on target1-6 something like
<target name="target2"> (run target2 always)
<target name="target3" if="my_property1">
<target name="target4" if="my_property1">
<target name="target5" if="my_property2">
<target name="target6" if="my_property2">

Check if two antcalls are successfull

I'm extremely new to ant script and i want to find out if my build is successful or not. my main target has two antcalls and i don't know how to check if they were successful or not, in order to evaluate the main target.
run all is my main target
<target name="run all">
<antcall target="Run basic configuration" />
<antcall target="Run custom configuration"/>
i want to add a fail condition for the "run all" target.
Each target does check individually if they are successful, but I want to know if the target that calls the ant is unsuccessful in case those two fail.
Also, if one fails does the other one get called?
To determine if an antcall is successful requires a more careful definition of what success is. It can mean:
The code executed without throwing an exception.
The code did what you wanted it to do.
In the first case, you can wrap the execution of your antcall with a trycatch block to catch exceptions. The trycatch task is part of ant-contrib, but that is frequently used in Ant coding. You'd do:
<trycatch property="exception.message" reference="exception.object">
<try>
<antcall target="targetName"/>
</try>
<catch>
<!-- handle exception logic here -->
</catch>
<finally>
<!-- do any final cleanup -->
</finally>
</trycatch>
In the second case, you need to pass back to the caller some state that indicates that the code did what you wanted it to do.
Note that the antcall task reloads the ant file (e.g., build.xml), so it can be an expensive operation. There are alternatives to using the antcall task:
Use the antcallback task (ant-contrib). The antcallback task specifically addresses the need to pass back data.
Use the depends attribute when defining a target to call dependent tasks.
Use the runtarget task (ant-contrib). With runtarget, all of your properties are passed and any properties you set in your target are available to the caller.
Use the macrodef task. It avoids reparsing of the ant file, can be passed attributes with default values, can be passed nested elements, and more. As such, this is the preferred solution in most cases.
In each of the cases above, just set return properties that you can inspect in the calling target to determine whether the called or dependent targets did what you expected them to do.

Can Ant continue when it encounters an error?

I have an Ant target that executes 2 steps in sequence:
<target name="release">
<antcall target="-compile"/>
<antcall target="-post-compile"/>
</target>
With the above script, it quits immediately if the "-compile" target fails. "-post-compile" does not get a chance to run. Is there a way to make sure the second step (-post-compile) is executed even if the 1st one (-compile) fails?
If you are using ant-contrib (which is very common), you could make use of the try-catch task and put your post-compile call into its finally element.
Also, if you are not using ant-contrib, then you might use the subant task to call your compile target. subant has a failonerror attribute, which you can use to individually ignore failed targets. Lots of usage examples on the task description page.
I think you are looking for
-keep-going (-k)
This will tell Ant to continue building all targets which do not depend on the failed target.

Manually Start ANT Task

For various reasons that I won't go into (I promise it's necessary to do this with the current code base; I know it's goofy), I want to execute a target twice in the same build task.
For example, I want to execute the target foo, then bar, then foo again. This is a simplified version of what I already tried:
<target name="foo">
...
</target>
<target name="bar" depends="foo">
...
</target>
<target name="project" depends="foo,bar">
...
</target>
In this case when executing the project target, foo only ran once. I also tried getting rid of the depends attribute on the bar target and making the project's depends attribute "foo,bar,foo", but still the same result.
Is there a way to force a task to execute, even if it's already successfully completed? Or is there a better way to go about this?
The antcall task allows you to explicitly call a target.
I think that's a better solution than using the depends mechanism. As you've identified, this determines what has already run. Antcall instructs the target to run regardless of whether it's run before.
You can parameterise the call to customise what it does on each invocation.

Resources