source: release-kits/lirk3/bin/ant-installer/web/manual1.6.2/manual/tutorial-writing-tasks.html@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 24.9 KB
Line 
1<html>
2<head>
3 <title>Tutorial: Writing Tasks</title>
4 <meta name="author" content="Jan Matï¿œne">
5 <style type="text/css">
6 <!--
7 .code { background: #EFEFEF; margin-top: }
8 .output { color: #FFFFFF; background: #837A67; }
9 -->
10 </style>
11<link rel="stylesheet" type="text/css" href="stylesheets/antmanual.css">
12</head>
13<body>
14<h1>Tutorial: Writing Tasks</h1>
15
16<p>This document provides a step by step tutorial for writing
17tasks.</p>
18<h2>Content</h2>
19<p><ul>
20<li><a href="#buildenvironment">Set up the build environment</a></li>
21<li><a href="#write1">Write the Task</a></li>
22<li><a href="#use1">Use the Task</a></li>
23<li><a href="#TaskAdapter">Integration with TaskAdapter</a></li>
24<li><a href="#derivingFromTask">Deriving from Ant's Task</a></li>
25<li><a href="#attributes">Attributes</a></li>
26<li><a href="#NestedText">Nested Text</a></li>
27<li><a href="#NestedElements">Nested Elements</a></li>
28<li><a href="#complex">Our task in a little more complex version</a></li>
29<li><a href="#TestingTasks">Test the Task</a></li>
30<li><a href="#resources">Resources</a></li>
31</ul></p>
32
33<a name="buildenvironment"></a>
34<h2>Set up the build environment</h2>
35<p>Ant builds itself, we are using Ant too (why we would write
36a task if not? :-) therefore we should use Ant for our build.<p>
37<p>We choose a directory as root directory. All things will be done
38here if I say nothing different. I will reference this directory
39as <i>root-directory</i> of our project. In this root-directory we
40create a text file names <i>build.xml</i>. What should Ant do for us?
41<ul>
42<li>compiles my stuff</li>
43<li>make the jar, so that I can deploy it</li>
44<li>clean up everything</li>
45</ul>
46So the buildfile contains three targets.
47<pre class="code">
48&lt;?xml version="1.0" encoding="ISO-8859-1"?>
49&lt;project name="MyTask" basedir="." default="jar">
50
51 &lt;target name="clean" description="Delete all generated files">
52 &lt;delete dir="classes"/>
53 &lt;delete file="MyTasks.jar"/>
54 &lt;/target>
55
56 &lt;target name="compile" description="Compiles the Task">
57 &lt;javac srcdir="src" destdir="classes"/>
58 &lt;/target>
59
60 &lt;target name="jar" description="JARs the Task">
61 &lt;jar destfile="MyTask.jar" basedir="classes"/>
62 &lt;/target>
63
64&lt;/project>
65</pre>
66
67This buildfile uses often the same value (src, classes, MyTask.jar), so we should rewrite that
68using &lt;property>s. On second there are some handicaps: &lt;javac> requires that the destination
69directory exists; a call of "clean" with a non existing classes directory will fail; "jar" requires
70the execution of some steps bofore. So the refactored code is:
71
72<pre class="code">
73&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
74&lt;project name="MyTask" basedir="." default="jar"&gt;
75
76 <b>&lt;property name="src.dir" value="src"/&gt;</b>
77 <b>&lt;property name="classes.dir" value="classes"/&gt;</b>
78
79 &lt;target name="clean" description="Delete all generated files"&gt;
80 &lt;delete dir="<b>${classes.dir}</b>" <b>failonerror="false"</b>/&gt;
81 &lt;delete file="<b>${ant.project.name}.jar</b>"/&gt;
82 &lt;/target&gt;
83
84 &lt;target name="compile" description="Compiles the Task"&gt;
85 <b>&lt;mkdir dir="${classes.dir}"/&gt;</b>
86 &lt;javac srcdir="<b>${src.dir}</b>" destdir="${classes.dir}"/&gt;
87 &lt;/target>
88
89 &lt;target name="jar" description="JARs the Task" <b>depends="compile"</b>&gt;
90 &lt;jar destfile="${ant.project.name}.jar" basedir="${classes.dir}"/&gt;
91 &lt;/target&gt;
92
93&lt;/project&gt;
94</pre>
95<i>ant.project.name</i> is one of the
96<a href="http://ant.apache.org/manual/using.html#built-in-props" target="_blank">
97build-in properties [1]</a> of Ant.
98
99
100<a name="write1"></a>
101<h2>Write the Task</h2>
102
103Now we write the simplest Task - a HelloWorld-Task (what else?). Create a text file
104<i>HelloWorld.java</i> in the src-directory with:
105<pre class="code">
106public class HelloWorld {
107 public void execute() {
108 System.out.println("Hello World");
109 }
110}
111</pre>
112and we can compile and jar it with <tt>ant</tt> (default target is "jar" and via
113its <i>depends</i>-clause the "compile" is executed before).
114
115
116
117<a name="use1"></a>
118<h2>Use the Task</h2>
119<p>But after creating the jar we want to use our new Task. Therefore we need a
120new target "use". Before we can use our new task we have to declare it with
121<a href="http://ant.apache.org/manual/CoreTasks/taskdef.html" target="_blank">
122&lt;taskdef> [2]</a>. And for easier process we change the default clause:
123<pre class="code">
124&lt;?xml version="1.0" encoding="ISO-8859-1"?>
125&lt;project name="MyTask" basedir="." default="<b>use</b>">
126
127 ...
128
129 <b>&lt;target name="use" description="Use the Task" depends="jar">
130 &lt;taskdef name="helloworld" classname="HelloWorld" classpath="${ant.project.name}.jar"/>
131 &lt;helloworld/>
132 &lt;/target></b>
133
134&lt;/project>
135</pre>
136
137Important is the <i>classpath</i>-attribute. Ant searches in its /lib directory for
138tasks and our task isn't there. So we have to provide the right location. </p>
139
140<p>Now we can type in <tt>ant</tt> and all should work ...
141<pre class="output">
142Buildfile: build.xml
143
144compile:
145 [mkdir] Created dir: C:\tmp\anttests\MyFirstTask\classes
146 [javac] Compiling 1 source file to C:\tmp\anttests\MyFirstTask\classes
147
148jar:
149 [jar] Building jar: C:\tmp\anttests\MyFirstTask\MyTask.jar
150
151use:
152[helloworld] Hello World
153
154BUILD SUCCESSFUL
155Total time: 3 seconds
156</pre>
157
158
159
160<a name="TaskAdapter"></a>
161<h2>Integration with TaskAdapter</h2>
162<p>Our class has nothing to do with Ant. It extends no superclass and implements
163no interface. How does Ant know to integrate? Via name convention: our class provides
164a method with signature <tt>public void execute()</tt>. This class is wrapped by Ant's
165<tt>org.apache.tools.ant.TaskAdapter</tt> which is a task and uses reflection for
166setting a reference to the project and calling the <i>execute()</i> method.</p>
167
168<p><i>Setting a reference to the project</i>? Could be interesting. The Project class
169gives us some nice abilities: access to Ant's logging facilities getting and setting
170properties and much more. So we try to use that class:
171<pre class="code">
172import org.apache.tools.ant.Project;
173
174public class HelloWorld {
175
176 private Project project;
177
178 public void setProject(Project proj) {
179 project = proj;
180 }
181
182 public void execute() {
183 String message = project.getProperty("ant.project.name");
184 project.log("Here is project '" + message + "'.", Project.MSG_INFO);
185 }
186}
187</pre>
188and the execution with <tt>ant</tt> will show us the expected
189<pre class="output">
190use:
191Here is project 'MyTask'.
192</pre></p>
193
194
195<a name="derivingFromTask"></a>
196<h2>Deriving from Ant's Task</h2>
197<p>Ok, that works ... But usually you will extend <tt>org.apache.tools.ant.Task</tt>.
198That class is integrated in Ant, get's the project-reference, provides documentation
199fiels, provides easier access to the logging facility and (very useful) gives you
200the exact location where <i>in the buildfile</i> this task instance is used.</p>
201
202<p>Oki-doki - let's us use some of these:
203<pre class="code">
204import org.apache.tools.ant.Task;
205
206public class HelloWorld extends Task {
207 public void execute() {
208 // use of the reference to Project-instance
209 String message = getProject().getProperty("ant.project.name");
210
211 // Task's log method
212 log("Here is project '" + message + "'.");
213
214 // where this task is used?
215 log("I am used in: " + getLocation() );
216 }
217}
218</pre>
219which gives us when running
220<pre class="output">
221use:
222[helloworld] Here is project 'MyTask'.
223[helloworld] I am used in: C:\tmp\anttests\MyFirstTask\build.xml:23:
224</pre>
225
226
227<a name="attributes"></a>
228<h2>Attributes</h2>
229<p>Now we want to specify the text of our message (it seems that we are
230rewriting the &lt;echo/> task :-). First we well do that with an attribute.
231It is very easy - for each attribute provide a <tt>public void set&lt;attributename>(&lt;type>
232newValue)</tt> method and Ant will do the rest via reflection.</p>
233<pre class="code">
234import org.apache.tools.ant.Task;
235import org.apache.tools.ant.BuildException;
236
237public class HelloWorld extends Task {
238
239 String message;
240 public void setMessage(String msg) {
241 message = msg;
242 }
243
244 public void execute() {
245 if (message==null) {
246 throw new BuildException("No message set.");
247 }
248 log(message);
249 }
250
251}
252</pre>
253<p>Oh, what's that in execute()? Throw a <i>BuildException</i>? Yes, that's the usual
254way to show Ant that something important is missed and complete build should fail. The
255string provided there is written as build-failes-message. Here it's necessary because
256the log() method can't handle a <i>null</i> value as parameter and throws a NullPointerException.
257(Of course you can initialize the <i>message</i> with a default string.)</p>
258
259<p>After that we have to modify our buildfile:
260<pre class="code">
261 &lt;target name="use" description="Use the Task" depends="jar">
262 &lt;taskdef name="helloworld"
263 classname="HelloWorld"
264 classpath="${ant.project.name}.jar"/>
265 &lt;helloworld <b>message="Hello World"</b>/>
266 &lt;/target>
267</pre>
268That's all.</p>
269
270<p>Some background for working with attributes: Ant supports any of these datatypes as
271arguments of the set-method:<ul>
272<li>elementary data type like <i>int</i>, <i>long</i>, ...</li>
273<li>its wrapper classes like <i>java.lang.Integer</i>, <i>java.lang.Long</i>, ...</li>
274<li><i>java.lang.String</i></li>
275<li>some more classes (e.g. <i>java.io.File</i>; see
276 <a href="http://ant.apache.org/manual/develop.html#set-magic">Manual
277 'Writing Your Own Task' [3]</a>)</li>
278</ul>
279Before calling the set-method all properties are resolved. So a <tt>&lt;helloworld message="${msg}"/></tt>
280would not set the message string to "${msg}" if there is a property "msg" with a set value.
281
282
283<a name="NestedText"></a>
284<h2>Nested Text</h2>
285<p>Maybe you have used the &lt;echo> task in a way like <tt>&lt;echo>Hello World&lt;/echo></tt>.
286For that you have to provide a <tt>public void addText(String text)</tt> method.
287<pre class="code">
288...
289public class HelloWorld extends Task {
290 ...
291 public void addText(String text) {
292 message = text;
293 }
294 ...
295}
296</pre>
297But here properties are <b>not</b> resolved! For resolving properties we have to use
298Project's <tt>replaceProperties(String propname) : String</tt> method which takes the
299property name as argument and returns its value (or ${propname} if not set).</p>
300
301
302<a name="NestedElements"></a>
303<h2>Nested Elements</h2>
304<p>There are several ways for inserting the ability of handling nested elements. See
305the <a href="http://ant.apache.org/manual/develop.html#nested-elements">Manual [4]</a> for other.
306We use the first way of the three described ways. There are several steps for that:<ol>
307<li>We create a class for collecting all the infos the nested element should contain.
308 This class is created by the same rules for attributes and nested elements
309 as for the task (set&lt;attributename>() methods). </li>
310<li>The task holds multiple instances of this class in a list.</li>
311<li>A factory method instantiates an object, saves the reference in the list
312 and returns it to Ant Core.</li>
313<li>The execute() method iterates over the list and evaluates its values.</li>
314</li></p>
315<pre class="code">
316import java.util.Vector;
317import java.util.Iterator;
318...
319 public void execute() {
320 if (message!=null) log(message);
321 for (Iterator it=messages.iterator(); it.hasNext(); ) { <b>// 4</b>
322 Message msg = (Message)it.next();
323 log(msg.getMsg());
324 }
325 }
326
327
328 Vector messages = new Vector(); <b>// 2</b>
329
330 public Message createMessage() { <b>// 3</b>
331 Message msg = new Message();
332 messages.add(msg);
333 return msg;
334 }
335
336 public class Message { <b>// 1</b>
337 public Message() {}
338
339 String msg;
340 public void setMsg(String msg) { this.msg = msg; }
341 public String getMsg() { return msg; }
342 }
343...
344</pre>
345<p>Then we can use the new nested element. But where is xml-name for that defined?
346The mapping XML-name : classname is defined in the factory method:
347<tt>public <i>classname</i> create<i>XML-name</i>()</tt>. Therefore we write in
348the buildfile
349<pre class="code">
350 &lt;helloworld>
351 &lt;message msg="Nested Element 1"/>
352 &lt;message msg="Nested Element 2"/>
353 &lt;/helloworld>
354</pre>
355
356
357<a name="complex"></a>
358<h2>Our task in a little more complex version</h2>
359<p>For recapitulation now a little refactored buildfile:
360<pre class="code">
361&lt;?xml version="1.0" encoding="ISO-8859-1"?>
362&lt;project name="MyTask" basedir="." default="use">
363
364 &lt;property name="src.dir" value="src"/>
365 &lt;property name="classes.dir" value="classes"/>
366
367 &lt;target name="clean" description="Delete all generated files">
368 &lt;delete dir="${classes.dir}" failonerror="false"/>
369 &lt;delete file="${ant.project.name}.jar"/>
370 &lt;/target>
371
372 &lt;target name="compile" description="Compiles the Task">
373 &lt;mkdir dir="${classes.dir}"/>
374 &lt;javac srcdir="${src.dir}" destdir="${classes.dir}"/>
375 &lt;/target>
376
377 &lt;target name="jar" description="JARs the Task" depends="compile">
378 &lt;jar destfile="${ant.project.name}.jar" basedir="${classes.dir}"/>
379 &lt;/target>
380
381
382 &lt;target name="use.init"
383 description="Taskdef the HelloWorld-Task"
384 depends="jar">
385 &lt;taskdef name="helloworld"
386 classname="HelloWorld"
387 classpath="${ant.project.name}.jar"/>
388 &lt;/target>
389
390
391 &lt;target name="use.without"
392 description="Use without any"
393 depends="use.init">
394 &lt;helloworld/>
395 &lt;/target>
396
397 &lt;target name="use.message"
398 description="Use with attribute 'message'"
399 depends="use.init">
400 &lt;helloworld message="attribute-text"/>
401 &lt;/target>
402
403 &lt;target name="use.fail"
404 description="Use with attribute 'fail'"
405 depends="use.init">
406 &lt;helloworld fail="true"/>
407 &lt;/target>
408
409 &lt;target name="use.nestedText"
410 description="Use with nested text"
411 depends="use.init">
412 &lt;helloworld>nested-text&lt;/helloworld>
413 &lt;/target>
414
415 &lt;target name="use.nestedElement"
416 description="Use with nested 'message'"
417 depends="use.init">
418 &lt;helloworld>
419 &lt;message msg="Nested Element 1"/>
420 &lt;message msg="Nested Element 2"/>
421 &lt;/helloworld>
422 &lt;/target>
423
424
425 &lt;target name="use"
426 description="Try all (w/out use.fail)"
427 depends="use.without,use.message,use.nestedText,use.nestedElement"
428 />
429
430&lt;/project>
431</pre>
432
433And the code of the task:
434<pre class="code">
435import org.apache.tools.ant.Task;
436import org.apache.tools.ant.BuildException;
437import java.util.Vector;
438import java.util.Iterator;
439
440/**
441 * The task of the tutorial.
442 * Print a message or let the build fail.
443 * @author Jan Matï¿œne
444 * @since 2003-08-19
445 */
446public class HelloWorld extends Task {
447
448
449 /** The message to print. As attribute. */
450 String message;
451 public void setMessage(String msg) {
452 message = msg;
453 }
454
455 /** Should the build fail? Defaults to <i>false</i>. As attribute. */
456 boolean fail = false;
457 public void setFail(boolean b) {
458 fail = b;
459 }
460
461 /** Support for nested text. */
462 public void addText(String text) {
463 message = text;
464 }
465
466
467 /** Do the work. */
468 public void execute() {
469 // handle attribute 'fail'
470 if (fail) throw new BuildException("Fail requested.");
471
472 // handle attribute 'message' and nested text
473 if (message!=null) log(message);
474
475 // handle nested elements
476 for (Iterator it=messages.iterator(); it.hasNext(); ) {
477 Message msg = (Message)it.next();
478 log(msg.getMsg());
479 }
480 }
481
482
483 /** Store nested 'message's. */
484 Vector messages = new Vector();
485
486 /** Factory method for creating nested 'message's. */
487 public Message createMessage() {
488 Message msg = new Message();
489 messages.add(msg);
490 return msg;
491 }
492
493 /** A nested 'message'. */
494 public class Message {
495 // Bean constructor
496 public Message() {}
497
498 /** Message to print. */
499 String msg;
500 public void setMsg(String msg) { this.msg = msg; }
501 public String getMsg() { return msg; }
502 }
503
504}
505</pre>
506
507And it works:
508<pre class="output">
509C:\tmp\anttests\MyFirstTask>ant
510Buildfile: build.xml
511
512compile:
513 [mkdir] Created dir: C:\tmp\anttests\MyFirstTask\classes
514 [javac] Compiling 1 source file to C:\tmp\anttests\MyFirstTask\classes
515
516jar:
517 [jar] Building jar: C:\tmp\anttests\MyFirstTask\MyTask.jar
518
519use.init:
520
521use.without:
522
523use.message:
524[helloworld] attribute-text
525
526use.nestedText:
527[helloworld] nested-text
528
529use.nestedElement:
530[helloworld]
531[helloworld]
532[helloworld]
533[helloworld]
534[helloworld] Nested Element 1
535[helloworld] Nested Element 2
536
537use:
538
539BUILD SUCCESSFUL
540Total time: 3 seconds
541C:\tmp\anttests\MyFirstTask>ant use.fail
542Buildfile: build.xml
543
544compile:
545
546jar:
547
548use.init:
549
550use.fail:
551
552BUILD FAILED
553C:\tmp\anttests\MyFirstTask\build.xml:36: Fail requested.
554
555Total time: 1 second
556C:\tmp\anttests\MyFirstTask>
557</pre>
558Next step: test ...
559
560
561
562<a name="TestingTasks"></a>
563<h2>Test the Task</h2>
564<p>We have written a test already: the use.* tasks in the buildfile. But its
565difficult to test that automatically. Common (and in Ant) used is JUnit for
566that. For testing tasks Ant provides a baseclass <tt>org.apache.tools.ant.BuildFileTest</tt>.
567This class extends <tt>junit.framework.TestCase</tt> and can therefore be integrated
568into the unit tests. But this class provides some for testing tasks useful methods:
569initialize Ant, load a buildfile, execute targets,
570expecting BuildExceptions with a specified text, expect a special text
571in the output log ... </p>
572
573<p>In Ant it is usual that the testcase has the same name as the task with a prepending
574<i>Test</i>, therefore we will create a file <i>HelloWorldTest.java</i>. Because we
575have a very small project we can put this file into <i>src</i> directory (Ant's own
576testclasses are in /src/testcases/...). Because we have already written our tests
577for "hand-test" we can use that for automatic tests, too. But there is one little
578problem we have to solve: all test supporting classes are not part of the binary
579distribution of Ant. So you can build the special jar file from source distro with
580target "test-jar" or you can download a nightly build from
581<a href="http://gump.covalent.net/jars/latest/ant/ant-testutil.jar">
582http://gump.covalent.net/jars/latest/ant/ant-testutil.jar [5]</a>.</p>
583
584<p>For executing the test and creating a report we need the optional tasks &lt;junit>
585and &lt;junitreport>. So we add to the buildfile:
586<pre class="code">
587...
588<font color="#9F9F9F">&lt;project name="MyTask" basedir="." </font>default="test"<font color="#9F9F9F">&gt;</font>
589...
590 &lt;property name="ant.test.lib" value="ant-testutil.jar"/>
591 &lt;property name="report.dir" value="report"/>
592 &lt;property name="junit.out.dir.xml" value="${report.dir}/junit/xml"/>
593 &lt;property name="junit.out.dir.html" value="${report.dir}/junit/html"/>
594
595 &lt;path id="classpath.run">
596 &lt;path path="${java.class.path}"/>
597 &lt;path location="${ant.project.name}.jar"/>
598 &lt;/path>
599
600 &lt;path id="classpath.test">
601 &lt;path refid="classpath.run"/>
602 &lt;path location="${ant.test.lib}"/>
603 &lt;/path>
604
605 &lt;target name="clean" description="Delete all generated files">
606 &lt;delete failonerror="false" includeEmptyDirs="true">
607 &lt;fileset dir="." includes="${ant.project.name}.jar"/>
608 &lt;fileset dir="${classes.dir}"/>
609 &lt;fileset dir="${report.dir}"/>
610 &lt;/delete>
611 &lt;/target>
612
613 <font color="#9F9F9F">&lt;target name="compile" description="Compiles the Task">
614 &lt;mkdir dir="${classes.dir}"/>
615 &lt;javac srcdir="${src.dir}" destdir="${classes.dir}" </font>classpath="${ant.test.lib}"<font color="#9F9F9F">/>
616 &lt;/target></font>
617...
618 &lt;target name="junit" description="Runs the unit tests" depends="jar">
619 &lt;delete dir="${junit.out.dir.xml}" />
620 &lt;mkdir dir="${junit.out.dir.xml}" />
621 &lt;junit printsummary="yes" haltonfailure="no">
622 &lt;classpath refid="classpath.test"/>
623 &lt;formatter type="xml"/>
624 &lt;batchtest fork="yes" todir="${junit.out.dir.xml}">
625 &lt;fileset dir="${src.dir}" includes="**/*Test.java"/>
626 &lt;/batchtest>
627 &lt;/junit>
628 &lt;/target>
629
630 &lt;target name="junitreport" description="Create a report for the rest result">
631 &lt;mkdir dir="${junit.out.dir.html}" />
632 &lt;junitreport todir="${junit.out.dir.html}">
633 &lt;fileset dir="${junit.out.dir.xml}">
634 &lt;include name="*.xml"/>
635 &lt;/fileset>
636 &lt;report format="frames" todir="${junit.out.dir.html}"/>
637 &lt;/junitreport>
638 &lt;/target>
639
640 &lt;target name="test"
641 depends="junit,junitreport"
642 description="Runs unit tests and creates a report"
643 />
644...
645</pre></p>
646
647<p>Back to the <i>src/HelloWorldTest.java</i>. We create a class extending
648<i>BuildFileTest</i> with String-constructor (JUnit-standard), a <i>setUp()</i>
649method initializing Ant and for each testcase (targets use.*) a <i>testXX()</i>
650method invoking that target.
651<pre class="code">
652import org.apache.tools.ant.BuildFileTest;
653
654public class HelloWorldTest extends BuildFileTest {
655
656 public HelloWorldTest(String s) {
657 super(s);
658 }
659
660 public void setUp() {
661 // initialize Ant
662 configureProject("build.xml");
663 }
664
665 public void testWithout() {
666 executeTarget("use.without");
667 assertEquals("Message was logged but should not.", getLog(), "");
668 }
669
670 public void testMessage() {
671 // execute target 'use.nestedText' and expect a message
672 // 'attribute-text' in the log
673 expectLog("use.message", "attribute-text");
674 }
675
676 public void testFail() {
677 // execute target 'use.fail' and expect a BuildException
678 // with text 'Fail requested.'
679 expectBuildException("use.fail", "Fail requested.");
680 }
681
682 public void testNestedText() {
683 expectLog("use.nestedText", "nested-text");
684 }
685
686 public void testNestedElement() {
687 executeTarget("use.nestedElement");
688 assertLogContaining("Nested Element 1");
689 assertLogContaining("Nested Element 2");
690 }
691}
692</pre></p>
693
694<p>When starting <tt>ant</tt> we'll get a short message to STDOUT and
695a nice HTML-report.
696<pre class="output">
697C:\tmp\anttests\MyFirstTask>ant
698Buildfile: build.xml
699
700compile:
701 [mkdir] Created dir: C:\tmp\anttests\MyFirstTask\classes
702 [javac] Compiling 2 source files to C:\tmp\anttests\MyFirstTask\classes
703
704jar:
705 [jar] Building jar: C:\tmp\anttests\MyFirstTask\MyTask.jar
706
707junit:
708 [mkdir] Created dir: C:\tmp\anttests\MyFirstTask\report\junit\xml
709 [junit] Running HelloWorldTest
710 [junit] Tests run: 5, Failures: 0, Errors: 0, Time elapsed: 2,334 sec
711
712
713
714junitreport:
715 [mkdir] Created dir: C:\tmp\anttests\MyFirstTask\report\junit\html
716[junitreport] Using Xalan version: Xalan Java 2.4.1
717[junitreport] Transform time: 661ms
718
719test:
720
721BUILD SUCCESSFUL
722Total time: 7 seconds
723C:\tmp\anttests\MyFirstTask>
724</pre></p>
725
726
727<a name="resources"></a>
728<h2>Resources</h2>
729<p>This tutorial and its resources are available via
730<a href="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=22570">BugZilla [6]</a>.
731The ZIP provided there contains<ul>
732<li>this tutorial</li>
733<li>the buildfile (last version)</li>
734<li>the source of the task (last version)</li>
735<li>the source of the unit test (last version)</li>
736<li>the ant-testutil.jar (nightly build of 2003-08-18)</li>
737<li>generated classes</li>
738<li>generated jar</li>
739<li>generated reports</li>
740</ul>
741The last sources and the buildfile are also available
742<a href="tutorial-writing-tasks-src.zip">here [7]</a> inside the manual.
743</p>
744
745
746Used Links:<br/>
747&nbsp;&nbsp;[1] <a href="http://ant.apache.org/manual/using.html#built-in-props">http://ant.apache.org/manual/using.html#built-in-props</a><br>
748&nbsp;&nbsp;[2] <a href="http://ant.apache.org/manual/CoreTasks/taskdef.html">http://ant.apache.org/manual/CoreTasks/taskdef.html</a><br>
749&nbsp;&nbsp;[3] <a href="http://ant.apache.org/manual/develop.html#set-magic">http://ant.apache.org/manual/develop.html#set-magic</a><br>
750&nbsp;&nbsp;[4] <a href="http://ant.apache.org/manual/develop.html#nested-elements">http://ant.apache.org/manual/develop.html#nested-elements</a><br>
751&nbsp;&nbsp;[5] <a href="http://gump.covalent.net/jars/latest/ant/ant-testutil.jar">http://gump.covalent.net/jars/latest/ant/ant-testutil.jar</a><br>
752&nbsp;&nbsp;[6] <a href="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=22570">http://nagoya.apache.org/bugzilla/show_bug.cgi?id=22570</a><br>
753&nbsp;&nbsp;[7] <a href="tutorial-writing-tasks-src.zip">tutorial-writing-tasks-src.zip</a><br>
754
755<hr>
756<p align="center">Copyright &copy; 2003-2004 The Apache Software Foundation. All rights
757Reserved.</p>
758
759</body>
760</html>
Note: See TracBrowser for help on using the repository browser.