ANT targets that depends on environment variables - ant

My code:
<property environment="env"/>
<target name="detectTomcatFromEnv" unless="${env.CATALINA_HOME}">
<echo message="${env.CATALINA_HOME}"/>
</target>
I defined CATALINA_HOME and as I understand, target should not run.
But my result is:
detectTomcatFromEnv:
[echo] c:\apache-tomcat-7.0.21\
BUILD SUCCESSFUL
How it can be???

You need to remove the ${...} from unless:
<property environment="env"/>
<target name="detectTomcatFromEnv" unless="env.CATALINA_HOME">
<echo message="${env.CATALINA_HOME}"/>
</target>
See https://ant.apache.org/manual/targets.html:
unless: the name of the property that must not be set in order for
this target to execute, or something evaluating to false.

Related

Checksum task in Ant not working as expected

I am struggling with a small ant file/target that is as follows:
<project name="test" default="test" basedir=".">
<property name="out.dir" value="${basedir}/out/"/>
<property name="apidoc.path" value="${out.dir}test.zip"/>
<property name="apidoc.input" value="${basedir}/../source//apidocs"/>
<property name="apidoc.sha" value="TODO"/>
<target name="test">
<echo message="Starting target APIDOC"/>
<zip destfile="${apidoc.path}" basedir="${apidoc.input}" update="no"/>
<echo message="${apidoc.path}"/>
<checksum file="${apidoc.path}" algorithm="SHA-256" property="apidoc.sha"/>
<echo message="Hash wert ist ${apidoc.sha}"/>
</target>
</project>
The target should create a zip file from a doc folder (it does) and then store the hash value of the zip file into a property for further use. However, the hash value is not stored in the property. I get the output as follow:
test:
[echo] Starting target APIDOC
[echo] /Users/user1/git/project/out/test.zip
[echo] Hash wert ist TODO
BUILD SUCCESSFUL
Does anybody have and idea, what is going wrong here?
Properties in Ant are immutable. This line
<property name="apidoc.sha" value="TODO"/>
sets the value, and after that it can't be changed.
If you run ant with the -v command-line option you should see a message like
Override ignored for property "apidoc.sha"
indicating that the attempt to alter the property value in the <checksum> task is being ignored.

Running an Ant target under certain conditions

I have the following Ant targets in my project.xml:
<target name="to.run.under.conditions">
</target>
<target name="deploy1">
<antcall target="deploy2"/>
</target>
<target name="deploy2">
<antcall target="to.run.under.conditions"/>
</target>
<target name="another.target">
<antcall target="deploy1"/>
</target>
My intent is to be able to exclude the target to.run.under.conditions when running another.target. I am not very familiar with ANT and I am struggling to understand how to approach the issue. I have tried to employ unless="${target.running}" in and set the property as true in the condition task inside the target name ="target.running"
Can you help with this?
Thank you for your help,
I.
----EDIT UPDATED SOLUTION----
This is my current attempt (I am using ANT 1.8.2):
<target name="to.run.under.conditions" if="${target.running}">
</target>
<target name="another.target">
<property name="target.running" value="false"/>
</target>
If I am not mistaken, since the property is set to false inside another.target, then to.run.under.conditions should not be run (I might be wrong, though). Does it make sense? Any comment is much appreciated!
Try this:
<target name="build-module-A" if="module-A-present"/>
<target name="build-own-fake-module-A" unless="module-A-present"/>
In the first example, if the module-A-present property is set (to any value, e.g. false), the target will be run. In the second example, if the module-A-present property is set (again, to any value), the target will not be run.
Please see Any Targets for more information.
I have ended up with this solution that seems to be work as expected:
<target name="deploy2">
<if>
<equals arg1="${target.running}" arg2="true" />
<then>
<echo message="the target will not run" />
</then>
<else>
<echo message="the target will run" />
<antcall target="to.run.under.conditions"/>
</else>
</if>
</target>
<target name="to.run.under.conditions">
</target>
<target name="another.target">
<property name="target.running" value="true"/>
</target>
Hope this helps,
I.

Ant - Run a Build.xml for all subdirectories

I have a build.xml sitting at the top level and I want the script to run a target for each subdirectory and pass in the subdirectory name as a parameter to the ANT target.
Can you help ?/??
Thanks
Take a look at the subant task. From that page:
<project name="subant" default="subant1">
<property name="build.dir" value="subant.build"/>
<target name="subant1">
<subant target="">
<property name="build.dir" value="subant1.build"/>
<property name="not.overloaded" value="not.overloaded"/>
<fileset dir="." includes="*/build.xml"/>
</subant>
</target>
</project>
this snippet build file will run ant in each subdirectory of the project directory, where a file called build.xml can be found. The property build.dir will have the value subant1.build in the ant projects called by subant.
this is might be what you looking for,
put this as one of your target in your parent build.xml
<target name="executeChildBuild">
<ant antfile="sub1/build.xml" target="build" />
<ant antfile="sub2/build.xml" target="build" />
</target>
If you would like to do it in ant build file, you could use Ant Contrib's for task to iterate over list of subdirectories and execute ant task for each of them.
<for param="subdir">
<dirset dir="${build.dir}">
<include name="./**"/>
</dirset>
<sequential>
<subant target="${target}">
<property name="subdir.name" value="#{subdir}"/>
</subant>
</sequential>
</for>
I didn't test this code since don't have ant installed, but it is close to what you're trying to do I suppose.
If I read the question correctly, this may be what you are looking for instead.
So for your example...
<target name="do-all">
<antcall target="do-first">
<param name="dir-name" value="first"/>
<param name="intented-target" value="init"/>
</antcall>
<antcall target="do-first">
<param name="dir-name" value="second"/>
<param name="intented-target" value="build"/>
</antcall>
<antcall target="do-first">
<param name="dir-name" value="third"/>
<param name="intented-target" value="compile"/>
</antcall>
</target>
<target name="do-first">
<echo>Hello from ${dir-name} ${intented-target}</echo>
<ant antfile="${dir-name}/build.xml" target="${intented-target}"/>
</target>
When you are calling this from Ant, you would enter this at the command line:
ant do-all
and your output should look like this:
do-all:
do-first:
[echo] Hello from first init
do-first:
[echo] Hello from second build
do-first:
[echo] Hello from third compile
BUILD SUCCESSFUL
Total time: 1 second
You will of course need to make sure that the directory name that you are using as a param actually exists, or the build will fail.
You can also always feed the variable that you want to use by adding the value to the build.properties file.

"global var" in ant

I'm calling one target (e.g target) from other targets (e.g. first, second). Is there a way to define a property (or whatever) in target in such a way that it could be used in first and second. Please don't advise me to pass a variable as a parameter into first and second
Every "variable" (property) ever set in ant is always "global"
<project name="foo" default="first">
<target name="first" depends="target">
<echo message="${foo}"/>
</target>
<target name="second" depends="target">
<echo message="${foo}"/>
</target>
<target name="target">
<property name="foo" value="bar"/>
</target>
</project>
In latest versions of ant you can use the "local" task to declare a variable as local.
Otherwise properties are always global.

Ant antcall a target that defines a property

In Ant I want to define a target (called A) that define a property and antcall it from another target (called B). I want that the target B, after antcalling the target A, can access the property defined in the target A.
For example:
<target name="B">
<antcall target="A" inheritAll="true" inheritRefs="true" />
<echo>${myprop}</echo>
</target>
<target name="A">
<property name="myprop" value="myvalue" />
</target>
However it doesn't work and <echo>${myprop}</echo> doesn't print myvalue (I think because the property myprop isn't defined in B).
Is there any way to do that?
According to the Apache Ant FAQ:
<target name="cond" depends="cond-if"/>
<target name="cond-if" if="prop1">
<antcall target="cond-if-2"/>
</target>
<target name="cond-if-2" if="prop2">
<antcall target="cond-if-3"/>
</target>
<target name="cond-if-3" unless="prop3">
<echo message="yes"/>
</target>
Note: <antcall> tasks do not pass property changes back up to the environment they were called from, so you wouldn't be able to, for example, set a result property in the cond-if-3 target, then do <echo message="result is ${result}"/> in the cond target.
In this respect, it is impossible to do what you want using antcall.
========== edit ===========
Try antcallback: AntCallBack is identical to the standard 'antcall' task, except that it allows properties set in the called target to be available in the calling target.
http://antelope.tigris.org/nonav/docs/manual/bk03ch20.html
Sample code pasted from the above page:
<target name="testCallback" description="Test CallBack">
<taskdef name="antcallback" classname="ise.antelope.tasks.AntCallBack" classpath="${antelope.home}/build" />
<antcallback target="-testcb" return="a, b"/>
<echo>a = ${a}</echo>
<echo>b = ${b}</echo>
</target>
<target name="-testcb">
<property name="a" value="A"/>
<property name="b" value="B"/>
</target>
Another approach is to refactor your targets into macros. You are trying to use targets like functions and they are just not intended to be used that way. I typically write the bulk of my logic as macros, so that I can compose it more easily into more complicated macros. Then I write simple wrapper targets for the command-line entry points that I need.
Rather than using <antcall>, why not just have target B depend on target A?
<target name="B" depends="A">
<echo>${myprop}</echo>
</target>
<target name="A">
<property name="myprop" value="myvalue" />
</target>
I think you want to use a param.
<project default="B">
<target name="B">
<antcall target="A">
<param name="myprop" value="myvalue"/>
</antcall>
</target>
<target name="A">
<echo>${myprop}</echo>
</target>
</project>
I surrounded this with a project tag and moved the echo statement into "A". My output says
B:
A:
[echo] myvalue
BUILD SUCCESSFUL
#alem0lars, since you said you would like to subdivide a target, let me offer a different solution (that unfortunately doesn't answer your original question).
<project default="mytarg">
<target name="mytarg">
<property name="tgt" value="build"/>
<antcall target="deps"/>
</target>
<target name="deps" depends="aTgt,bTgt"/>
<target name="aTgt">
<echo>"In aTgt doing a ${tgt}"</echo>
</target>
<target name="bTgt">
<echo>"In bTgt doing a ${tgt}"</echo>
</target>
</project>
This subdivides the build into aTgt and bTgt.
Output will be
aTgt:
[echo] "In aTgt doing a build"
bTgt:
[echo] "In bTgt doing a build"
deps:
BUILD SUCCESSFUL

Resources