I have target which in the end call itself on a particular condition but as the values are already set it goes into infinite loop. Is any way to reset the addproperty value.
You could use ant-contrib's variable task:
<var name="your.property" unset="true"/>
<input message="your message to the user" addproperty="your.property"/>
If you're using Ant 1.8 or greater, Ant's built-in <local> task provides locally scoped properties:
<local name="user.input"/>
<input message="Prompt the user" addproperty="user.input"/>
Local task - Apache Ant's documentation
Related
I want to mark the build as successful when the file exist(when I mark ) OR failed when file does not exist (when I mark var name="build-result" value="FAILED" />).
I want to update build status after reading build-result OR by using "build.status" which I am updating depending on build-result as
<var name="build-result" value="SUCCEEDED" />
<echo message="Sending mail status- ${build-result}"/>
<propertyfile file="${build-status.file}">
<entry key="build.status" value="${build-result}" />
</propertyfile>
Currently I am doing in the way:
<isset variable="build-result" value="FAILED" />
</condition>
</fail>
But is giving the message as: BUILD FAILED
D:\projects\Self\AntExample\build.xml:51: isset doesn't support the "variable" attribute
which I want should be like "Build Failed as File Does not Exist"
Always refer to the on line documentation. <isset> takes the parameter property and not variable. Ant doesn't have the concept of variables -- just properties. What the <var/> task does is that it allows you to change a property once it is set. You should not be using <var> except in rare circumstances. As it says on the <var> task's page: In general, use of this task is DISCOURAGED, and the standard Ant Property should be used if possible.
In fact, now that you have <local/> in the list of standard Ant tasks, I find that you no longer really need <var/>.
If you want to fail your build if a file does not exist, look at the <available> test:
<fail message="This build is an utter and complete failure".>
<condition>
<not>
<available file="${result.file}" type="file"/>
</not>
</condition>
</fail>
<echo message="This build is a smashing success! We're so proud!"/>
The <fail> task will execute if the file ${result.file} is not found. Otherwise, the <echo> message will print.
<isset> accepts only one attribute- property and checks whether the specified property has been set or not (i.e. has been provided a value, including null)
See HERE for <isset>
what you may use is <equals> which compares the values of two arguments:
<equals arg1="${build-result}" arg2="FAILED">
See HERE for <equals>
as you've mentioned: I want to mark the build as successful when the file exist you may also want to look at the <available> task,
<available property="result" file="your_file_location" />
See HERE for <available>
I need some help with ant. I have a target where I loop over a fileset using foreach from ant-contrib. I call another target(lets call it doStuff) for each of iteration of the loop.
The output of doStuff is something that I would like to store in a file. I would like the files to have unique names and I thought that an integer that gets incremented with every loop would suit me well.
I tried many variations of the code below and had no success. I have probably not understod and yet. It seems to work with immutable properties, making the targets stateless. While I do enjoy that, it doesn't help me with my current problem.
Is there any way to set the myInt in the first target and keep the 'state', increment it with every loop and pass it on to the next target?
<var name="myInt" unset="true"/>
<var name="myInt" value="0"/>
<target name="default">
<foreach target="doStuff" param="theFile">
<fileset dir="" casesensitive="yes">
<depth max="0"/>
</fileset>
</foreach>
</target>
<target name="doStuff" description="Make output directories and run the MXUnit task">
<var name="op1" value="${myInt}"/>
<var name="op2" value="1"/>
<var name="op" value="+"/>
<math result="result" operand1="${op1}" operation="${op}" operand2="${op2}" datatype="int"/>
<var name="myInt" unset="true"/>
<var name="myInt" value="${result}"/>
<!-- Here I save the file with the name ${result}-->
</target>
First of all, a suggestion: consider if it is really necessary to use a self-increment integer -- if you just want a unique, sortable filename, you can use <tstamp> instead.
And this part should be considered as a bad practice to use Ant.
From your description I don't see how your "test" target is called. So I will assume that you just want your "doStuff" to use a self-increment integer each time when it's called.
You can try <script> (example code below is not tested):
<target name="default">
<script language="beanshell" classpathref="your-classpath-ref-id">
String[] theFiles = getProject().getProperty("theFile").split(",");
for (int i = 1; i <= theFiles.length; i++) {
CallTarget antcall = new CallTarget(); // the class of antcall task
antcall.setTarget("doStuff");
Property param1 = antcall.createParam();
param1.setName("number");
param1.setValue(String.valueOf(i));
... // maybe param2 to pass theFiles[i] to doStuff?
antcall.execute();
}
</script>
</target>
If the dependency library of beanshell is not in your Ant's default classpath, you need to include the jar in your classpath with the id "your-classpath-ref-id".
Update
Please read David W's answer to this question:
Ant - How can I run the same depends from multiple targets. This answer gives a good point about what Ant really is -- not a programming language, but a Matrix Dependency Language.
Using a self-increment int with a loop is a feature of a fully featured programming language. If you do want it, you can develop a library like Ant-contrib to provide such a feature. However, I still prefer time stamp over integer. When you processes the filenames as strings, time stamps can be sorted properly without any additional effort, while ints will lead to a result like ["1","10","2","3","4"...].
Hi all please give a look to this code
in my properties file i have
win-x86.pc-shared-location=E:\Ant_Scripts
Now below i am trying to call PrintInstallerName_build from my build.xml,while as PrintInstallerName_build is in test.xml. In build.xml file,${platform.id} has value=win-x86 in the calling target and in called target param1 also has value=win-x86
<target name="PrintInstallerName" >
<echo>PlatForm.Id====>${platform.id}</echo>
<ant antfile="test.xml" target="PrintInstallerName_build">
<property name="param1" value="${platform.id}"/>
</ant>
<target name="PrintInstallerName_build" >
<echo>${param1.pc-shared-location}</echo><!--${param1.pc-shared-location}-->
<echo>${param1}.pc-shared-location}</echo><!--win-x86.pc-shared-location-->
<echo>${win-x86.pc-shared-location}</echo><!--E:\\Ant_Scripts-->
</target>
as you can see only the last statement gives correct output but it is hardcoded,i want to use param1 and the output should be E:\\Ant_Scripts i tried to use $ and # but none works,may be i am doing wrong somewhere can someone help please,i am struck and tomorrow is its DOD.
See Nesting of Braces in the Properties page of the Ant Manual.
In its default configuration Ant will not try to balance braces in
property expansions, it will only consume the text up to the first
closing brace when creating a property name. I.e. when expanding
something like ${a${b}} it will be translated into two parts:
the expansion of property a${b - likely nothing useful.
the literal text } resulting from the second closing brace
This means you can't use easily expand properties whose names are
given by properties, but there are some workarounds for older versions
of Ant. With Ant 1.8.0 and the the props Antlib you can configure Ant
to use the NestedPropertyExpander defined there if you need such a
feature.
You can use <propertycopy> to make it happen.
Consider that you need to have the property value of ${propA${propB}}
Use ant tag of propertycopy as follows:
<propertycopy property="myproperty" from="PropA.${PropB}"/>
<echo >${myproperty}</echo>
This will echo the value of ${propA${propB}}
<target name="PrintInstallerName_process" >
<echo>${param1}</echo><!--win-x86-->
<macrodef name="testing">
<attribute name="v" default="NOT SET"/>
<element name="some-tasks" optional="yes"/>
<sequential>
<echo>Source Dir of ${param1}: ${#{v}}</echo><!-- Dir of Win-x86:E:\Ant_Scripts-->
<some-tasks/>
</sequential>
</macrodef>
<testing v="${param1}.pc-shared-location">
<some-tasks>
</some-tasks>
</testing>
</target>
this is the way it works and for me it works fine anyways #sudocode your tip took me there so thank you very much
Dear, I currently face some problem to retrieve the value of a property setted in a foreach loop. Maybe one of you could help me...
The purpose is to check if one file of a folder has been modified since the corresponding jar has been generated. This way I know if I have to generate the jar again.
What I do is to go through the folder with a foreach loop and if one file match my test, set a property to true.
The problem is that my variable doesn't seems to exist after my loop... Here is a simplified code example that has the same problem:
<target name="target">
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant-contrib.jar"></taskdef>
<foreach target="setVar" param="var" list="a,b"/>
<echo>myreturn in target: ${env.myreturn}</echo>
<property name="env.myreturn" value="c"/>
<echo>myreturn in second: ${env.myreturn}</echo>
</target>
<target name="setVar">
<property name="env.myreturn" value="${var}"/>
<echo>myreturn in setVar: ${env.myreturn}</echo>
</target>
The result of this code is:
target:
setVar:
[echo] myreturn in setVar: a
setVar:
[echo] myreturn in setVar: b
[echo] myreturn in target: ${env.myreturn}
[echo] myreturn in second: c
BUILD SUCCESSFUL
It seems that the variable is correctly set as it could be printed in the "setVar" target but no way to retrieve value from the calling target.
I also know it's not possible to assign a value to a property twice. But the problem doesn't even occurs... When it'll be the case I could add a check on the value of the property before to assign it to be sure it is not already initialized...
Do you have a clue on the way I can solve my problem ???
Many thanks in advance for your help :)
Try <for> task from ant-contrib instead of <foreach>. The <for> task takes advantage of Ant macro facility that came later. It works faster and is more flexible than the older <foreach> task. You are in the same project context when using <for>. That means properties set in the loop will be visible outside of the loop. Of course, normal rules for properties apply... you only get to set it once... unless you use <var> task from ant-contrib to overwrite or unset previously set properties.
Ah the joys of Ant hacking.
Not sure about your foreach problem, but can you not use the uptodate task for your requirement?
Even if I don't need it anymore thanks to sudocode, I found a solution for my question. Maybe it could be useful for someone else...
A collegue talked about the "antcallback" target of ant-contrib: it allows to return a result from a called target to the calling one. With a combination of "for" target and "antcallback" it is possible to do what I wanted to do:
<target name="target">
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant-contrib.jar"></taskdef>
<for param="file">
<path>
<fileset dir="../myDirectory" includes="**/*" />
</path>
<sequential>
<antcallback target="setVar" return="retValue">
<param name="file" value="#{file}"/>
</antcallback>
</sequential>
</for>
<echo>result: ${retValue}</echo>
</target>
<target name="setVar">
<property name="retValue" value="${file}"/>
</target>
"file" contains the name of the file in the directory. It is given to the called target as parameter with value "#{file}" ('#' necessary due to "for" target implementation).
At the end of the main target, ${retValue} contains the first value setted by the "setVar" target. No error is thrown when trying to set it multiple times, so it's not necessary to check if variable has already been instantiated before to set it in "setVar" target.
The <foreach> task uses the same logic as <antcall> under the covers, and any proprrties set inside a target invoked by <antcall> do not have scope beyond the execution of that target.
In other words, the env.myreturn property that you define in the setVar target is lost as soon as execution of that target completes.
This sort of scripting really isn't what Ant is designed for. The Ant-contrib library tries to patch up the holes, but it's still bending it way out of shape.
If you need to write such scripts, and want to use Ant tasks to achieve them, have a look at Gradle instead. It's a rather lovely blend of Groovy (for scripting) and Ant (for the tasks).
The other approaches here (<for>, <var>, <groovy>properties.put(....)</groovy>, <property>, <antcallback>) did not work with ANT 1.9.4, so I used the file system similar to this (pseudocode):
<target name="outer">
<for> <antcall target="inner" /> </for>
<loadproperties srcfile="tmpfile.properties" />
<echo message="${outerprop}" />
</target>
<target name="inner">
<!-- did not work: -->
<!--
<property name="outerprop" value="true" />
<var name="outerprop" value="true" />
<groovy>properties.put('outerprop','true')</groovy>
<antcallback target="setouterprop" />
-->
<echo message="outerprop=true" file="tmpfile.properties" />
</target>
Maybe the other approaches did not work because of my <antcall>, but I need it here. (outerprop is initially unset)
I have an ant file that does the following:
<property file="project.properties" description="Project configuration properties"/>
<property file="build-defaults.properties" description="default build configuration."/>
<property file="build.properties" description="local build configuration overrides"/>
I want to have defaults set in build-defaults.properties (which is checked in to SCM) but allow developers to override values in a local build.properties so that they can work with local paths.
The problem is, it doesn't seem to be working; I've set this up, created an override in build.properties, but the value of my path remains the one set in build-defaults.properties. How do I accomplish this?
The initial problem with your set up is that you've got build.properties and build-defaults.properties reversed.
Ant Properties are set once and then can never be overridden. That's why setting any property on the command line via a -Dproperty=value will always override anything you've set in the file; the property is set and then nothing can override it.
So the way you want this set up is:
<property file="build.properties" description="local build configuration overrides"/>
<property file="project.properties" description="Project configuration properties"/>
<property file="build-defaults.properties" description="default build configuration."/>
This way:
Anything set at the command line takes precedence over build.properties
Anything set in build.properties overrides other values
etc. on down the line.
Actually ant properties may be overriden. See the documentation of the property task:
Normally property values can not be changed, once a property is set,
most tasks will not allow its value to be modified.
One of the tasks that are able to override the property value is script. Also any custom task may use this backdoor. Other proposals are in question Ant loadfile override property. This is against the spirit of ant and usually unnecessary. But it's good to know that, because I just had an opposite problem: why the property value changed although it is immutable.
Here is a sample target that uses script task to change the value of a property. It shows the basic methods to work with properties. All methods are described in Ant Api which is not available online. You need to download the Ant Manual. In its api directory there is the api documentation.
<target name="t1">
<property name="a" value="one" />
<script language="javascript">
sProp = project.getProperty("a");
sProp = sProp.replace("e", "ly");
project.setProperty("a", sProp);
project.setNewProperty("a", "new value");
</script>
<property name="a" value="two" />
<echo>a=${a}</echo>
</target>
How to easily setup the script task? Making the script task running with beanshell language is a bit tricky and non-trivial, but it's explained in this answer. However as Rebse noted, using javascript language is supported out of the box in jdk 6.
Ant property can't be overwritten unless using macro and javascript plug-in to do:
Step 1: define a macro function to overwrite property
<!--overwrite property's value-->
<macrodef name="set" >
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<script language="javascript">
<![CDATA[
project.setProperty("#{name}", "#{value}");
]]>
</script>
</sequential>
</macrodef>
Step 2: use the macro in the ant xml
<set
name="your_target_property"
value="your_value" or "${another_property}"
</set>