I'm trying to add an excludes list to my ant build script. I have a property (lets call it build.excludes) which looks something like this:
build.excludes=MyApp,AnotherApp
in my build script I have an if statement similar to the following:
<for list="${appsList}" delimiter="" trim="true" param="currentApp" keepgoing="yes">
<sequential>
<if>
<!-- check if my current build item is in the build.excludes list -->
<then>
<!-- build of a project happens here -->
</then>
</if>
</sequential>
</for>
The only way I can think of doing it is to have a for loop to iterate over my build.excludes list and then do something (but I don't know where to put this for loop... perhaps in a macro?).
Thanks!
EDIT: Ant 1.6.5 and can't upgrade.
Looks like you're using the ant-contrib for task. if supports the same elements as the ant condition task, which has been around long enough to be in version 1.6.5.
Here's an example:
<property name="build.excludes" value="MyApp,AnotherApp" />
<property name="appsList" value="MyApp,ExtraApp" />
<for list="${appsList}" delimiter="," trim="true" param="currentApp" keepgoing="yes">
<sequential>
<echo message="Checking #{currentApp}" />
<if>
<not>
<contains string=",${build.excludes}," substring=",#{currentApp}," />
</not>
<then>
<echo message="Building #{currentApp}" />
</then>
<else>
<echo message="Not Building #{currentApp} - excluded" />
</else>
</if>
</sequential>
</for>
Gives:
[echo] Checking MyApp
[echo] Not Building MyApp - excluded
[echo] Checking ExtraApp
[echo] Building ExtraApp
Related
I have this ant script that is reading from a parameter a list of components and running other ant tasks (build.xml's):
<for list="${components.locations}" param="component" failonany="false">
<sequential>
<property name="#{component}" value="true"/>
<if>
<and>
<available file="${repository.location}/#{component}"/>
<available file="${repository.location}/${jars.location}"/>
</and>
<then>
<ant inheritAll="false" antfile="${repository.location}/#{component}/build.xml">
<!-- failonerror="false" -->
<property name="copy.libs" value="${copy.libs}"/>
<property name="repository.location" value="${repository.location}"/>
<property name="jars.location" value="${repository.location}/${jars.location}"/>
</ant>
</then>
</if>
</sequential>
</for>
The problem is if one component is failing, the script doesn't continue to next one.
I tried running with -k (-keep-going) argument but it doesn't help.
I found this property failonerror="false" but it's valid for "exec" tasks and couldn't integrate it with "ant" tasks or inside a "target".
Other direction was "failonany" property of the "for" but I didn't manage setting it up explicitly.
Can you please advice...
Thanks.
First of all, I would suggest deleting ant-contrib.jar and never looking back. Believe me, you will be doing yourself a favor.
You can use the subant task to iterate Ant builds on a set of directories or files. Simply define a dirset and pass any extra properties you need.
Instead of using ant-contrib's <if> block, use the standard target's if attribute to switch the entire target on or off. This is much safer and better practice.
<property name="repository.location" location="repository_location" />
<property name="jars.location" location="${repository.location}/jars" />
<property name="components" value="dir1,dir2,dir3" />
<target name="init">
<condition property="jars.available">
<available file="${jars.location}" />
</condition>
</target>
<target name="default" depends="init" if="jars.available">
<subant inheritall="false" failonerror="false">
<dirset id="components.dirs" dir="${repository.location}" includes="${components}" />
<property name="copy.libs" value="${copy.libs}" />
<property name="repository.location" value="${repository.location}" />
<property name="jars.location" value="${jars.location}" />
</subant>
</target>
I am using the following code with the idea of finding a file in a directory that is also part of a list in a file:
<loadfile property="ReportFileContent" srcFile="${ReportFile}"/>
<for param="file">
<path>
<fileset dir="${MainDir}" includes="**/**"/>
</path>
<sequential>
<basename file="#{file}" property="#{file}" />
<condition property="found-file${index2}">
<matches pattern="#{file}" string="${ReportFileContent}"/>
</condition>
<if>
<isset property="found-file${index2}"/>
<then>
<echo message=" Found file #{file}" level="warning" />
</then>
<else>
<echo message="Not Found file #{file}" level="warning" />
</else>
</if>
<math result="index2" operand1="${index2}" operation="+" operand2="1" datatype="int" />
</sequential>
</for>
The command is not working though as it is not finding the file that is available in ${ReportFileContent}.
The content of the ReportFileContent property is the following:
c:\___tools\test\file1.txt;2
c:\___tools\test\file2.txt;2
c:\___tools\test\file3.txt;2
Any idea why the condition is not working correctly?
Thanks
Tony
<target name="build">
<for list="${platform}" param="platform" trim="true">
<sequential>
<if>
<equals arg1="${platform}" arg2="${project.SuppoortedPlatforms}" />
<then>
<antcall target="package.${platform}" />
</then>
</if>
</sequential>
</for>
</target>
where i'm getting platfrom values at runtime (eg:windows,ios) and project.SuppoortedPlatforms is declared under build.properties (eg:android,ios). how can i compare the list of strings?
could anyone help me to solve this problem?
Thanks,
sandhiya
You are looping over a comma-separated list of platforms, and for each one you're checking if it is contained in the list of supported platforms in project.SuppoortedPlatforms. This should go like this:
<for list="${platform}" param="platformParam" trim="true">
<sequential>
<if>
<contains string="${project.SuppoortedPlatforms}" substring="#{platformParam}" />
<then>
<antcall target="package.#{platformParam}" />
</then>
</if>
</sequential>
</for>
The parameter in the loop should be accessed with # instead of $. Also it would be better to rename the parameter for readability (platformParam instead of platform).
Instead of using contains task, i myself tried with the nested for loop, its cool working fine.
<for list="${platforms}" param="platformparam" trim="true">
<sequential>
<for list="${project.SupportedPlatforms}" param="supplatformparam" trim="true">
<sequential>
<if>
<equals arg1="#{platformparam}" arg2="#{supplatformparam}" />
<then>
<antcall target="package.#{platformParam}" />
</then>
</if>
</sequential>
</for>
</sequential>
</for>
I need to copy all dml.sql files to inside DB2_List.txt file if DML.sql file is present. But after executing this file i'm getting error like this:
copy doesn't support the nested "if" element.
Please let me know if you have any better idea about the nested loop in Ant.
<available file="DB/DML.sql" property="db.check.present"/>
<copy file="DB/DDL.sql" tofile="DB2/DB2_List.txt" >
<if>
<equals arg1="${db.check.present}" arg2="true"/>
<then>
<filterchain>
<concatfilter append="DB/DML.sql" />
<tokenfilter delimoutput="${line.separator}" />
</filterchain>
</then>
</if>
</copy>
It is possible to accomplish what you are after, you just have to approach it quite differently in Ant. Just note that you will need to utilize separate targets.
<target name="db.check">
<available file="DB/DML.sql" property="db.check.present"/>
</target>
<target name="db.copy" depends="db.check" if="db.check.present">
<copy file="DB/DDL.sql" tofile="DB2/DB2_List.txt" >
<filterchain>
<concatfilter append="DB/DML.sql" />
<tokenfilter delimoutput="${line.separator}" />
</filterchain>
</copy>
</target>
Take a look at Ant 1.9.1 which supports special if/unless attributes on tags. This might be possible:
<project name="mysterious.moe" basedir="." default="package"
xmlns:if="ant:if"
xmlns:unless="ant:unless"/>
<target name="db.copy">
<available file="DB/DML.sql" property="db.check.present"/>
<copy file="DB/DDL.sql"
tofile="DB2/DB2_List.txt">
<filterchain if:true="db.ceck.present">
<concatfilter append="DB/DML.sql" />
<tokenfilter delimoutput="${line.separator}" />
</filterchain>
</copy>
<target>
...
</project>
Otherwise, you'll have to use two separate copies. You can't put <if> antcontrib inside tasks. Only around tasks:
<available file="DB/DML.sql" property="db.check.present"/>
<if>
<equals arg1="${db.check.present}" arg2="true"/>
<then>
<copy file="DB/DDL.sql" tofile="DB2/DB2_List.txt" >
<filterchain>
<concatfilter append="DB/DML.sql" />
<tokenfilter delimoutput="${line.separator}" />
</filterchain>
</copy>
</then>
<else>
<copy file="DB/DDL.sql" tofile="DB2/DB2_List.txt" >
</else>
</if>
</copy>
I am currently writing an ant project xml file and I am looking for some hints and tips to improve the structure and readability of the project.
<target name="eatnutsOnClient" >
<monkey.eatnuts clientName="${clientName}" label="${nutLabel}" />
<if><not> <equals arg1="${returnCode}" arg2="0"/> </not><then>
<echo message="eatnuts-[${nutlabel}]_[${returnCode}]${line.separator}" file="${reachedFile}" append="true" />
</then></if>
</target>
<target name="eatnuts" depends="createClient,eatnutsOnClient,destroyClient"/>
In order to manage the return codes I would like to have the possibility to replace the full if section that I need to replicate over quite some targets by a sort of function which I can call to handle the returncode logic. I guess one option would be to create a target which only contains the if section and add it to the depend list of each task? Are there better ways?
An Ant <macrodef> provides a function-like way to share code:
<project name="ant-macrodef-echo" default="run">
<taskdef resource="net/sf/antcontrib/antlib.xml" />
<macrodef name="echo-macrodef">
<attribute name="returnCode"/>
<sequential>
<if>
<not>
<equals arg1="#{returnCode}" arg2="0"/>
</not>
<then>
<echo message="#{returnCode}" />
</then>
</if>
</sequential>
</macrodef>
<target name="run">
<echo-macrodef returnCode="42"/>
<echo-macrodef returnCode="0"/>
<echo-macrodef returnCode="-9"/>
</target>
</project>
Results:
run:
[echo] 42
[echo] -9