I am using the ant task <record> to create a log file of the output and activity of my ant build script. The problem is:
i am not seeing the names of the targets that are being executed.
For instance: When my target called cleanFW is being executed, i only see the stuff being done inside the target and NOT the name of the target it self. Since this is happening, i have no way of telling when cleanFW began in the log file.
Is there a way to get this cleanFW target name to appear? It was appearing when i was using the flag -logfile. But i had to switch to <record> because i want to record log file and see the output in console.
Using Ant 1.8.2
simple solution
My simple solution to this is to just put an echo in each one of the targets. Just wondering if there was a better way.
sample code where it is not working
<project name="foobar">
<record name="test.txt" action="start" append="true" loglevel="verbose" />
... lots of property stuff here ...
<target name="cleanFW">
<record name="test.txtaction="start" append="true" loglevel="verbose"/>
<mkdir dir="${FOOBAR_OUTPUT}"/>
<mkdir dir="${FOOBAR_GEN}"/>
<delete includeemptydirs="true">
<fileset dir="${FOOBAR_BIN}" includes="**/*"/>
<fileset dir="${FOOBAR_GENERATED}" includes="**/*"/>
<fileset dir="${FOOBAR_NODES}" includes="**/*"/>
<fileset dir="${FOOBAR_GEN}" includes="**/*"/>
</delete>
<mkdir dir="${FOOBAR_OUTPUT}"/>
<record name="test.txt" action="stop"/>
</target>
<record name="test.txt" action="stop"/>
</project>
The reason why i have the first record name="test.txt" action="start" append="true" loglevel="verbose" /> at the top, is because i want all of the statements and stuff that are before the targets to be displayed too. Like my property sets and all that jazz. I left that junk out because it is not important.
I'm at a bit of a loss to explain why exactly, but I think you need to omit the last record 'stop' task - the one that is outside of a target.
Having said that, you can probably omit all of the record tasks except the first 'start', and get the result you want.
Related
I am new to ANT.
I have a very specific scenario to handle in this:
STEP-1: I need to look for the pattern of filenames in certain ear files. If the pattern matches then I need to extract those files.
STEP-2: And if any file is extracted from a certain ear (similar to zip-file) file, then I need to search for another set of files, and copy those set of files too.
The case to handle is "How to identify if a file is copied from a particular archive" if found then proceed to step 2, else move to next archive.
I have achieved STEP-1 but no idea how to achieve step-2.
STEP-1
<!-- Set via arguments passed -->
<patternset id="pattern.needtocopy" includes="${needtocopyfile.pattern}" excludes="${ignore.pattern}">
</patternset>
<target name="get-binaries-from-baseline">
<for param="binary">
<path>
<fileset dir="${baseline.dir}/target/aaa/bbb/ccc" includes="*.ear" />
</path>
<sequential>
<basename file="#{binary}" property="#{binary}.basename" />
<unzip src="#{binary}" dest="${baseline.dir}">
<patternset refid="pattern.needtocopy" />
<mapper type="flatten" />
</unzip>
</sequential>
</for>
</target>
STEP-2:
????
Need help in this.
Thanks.
Well I resolved the same, using a groovy script based on the resources I could find.
<target name="findJars">
<zipfileset id="found" src="${ear-name}">
<patternset refid="${patternsetref}" />
</zipfileset>
<groovy>
project.references.found.each {
println it.name
println project.properties.'ear-name'
println project.properties.'dest.dir'
}
</groovy>
</target>
And then I added another task which takes this filename and ear-file-name as input and extracts the related jars based on file to search pattern.
To explain it briefly, here is an example:
In build.xml, local-db.xml is imported. And in local-db.xml, there is a target named "warmup" which calls one target of the third file -- local-gr.xml using task.
All the common properties and classpath defs are imported and set in build.xml.
in project.properties:
dest-dir=./destination
in build.xml:
<path id="gr-classpath"> ... </path>
<import file="local-db.xml" />
in local-db.xml:
<ant antfile="local-gr.xml" target="deploy" inheritAll="true" inheritRefs="true" />
In local-gr.xml, there are two targets like this:
<target name="deploy">
<tar ....../>
<foreach list="${list1}" delimiter="," parallel="true" trim="true" param="item" target="deploy-single" />
</target>
<target name="deploy-single">
something using property ${dest-dir} and path "gr-classpath"
</target>
Now here is the problem:
The property ${dest-dir} and path "gr-classpath" can be used in "deploy" because I set inheritAll and inheritRefs, but it can't be used directly in "deploy-single". "inherit" doesn't when the target is called by foreach?
I managed to pass ${dest-dir} to "deploy-single" with the help of the , but I didn't find any way to pass the classpathref "gr-classpath" to "deploy-single".
What I did to work around it was to claim the again in "deploy-single", but I don't like it at all.
Why this happens? What can I do to make it more elegant?
The ant-contrib foreach task doesn't by default propagate all properties and references to it's target. But it does have inheritall and inheritrefs attributes that you can use to make that happen.
<foreach list="${list1}" delimiter="," parallel="true" trim="true"
param="item" target="deploy-single"
inheritall="true" inheritrefs="true"
/>
I want to use manifestclasspath Ant task. I have a very large build.xml file with a couple of imported other build files and when I run it I get this:
build.xml:1289: The following error occurred while executing this line:
build.xml:165: Property 'some.property' already set!
I am sure that this property is defined only in manifestclasspath task. Here is my code:
<manifestclasspath property="some.property" jarfile="some.jar">
<classpath refid="some.classpath"/>
</manifestclasspath>
This code is located inside of <project>.
What am I doing wrong? Is there a way to add something like condition to set property only if it is not already set? I don't want to use custom Ant tasks such as Ant Contrib's if if there is other way around.
Antcall opens a new project scope, but by default, all of the properties of the current project will be available in the new project. Also if you used something like =
<antcall target="whatever">
<param name="some.property" value="somevalue"/>
</antcall>
in the calling project then ${some.property} is also already set and won't be overwritten, as properties once set are immutable in ant by design.
Alternatively, you may set the inheritAll attribute to false and only "user" properties (those passed on the command-line with -Dproperty=value) will be passed to the new project.
So, when ${some.property} ain't no user property, then use inheritAll="false" and you're done.
btw. it's better to use a dependency between targets via depends="..." attribute than to use antcall, because it opens a new project scope and properties set in the new project won't get back to the calling target because it lives in another project scope..
Following a snippet, note the difference, first without inheritAll attribute
<project default="foo">
<target name="foo">
<property name="name" value="value1" />
<antcall target="bar"/>
</target>
<target name="bar">
<property name="name" value="value2" />
<echo>$${name} = ${name}</echo>
</target>
</project>
output :
[echo] ${name} = value1
second with inheritAll=false
<project default="foo">
<target name="foo">
<property name="name" value="value1" />
<antcall target="bar" inheritAll="false" />
</target>
<target name="bar">
<property name="name" value="value2" />
<echo>$${name} = ${name}</echo>
</target>
</project>
output :
[echo] ${name} = value2
some rules of thumb for antcall, it's rarely used for good reasons :
1. it opens a new project scope (starting a new 'ant -buildfile yourfile.xml yourtarget') so it uses more memory, slowing down your build
2. depending targets of the called target will be called also !
3. properties don't get passed back to the calling target
In some cases it might be ok when calling the same 'standalone' target (a target that has no target it depends on) with different params for reuse. Normally macrodef or scriptdef are used for that purpose. So, think twice before using antcall which also puts superfluous complexity to your scripts, because it works against the normal flow.
Answer to your question in the comment, using a dependency graph instead of antcall
you have some target that holds all conditions and sets the appropriate properties which may be evaluated by targets via if and unless attributes to control the further flow
<project default="main">
<target name="some.target">
<echo>starting..</echo>
</target>
<!-- checking requirements.. -->
<target name="this.target">
<condition property="windowsbuild">
<os family="windows"/>
</condition>
<condition property="windowsbuild">
<os family="unix"/>
</condition>
<!-- ... -->
</target>
<!-- alternatively
<target name="yet.another.target" depends="this.target" if="unixbuild">
-->
<target name="another.target" depends="this.target" unless="windowsbuild">
<!-- your unixspecific stuff goes here .. -->
</target>
<!-- alternatively
<target name="yet.another.target" depends="this.target" if="windowsbuild">
-->
<target name="yet.another.target" depends="this.target" unless="unixbuild">
<!-- your windowspecific stuff goes here .. -->
</target>
I'm rather new to Ant but I have experienced it's quite good pattern to create generic ant targets which are to be called with antcall task with varying parameters.
My example is compile target, which compiles multiple systems using complex build command which is a bit different for each system. By using pattern described above it's possible not to create copy paste code for that compile command.
My problem here is, that I'm not aware of any way to pass return value (for example the return value of compiler) back to target which called the antcall task. So is my approach pathological and it's simply not possible to return value from antcall task or do you know any workaround?
Thanks,
Use antcallback from the ant-contrib jar instead of antcall
<target name="testCallback">
<antcallback target="capitalize2" return="myKey">
</antcallback>
<echo>a = ${myKey}</echo>
</target>
<target name="capitalize2">
<property name="myKey" value="it works"/>
</target>
Output:
testCallback:
capitalize2:
[echo] a = it works
BUILD SUCCESSFUL
One approach is to write out a property to a temp file using "echo file= ...." or PropertyFile task. Then read the property back in where required. Kludge but works.
Ant tasks are all about stuff goes in, side effect happens. So trying to program in terms of functions (stuff goes in, stuff comes out) is going to be messy.
That said what you can do is generate a property name per invocation and store the result value in that property. You would need to pass in a indentifier so you do not end up trying to create copies of the same property. Something like this:
<target name="default">
<property name="key" value="world"/>
<antcall target="doSomethingElse">
<param name="param1" value="${key}"/>
</antcall>
<echo>${result-${key}}</echo>
</target>
<target name="doSomethingElse">
<property name="hello-${param1}" value="it works?"/>
</target>
But I believe the more typical approach -instead of antcalls- is to use macros. http://ant.apache.org/manual/Tasks/macrodef.html
Antcall can be used from the ant-contrib jar task.
You can get a similar behaviour with the keyword "depends".
<?xml version="1.0" encoding="UTF-8"?>
<project name="test" default="main">
<target name="main">
<antcall target="build-system-with-depends" />
<!-- wait for different results -->
<waitfor checkevery="1000" checkeveryunit="millisecond" maxwaitunit="millisecond" maxwait="2000">
<available file="dummy.not.present.file" classname="" property=""></available>
</waitfor>
<antcall target="build-system-with-depends" />
</target>
<target name="build-system-with-depends" depends="do-compiler-stuff">
<echo>$${compiler.result}=${compiler.result}</echo>
</target>
<target name="do-compiler-stuff">
<!-- simulate different return states -->
<tstamp>
<format pattern="yyyyMMddHHmmss" property="compiler.result" />
</tstamp>
</target>
</project>
It sounds a little far fetched to me, but is there an ANT task for watching a directory for changes and then running a particular ANT class when the directory changes?
If files can only be added to or changed in the watched directory, then you can use this simple OutOfDate task from antcontrib.
<property name="watched-dir.flagfile"
location="MUST be not in watched dir"/>
<outofdate>
<sourcefiles>
<fileset dir="watched-dir"/>
</sourcefiles>
<targetfiles>
<pathelement location="${watched-dir.flagfile}"/>
</targetfiles>
<sequential>
<!--Tasks when something changes go here-->
<touch file="${watched-dir.flagfile}"/>
</sequential>
</outofdate>
If files can disappear from the watched-dir, then you have more complicated problem, that you can solve by creating shadow directory structure of the watched dir and checking if its consistent with the watched-dir. This task is more complex, but I'll give you a script to create a shadow directory, as it is not straight forward:
<property name="TALK" value="true"/>
<property name="shadow-dir"
location="MUST be not in watched dir"/>
<touch
mkdirs="true"
verbose="${TALK}"
>
<fileset dir="watched-dir">
<patterns/>
<type type="file"/>
</fileset>
<!-- That's the tricky globmapper to make touch task work -->
<globmapper from="*" to="${shadow-dir}/*"/>
</touch>
<!--
Due to how touch task with mapped fileset is implemented, it
truncates file access times down to a milliseconds, so if you
would have used outofdate task on shadow dir it would always
show that something is out of date.
Because of that, touching all files in ${shadow-dir} again fixes
that chicken and egg problem.
-->
<touch verbose="${TALK}">
<fileset dir="${shadow-dir}"/>
</touch>
With shadow directory created, I'll leave the task of checking directory consistency as an exercise for the reader.
Yes there is an Ant Task that will do this:
https://github.com/chubbard/WatchTask
It requires 1.7+. It can watch any number of filesets, and invoke any target depending on which fileset it came from.
You might be able to use the Waitfor task to achieve what you want. It blocks until one or more conditions (such as the presence of a particular file) become true.
You can combine the apply task with a fileset selector
<apply executable="somecommand" parallel="false">
<srcfile/>
<fileset dir="${watch.dir}">
<modified/>
</fileset>
</apply>
The fileset will check the files against a stored MD5 checksum for changes. You'll need to put ANT into a loop in order to repeatedly run this check. this is easy to do in Unix:
while true
> do
> ant
> sleep 300
> done