Trying to make this target conditional - ant

This is what I'm trying to do:
<target name="example">
<if>
<equals arg1="${var}" arg2="true" />
<then>
<exec executable="/bin/bash">
<arg value="script.sh" />
</exec>
</then>
</if>
</target>
And when I execute the target with ant example I get this error:
Problem: failed to create task or type if
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken place.
I really need help in here. I would really appreciate it

That is because, if is custom task from ant-contrib library.
Make sure, ant-contrib library in your class path. Binaries can be downloaded from here. Extract the ant-contrib jar file to a location. And specify the same in below taskdef.
Then add the taskdef at the beginning of the build.xml. Refer documentation for more details.
For eg:
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="/absolute/path/to/ant-contrib-1.0b3.jar" />
</classpath>
</taskdef>

Related

Problem : ant unable to recognize for task

I am trying to iterate over all the files in a ant however ant seems to be unable to recognize for task.
I have installed ant-contrib on a location and have provided the path in the build file.
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="${basedir}\build\ant-contrib.jar"/>
</classpath>
</taskdef>
<for param="file">
<path>
<fileset dir="${basedir}/src/objects"/>
</path>
<sequential>
perform operations here.
</sequential>
</for>
</target>
Problem: failed to create task or type for
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken place.
First of all, I would suggest avoiding the use of ant-contrib if at all possible. If you have anything resembling a normal build, native Ant can probably handle it better. Feel free to post a higher level description what you're trying to do here and I can help you out with it.
That said, your task isn't recognized because antcontrib.properties doesn't define it, for some strange reason. Instead, try pointing the resource attribute to antlib.xml.
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<pathelement location="${basedir}\build\ant-contrib.jar"/>
</classpath>
</taskdef>

Ant for script how to continue if any iteration fails

I writing an ant build file to check all translate files in a directory.
I want the ant for script to continue checking the rest files if an checking error in any file appear.
My ant task:
<taskdef name="validate" classname="ValidateTranslateFile">
<classpath>
<pathelement location="${ant-libs-dir}/TranslateFileUtilities.jar" />
<pathelement location="../web/WEB-INF/lib/commons-io-2.5.jar" />
<pathelement location="../web/WEB-INF/lib/commons-lang3-3.5.jar" />
</classpath>
</taskdef>
<for param="program">
<path>
<fileset dir="../web/WEB-INF" includes="*.txt" />
</path>
<sequential>
<validate targetFile="#{program}" checkLanguages="true" checkKeysOrder="true" />
</sequential>
</for>
</target>
the Result:
it checks the files till the first error appear, and then the BUILD FAILED.
Could any one help me with that?
The for task is not part of standard ANT. It is a 3rd party extension documented here:
http://ant-contrib.sourceforge.net/tasks/tasks/for.html
The documentation suggests using a "keepgoing" attribute to ignore errors, this might be the answer you're looking for.
If this is a custom ANT task you are writing, perhaps you should consider refactoring the code to operate on a fileset? This would enable you to call task as follows:
<validate checkLanguages="true" checkKeysOrder="true">
<fileset dir="../web/WEB-INF" includes="*.txt" />
</validate>
Simpler and more robust.

Ant Throws Reference Error for Existing Jar File

I want to add task to my build.xml file:
<target name="forbidden-checks" depends="download-forbidden-checks">
<taskdef name="forbidden-apis" classname="de.thetaphi.forbiddenapis.AntTask"
classpathref="lib/forbiddenapis-2.2.jar"/>
<fa:forbiddenapis classpathref="build.classpath" dir="${build.dir}" targetVersion="${jdk.version}">
<bundledsignatures name="jdk-unsafe"/>
<bundledsignatures name="jdk-deprecated"/>
<bundledsignatures name="jdk-non-portable"/>
</fa:forbiddenapis>
</target>
I see that jar is downloaded, there is no problem. However I get an error:
download-forbidden-checks:
setup-maven-url:
download-via-maven:
[get] Getting: https://repo1.maven.org/maven2/de/thetaphi/forbiddenapis/2.2/forbiddenapis-2.2.jar
[get] To: /home/kamaci/pro/lib/forbiddenapis-2.2.jar
forbidden-checks:
BUILD FAILED
/home/kamaci/pro/build.xml:2391: Reference /home/kamaci/pro/lib/forbiddenapis-2.2.jar not found.
I checked if I have a problem with the path of jar. So, I've put forbiddenapis-2.2.jar to another place than the project. I've pointed that jar from my taskef but I got same error.
Any ideas?
EDIT 1:
I've changed it to that:
<target name="forbidden-checks" depends="download-forbidden-checks">
<taskdef name="forbidden-apis" classname="de.thetaphi.forbiddenapis.AntTask">
<classpath>
<pathelement location="/home/kamaci/pro/forbiddenapis-2.2.jar"/>
</classpath>
</taskdef>
<fa:forbiddenapis targetVersion="${jdk.version}">
<classpath>
<pathelement location="lib/forbiddenapis-2.2.jar"/>
</classpath>
<bundledsignatures name="jdk-unsafe"/>
<bundledsignatures name="jdk-deprecated"/>
<bundledsignatures name="jdk-non-portable"/>
</fa:forbiddenapis>
</target>
However, it didn't work:
Problem: failed to create task or type antlib:de.thetaphi.forbiddenapis:forbiddenapis
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken place.
No types or tasks have been defined in this namespace yet
This appears to be an antlib declaration.
Action: Check that the implementing library exists in one of:
-/usr/share/ant/lib
-/home/kamaci/.ant/lib
-a directory added on the command line with the -lib argument
When I run this:
ant forbidden-checks -lib lib/
it works. My project definition starts with that at build.xml:
Why I should add -lib? Is there any way to avoid it?
Pretty sure the issue is the classpathref as it is using a literal value and not a path element, so the jar may exist just not on the classpath, try creating a path element to use for the taskdef
<path id="lib.path">
<fileset dir="lib" includes="lib/*.jar"/>
</path>
<taskdef name="forbidden-apis" classname="de.thetaphi.forbiddenapis.AntTask"
classpathref="lib.path"/>
or defining the classpath inside the taskdef.
<taskdef name="forbidden-apis" classname="de.thetaphi.forbiddenapis.AntTask">
<classpath>
<pathelement location="lib/forbiddenapis-2.2.jar"/>
</classpath>
</taskdef>

if else condition in ant task produces error

I have a scenario where i need to move a directory from one location to another. If the same directory exists in the destination folder i need to rename the directory name as oldname_1.
So i wrote a snippet as follows:
<target name="Move">
<IF>
<available file="${output.dir}" type="dir" />
<then>
<echo message="Directory exists" />
<rename src="${output.dir}" dest="${output.dir}_1"/>
<property name="newdirectory" value="${dest}"/>
</then>
<ELSE>
<echo message="Directory does not exist" />
</ELSE>
</IF>
<move file="${newdirectory}" todir="C:\reports" />
</target>
The error i am getting is :
Problem: failed to create task
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any / declarations have taken place.
As Ian Roberts has already mentioned, you need the Ant-Contrib jar, and then setup the <taskdef/> to point to this jar. I highly recommend putting it inside your project and checking it into your version control system. This way, when someone checks out your project, they already have the Ant-Contib.jar installed.
My standard is to put all optional jars required for the build (not jars required for compiling) in the directory ${basedir}/antlib, then put each optional jar in its own directory, so I would put ant-contrib-1.0b3.jar into ${basedir}/antlib/antcontrib.
Then I define the task this way:
<property name="antlib.dir" value="${basedir}/antlib"/>
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<fileset dir="${antlib.dir}/antcontrib"/>
</classpath>
</taskdef>
This way, if you update the jar file to a new version of the Ant-Contrib jar, you simply plug it into the directory. You don't have to update the build.xml.
Also note that I use net/sf/antcontrib/antlib.xml and not net/sf/antcontrib/antcontrib.properties. The XML file is what you should use. The directions for this are on the tasks page and differ from the ones on the main page under the installation directions. The reason is that the XML file has the correct definition for the <for> task, and the properties file does not.
However, there is another way to do if and unless in Ant 1.9.1 without the need for optional jar files. These are the new If and Unless entity attributes.
These can be placed in all tasks, or sub-entities, and can usually replace the Ant-Contrib if/else stuff:
<target name="move">
<available file="${output.dir}" type="dir"
property="output.dir.exists"/>
<echo message"Directory exists"
if:true="output.dir.exists"/>
<move file="${output.dir}" tofile="${output.dir}_1"
if:true="output.dir.exists"/>
<property name="newdirectory" value="${dest}"
if:true="output.dir.exists"/>
<echo message="Directory does not exists"
unless:true="output.dir.exists"/>
<move file="${newdirectory}" todir="C:\reports" />
</target>
Not so clean as your example. However, I would instead use the if= and unless= parameters on target names:
<target name="move.test">
<available file="${output.dir}" type="dir"
property="output.dir.exists"/>
</target>
<target name="move"
depends="move.test, move.exists, move.does.not exists">
<move file="${newdirectory}" todir="C:\reports" />
</target>
<target name="move.exists"
if="output.dir.exists">
<echo message="Directory exists" />
<move file="${output.dir}" tofile="${output.dir}_1"/>
<property name="newdirectory" value="${dest}"/>
</move.exists/>
<target name="move.does.not.exists"
unless="output.dir.exists"/>
<echo message="Directory does not exist" />
</target>
If you didn't echo everything, the structure would be a bit cleaner:
<target name="move.test">
<available file="${output.dir}" type="dir"
property="output.dir.exists"/>
</target>
<target name="move"
depends="move.test, backup">
<move file="${newdirectory}" todir="C:\reports" />
</target>
<target name="backup"
if="output.dir.exists">
<move file="${output.dir}" tofile="${output.dir}_1"/>
<property name="newdirectory" value="${dest}"/>
</move.exists/>
The if/else construct is not a native part of Ant out of the box, it is provided by the ant-contrib project, and you need to download a JAR and add the relevant <taskdef> to your build file. For example, if you download ant-contrib-1.0b3.jar and put it in a directory named build in the same directory as your build.xml, then you can say
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="build/ant-contrib-1.0b3.jar"/>
</classpath>
</taskdef>

subant on condition

I'd like to execute subant on some condition. something like:
<if>
<equals value="value1" property="${some.property">
<then>
<subant target="#{target}" failonerror="true" inheritall="false">
<buildpath refid="some-ref1" />
</subant>
</then>
<else>
<subant target="#{target}" failonerror="true" inheritall="false">
<buildpath refid="some-ref2" />
</subant>
</else>
</if>
But can't find a way to do it. Read the ant manual and googled, but no solution is found.
Thanks.
I believe the error may lie in your equals tag. Instead of using the 'value' and 'propery' attributes, try using 'arg1' and 'arg2', i.e.:
<equals arg1="value1" arg2="${some.property}">
Check out the examples in the ant-contrib doc: http://ant-contrib.sourceforge.net/tasks/tasks/if.html.
If the problem is that your 'if', 'then', and/or 'else' tags are not resolving properly, then you may be missing the ant-contrib libraries. Ant-contrib is not natively included with ant, but you can download it here: http://sourceforge.net/projects/ant-contrib/files/
Per the ant-contrib site (http://ant-contrib.sourceforge.net/), here's what you must do to install ant-contrib:
Option 1: Copy ant-contrib-0.3.jar to the lib directory of your Ant installation. If you want to use one of the tasks in your own project, add the lines
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
to your build file.
Option 2: Keep ant-contrib-0.3.jar in a separate location. You now have to tell Ant explicitly where to find it (say in /usr/share/java/lib):
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="/usr/share/java/lib/ant-contrib-0.3.jar"/>
</classpath>
</taskdef>
Please look up a <target if="${some.property}>. You may want another target with an unless.
If the property has to do with a file existing, see Ant task to check a file exists?. Even if this is not your main concern, I am sure you can get the idea from the accepted answer.
Do you mean calling another target
if so here is
<if>
<equals value="value1" property="${some.property">
<then>
<antcall target="#{target}" failonerror="true" inheritall="false">
</then>
<else>
<antcall target="#{target}" failonerror="true" inheritall="false">
</else>
</if>

Resources