25.10 Ant
Die Arbeiten eines Softwareentwicklers sind nicht immer so spannend, wie es die Fantasie vorgaukelt. Der Alltag besteht aus Compilieren, Dokumentationen erstellen, Web-Seiten aktualisieren, Archive ausliefern und weiteren Dingen. Der schlaue Zeitgenosse schreibt sich für diese Aufgabe Skripte. Unter Unix wurde für die Sammlung dieser Skripte ein so genanntes make-Tool benutzt. Besondere Aufgabe von make war es, Zusammenhänge zwischen verschiedenen Quellcodedateien zu erkennen und dann die benötigten neu zu übersetzen. Wenn sich zum Beispiel eine Header-Datei geändert hat, so sollte auch die C-Datei, die diese Header-Datei einbindet, neu übersetzt werden. Unter Java können wir mit diesem make-Tool nicht so viel anfangen, doch Aufgaben wie das Erstellen von Archiven, die Neuübersetzung aller Quellen und das Erzeugen von Dokumentation bleiben. Für diese Aufgaben wurde von der Apache-Gruppe ein neues Tool mit dem Namen Ant (http://ant.apache.org/) entwickelt. Der Name selbst ist ein Akronym aus Another Neat Tool.
25.10.1 Bezug und Installation von Ant
Wir erhalten ein Archiv von Ant auf den Seiten der Indianer-Gruppe, genauer unter http://ant.apache.org/bindownload.cgi. Nach dem Entpacken sollten wir unsere Umgebungsvariable (PATH) so anpassen, dass sie auf das bin/-Verzeichnis von Ant zeigt. Wenn wir jetzt Ant auf der Kommandozeile aufrufen, dann sollte folgende Ausgabe zu sehen sein:
$ ant
Buildfile: build.xml does not exist!
Build failed
Die Installation liefert alle benötigten Bibliotheken mit. Insbesondere ist der XML-Parser Crimson eingebunden.
Wir begnügen uns am Anfang mit einer einfachen Java-Klasse, die von Ant verwaltet werden soll.
Listing 25.3 AntDemo.java
package ant;
public class AntDemo
{
public static void main( String args[] )
{
System.out.println( "Ant ist schon toll." );
}
}
Dieses Mal wollte ich die Quellcodedatei jedoch nicht von Hand übersetzen lassen, sondern es soll unser Hilfsprogramm machen. Dazu müssen wir eine Konfigurationsdatei schreiben. Sie wird Build-File genannt und beschreibt Ant, was zu machen ist. In der Regel wird diese Datei build.xml genannt. Wir wollen diese Datei in das gleiche Verzeichnis stellen, in dem auch unsere Java-Quellcodedatei steht.
<?xml version="1.0"?>
<project name="InselBeispiel" default="build" basedir=".">
<target name="build">
<javac srcdir="." />
</target>
</project>
Die Überschrift der Datei zeigt uns, dass es sich um eine XML-Datei handelt. Es muss keine DTD angegeben werden, da der Parser dieser XML-Datei nicht validierend arbeitet. Der Eintrag <project> definiert anschließend das Projekt unter dem Namen InselBeispiel. Die Attribute definieren weiterhin, dass der einfache Aufruf von Ant automatisch das Ziel build aufrufen soll. Unter dem Eintrag project folgt eine Reihe von target-Einträgen. Dass unser Eintrag build hieß, erkennen wir am Eintrag javac. Compiliert werden alle Dateien, die sich im aktuellen Verzeichnis befinden. Neben javac stellt Ant eine große Anzahl von zusätzlichen Möglichkeiten bereit.
Wechseln wir auf der Kommandozeile in das Verzeichnis mit den Dateien, dann reicht es, Ant aufzurufen, und der Konstruktionsprozess beginnt. Ant sucht selbstständig nach der Datei build.xml. Folgendes wird erscheinen:
$ ant
Buildfile: build.xml
build:
[javac] Compiling 1 source file
BUILD SUCCESSFUL
Die Option -verbose gibt zusätzliche Informationen über den Entstehungsprozess aus. Wenn wir jetzt Interpreter aufrufen, kann das übersetzte Programm gestartet werden.
Die Datei build.xml lässt sich vielfältig anpassen. Nehmen wir uns den Eintrag javac noch einmal vor und erweitern ihn zu:
<javac srcdir="." debug="true" optimize="false" includes="**/*.java" />
Ant wird angewiesen, während der Übersetzung zu optimieren und Debug-Informationen mit aufzunehmen. Das Attribut includes zeigt an, nicht nur Quellcodedateien des aktuellen Verzeichnisses zu übersetzen, sondern auch alle Dateien aller Unterverzeichnisse. Die Notation **/ ist eine Vereinfachung, die für alle Unterverzeichnisse steht. An Stelle dessen ist auch eine Aufzählung der Verzeichnisse zulässig.
25.10.2 Properties
Eine gute Idee ist es, sich von den konkreten Pfaden im javac-Element zu lösen. Denn Ant erlaubt es, Eigenschaften zu definieren, die ähnlich wie Makros verwendet werden können. Um Programme aus einem Verzeichnis, nennen wir es src, in ein Zielverzeichnis, nennen wir es build, zu übersetzen, schreiben wir:
<property name="src" value="."/>
<property name="build" value="build"/>
<target name="compile" depends="init">
<javac srcdir="${src}" destdir="${build}"/>
</target>
Bisher haben wir uns mit der Übersetzung beschäftigt. Dennoch wissen wir, dass wir auch noch andere target-Elemente verwenden können. Und obwohl die Benennung dieser Targets prinzipiell willkürlich ist, gibt es eine vorgeschlagene Namenskonvention.
init
|
Erstellt Verzeichnisse und Initialisierungsdateien.
|
build
|
Inkrementeller Aufbau
|
test
|
Ablaufen der Tests mit JUnit
|
clean
|
Ausgabeverzeichnisse löschen
|
deploy
|
Jar, War und sonstige Archive erstellen
|
publish
|
Veröffentlichen der Ergebnisse
|
fetch
|
Bezieht die letzten Quellcodedateien vom Cvs-Server.
|
docs, javadocs
|
Erstellt die Dokumentation.
|
all
|
Abfolge von clean, fetch, build, test, docs, deploy
|
main
|
Erstellt das Projekt, in der Regel build oder build, test.
|
Wir können an dem Eintrag init ablesen, dass eine Verzeichnisstruktur aufgebaut werden soll. Nehmen wir an, der Compiler soll in unser oben genanntes Verzeichnis build übersetzen. Dann muss dieses Verzeichnis natürlich existieren. Das Anlegen dieses Verzeichnisses kann in init geschehen.
<target name="init">
<mkdir dir="${build}"/>
</target>
Zum Löschen der erstellten Verzeichnisse in einem Target clean wollen wir eine Property dist für das Distributionsverzeichnis hinzunehmen.
<target name="clean">
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
25.10.3 Externe und vordefinierte Properties
Falls sich das Versionsrad eine Nummer weiterdreht, ist es ungünstig, wenn Änderungen an der XML-Datei vorgenommen werden müssen. Eine gute Lösung für das Problem besteht darin, eine externe Datei zu definieren, die die Version definiert. Das kann so aussehen:
Listing 25.4 version.properties
version=0.6
Jetzt fehlt nur noch der Bezug zu dieser Eigenschaften-Datei in der Xml-Datei. Bisher kennen wir zwar einen Eintrag property name und value, aber eine zweite Variante mit dem Attribut file bindet eine Datei ein, die Schlüssel-/Wertepaare wie bei unserer version.properties definiert.
<property file="version.properties"/>
Jetzt lässt sich auf version ganz normal zugreifen, um zum Beispiel eine zweite Eigenschaft zu definieren:
<property name="distname" value="Mein-${version}"/>
version ist jetzt unsere Variable, und der Inhalt der Variablen wird durch ${version} eingesetzt. Daneben gibt es aber noch einige Standard-Properties:
basedir
|
Absoluter Pfad zum Basisverzeichnis des Projekts. In basedir gesetzt
|
ant.file
|
Absoluter Pfad der Build-Datei
|
ant.version
|
Version von Ant
|
ant.project.name
|
Name des Projekts, wie in <project> gesetzt
|
ant.java.version
|
JVM-Version, wie von Ant entdeckt, etwa »1.4«
|
Beispiel Für ein zügiges Übersetzen lässt sich der Compiler Jikes von IBM einsetzen - er ist in C++ implementiert. Um ihn als Standard-Compiler einzusetzen, muss lediglich das Property build.compiler auf jikes gesetzt werden.
<property name="build.compiler" value="jikes"/>
|
25.10.4 Weitere Leistungen
Ant kann angewiesen werden, Programme mit automatischen Tests mit Junit zu überprüfen. Ebenfalls erlaubt Ant, Klassendateien zu einem Archiv zusammenzubinden. Dabei werden die speziellen Archive berücksichtigt, also etwa .jar, .war oder .ear. Die Archive lassen sich automatisch auf einen Ftp-Server übertragen. Für weitere Dokumentationen sollte ein Blick auf das doc-Verzeichnis der Installation geworfen werden.
|