This question already has answers here:
How can I get the value of the current target ant?
(5 answers)
Closed 7 years ago.
How can an ANT task like this one:
<target name="mytask">
<echo>processing ${blabla}</echo>
</target>
print processing mytask ?
What should I replace blabla with ? Or this is actually even possible ?
This might work for you with vanilla Ant, if your version is recent enough to include javascript support.
<scriptdef name="currenttarget" language="javascript">
<attribute name="property"/>
<![CDATA[
importClass( java.lang.Thread );
project.setProperty(
attributes.get( "property" ),
project.getThreadTask(
Thread.currentThread( ) ).getTask( ).getOwningTarget( ).getName( ) );
]]>
</scriptdef>
<target name="foobar">
<currenttarget property="my_target" />
<echo message="${my_target}" />
</target>
The scriptdef sets up a task currenttarget that can be used to get the current target in a property, which you can then use as you see fit.
The task name is always output to console by Ant:
Here is an example:
<project default="test">
<target name="test" depends="mytask-silent, mytask-echo"/>
<target name="mytask-echo">
<echo>processing</echo>
</target>
<target name="mytask-silent"/>
</project>
Here is the output:
C:\tmp\ant>ant
Buildfile: c:\tmp\ant\build.xml
mytask-silent:
mytask-echo:
[echo] processing
test:
BUILD SUCCESSFUL
Total time: 0 seconds
The only way I know it do this is to write an ANT task or use a groovy script as follows:
<target name="mytask" depends="init">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<groovy>
println "processing ${target}"
</groovy>
</target>
Related
Hi I am having a csv file with 2 lines :
mf1,eg1,eg2,br1,br2
mf2,eg2,eg3,br2,br3
I want to store each comma separated value in separate variables using ant.
I am able to parse lines, but not individual values since list is not supporting nesting.
Below is my script :
<?xml version="1.0" encoding="UTF-8"?>
<project name="ForTest" default="getLine" basedir="."
xmlns:ac="antlib:net.sf.antcontrib">
<taskdef uri="antlib:net.sf.antcontrib" resource="net/sf/antcontrib/antlib.xml"
classpath="C:\Manju\apache-ant-1.8.4\ant-contrib-1.0b3-bin\ant-contrib\ant-contrib-1.0b3.jar" />
<loadfile property="message" srcFile="build_params.csv" />
<target name="getLine">
<ac:for list="${message}" delimiter="${line.separator}" param="val">
<sequential>
<echo>#{val}</echo>
<property name="var1" value=#{val}/>
</sequential>
</ac:for>
</target>
<target name="parseLine" depends="getLine">
<for list=#{val} delimiter="," param="letter">
<sequential>
<echo>#{letter}</echo>
</sequential>
</for>
</target>
</project>
Target parseline is giving error saying for list is expecting open quotes. Help is appreciated.
Have you considered embedding a scripting language like groovy instead? Far simpler compared to fighting ant-contrib.
<project name="demo" default="run">
<target name="run">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/>
<groovy>
new File("build_params.csv").splitEachLine(",") { fields ->
println "===================="
println "field1: ${fields[0]}"
println "field2: ${fields[1]}"
println "field3: ${fields[2]}"
println "field4: ${fields[3]}"
println "field5: ${fields[4]}"
println "===================="
}
</groovy>
</target>
</project>
You can add a special bootstrap target to install the groovy jar automatically:
<target name="bootstrap">
<mkdir dir="${user.home}/.ant/lib"/>
<get dest="${user.home}/.ant/lib/groovy-all.jar" src="http://search.maven.org/remotecontent?filepath=org/code
haus/groovy/groovy-all/2.2.1/groovy-all-2.2.1.jar"/>
</target>
For one thing, your parseLine target should start like this:
<for list="#{val}" delimiter="," param="letter">
Note the quotes around #{val}.
My xml does not work:
When I run in command line
ant compile -Dmodules=a,b,c
My build file need to count how many modules in modules parameters, compile them one by one using for loop
<target name="count_modules">
<resourcecount property="count">
<tokens>
<concat>
<filterchain>
<tokenfilter>
<stringtokenizer delims=","/>
</tokenfilter>
</filterchain>
<propertyresource name="modules" />
</concat>
</tokens>
</resourcecount>
<echo message="count is ${count}" />
</target>
count will always return 1
[echo] count is 1
The propertyresource will return a single resource to the concat task which is designed to act on resources like files.
This complex piece of logic is best replaced by an in-line script.
<project name="myproject" default="count_modules">
<property name="modules" value="a,b,c"/>
<target name="count_modules">
<script language="javascript"><![CDATA[
modules = project.getProperty("modules");
project.setProperty("count", modules.split(",").length);
]]></script>
<echo message="Number of modules: ${count}"/>
</target>
</project>
Running sub-module builds
The for task is not part of core ant, it's part of an extension called ant-contrib. My advice is to use the subant task when invoking sub-module builds. The following answer has some simple and advanced examples of its use:
Ant Script to Automate the build process
I have an ant script to manage out build process. For WiX I need to produce a new guid when we produce a new version of the installer. Anyone have any idea how to do this in ANT? Any answer that uses built-in tasks would be preferable. But if I have to add another file, that's fine.
I'd use a scriptdef task to define simple javascript task that wraps the Java UUID class, something like this:
<scriptdef name="generateguid" language="javascript">
<attribute name="property" />
<![CDATA[
importClass( java.util.UUID );
project.setProperty( attributes.get( "property" ), UUID.randomUUID() );
]]>
</scriptdef>
<generateguid property="guid1" />
<echo message="${guid1}" />
Result:
[echo] 42dada5a-3c5d-4ace-9315-3df416b31084
If you have a reasonably up-to-date Ant install, this should work out of the box.
If you are using (or would like to use) groovy this will work nicely.
<project default="main" basedir=".">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"
classpath="lib/groovy-all-2.1.5.jar" />
<target name="main">
<groovy>
//generate uuid and place it in ants properties map
def myguid1 = UUID.randomUUID()
properties['guid1'] = myguid1
println "uuid " + properties['guid1']
</groovy>
<!--use the uuid from ant -->
<echo message="uuid ${guid1}" />
</target>
</project>
Output
Buildfile: C:\dev\anttest\build.xml
main:
[groovy] uuid d9b4a35e-4a75-454c-9f15-16b4b83bc6d0
[echo] uuid d9b4a35e-4a75-454c-9f15-16b4b83bc6d0
BUILD SUCCESSFUL
Using groovy 2.1.5 and ant 1.8
I have this dummy target:
<mkdir dir="${project.stage}/release
<war destfile="${project.stage}/release/sigma.war">
...
...
</war>
What I want to do is provide two parameters say "abc" & "xyz" which will replace the word release with the values of abc and xyz parameters respectively.
For the first parameter say abc="test", the code above will create a test directory and put the war inside it.Similarly for xyz="production" it will create a folder production and put the war file inside it.
I tried this by using
<antcall target="create.war">
<param name="test" value="${test.param.name}"/>
<param name="production" value="${prod.param.name}"/>
</antcall>
in the target which depends on the dummy target provided above.
Is this the right way to do this.I guess there must be some way to pass multiple parameters and then loop through the parameters one at a time.
unfortunately ant doesn't support iteration like for or foreach loops unless you are refering to files. There is however the ant contrib tasks which solve most if not all of your iteration problems.
You will have to install the .jar first by following the instructions here : http://ant-contrib.sourceforge.net/#install
This should take about 10 seconds. After you can simply use the foreach task to iterate through you custom list. As an example you can follow the below build.xml file :
<project name="test" default="build">
<!--Needed for antcontrib-->
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
<target name="build">
<property name="test" value="value_1"/>
<property name="production" value="value_2"/>
<!--Iterate through every token and call target with parameter dir-->
<foreach list="${test},${production}" param="dir" target="create.war"/>
</target>
<target name="create.war">
<echo message="My path is : ${dir}"/>
</target>
</project>
Output :
build:
create.war:
[echo] My path is : value_1
create.war:
[echo] My path is : value_2
BUILD SUCCESSFUL
Total time: 0 seconds
I hope it helps :)
Second solution without using ant contrib. You could encapsulate all your logic into a macrodef and simply call it twice. In any case you would need to write the two parameters at some point in your build file. I don't think there is any way to iterate through properties without using external .jars or BSF languages.
<project name="test" default="build">
<!--Needed for antcontrib-->
<macrodef name="build.war">
<attribute name="dir"/>
<attribute name="target"/>
<sequential>
<antcall target="#{target}">
<param name="path" value="#{dir}"/>
</antcall>
</sequential>
</macrodef>
<target name="build">
<property name="test" value="value_1"/>
<property name="production" value="value_2"/>
<build.war dir="${test}" target="create.war"/>
<build.war dir="${production}" target="create.war"/>
</target>
<target name="create.war">
<echo message="My path is : ${path}"/>
</target>
</project>
I admit that I don't understand the question in detail. Is ${project.stage} the same as the xyz and abc parameters? And why are there two parameters xyz and abc mentioned, when only the word "release" should be replaced?
What I know is, that macrodef (docu) is something very versatile and that it might be of good use here:
<project name="Foo" default="create.wars">
<macrodef name="createwar">
<attribute name="stage" />
<sequential>
<echo message="mkdir dir=#{stage}/release " />
<echo message="war destfile=#{stage}/release/sigma.war" />
</sequential>
</macrodef>
<target name="create.wars">
<createwar stage="test" />
<createwar stage="production" />
</target>
</project>
The output will be:
create.wars:
[echo] mkdir dir=test/release
[echo] war destfile=test/release/sigma.war
[echo] mkdir dir=production/release
[echo] war destfile=production/release/sigma.war
Perhaps we can start from here and adapt this example as required.
How can i overwrite some existing property with a newly created properties file?
Here is the required structure:
initially load Master.properties
generate new.properties
load new.properties and master.properties
run master.xml (ANT script)
The idea is that Master.properties generates some product version which should be replaced by new.properties. However, other properties in Master.properties should be kept the same.
Reading this does not help as i do not know how can i load the new.properties file
EDIT Here is ANT Script:
<project name="nightly_build" default="main" basedir="C:\Work\NightlyBuild">
<target name="init1">
<sequential>
<property file="C:/Work/NightlyBuild/master.properties"/>
<exec executable="C:/Work/Searchlatestversion.exe">
<arg line='"/SASE Lab Tools" "${Product_Tip}/RELEASE_"'/>
</exec>
<sleep seconds="10"/>
<property file="C:/Work/new.properties"/>
</sequential>
</target>
<target name="init" depends="init1">
<sequential>
<echo message="The product version is ${Product_Version}"/>
<exec executable="C:/Work/checksnapshot.exe">
<arg line='-NightlyBuild ${Product_Version}-AppsMerge' />
</exec>
<sleep seconds="10"/>
<property file="C:/Work/checksnapshot.properties"/>
<tstamp>
<format property="suffix" pattern="yyyy-MM-dd.HHmm"/>
</tstamp>
</sequential>
</target>
<target name="main" depends="init">
<echo message="loading properties files.." />
<echo message="Backing up folder" />
<move file="C:\NightlyBuild\NightlyBuild" tofile="C:\NightlyBuild\NightlyBuild.${suffix}" failonerror="false" />
<exec executable="C:/Work/sortfolder.exe">
<arg line="6" />
</exec>
<exec executable="C:/Work/NightlyBuild/antc.bat">
</exec>
</target>
</project>
in the above script, <exec executable="C:/Work/NightlyBuild/antc.bat"> will run Master.xml ANT script. This Master.xml will load up Master.properties:
<project name="Master ANT Build" default="main" >
<taskdef name="CFileEdit" classname="com.ANT_Tasks.CFileEdit"/>
<!-- ========================================================== -->
<!-- init: sets global properties -->
<!-- ========================================================== -->
<target name="init">
<property environment="env"/>
<!-- ========================================================== -->
<!-- Set the timestamp format -->
<!-- ========================================================== -->
<property file="Master.properties"/>
...
</project>
You should be able to resolve this by looking at the order in which you load (or otherwise specify) your property values. You probably don't need to override property values at all, which something not supported by core Ant.
Maybe you can split your Master.properties into two files - one loaded before you generate new.properties and one loaded after?
Maybe you don't need to generate new.properties at all.
Could you give some more detail on what you need to do?
Since you eventually fork a new Ant process (exec antc.bat), does that not start a fresh environment anyway? If it just loads Master.properties, those are the only properties it will have.
Not sure what your antc.bat does, but it's pretty unusual to exec Ant from Ant in this way. There are two standard tasks which might be useful - Ant and AntCall.
OK running on from your later comments...
Let's say that instead of doing this:
<exec executable="antc.bat">
you instead did something like this:
<ant file="Master.xml" inheritall="false">
<property name="Product_Version" value="${Product_Version}"/>
</ant>
I think that is getting towards what you want. You selectively pass specific values that you have obtained by loading new.properties. See the documentation for the Ant task.
If you still have the problem that you already defined Product_Version before loading new.properties, then I would say get the script you have that produces new.properties to output the version with a different name, e.g. New_Product_Version. Then invoke your master build something like this:
<ant file="Master.xml" inheritall="false">
<property name="Product_Version" value="${New_Product_Version}"/>
</ant>
May be this is a old question. Hopefully OP is reading this.
You can just use the ant task "propertyfile". reference
it can read properties from the file and write back updated values to them.