Ant - Das Apache Build-Werkzeug für Java

Ein Vergleich mit dem Make-System
Simon Lembke (WI4139)


... [ Seminar WS 2002/03 ] ... [ Ant ] ... [ Plattform(un)abhängigkeit ] ... [ Erweiterbarkeit ] ...

Übersicht : Erweiterbarkeit


Make

Der Erweiterung von Make sind keine Grenzen gesetzt. Jedes eigene Programm, das in der zugrunde liegenden Shell lauffähig ist, kann von Make aus aufgerufen werden. Daher ist es egal, ob es sich bei der Erweiterung um ein Shell-Skript, ein Perl-Programm oder irgendeine andere ausführbare Datei handelt. Man muss allerdings beachten, das die eigenen Erweiterungen auf den Systemen laufen, auf denen das Makefile verwendet wird und man das entsprechende Programm zusammen mit dem Makefile ausliefern muss.


Eigene Tasks in Ant

Ant lässt sich auf zwei Wegen erweitern. Zum einen können, wie schon im vorigen Abschnitt kurz angesprochen, externe Programme ausgeführt werden. Damit schränkt man Ant jedoch gleichzeitig ein, denn die Plattformunabhängigkeit bleibt natürlich nur bestehen, wenn diese Programme auf allen Systemen vorhanden sind. Die zweite und deutlich elegantere Methode ist, einen eigenen Task zu entwickeln.
Jeder Task in Ant entspricht einer Klasse. Um nun selber einen solchen Task zu schreiben, muss man zunächst eine Klasse erstellen, die die Klasse org.apache.tools.ant.Task erweitert.
Für jedes Attribut, über das der Task verfügen soll, muss eine setter-Methode geschrieben werden. Die Namen dieser Methoden beginnen mit set, gefolgt vom Namen des Attributs, wobei der erste Buchstabe groß geschrieben wird. Alle setter-Methoden sind dabei public void und haben genau ein Argument, dessen Typ der Entwickler festlegen kann. Diese Methode wäre also zuständig für ein Attribut namens version:

public void setVersion(int version)

Ant führt diverse Konvertierungen durch, bevor die Methoden aufgerufen werden. boolean-Typen erhalten den Wert true, wenn im Build-File yes, true oder on angegeben wurde, char-Typen erhalten den ersten Buchstaben, die anderen primitiven Datentypen den Zahlenwert des angegebenen Wertes. Bei den Typen java.io.File und org.apache.tools.ant.types.Path wird zunächst geprüft, ob es sich um absolute oder relative Pfade handelt und letztere danach, ausgehend vom basedir, umgesetzt. Wenn es sich bei dem Typen um java.lang.Class handelt, wird der angegebene Wert als Name einer Klasse angesehen. Ant versucht dann eine Instanz dieser Klasse zu erstellen. Bei allen anderen Typen, die einen Konstruktor mit einem Parameter vom Typ String besitzen, wird Ant ebenfalls versuchen eine Instanz dieser Klasse zu erstellen.
Ein spezieller Fall sind Nachkommen der abstrakten Klasse EnumeratedAttribute. Dieser Typ repräsentiert eine Liste von gültigen Werten, wobei bereits beim Parsen des Build-Files entschieden wird, ob es sich um einen gültigen Wert für dieses Attribut handelt. Jede Klasse, die EnumeratedAttribute erweitert, muss dazu nur folgende Methode implementieren:

public String[] getValues();

Diese Methode gibt ein Array mit allen gültigen Werten immer in der gleichen Reihenfolge zurück.
Wenn der Task ausgeführt werden soll, ruft Ant indirekt die Methode execute auf. Diese muss ebenfalls public sein, darf keinen Rückgabewert und keine Parameter haben und muss eine BuildException im Fehlerfall werfen.


Beispiel für einen Task

package de.fh-wedel;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
public class MessageTask extends Task {
   private String msg;
   
   public void execute() throws BuildException {
     System.out.println(msg);
   }
   public void setMessage(String msg) {
     this.msg = msg;
   }
}

Dieses Beispiel ist der Hilfe von Ant entnommen und schreibt die Nachricht, die im Build-File als Attribut message (Methode setMessage) angegeben wurde, auf die Standard-Ausgabe.


Tasks einbinden

Um einen eigenen Task im Build-File verfügbar zu machen, muss man mit Hilfe des taskdef-Elements der Klasse einen Namen geben, unter dem sie in Ant referenziert werden kann.

<taskdef classname=“de.fh-wedel.MessageTask“ name=“printmessage“>

Danach kann man seinen Task wie jeden anderen Task auch verwenden:

<printmessage message=“Hallo Welt!“>

... [ Seminar WS 2002/03 ] ... [ Ant ] ... [ Plattform(un)abhängigkeit ] ... [ Erweiterbarkeit ] ...