Use pure Ant to implement if else condition (check command line input) - ant

I am a newbie in Ant. My ant script receives a user input variable named "env" from command line:
e.g. ant doIt -Denv=test
The user input value could be "test","dev" or "prod".
I also have the "doIt" target:
<target name="doIt">
//What to do here?
</target>
In my target, I would like to create the following if else condition for my ant script:
if(env == "test")
echo "test"
else if(env == "prod")
echo "prod"
else if(env == "dev")
echo "dev"
else
echo "You have to input env"
That's to check which value user has inputted from command line, then, print a message accordingly.
I know with ant-Contrib, I can write ant script with <if> <else> . But for my project, I would like to use pure Ant to implement if else condition. Probably, I should use <condition> ?? But I am not sure how to use <condition> for my logic. Could some one help me please?

You can create few targets and use if/unless tags.
<project name="if.test" default="doIt">
<target name="doIt" depends="-doIt.init, -test, -prod, -dev, -else"></target>
<target name="-doIt.init">
<condition property="do.test">
<equals arg1="${env}" arg2="test" />
</condition>
<condition property="do.prod">
<equals arg1="${env}" arg2="prod" />
</condition>
<condition property="do.dev">
<equals arg1="${env}" arg2="dev" />
</condition>
<condition property="do.else">
<not>
<or>
<equals arg1="${env}" arg2="test" />
<equals arg1="${env}" arg2="prod" />
<equals arg1="${env}" arg2="dev" />
</or>
</not>
</condition>
</target>
<target name="-test" if="do.test">
<echo>this target will be called only when property $${do.test} is set</echo>
</target>
<target name="-prod" if="do.prod">
<echo>this target will be called only when property $${do.prod} is set</echo>
</target>
<target name="-dev" if="do.dev">
<echo>this target will be called only when property $${do.dev} is set</echo>
</target>
<target name="-else" if="do.else">
<echo>this target will be called only when property $${env} does not equal test/prod/dev</echo>
</target>
</project>
Targets with - prefix are private so user won't be able to run them from command line.

If any of you require a plain if/else condition (without elseif); then use the below:
Here I am dependent on a env variable DMAPM_BUILD_VER, but it may happen that this variable is not set in the env. So I need to have mechanism to default to a local value.
<!-- Read build.version value from env variable DMAPM_BUILD_VER. If it is not set, take default.build.version. -->
<property name="default.build.version" value="0.1.0.0" />
<condition property="build.version" value="${env.DMAPM_BUILD_VER}" else="${default.build.version}">
<isset property="env.DMAPM_BUILD_VER"/>
</condition>

Related

Getting condition doesn't support the nested "then" element in <condition>

I'm new to Ant/Apache. When I tried to use <condition> tag in XML it's throwing an error. condition doesn't support the nested "then" element. Here is my code
<target name="determine-ae-build">
<condition property="ApplicationName">
<equals arg1="${ApplicationName}" arg2="new"/>
<then>
<echo>3.9 Robots Config Copied</echo>
</then>
<else>
<condition property="ApplicationName">
<equals arg1="${ApplicationName}" arg2="old"/>
<then>
<echo>3.8 Robots Config Copied</echo>
</then>
<else>
<echo>3.9 Robots Config Copied</echo>
</else>
</condition>
</else>
</condition>
</target>
I've tried with IF also but since my Ant version is not supporting to do this. Can someone help to resolve this issue. Thanks! in advance
The condition task simply sets a property; it doesn't contain nested build logic. The property that it sets can later be used to control which targets are executed.
While you can use antcontrib's extra if, then, and else tasks to accomplish something like what you showed in your example, I'd recommend sticking to the native Ant approach, which relies on target dependencies and uses separate targets to control build logic:
<project name="build" basedir="." default="build">
<target name="build" depends="copy-3.8,copy-3.9" />
<target name="copy-3.8" depends="determine-ae-build" if="copy.old">
<echo>3.8 Robots Config Copied</echo>
</target>
<target name="copy-3.9" depends="determine-ae-build" unless="copy.old">
<echo>3.9 Robots Config Copied</echo>
</target>
<target name="determine-ae-build">
<condition property="copy.old">
<equals arg1="${ApplicationName}" arg2="old"/>
</condition>
</target>
</project>
With the above script, you would run ant build (possibly with -DApplicationName=old). The build target depends on both copy targets, both of which depend on determine-ae-build. The determine-ae-build target will therefore run first. If ApplicationName is set to "old" (either from a properties file that has been loaded, or from being provided in command line with -DApplicationName=old) then the property copy.old will be set to true. Otherwise it will remain unset.
Then copy-3.8 and copy-3.9 will be called. If copy.old is is true, copy-3.8 will run. Otherwise, it will be skipped. copy-3.9 has no condition so it will run no matter what.
Lastly, the build target will execute because it was the original target called from the command line, but it contains no actual steps so the build will finish.
<target name="prepare-copy" description="copy file based on condition" depends="determine-ae-build, prepare-copy-old, prepare-copy-new, prepare-copy-default">
<sleep seconds="10"/> --To read the results
</target>
<target name="prepare-copy-old" description="copy file based on condition" if="copy.old">
<echo>Old File Copied </echo>
</target>
<target name="prepare-copy-new" description="copy file based on condition" if="copy.new">
<echo>New File Copied</echo>
</target>
<target name="prepare-copy-default" description="copy file based on false condition" if="copy.default">
<echo>Default File Coping</echo>
</target>
<target name="determine-ae-build">
<condition property="copy.old">
<equals arg1="${ApplicationName}" arg2="old"/>
</condition>
<condition property="copy.new">
<equals arg1="${ApplicationName}" arg2="new"/>
</condition>
<condition property="copy.default">
<not>
<or>
<equals arg1="${ApplicationName}" arg2="new"/>
<equals arg1="${ApplicationName}" arg2="old"/>
</or>
</not>
</condition>
</target>
Explanation: Calling way "ant -Dcopy.old = true prepare-copy". Here we are passing to copy old file hence, "Old File Copied" will copied. If you call it like "ant prepare-copy" it'll call "Default File Coping".
Kindly Accept my answer if it is answered your question.Thankyou!

Ant property not setting correctly?

I'm reasonably new to ant and I'm not quite sure why
I am getting the following error when I run ant: Cannot locate target java: please set JAVA_HOME to its location. I've pasted the relevant source code below. From what I can see, the target -check-langtools.jdk.home is being executed. But because it depends on -def-check, that gets executed. Do the attributes (name, property, marker) get passed into -def-check when -check-langtools.jdk.home is being called? If so - the failure must be happening at the condition where is the property is not being set (i.e isset must be returning false). I don't understand how the property is not being set, if it is able to print out the value (i.e. JAVA_HOME).
Background: Trying to build langtools from OpenJDK
<target name="-def-check">
<macrodef name="check">
<attribute name="name"/>
<attribute name="property"/>
<attribute name="marker" default=""/>
<sequential>
<fail message="Cannot locate #{name}: please set #{property} to its location">
<condition>
<not>
<isset property="#{property}"/>
</not>
</condition>
</fail>
<fail message="#{name} is not installed in ${#{property}}">
<condition>
<and>
<not>
<equals arg1="#{marker}" arg2=""/>
</not>
<not>
<available file="${#{property}}/#{marker}"/>
</not>
</and>
</condition>
</fail>
</sequential>
</macrodef>
</target>
<target name="-check-langtools.jdk.home" depends="-def-check">
<!-- <check name="target java" property="langtools.jdk.home" marker="${java.marker}"/> -->
<check name="target java" property="JAVA_HOME" marker="${java.marker}"/>
</target>
<target name="-check-jtreg.home" depends="-def-check">
<check name="jtreg" property="jtreg.home" marker="lib/jtreg.jar"/>
</target>
This question was a bit of a blonde one but I ended up approaching this problem the wrong way, but I'll post up the answer here if anyone is new to Ant, and looking to do the same thing. To build the langtools portion of javac, what they need to do is set langtools.jdk.home=path_to_jdk_installation in a separate build.properties file that is included.
(eg. langtools.jdk.home=/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home)

How to emulate if-elseif-else in Ant without using Ant-contrib?

I need an if-elseif-else conditional statement in Ant.
I do not want to use Ant-contrib.
I tried the solution here
<target name="condition.check">
<input message="Please enter something: " addproperty="somethingProp"/>
<condition property="allIsWellBool">
<not>
<equals arg1="${somethingProp}" arg2="" trim="true"/>
</not>
</condition>
</target>
<target name="if" depends="condition.check, else" if="allIsWellBool">
<echo message="if condition executes here"/>
</target>
<target name="else" depends="condition.check" unless="allIsWellBool">
<echo message="else condition executes here"/>
</target>
But I will have to set properties inside the if and else targets which will not be visible in the calling target.
Is there any other way out using conditions?
Move the dependencies out of if and else into a new target that depends on all of the other targets:
<project name="ant-if-else" default="newTarget">
<target name="newTarget" depends="condition.check, if, else"/>
<target name="condition.check">
<input message="Please enter something: " addproperty="somethingProp"/>
<condition property="allIsWellBool">
<not>
<equals arg1="${somethingProp}" arg2="" trim="true"/>
</not>
</condition>
</target>
<target name="if" if="allIsWellBool">
<echo message="if condition executes here"/>
</target>
<target name="else" unless="allIsWellBool">
<echo message="else condition executes here"/>
</target>
</project>

How check for a condition in ant and depending on its value print a message?

This is a small piece of code please give a look at it then follow the description....
<condition property="${param1}">
<or>
<istrue value="win-x86"/>
<istrue value= "win-x86-client"/>
<istrue value= "win-x64"/>
</or>
</condition>
<target name="Mytarget" if="${param1}">
<echo message="executing windows family build:::${param1}"/>
</target>
<target name="print.name" >
<antcall target="win-x86-build">
<param name="param1" value="${platform.id}"/>
</antcall>
</target>
I want that when ever platform.id contains any of the windows family name it should print the message EXECUTING WINDOWS FAMILY BUILD but the problem is that it is printing this message even when the family is unix.
I think either I am not checking the condition properly or else i am doing some other mistake.
Can someone help me out with this please?
Since ant 1.9.1 you can do this:
<project name="tryit" xmlns:if="ant:if" xmlns:unless="ant:unless">
<exec executable="java">
<arg line="-X" if:true="${showextendedparams}"/>
<arg line="-version" unless:true="${showextendedparams}"/>
</exec>
<condition property="onmac">
<os family="mac"/>
</condition>
<echo if:set="onmac">running on MacOS</echo>
<echo unless:set="onmac">not running on MacOS</echo>
</project>
Looks like you misunderstood the Condition Task:
property: The name of the property to set.
Try using the Conditionos:
Test whether the current operating system is of a given type.
Peter is trying to explain that you must explicitly specify the property name. Try the following to make your code work:
<project name="demo" default="Mytarget">
<condition property="windoze">
<or>
<equals arg1="${param1}" arg2="win-x86"/>
<equals arg1="${param1}" arg2="win-x86-client"/>
<equals arg1="${param1}" arg2="win-x64"/>
</or>
</condition>
<target name="Mytarget" if="windoze">
<echo message="executing windows family build:::${param1}"/>
</target>
</project>
A better solution would be to make use of operating system tests built into ANT's condition task.
<project name="demo" default="Mytarget">
<condition property="windoze">
<os family="windows"/>
</condition>
<target name="Mytarget" if="windoze">
<echo message="executing windows family build:::${os.name}-${os.arch}-${os.version}"/>
</target>
</project>

How to check if a property has value in Ant

I have an Ant XML file which I use for build.
I have 3 properties. I want to break the build if these properties does not contain any value. Also I want to break the build if the value is empty.
How can I do this in Ant?
I a using Ant and not Ant-contrib.
You can use conditions using the <fail> task:
<fail message="Property "foo" needs to be set to a value">
<condition>
<or>
<equals arg1="${foo}" arg2=""/>
<not>
<isset property="foo"/>
</not>
</or>
</condition>
This is equivalent to saying if (not set ${foo} or ${foo} = "") is pseudocode. You have to read the XML conditions from the inside out.
You could have used the <unless> clause on the <fail> task if you only cared whether or not the variable was set, and not whether it has an actual value.
<fail message="Property "foo" needs to be set"
unless="foo"/>
However, this won't fail if the property is set, but has no value.
There's a trick that can make this simpler
<!-- Won't change the value of `${foo}` if it's already defined -->
<property name="foo" value=""/>
<fail message="Property "foo" has no value">
<condition>
<equals arg1="${foo}" arg2=""/>
</condition>
</fail>
Remember that I can't reset a property! If ${foo} already has a value, the <property> task above won't do anything. This way, I can eliminate the <isset> condition. It might be nice since you have three properties:
<property name="foo" value=""/>
<property name="bar" value=""/>
<property name="fubar" value=""/>
<fail message="You broke the build, you dufus">
<condition>
<or>
<equals arg1="${foo}" arg2=""/>
<equals arg1="${bar}" arg2=""/>
<equals arg1="${fubar}" arg2=""/>
</or>
</condition>
</fail>
Building on the other answers, this is my preferred form, as a Macro:
<!-- Macro to require a property is not blank -->
<macrodef name="prop-require">
<attribute name="prop"/>
<sequential>
<fail message="Property "#{prop}" must be set">
<condition>
<not>
<isset property="#{prop}"/>
</not>
</condition>
</fail>
<fail message="Property "#{prop}" must not be empty">
<condition>
<equals arg1="${#{prop}}" arg2=""/>
</condition>
</fail>
</sequential>
</macrodef>
To Be used as:
<target name="deploy.war" description="Do the war deployment ;)">
<prop-require prop="target.vm" />
<prop-require prop="target.vip" />
<!-- ... -->
For brevity you can collapse the two fail elements into one by using an <or>, but I prefer my error messages to treat me like I cannot think for myself ;)
You could try using conditions... or creating a target with unless
With Ant addon Flaka you may use patterns like :
<property name="foo" value="bar"/>
...
<fl:unless test="has.property.foo">
...
</fl:unless>
...
<fl:when test="has.property.foo">
...
</fl:when>
Concrete check for emptyness :
<fl:when test=" empty '${foo}' ">
<fail message="Houston we have a problem!!"/>
</fl:when>
A complete example, also using some equals check with 'eq' (opposite would be 'neq'):
<project xmlns:fl="antlib:it.haefelinger.flaka">
<!-- some if/then/else construct -->
<fl:choose>
<!-- if -->
<when test=" '${buildtype}' eq 'prod' ">
<!-- then -->
<echo>..starting ProductionBuild</echo>
</when>
<when test=" '${buildtype}' eq 'test' ">
<!-- then -->
<echo>..starting TestBuild</echo>
</when>
<!-- else -->
<otherwise>
<fl:unless test="has.property.dummybuild">
<fail message="No valid buildtype !, found => '${buildtype}'"/>
</fl:unless>
<echo>.. is DummyBuild</echo>
</otherwise>
</fl:choose>
</project>
output with ant -f build.xml -Dbuildtype=prod or
ant -f build.xml -Dbuildtype=prod -Ddummybuild=whatever
[echo] ..starting ProductionBuild
output with typo => ant - build.xml -Dbuildtype=testt
BUILD FAILED
/home/rosebud/workspace/AntTest/build.xml:21: No valid buildtype !, found => 'testt'
output with ant -f build.xml -Ddummybuild=whatever
[echo] .. is DummyBuild
I'm on an older version of Ant, so isset wasn't available. Instead I used the following notation with the double $ in the equals.
<target name="xxx">
<echo message="${contextRoot}" />
<if>
<!-- check if the contextRoot property is defined. -->
<equals arg1="${contextRoot}" arg2="$${contextRoot}" />
<then>
<!-- it isn't set, set a default -->
<property name="contextRoot" value="/WebAppCtx" />
</then>
</if>
<echo message="${contextRoot}" />
</target>
Try this.
<condition property="isPropertySet" value="true" else="false">
<and>
<isset property="my_property"/>
<length string="${my_property}" trim="true" when="greater" length="0"/>
</and>
</condition>
<fail unless="isPropertySet" message="The property my_property is not set."/>
Since Ant 1.9.1, it is possible to add if and unless attributes on all
tasks and nested elements using special namespaces.
In order to use this feature you need to add the following namespace declarations
xmlns:if="ant:if"
xmlns:unless="ant:unless"
The if and unless namespaces support the following conditions:
true - true if the value of the attribute evaluates to true
blank - true if the value of the attribute is null or empty
set - true if the specified property is set
Sample:
<project name="tryit"
xmlns:if="ant:if"
xmlns:unless="ant:unless">
<exec executable="java">
<arg line="-X" if:true="${showextendedparams}"/>
<arg line="-version" unless:true="${showextendedparams}"/>
</exec>
<condition property="onmac">
<os family="mac"/>
</condition>
<echo if:set="onmac">running on MacOS</echo>
<echo unless:set="onmac">not running on MacOS</echo>
</project>
From Ant manual "If And Unless"

Resources