can we pass command line argument to ant target - ant

How can we pass command line argument to ant target
for example I have target in build.xml defined as below
<target name="test">
<echo>Hello,</echo>
</target>
if I invoke ant as
cmd>ant -buildfile build.xml test USERNAME
It should print echo as "Hello, USERNAME"
is it possible some way?
Thanks in advance for help

ant -buildfile build.xml test USERNAME would mean run the two targets, test and USERNAME (see Ant manual).
Instead, do ant -buildfile build.xml -Dname=USERNAME test and
<target name="test">
<echo>Hello, ${name}</echo>
</target>

Related

Tags between <echo> and </echo> in ant

I have an Ant script like this:
<target name="create_report_file">
<echo file="${testResultsDir}/test_report.xml">
<testsuite name="${platformTask}">
</testsuite>
</echo>
</target>
What do the tags between <echo> and </echo> mean? Will Ant run them or output? Or both?
file is an echo parameter. It's the file to write the message to.
testsuite is possibly a JUnit task.
The Ant target runs the test suite and outputs the results to the test_report.xml file.
Does your Ant script work? What about if it attempts to execute the create_report_file target?
Usually, echo tasks simply echo the contents to either the console or to a file if the file parameter is specified.
However, as written, it makes <testsuite> is a sub-entity of the <echo/> task, and it's not. In fact, there's no documented sub-entities in the <echo/> task. In fact, <echo> doesn't even take <condition/> sub-entity tasks like <fail/> would.
This is why I'm asking whether or not your build file is even working.
It appears they might want to log the testsuite being executed. There are two ways to do this to make this work:
Change all < and > to character entities:
<target name="create_report_file">
<echo file="${testResultsDir}/test_report.xml">
<testsuite name="${platformTask}">
</testsuite>
</echo>
</target>
Use <echoxml> instead of <echo>:
<target name="create_report_file">
<echoxml file="${testResultsDir}/test_report.xml">
<testsuite name="${platformTask}">
</testsuite>
</echoxml>
</target>
Another possibility
It is possible that you're using some Ant plugin that has a <testsuite> task. I don't know what this would be. The <testsuite> task isn't part of JUnit or TestNG. However, if there is an Ant plugin being used that defines a <testsuite> task, it might redefine the <echo> task which it's at it. Does your build script have a <taskdef> in it? If so, what's the class reference?
It could be that the user defines their own <testsuite> macro in your build script. However, that wouldn't redefine the <echo> task and it still wouldn't work.

Ant handle Target not found

I have created an ant project which has some targets inside. One target is called info, which displays all available targets. This target is set as the default:
<project name="XXX" basedir="." default="info">
Now I want this target to be called in case of target not found:
Target "infp" does not exist in the project "XXX"
I need this in case the user calls a target that doesn't exist. Then I want the info to be displayed, so that he sees all the available options.
Thanks
ANT does not support this functionality. The "default" target is called if no target is specified on the command line.
Instead I would suggest making your build self describing and teaching your users about ANT
's -p option.
Example
The following build file:
<project name="demo" default="welcome">
<description>
The purpose of this build file is to explain how one
can make an ANT file self describing
</description>
<target name="welcome" description="Print a hello world message">
<echo message="hello world"/>
</target>
<target name="do-somthing" description="Print a dummy message">
<echo message="hello world"/>
</target>
<target name="do-somthing-silent">
<echo message="hello world"/>
</target>
</project>
Can describe itself as follows:
$ ant -p
Buildfile: /home/mark/build.xml
The purpose of this build file is to explain how one
can make an ANT file self describing
Main targets:
do-somthing Print a dummy message
welcome Print a hello world message
Default target: welcome

'make -n' equivalent for ant

According to the man page of make, -n option does the following job:
Print the commands that would be executed, but do not execute them.
I am looking for an option which acts the same in Apache Ant.
Horrific, but here it is. We can hack the targets at runtime using some code inside a <script> tag*. The code in do-dry-run below sets an unless attribute on each of your targets, and then sets that property so that none of them executes. Ant still prints out the names of targets that are not executed because of an unless attribute.
*(JavaScript script tags seem to be supported in Ant 1.8+ using the Oracle, OpenJDK and IBM versions of Java.)
<?xml version="1.0" encoding="UTF-8"?>
<project default="build">
<target name="targetA"/>
<target name="targetB" depends="targetA">
<echo message="DON'T RUN ME"/>
</target>
<target name="targetC" depends="targetB"/>
<target name="build" depends="targetB"/>
<target name="dry-run">
<do-dry-run target="build"/>
</target>
<macrodef name="do-dry-run">
<attribute name="target"/>
<sequential>
<script language="javascript"><![CDATA[
var targs = project.getTargets().elements();
while( targs.hasMoreElements() ) {
var targ = targs.nextElement();
targ.setUnless( "DRY.RUN" );
}
project.setProperty( "DRY.RUN", "1" );
project.executeTarget( "#{target}" );
]]></script>
</sequential>
</macrodef>
</project>
When I run this normally, the echo happens:
$ ant
Buildfile: build.xml
targetA:
targetB:
[echo] DON'T RUN ME
build:
BUILD SUCCESSFUL
Total time: 0 seconds
But when I run dry-run, it doesn't:
$ ant dry-run
Buildfile: build.xml
dry-run:
targetA:
targetB:
build:
BUILD SUCCESSFUL
Total time: 0 seconds
Ant has no dry-run option as make or maven have. But you could run the ant file step by step it in debugging mode under eclipse.
No I belive. There is no such way by default in Ant. And many unstisfying attempts you would find on google. But I have searched once and was unsuccessful.
It would be a useful feature, but not easily implemented.
Make and ANT are architecturally quite different. ANT doesn't run external OS commands, instead, most ANT "tasks" execute within the same Java thread.
It would be possible to emulate a "dry run" as follows:
<project name="Dry run" default="step3">
<target name="step1" unless="dry.run">
<echo>1) hello world</echo>
</target>
<target name="step2" depends="step1" unless="dry.run">
<echo>2) hello world</echo>
</target>
<target name="step3" depends="step2" unless="dry.run">
<echo>3) hello world</echo>
</target>
</project>
Running ANT as follows will print the target name but won't execute the enclosed tasks:
$ ant -Ddry.run=1
Buildfile: build.xml
step1:
step2:
step3:
BUILD SUCCESSFUL
Total time: 0 seconds
Create a special target in your buildscript that does some echoing only i.e. to check whether properties, path .. are resolved correctly.
see https://stackoverflow.com/a/6724412/130683 for a similar question answered.
For checking the details of your ant installation use ant -diagnostics

How can I run all the targets in an Ant buildfile?

I would like to execute all targets instead of specifying each one.
For example:
<?xml version="1.0"?>
<project name="Kte" default="all" basedir="/home/Kte">
<target name="target1">
</target>
<target name="target2">
</target>
</project>
Currently I have use:
$ ant target1
$ ant target2
I'd like to use:
$ ant
and have both targets get built (this is just an example. Reality I have a long ever changing Ant buildfile with sub-ant files so would be very handy to have an "all" feature.
You could create an ant task all, which depends on all the specific targets that you have...
<target name="all" depends="target1, target2, ... ">
</target>
ant all
You can also set up a default task that will run when you just type ant. The default attribute is in the project element.
<project name="foo" default="all">
<target name="all" depends="target1, target2"/>
<target name="target1">
...
</target>
<target name="target2">
...
</target>
</project>
$ ant
Because Ant is declarative it doesn't do this sort of thing nicely. You might consider a script task though.
Ant buildfiles have an implicit un-named target that 'holds' all the tasks that are not part of named targets. So this, placed at the top-level, would do what you describe.
<script language="javascript"><![CDATA[
importClass( java.util.Vector );
vec = new Vector( project.getTargets().keySet() );
vec.setSize( vec.size( ) - 1 );
project.executeTargets( vec );
]]>
</script>
(The implicit target appears at the end of the list, hence the size adjustment to prevent recursion.)
If you put that script in a 'runner' target - which would execute all other targets in the buildfile - you would need to remove the 'runner' from the Vector (and the implicit target-with-no-name) to prevent recursion.

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