Condition based on environment in Ant buildfile - ant

I am new to Ant and any help will be appreciated.
What I want to do is:
<target name="run-tenantManagement" depends="jar"
description="Running TestNG Tests">
<if> ... SIMV3.1 env variable set
<property name="output.dir.name" value="tenantManagementV3"/>
<else>
<property name="output.dir.name" value="tenantManagement"/>
</if>
</target>
Basically I am setting one env variable
setenv SIMV3.1 true
I want to put a check in the Ant target if this variable is set and has value=true, then set output.dir.name to a particular value, else set it to another value.
Kindly help. I have googled through many Ant tutorials but everything seems ambiguous.

There's a few ways to do this, for example using an Ant <condition> task:
<property environment="env" />
<condition property="output.dir.name" value="tenantManagementV3"
else="tenantManagement">
<istrue value="${env.SIMV3.1}" />
</condition>
There are a number of other tests you can use and combine in the task, see Conditions for the list.
Also: I'd avoid using an environment variable name with an embedded dot - it won't work in all shells.

Related

How do you determine within Ant whether verbose is enabled?

Within an ant build.xml, I want to influence a child process's verbose flag based on whether ant itself was run with verbose enabled. Is there a variable set to determine this? Or otherwise, can I parse the raw Ant command line somehow to check whether -v is passed?
The property sun.java.command contains command line options
<project >
<echo message="${sun.java.command}" />
<condition property="verbose.is.set">
<contains string="${sun.java.command}" substring="-v" />
</condition>
<echo message="${verbose.is.set}" />
</project>

how to use exec exit status in ant target and other targets also

I am calling one target(targetCalled) from some other target(targetCaller), as follows:
<target depends="local.init"
description="creating application jar file of the classes dir"
name="run_check_server_client_jar_gen">
<antcall target="run_check_server_client_jar_callExec"/>
<if>
<isset property="result"/>
<then>
<echo>Result: ${result}</echo>
</then>
<else>
<echo>Propert result is not set yet !! </echo>
</else>
</if>
</target>
Now I call one exec from targetCalled as follows:
<target depends="local.init"
description="Running check for all classes in
client jar should also be present in server jar"
name="run_check_server_client_jar_callExec">
<exec executable="/bin/bash" resultproperty="${result}" failonerror="false">
<arg value="count_client_server_inner_classes.sh"/>
<arg value="gjf1common_client_classes.jar"/>
<arg value="gjf1common_classes.jar"/>
</exec>
<if>
<isset property="result"/>
<then>
<echo>Inside::Result: ${result}</echo>
</then>
<else>
<echo>Inside::Property result is not set yet !!!! </echo>
</else>
</if>
</target>
In my count_client_server_inner_classes.sh, i am exiting the status as:
exit "$result"
it is giving me ": numeric argument required"
i want that executable should return me a string, is that possible ??
I want to use this returned value in my targetCalled and targetCaller.
but when i am echoing the result property.. it is giving me 255.
Can anybody points out where i am going wrong ?
Ant isn't a scripting language. It's not a very good way to describe a build - but it's an awful scripting language. Trying to script in ant with pseudo-function calls and if/else like this is going to suck. In generally, stay away from if/else - if you find you need them you likely want to reevaluate your tool choice. Avoid antcall at all costs - it spins up a new jvm and makes for some crazy spaghetti - use depends to control the execution flow between targets.
To answer one of your question - the result property is always going to be the exit code, in the case of bash it's always goign to be an int 0-255.
The interesting part is in the bash script... post that. It's returning 255, which is a special code - means it's out of range. I suspect you're having it return a string?
You could simplify the whole mess by simply failing on error:
<target name="run-check-server-client-jar-gen" depends="local-init"
description="creating application jar file of the classes dir">
<exec executable="/bin/bash" failonerror="true">
<arg value="count_client_server_inner_classes.sh"/>
<arg value="gjf1common_client_classes.jar"/>
<arg value="gjf1common_classes.jar"/>
</exec>
</target>
If you really must give custom error status you can set the result property as you where and then you could:
<target name="run-check-server-client-jar-gen" depends="local-init"
description="creating application jar file of the classes dir">
<exec executable="/bin/bash" resultproperty="${return.code}">
<arg value="count_client_server_inner_classes.sh"/>
<arg value="gjf1common_client_classes.jar"/>
<arg value="gjf1common_classes.jar"/>
</exec>
<fail message="crazy shell script madness terminated abnormally.">
<condition>
<isfailure code="${return.code}"/>
</condition>
</fail>
</target>
I admit I didn't actually run the snippets above, you may have to massage a bit, but I'm pretty sure they'll go.
another editorial note on style: targets generally use - rather than _ or . to delimit word, where properties use .

Conditional property in Ant properties' file

Is it possible to set a property value in Ant property files (as opposed to build.xml) in a conditional way? For example, if apache.root property is set - the my_property will be ${apache.root}/myapp, /var/www/myapp otherwise. If not, what would be the common practice - reusable build.xml files?
Use the condition task:
<project name="demo" default="run">
<condition property="my_property" value="${apache.root}/myapp" else="/var/www/myapp">
<isset property="apache.root"/>
</condition>
<target name="run">
<echo message="my_property=${my_property}"/>
</target>
</project>
You can include different property files based on environments or the conditional variables. For example
<echo>Building ${ant.project.name} on OS: ${os.name}-${os.arch}</echo>
<property file="build-${os.name}.properties" />
this would include a file named 'build-Windows 7.properties' or 'build-Linux.properties' depending on where the build is being run. Of course the property directive looks in the current directory as well as home directory. So the property file could be a part of the build source or in the home directory of the build account.
You can use the condition tag to generate part of the name of the property file as well to select
One of the simplest form of condition you can use is:
<exec executable="hostname" outputproperty="hostname"/>
<condition property="python" value="/usr/bin/python3.4">
<equals arg1="${hostname}" arg2="host0"/>
</condition>
<property name="python" value="/usr/bin/python"/>
to accommodate different python installation path for example. Here, default install path is /usr/bin/python except for host0 where it /usr/bin/python3.4
The OP was asking about a properties file, not within the ant build file. Unfortunately conditionals cannot be done from within the build file. What you can do is have separate property files for each set of dependant properties. For instance:
Build.xml
<condition property="app.name" value="appA">
<equals arg1="${appName}" arg2="A" />
</condition>
<condition property="app.name" value="appB">
<equals arg1="${appName}" arg2="B" />
</condition>
<property file="${app.name}.properties" />
<!-- since properties are immutable, set your defaults here -->
<property name="apache.root" value="/var" />
<property file="restOfProps.properties" />
appA.properties
apache.root=/appA
restOfProps.properties
my_property=${apache.root}/myapp

How to set an Ant property only if it is unset

I can't figure out how to set an Ant property on the condition that it has not been set (i.e it is not defined in the properties file and should automatically default).
So far, I only have the following code:
<condition property="core.bin" value="../bin">
<isset property="core.bin"/>
</condition>
But this only seems to work if the value is defined in a <property> tag.
Does anyone know how to conditionally set a property for the first time if it currently unset?
You simply can set the property with the property-task. If the property is already set, the value is unchanged, because properties are immutable.
But you can also include 'not' in your condition:
<condition property="core.bin" value="../bin">
<not>
<isset property="core.bin"/>
</not>
</condition>
Ant does this by default; if the property is already set; setting it again has no effect:
<project name="demo" default="demo">
<target name="demo" >
<property name="aProperty" value="foo" />
<property name="aProperty" value="bar" /> <!-- already defined; no effect -->
<echo message="Property value is '${aProperty}'" /> <!-- Displays 'foo' -->
</target>
</project>
Gives
/c/scratch> ant -f build.xml
Buildfile: build.xml
demo:
[echo] Property value is '${aProperty}'
BUILD SUCCESSFUL
Total time: 0 seconds
/c/scratch> ant -f build.xml
Buildfile: build.xml
demo:
[echo] Property value is 'foo'
BUILD SUCCESSFUL
Properties cannot be redefined; to do this you need to use something like the variable task from ant-contrib.
The easiest way to do what you want:
<if>
<not>
<isset property="your.property"/>
</not>
<then>
<property name="your.property" value="your.value"/>
</then>
</if>
There is support of using 'else' within : https://ant.apache.org/manual/Tasks/condition.html to serve your exact purpose.
else
The value to set the property to if the condition evaluates to false. By default the property will remain unset. Since Apache Ant 1.6.3
So change to :
<condition property="core.bin" else="../bin">
<isset property="core.bin"/>
</condition>
Properties in Ant are immutable. After defined they cannot be changed.
But the Ant Contrib package offers the variable task. It works like a property but the values can be modified and unset.
Exmaple from the variable task documentation:
<var name="x" value="6"/>
<if>
<equals arg1="${x}" arg2="6" />
<then>
<var name="x" value="12"/>
</then>
</if>
<echo>${x}</echo> <!-- will print 12 -->

Can I make the Ant copy task OS-specific?

I have an Ant script that performs a copy operation using the 'copy' task. It was written for Windows, and has a hardcoded C:\ path as the 'todir' argument. I see the 'exec' task has an OS argument, is there a similar way to branch a copy based on OS?
I would recommend putting the path in a property, then setting the property conditionally based on the current OS.
<condition property="foo.path" value="C:\Foo\Dir">
<os family="windows"/>
</condition>
<condition property="foo.path" value="/home/foo/dir">
<os family="unix"/>
</condition>
<fail unless="foo.path">No foo.path set for this OS!</fail>
As a side benefit, once it is in a property you can override it without editing the Ant script.
The previously posted suggestions of an OS specific variable will work, but many times you can simply omit the "C:" prefix and use forward slashes (Unix style) file paths and it will work on both Windows and Unix systems.
So, if you want to copy files to "C:/tmp" on Windows and "/tmp" on Unix, you could use something like:
<copy todir="/tmp" overwrite="true" >
<fileset dir="${lib.dir}">
<include name="*.jar" />
</fileset>
</copy>
If you do want/need to set a conditional path based on OS, it can be simplified as:
<condition property="root.drive" value="C:/" else="/">
<os family="windows" />
</condition>
<copy todir="${root.drive}tmp" overwrite="true" >
<fileset dir="${lib.dir}">
<include name="*.jar" />
</fileset>
</copy>
You could use the condition task to branch to different copy tasks... from the ant manual:
<condition property="isMacOsButNotMacOsX">
<and>
<os family="mac"/>
<not>
<os family="unix"/>
</not>
</and>
Declare a variable that is the root folder of your operation. Prefix your folders with that variable, including in the copy task.
Set the variable based on the OS using a conditional, or pass it as an argument to the Ant script.
You can't use a variable and assign it depending on the type? You could put it in a build.properties file. Or you could assign it using a condition.
Ant-contrib has the <osfamily /> task. This will expose the family of the os to a property (that you specify the name of). This could be of some benefit.

Resources