ant diagnostics to a sepate file? - ant

can we print ant diagnostics result to separate file?
I am using,
<target name="diagnostics" description="diagnostics" >
<diagnostics/>
</target>
It is printing in the console.

The only way I can figure to do it is to call the target from inside an task in another target and have it dump the output into a text file.
<project name="help" default="help">
<target name="diagnostics">
<diagnostics/>
</target>
<target name="help">
<ant output="diag.txt" target="diagnostics"/>
</target>
</project>

Related

If there is no properties file declared, what does the $ do in an Ant build file?

Essentially, I am wondering how ant knows that $ means to pull from the properties file.. what if there was no properties file named?
Take example this build file
<?xml version="1.0" encoding="UTF-8"?>
<project name="Hello World Project" default="info">
<property file="build.properties"/>
<fileset dir="${build.dir}" >
<include name="**/*.java"/>
</fileset>
<target name="info">
<echo>${src}</echo>
</target>
</project>
I know that the $ sign is referencing a property in the build.properties file, however what if there is no properties file, what does the $ sign do in a regular Ant compilation?
Ant leaves references to non-existent properties unchanged. For example, the following Ant script...
<project name="ant-echo-missing-property" default="run">
<target name="run">
<property file="non-existent-file.properties"/>
<echo>${missing-property}</echo>
</target>
</project>
...outputs...
run:
[echo] ${missing-property}

How to execute Ant build in command line

I have an Ant build file, and I try to execute it in the command line with the following command:
$ C:\Program Files (x86)\.....>ant -f C:\Silk4J\Automation\iControlSilk4J\build.xml
But nothing happens, and the result is:
BUILD SUCCESSFUL
Total time: 0 seconds
My environment variable is correct.
What is the problem? Here is my build file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- WARNING: Eclipse auto-generated file.
Any modifications will be overwritten.
To include a user specific buildfile here, simply create one in the same
directory with the processing instruction <?eclipse.ant.import?>
as the first entry and export the buildfile again. -->
<project basedir="." default="build" name="iControlSilk4J">
<property environment="env"/>
<property name="ECLIPSE_HOME" value="../../../Program Files (x86)/Silk/SilkTest/eclipse"/>
<property name="junit.output.dir" value="junit"/>
<property name="debuglevel" value="source,lines,vars"/>
<property name="target" value="1.6"/>
<property name="source" value="1.6"/>
<path id="Silk Test JTF 13.5.0 Library.libraryclasspath">
<pathelement location="../../../Program Files (x86)/Silk/SilkTest/ng/JTF/silktest-jtf-nodeps.jar"/>
</path>
<path id="JUnit 4.libraryclasspath">
<pathelement location="${ECLIPSE_HOME}/plugins/org.junit_4.8.2.v4_8_2_v20110321-1705/junit.jar"/>
<pathelement location="${ECLIPSE_HOME}/plugins/org.hamcrest.core_1.1.0.v20090501071000.jar"/>
</path>
<path id="iControlSilk4J.classpath">
<pathelement location="bin"/>
<pathelement location="lib/apache-log4j.jar"/>
<pathelement location="lib/commons-io-2.4.jar"/>
<pathelement location="lib/commons-lang3-3.1.jar"/>
<pathelement location="lib/junit.jar"/>
<pathelement location="lib/org.hamcrest.core_1.1.0.v20090501071000.jar"/>
<pathelement location="lib/silktest-jtf-nodeps.jar"/>
<path refid="Silk Test JTF 13.5.0 Library.libraryclasspath"/>
<path refid="JUnit 4.libraryclasspath"/>
<pathelement location="../../../Users/Admin/Desktop/java-mail-1.4.4.jar"/>
<pathelement location="../../../Users/Admin/Desktop/javax.activation.jar"/>
<pathelement location="lib/joda-time-2.3.jar"/>
</path>
<target name="init">
<mkdir dir="bin"/>
<copy includeemptydirs="false" todir="bin">
<fileset dir="src">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
<target name="clean">
<delete dir="bin"/>
</target>
<target depends="clean" name="cleanall"/>
<target depends="build-subprojects,build-project" name="build"/>
<target name="build-subprojects"/>
<target depends="init" name="build-project">
<echo message="${ant.project.name}: ${ant.file}"/>
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" source="${source}" target="${target}">
<src path="src"/>
<classpath refid="iControlSilk4J.classpath"/>
</javac>
</target>
<target description="Build all projects which reference this project. Useful to propagate changes." name="build-refprojects"/>
<target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler">
<copy todir="${ant.library.dir}">
<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
</copy>
<unzip dest="${ant.library.dir}">
<patternset includes="jdtCompilerAdapter.jar"/>
<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
</unzip>
</target>
<target description="compile project with Eclipse compiler" name="build-eclipse-compiler">
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
<antcall target="build"/>
...
Go to the Ant website and download. This way, you have a copy of Ant outside of Eclipse. I recommend to put it under the C:\ant directory. This way, it doesn't have any spaces in the directory names. In your System Control Panel, set the Environment Variable ANT_HOME to this directory, then pre-pend to the System PATHvariable, %ANT_HOME%\bin. This way, you don't have to put in the whole directory name.
Assuming you did the above, try this:
C:\> cd \Silk4J\Automation\iControlSilk4J
C:\Silk4J\Automation\iControlSilk4J> ant -d build
This will do several things:
It will eliminate the possibility that the problem is with Eclipe's version of Ant.
It is way easier to type
Since you're executing the build.xml in the directory where it exists, you don't end up with the possibility that your Ant build can't locate a particular directory.
The -d will print out a lot of output, so you might want to capture it, or set your terminal buffer to something like 99999, and run cls first to clear out the buffer. This way, you'll capture all of the output from the beginning in the terminal buffer.
Let's see how Ant should be executing. You didn't specify any targets to execute, so Ant should be taking the default build target. Here it is:
<target depends="build-subprojects,build-project" name="build"/>
The build target does nothing itself. However, it depends upon two other targets, so these will be called first:
The first target is build-subprojects:
<target name="build-subprojects"/>
This does nothing at all. It doesn't even have a dependency.
The next target specified is build-project does have code:
<target depends="init" name="build-project">
This target does contain tasks, and some dependent targets. Before build-project executes, it will first run the init target:
<target name="init">
<mkdir dir="bin"/>
<copy includeemptydirs="false" todir="bin">
<fileset dir="src">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
This target creates a directory called bin, then copies all files under the src tree with the suffix *.java over to the bin directory. The includeemptydirs mean that directories without non-java code will not be created.
Ant uses a scheme to do minimal work. For example, if the bin directory is created, the <mkdir/> task is not executed. Also, if a file was previously copied, or there are no non-Java files in your src directory tree, the <copy/> task won't run. However, the init target will still be executed.
Next, we go back to our previous build-project target:
<target depends="init" name="build-project">
<echo message="${ant.project.name}: ${ant.file}"/>
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" source="${source}" target="${target}">
<src path="src"/>
<classpath refid="iControlSilk4J.classpath"/>
</javac>
</target>
Look at this line:
<echo message="${ant.project.name}: ${ant.file}"/>
That should have always executed. Did your output print:
[echo] iControlSilk4J: C:\Silk4J\Automation\iControlSilk4J\build.xml
Maybe you didn't realize that was from your build.
After that, it runs the <javac/> task. That is, if there's any files to actually compile. Again, Ant tries to avoid work it doesn't have to do. If all of the *.java files have previously been compiled, the <javac/> task won't execute.
And, that's the end of the build. Your build might not have done anything simply because there was nothing to do. You can try running the clean task, and then build:
C:\Silk4J\Automation\iControlSilk4J> ant -d clean build
However, Ant usually prints the target being executed. You should have seen this:
init:
build-subprojects:
build-projects:
[echo] iControlSilk4J: C:\Silk4J\Automation\iControlSilk4J\build.xml
build:
Build Successful
Note that the targets are all printed out in order they're executed, and the tasks are printed out as they are executed. However, if there's nothing to compile, or nothing to copy, then you won't see these tasks being executed. Does this look like your output? If so, it could be there's nothing to do.
If the bin directory already exists, <mkdir/> isn't going to execute.
If there are no non-Java files in src, or they have already been copied into bin, the <copy/> task won't execute.
If there are no Java file in your src directory, or they have already been compiled, the <java/> task won't run.
If you look at the output from the -d debug, you'll see Ant looking at a task, then explaining why a particular task wasn't executed. Plus, the debug option will explain how Ant decides what tasks to execute.
See if that helps.
Try running all targets individually to check that all are running correct
run ant target name to run a target individually
e.g. ant build-project
Also the default target you specified is
project basedir="." default="build" name="iControlSilk4J"
This will only execute build-subprojects,build-project and init
is it still actual?
As I can see you wrote <target depends="build-subprojects,build-project" name="build"/>, then you wrote <target name="build-subprojects"/> (it does nothing). Could it be a reason?
Does this <echo message="${ant.project.name}: ${ant.file}"/> print appropriate message? If no then target is not running.
Take a look at the next link http://www.sqaforums.com/showflat.php?Number=623277

Ant build script not seeing refid

I have a build.xml file that includes a common.xml file that defines some refid values. However, my task cannot see the refid value. I have not been able to find a solution on the web and am looking for some help.
I call the genbeans target in the build.xml file. It fails on the xmlbean taskdef with the message Reference my_classpath_jars not found.
build.xml
----------------------------
[includes common.xml]
**my_classpath_jars fails to be seen at this point - defined in common.xml**
<taskdef name="xmlbean" classname="org.apache.xmlbeans.impl.tool.XMLBean">
<classpath refid="my_classpath_jars"/>
</taskdef>
<!-- Generate the XMLBeans java code from our source XSD file(s) -->
<target name="genbeans" description="Generate XML Bean files" depends="build_my_jar_cpath">
<mkdir dir="${lib}"/>
<xmlbean destfile="${lib}/${appname}Beans.jar" failonerror="true">
<classpath refid="my_classpath_jars"/>
<fileset dir="src/XSD Files" includes="*.xsd, *.wsdl"/>
</xmlbean>
</target>
common.xml
-----------------------------
<target name="build_my_jar_cpath">
<path id="my_classpath_jars">
<fileset dir="${jardir}" includes="**/*.jar" />
</path>
<pathconvert pathsep="${path.separator}" property="myjar.clpath" refid="my_classpath_jars"/>
</target>
When in doubt, use the ant -d switch when calling your target. You'll see a ton of output. Save it to a file and parse through it.
Do that, and the first thing you'll notice in the output is that it's defining your taskdefbefore you have defined your my_classpath_jars. That my_classpath_jars refid is only set when you call that greenbeans target. Your <taskdef> is executed before any of your targets are called.
Either take the definition of my_classpath_jars out of the target greenbeans, or put your <taskdef> in there.

build multiple projects and clean multiple projects in a single build file with ANT

I have a doubt, I made this build file in order to build 3 different projects
<?xml version="1.0" encoding="UTF-8"?>
<project name="Trinity" basedir="." default="buildall">
<target name="project1">
<ant dir="C:/work/project1"/>
</target>
<target name="project2" depends="project1">
<ant dir="C:/work/project2"/>
</target>
<target name="project3" depends="project1, project2">
<ant dir="C:/work/project3"/>
</target>
<target name="buildall" depends="project3"/>
</project>
This is working now. But I wan to also clean the project before doing the build.
In fact I want to acomplish this:
C:/work/project1 ant clean build
C:/work/project2 ant clean build
C:/work/project3 ant clean build
Thanks in advance.
update: Thanks to the quick response from Alex I did a new build.xml file with the following. And I believe is working well, what do you think?.
<?xml version="1.0" encoding="UTF-8"?>
<project name="Trinity" basedir="." default="buildall">
<target name="project1">
<ant dir="C:/work/project1" target="clean"/>
<ant dir="C:/work/project1" target="build"/>
</target>
<target name="project2" depends="project1">
<ant dir="C:/work/project2" target="clean"/>
<ant dir="C:/work/project2" target="build"/>
</target>
<target name="project3" depends="project1, project2">
<ant dir="C:/work/project3" target="clean"/>
<ant dir="C:/work/project3" target="build"/>
</target>
<target name="buildall" depends="project3"/>
</project>
Thanks.
According to the ant task, you can specify the targets of the external ant build files
<ant dir="C:/work/project1" target="clean build">
Edit:
According to the ant documentation:
You can specify multiple targets using nested elements instead of using the target attribute. These will be executed as if Ant had been invoked with a single target whose dependencies are the targets so specified, in the order specified.
So you can list out multiple targets this way:
<ant dir="C:/work/project1">
<target name="clean" />
<target name="build" />
</ant>
Alternatively you can define a new target in the Project1,2,3 build.xml files called cleanBuild which will in turn call clean followed by build if you want to keep it as a single xml element <ant dir="C:/work/project1" target="cleanBuild">

How do I pass an argument to an Ant task?

I'm not very good with Ant, but we're using it as a build tool. Right now, we can run "ant test" and it'll run through all the unit tests.
However, I'd love to be able to do something like ant test some_module and have it accept some_module as a parameter, and only test that.
I haven't been able to find how to pass command line args to Ant - any ideas?
One solution might be as follows. (I have a project that does this.)
Have a separate target similar to test with a fileset that restricts the test to one class only. Then pass the name of that class using -D at the ant command line:
ant -Dtest.module=MyClassUnderTest single_test
In the build.xml (highly reduced):
<target name="single_test" depends="compile" description="Run one unit test">
<junit>
<batchtest>
<fileset dir="${test.dir}" includes="**/${test.module}.class" />
</batchtest>
</junit>
</target>
You can also define a property with an optional default value that can be replaced via command line, e.g.
<target name="test">
<property name="moduleName" value="default-module" />
<echo message="Testing Module: ${moduleName}"/>
....
</target>
and run it as:
ant test -DmoduleName=ModuleX
What about using some conditional in your test target and the specifying -Dcondition=true?
<target name="test" depends="_test, _test_if_true>
...
</target>
<target name="_test_if_true" if="condition">
...
</target>
<target name="_test" unless="condition">
...
</target>
Adapted a bit from the ant faq.
You can define a property on commandline when invoking ant:
ant -Dtest.module=mymodulename
Then you can use it as any other ant property:
...
<fileset dir="${test.dir}" includes="**/${test.module}.class" />
...
Have a look at Ant's manual.
I tried the solutions posted here for the very same original question. Yes just use ant -D<arg_name>. THe -D is a "keyword" I guess. I'm no ant expert and have not read the manuals in detail. Then inside the ant XML files can be accessed like: ${arg_name}
For instance you can have an argument name like: arg.myarg, so in XML ${arg.myarg}.
Ant really doesn't have parameters_ for the build file. I can think of a few ways to do this:
Use a special target to specify the tests. You can use the <for/> task from AntContrib to allow you to specify multiple tests. You'll need to download the Ant-Contrib jar file. I recommend placing it inside your project under the `${basedir}/antlib/antcontrib" directory. That way, when others checkout your project, they get the needed Ant-Contrib jar file.
<property name="antlib.dir" value="${basedir}/antlib"/>
<property name="antcontrib.dir" value="${antlib}/antcontrib"/>
<!-- Set up the ant contrib tasks for your use -->
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<fileset dir="${antcontrib.dir}"/>
</classpath>
</taskdef>
<target name="select-test"
description="Select the tests to run"
depends="test-compile"
if="junit-tests">
<for parameter="module"
list="${junit-tests}"
delimiter=" ">
<sequential>
<junit
fork="true"
...>
<batchtest todir="$target/unit-tests">
<fileset dir="${test.destdir}">
<include name="**/#{module}.class"/>
</fileset>
</junit>
</sequential>
</for>
</target>
You cab now run multiple tests like this:
$ ant -D"test-one test-two test-three" select-test
You could try this to access one target at a time. Add these lines to your build.xml file :
<project name="whatever" default="default">
<input message="Please select module:" addproperty="mod" />
<target name="default" depends="${mod}/>
...
</project>
This allows you to enter the module you want to execute and execute that itself instead of running the whole build.xml
You might need to make a few more changes to your build.xml for this to work perfectly.
For the arguments , there is Facility called property. You need to set the property. As in ANT plain arguments is taken as target name.
Lest say you have two modules in your project ModuleX and ModuleY where ModuleX has 2 testcases to run and ModuleY with 10 testcases.
You could do something like this :
ant runTestsOnModule -Dtestmodule="ModuleX"
OR to test all modules by calling
ant tests
<target name="runTestsOnModule">
<antCall target="testcase${testmodule}"/>
</target>'
<! -- run single module -->
<target name="runTestsOnModule">
<antCall target="testcase${testmodule}"/>
</target>
<!--run all tests-->
<target name="tests">
<antcall target="testcaseModuleX">
<antcall target="testCaseModuleY">
</target>
<target name="testcaseModuleX">
..run junit task to call 2 testcase
</target>
<target name="testcaseModuleY">
....run junit task to call 10 testcase
</target>

Resources