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
Related
I have latest Jenkins running on Windows 2003 server.
Under, manage Jenkins:
I have IBM JDK set
I have ant: org.apache.ant_1.7.1.v20100518-1145 set as ant home
I have Jenkins AntExec plug in installed.
I have ant-contrib-0.6.jar inside anthome/lib.
I created a job, and added a build step, Execute Apache Ant, and I have this:
<echo> java home = ${JAVA_HOME}</echo>
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<project name="Test">
<description> Sample bulid file </description>
<target name="first">
<echo message="The first five letters of the alphabet are:"/>
<antcontrib:for list="a,b,c,d,e" param="letter">
<sequential>
<echo>Letter #{letter}</echo>
</sequential>
</antcontrib:for>
</target>
</project>
when I run build, it fails.
antexec_build.xml:
[echo] ant home = ${ANT_HOME}
[echo] java home = ${JAVA_HOME}
BUILD FAILED
C:\Program Files (x86)\Jenkins\jobs\MCSOWelcome\workspace\antexec_build.xml:13: Problem: failed to create task or type project
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken place.
I have tried many different things, no luck. Please suggest
AntExec comes bundled with AntContrib. You do not need to add or define it. On the contrary, to disable it, you need to open 2 Advanced... dialogs before you get the option.
What you need to do though, is use antcontrib namespace.
For example, to use for, type:
<antcontrib:for>
I ran into the same problem (I got the same error message: Problem: failed to create task or type project), although I didn't use <antcontrib:for> tag.
If you type some code to the Script source field at the Project configuration > Execute Apache Ant, the plugin doesn't use it as an entire Ant script file, but it inserts into a template script. It appears if you choose to keep the buildfile (Advanced view at Execute Ant Build step). In this case the generated antexec_build.xml Ant script will not be deleted from the Workspace of the Project after the build.
The issue is reproducable with this simple script typed in Script source:
<project>
</project>
The generated antexec_build.xml:
<?xml version="1.0" encoding="utf-8"?>
<project default="antexec_build.xml" xmlns:antcontrib="antlib:net.sf.antcontrib" basedir=".">
<!-- Read additional properties -->
<property file="antexec_build.xml.properties"/>
<!-- Make environment variables accesible via ${env.VARIABLE} by default -->
<property environment="env"/>
<target name="antexec_build.xml">
<!-- Default target entered in the first textarea - begin -->
<project>
</project>
<!-- Default target entered in the first textarea - end -->
</target>
</project>
So that, a solution would be that only include the Ant script that you intend to insert into the <target></target> tag.
Our ant build is run using Java 1.7.0 for JAVA_HOME. This way javac and all other Java dependent targets use the correct Java by default.
But 1 ant target from an external supplier does not support (or rather has a bug) using Java 1.7.0. And unlike e.g. javac or a forked junit, this target does not support parameters to switch jvm.
Is it possible to run a specific ant target in a different jvm?
To make Jeanne Boyarsky's suggestion of using the exec Ant task concrete, the following example wraps the exec task in a macro to simplify calling targets with various JVMs. Notice that the JVM is set using the Ant environment variable JAVACMD.
Example Project
<?xml version="1.0" encoding="UTF-8"?>
<project name="run-target-with-specified-java-version" default="test">
<macrodef name="exec-target">
<attribute name="antfile" default="${ant.file}" />
<attribute name="target" />
<attribute name="jvm" default="${java.home}/bin/java" />
<sequential>
<exec executable="ant">
<env key="JAVACMD" value="#{jvm}" />
<arg line='-f "#{antfile}"' />
<arg line="#{target}" />
</exec>
</sequential>
</macrodef>
<target name="echo-java-version">
<echo message="Java version: ${java.version}" />
</target>
<target name="test">
<exec-target target="echo-java-version" />
<property name="java1.6"
location="/usr/lib/jvm/jdk1.6/bin/java" />
<exec-target target="echo-java-version" jvm="${java1.6}" />
</target>
</project>
Output
test:
[exec] Buildfile: /home/your/project/build.xml
[exec]
[exec] echo-java-version:
[exec] [echo] Java version: 1.7.0
[exec]
[exec] BUILD SUCCESSFUL
[exec] Total time: 0 seconds
[exec] Buildfile: /home/your/project/build.xml
[exec]
[exec] echo-java-version:
[exec] [echo] Java version: 1.6.0
[exec]
[exec] BUILD SUCCESSFUL
[exec] Total time: 0 seconds
BUILD SUCCESSFUL
Total time: 2 seconds
You can use the exec task to run the build file with that target defined to run as a parameter. It could be running in a different JVM since you can pass the JVM to that exec call.
Note that you'd have to refactor the target to rely on files for communication rather than setting properties. Since it would be in a different JVM, it obviously can't rely on memory.
You can run a target in a different JVM (we do it all the time). You just need to use fork:
<javac srcdir="${src}"
destdir="${build}"
fork="yes"
/>
But I sense you are aware of this, so how about running the external ANT task as it is, and rest of them (lets say you have 3 more javac tasks) in the JVM you want. This can be achieved by setting a property file. See javac task
It is possible to use different compilers. This can be specified by either setting the global build.compiler property, which will affect all tasks throughout the build
So this property will affect your 3 tasks and run them in the JVM you specified (say 1.7) and you can set the default JAVA_HOME to whatever your external library task needs.
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.
I use Ant to build my Android application. I want to be able to do this:
ant debug android-market; //build the debug version for android-market;
ant debug motorola-market; //Builds debug version for motorola-market;
ant release android-market; //etc.
Is there a way to detect that "android-market" parameter from within my custom ant debug/release task?
I would prefer not to use Dparam=value, since that is less clean looking.
This syntax is used to invoke multiple targets at once. So you could perhaps use
ant android-market debug
and make the android-market target set a property used in the debug target to identify which version to build:
<project basedir="." default="debug">
<target name="android-market">
<property name="market" value="android"/>
</target>
<target name="debug">
<echo message="debugging for the following market : ${market}"/>
</target>
</project>
> ant android-market debug
> android-market:
> debug:
> [echo] debugging for the following market : android
I would prefer not to use -Dparam=value, since that is less clean looking.
I think you should get over your preferences. But add a 'help' target that describes the parameters accepted by the other targets.
JB's answer totally worked but I wanted to find a way to have a default. I found an answer to that here by someone named Mike Schilling: http://www.velocityreviews.com/forums/t137033-is-it-possible-to-alter-ant-properties-after-theyve-been-initialized.html
So I ended up having something like this:
<project basedir="." default="debug">
<target name="set-defaults">
<property name="market" value="android"/>
</target>
<target name="motorola-market">
<property name="market" value="motorola/>
</target>
<target name="debug" depends="set-defaults">
<echo message="debugging for the following market : ${market}"/>
</target>
</project>
So you could do ant debug for android or ant motorola-market debug for motorola.
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>