[X] Build-Systeme Teil 2: Apache Ant



  • Stand des Aritkels (Updated: 13.12.05)
    Sodala, bin erstmal fertig. Warte auf RS-Korrektur 🙂

    MfG SideWinder



  • Bin vor der Fertigstellung jetzt noch Segeln, sorry, aber schaffs vorher nicht mehr.

    MfG SideWinder



  • bitte als post ins forum, keine externen ressourcen. sonst ist das korrigieren so schwer



  • Build-Systeme Teil 2: Apache Ant

    Inhalt:
    
    Voraussetzungen
    Einführung
    Basiswissen
    Ein Beispielprojekt
    	Property-Dateien
    	Implementierung der Build-Datei
        Implementierung der Sub-Targets
    Ein paar Dinge mehr
    What comes next...
    Anhang
    Quellen
    

    Voraussetzungen:
    - Kenntnisse über Build-Systeme im Allgemeinen (Erhältlich im 1. Teil dieser Serie)
    - Basis-Kenntnisse im Bereich XML (Erhältlich auf http://www.w3schools.com)

    Einführung:
    Herzlich Willkommen beim 2. Teil unserer Artikel-Serie über Build-Systeme. Nachdem GPC die theoretischen Grundlagen für mich erledigt hat, werde ich euch das Build-Tool Apache Ant näher bringen. Das von der Apache Software Foundation frei zur Verfügung gestellte Build-System ist reich an Funktionalität und einfach einzusetzen. Ant bezeichnet sich selbst als "Make[1] without wrinkles", was das Build-System imho sehr treffend beschreibt.

    Einige Vorteile von Ant sind:
    -> Eine sehr mächtige BuiltIn-Bibliothek mit oft benötigten Funktionen
    -> Ant ist in reinem Java geschrieben und daher auf nahezu allen modernen Plattformen einsetzbar
    -> Dank XML sind die Build-Dateien gut strukturiert und wartbar

    Andere Build-Systeme gehen meist den Weg eingespeiste Befehle auf der Shell des Systems auszuführen, dass hat den Vorteil, dass sie für jede Programmiersprache gleich gut aber auch gleich schlecht eingesetzt werden können. Ant geht einen anderen Weg: Befehle werden über eine BuiltIn-Bibliothek angeboten, das vereinfacht die Anwendung ungemein und ermöglicht mächtige Features mit wenigen Zeilen einzubinden. Jede Medaille hat aber auch ihre Kehrseite: Die BuiltIn-Bibliothek ist nahezu ausschließlich auf Java ausgelegt, was Ant auf diese Sprache einschränkt.

    Hinweis: Die BuiltIn-Bibliothek ist mit eigenen Modulen erweiterbar. Ant wäre also durchaus in der Lage auch mit anderen Programmiersprachen als Java eingesetzt zu werden. Der Aufwand ist allerdings nicht gerechtfertigt, ein anderes Build-Tool liegt da näher.

    Was diese BuiltIn-Bibliothek alles leistet wird spätestens bei folgendem Beispiel deutlich:

    Sämtliche Source-Dateien liegen auf einem CVS-Server[2], die neueste Version ist natürlich vor dem Build von dort zu beziehen. Danach soll der eigentliche Build-Prozess von statten gehen. Wird dieser korrekt beendet sollen automatisierte Tests am Ergebnis durchgeführt werden (Kurzfassung der Ergebnisse per Mail an den Projektleiter). Zu guter letzt soll die computergenerierte Entwickler-Dokumentation erneuert werden und der fertige Build mit der richtigen Build-Nummer auf einen Web-Server geladen werden.

    Mit einem auf Shellbefehlen basierendem Build-System würde man hier gehörig ins Schwitzen kommen, mit Ant reichte es in diesem Fall einen Ferialpraktikanten einzustellen.

    Um auch anderen zu zeigen wie einfach Ant in ein bestehendes System zu integrieren ist, möchte ich mein Wissen - learning by doing - an einem Beispielprojekt weitergeben.

    Basiswissen
    Nach den theoretischen Grundlagen kommen wir nun zur praktischen Anwendung. Im Gegensatz zu Make werden Ant die auszuführenden Targets im XML-Schema zugeführt. Der grundlegene Aufbau gleicht dem der meisten Build-Systeme:

    - Projekt (= Projekt)
    - Target (= Ziel)
      Typisches Beispiel: build, create_docs
    - Task (= Aufgabe)
      Typisches Beispiel: javac
    

    Während die Targets von uns definiert werden, verwenden wir Tasks aus der BuiltIn-Bibliothek.

    Kommen wir also zur Build-Datei. Die Datei heißt gewöhnlich build.xml und liegt im Projekt-Root-Verzeichnis. Durch übersetzen des oben gezeigten Schemas in XML erhalten wir folgenden Grundaufbau:

    <?xml version="1.0"?>
    <project name="MeinProjekt">
    
        <target name="Ziel">
    
            <task param="value" />
            <task param="value" />
            ...
    
        </target>
        ...
    
    </project>
    

    Hinweis: Kommentare können im XML-Format gemacht werden:

    <!-- Kommentar -->
    <!-- Auch
         mehrzeilig
         möglich.
    -->
    

    Ein Beispielprojekt:
    Damit wir den genauen Aufbau der Build-Datei nicht am Trockendock der Theorie erlernen müssen, muss ein fiktiver Taschenrechner als Beispielprojekt herhalten. Die Source-Dateien liegen relativ zur Build-Datei im Verzeichnis source. Mehr ist noch nicht vorhanden. In Zukunft möchten wir im Verzeichnis /docs stets die aktuelle JavaDoc für unser Projekt haben und im Verzeichnis release jeweils die aktuelle Jar-Datei für unseren Taschenrechner (mit aktueller Build-Nummer im Namen).

    Property-Dateien:
    Bevor wir uns jetzt allerdings an die Implementierung machen können muss ich noch ein kurzes Wort über Property-Dateien verlieren. Sehr oft hat man es in Build-Dateien mit Konstanten zu tun (Pfade, Dateien, Bezeichner, etc.), damit diese nicht hardcoded in der Build-Datei - sicherlich auch noch redundant und unauffindbar für Änderungen - ihr Dasein fristen, werden sie in Property-Dateien zusammengefasst. Diese tragen die Endung ".properties" und man verwendet für die Standard-Property-Datei analog zur "build.xml" den Namen "build.properties".

    Ein Property selbst ist nicht mehr als ein Key-Value-Paar bestehend aus Konstanten-Name (Key) und -Wert (Value) getrennt durch ein Gleich-Zeichen. Alle Konstanten aus unserem Beispielprojekt ergeben folgende Property-Datei:

    project.name=Taschenrechner
    project.version=1.2
    
    path.source=source
    path.dest=classes
    path.docs=docs
    path.release=release
    

    Implementierung der Build-Datei:
    Nun denn, wollen wir unserem Taschenrechner ein ordentliches Build-System verpassen. Erweitern wir den Rahmen aus dem letzten Kapitel und wir erhalten folgende Build-Datei:

    <?xml version="1.0"?>
    <!-- Unser Projekt
         name ... Projektname
         basedir ... Basis-Verzeichnis für alle relativen Pfadangaben
         default ... Standard-Target, das ausgeführt wird, wenn Ant ohne Parameter gestartet wird
    -->
    <project name="Taschenrechner" basedir="." default="full">
    
        <!-- Kleine Beschreibung wozu die vorliegende Build-Datei gut ist -->
        <description>
        Automatisierung des Build-Prozesses für Taschenrechner 1.2
        </description>
    
        <!-- Laden unserer Property-Datei für Zugriff auf Konstanten (Details folgen unten) -->
        <property file="build.properties" />    
    
        <!-- Legt die richtig hochgezähle Build-Nummer in eine Konstante (Details folgen unten) -->
        <buildnumber />
    
        <!-- Unser Standard-Target
             name ... Target-Name
             depends ... Abhängigkeiten von anderen Targets, diese müssen ausgeführt worden sein *bevor* full ausgeführt wird
        -->
        <target name="full" depends="compile,javadoc,jar">
        </target>
    
        <!-- Sub-Targets -->
        <target name="compile">
            ...
        </target>
    
        <target name="javadoc">
        <!-- Nicht abhängig von compile - JavaDoc wird aus den Source-Dateien erzeugt und nicht aus den compilierten Class-Dateien! -->
            ...
        </target>
    
        <target name="jar" depends="compile">
            ...
        </target>
    
    </project>
    

    Es hat sich einiges getan an unserer Basis-Datei. Wir haben das Gesamt-Target in 3 Sub-Targets aufgeteilt. Zudem haben wir einige globale Tasks (= Tasks ohne Zugehörigkeit zu einem Target) angelegt, diese werden unabhängig vom gewählten Target immer ausgeführt. Gehen wir die Tasks also Schritt für Schritt durch:

    [b]Name:       description[/b]
    Attribute:  -
    Inhalt:     Beschreibung des Projekts
    

    Dieser Task wird von Ant ignoriert, er dient lediglich der Beschreibung, damit ein Entwickler weiß, um welche Datei es sich handelt.

    [b]Name:       property[/b]
    Attribute:  file ... Datei-Name
    Inhalt:     -
    

    Dieser Task lädt unsere Property-Datei die wir im vorangegangenen Kapitel angelegt haben. Ab jetzt können wir mit ${key} auf die Konstanten zugreifen.

    [b]Name:       buildnumber[/b]
    Attribute:  -
    Inhalt:     -
    

    Dieser Task legt im Verzeichnis eine zusätzliche Datei "build.number" an und speichert dort die aktuelle Build-Nummer. Wird die Build-Datei von Ant abermals ausgeführt findet der Task die Datei und erhöht die Build-Nummer. Zudem legt der Task die aktuelle Build-Nummer automatisch in das Property "build.number", auf das wir dann mit Hilfe von ${build.number} zugreifen können.

    Implementierung der Sub-Targets:
    Eigentlich hat man jetzt schon genügend Basiswissen um mit Ant vernünftig zu arbeiten. Die gesamte BuiltIn-Bibliothek ist sehr detailliert im Manual[->1] beschrieben. Dennoch möchte ich noch einige Feinheiten zeigen, dahier erstmal die fehlenden Teile unserer Build-Datei:

    <target name="compile">
    
            <echo>Compiling (Beispiel-Konsolen-Ausgabe)</echo>
            <javac
                srcdir="${path.source}"
                destdir="${path.dest}"
                failonerror="true"
            />
    
        </target>
    
        <target name="javadoc">
    
            <javadoc
                sourcepath="${path.source}"
                destdir="${path.docs}"
                packagenames="*"
                access="private"
                source="1.5"
                use="true"
                windowtitle="${project.name}"
            />
    
        </target>
    
        <target name="jar" depends="compile">
    
            <jar
                basedir="${path.dest}"
                destfile="${path.release}/${project.name}-${project.version}.${build.number}.jar"
            >
                <manifest />
            </jar>
    
        </target>
    

    Endlich greifen wir ordentlich auf die BuiltIn-Bibliothek von Ant zurück. Zuerst wieder eine kleiner Übersicht über die benützten Tags:

    [b]Name:       echo[/b]
    Attribute:  -
    Inhalt:     Nachricht
    

    Gibt eine Nachricht auf der Konsole aus.

    [b]Name:       javac[/b]
    Attribute:  srcdir ... Pfad in dem unsere Java-Dateien liegen
                destdir ... Pfad in den die Class-Dateien kommen sollen
    Inhalt:     -
    

    Dieser Task ruft den Java-Compiler auf.

    [b]Name:       javadoc[/b]
    Attribute:  sourcepath ... Pfad in dem unsere Java-Dateien liegen
                destdir ... Pfad in dem die fertige JavaDoc landen soll
                packagenames ... Packages die dokumentiert werden sollen (* = alle Packages)
                access ... Bis zu welchem Grad soll dokumentiert werden (private = Alle Methoden, public = Nur öffentliche Methoden, etc.)
                source ... Java-Version des Source
                use ... Soll ein Use-File erstellt werden?
                windowtitle ... Kommt in den <title>-Tag der HTML-Dokumente
    Inhalt:     -
    

    Dieser Task ruft den JavaDoc-Builder auf, er lässt sich sehr detailliert konfigurieren über Ant. Alle Attribute findet man im Ant-Manual.

    [b]Name:       jar[/b]
    Attribute:  basedir ... Pfad in dem die Class-Dateien liegen
                destfile ... Angabe des Pfad- und Dateinamens an dem die fertige Jar-Datei gespeichert werden soll
    Inhalt:     -
    

    Ruft den Jar-Packer auf.

    [b]Name:       manifest[/b]
    Attribute:  -
    Inhalt:     -
    

    Weist den Jar-Packer darauf hin, auch eine Manifest-Datei zu erzeugen.

    Damit haben wir erst einmal unsere Build-Datei fertiggestellt, mit einem Aufruf von:

    ant
    

    im Verzeichnis der build.xml führt Ant das Default-Target für uns aus, ein bestimmtes Target kann natürlich ebenfalls mit angegeben werden:

    ant javadoc
    

    Ein paar Dinge mehr:
    -> Manchen Tasks kann ein bestimmtes Attribut gesetzt werden, in dem man etwas in den Body des Tags schreibt. So muss man zB nicht <echo message="Blubb" /> schreiben sondern kann bequem <echo>Blubb</echo> verwenden
    -> Viele Tasks besitzen ein Attribut failonerror, dass - wenn auf "true" gesetzt - den gesamten Ant-Build-Prozess beendet wenn ein Fehler auftritt (So kann man zB verhindern, dass trotz fehler im Compile-Vorgang ein Release auf einen Webserver geladen wird)
    -> Einige Tasks unterstützen Sub-Tasks, so verhilft uns der Task <manifest> im <jar>-Task zu einer Manifest-Datei (siehe oben), diese Sub-Tags fallen unter den Begriff "Nested Tags"

    Den Start von Ant auch noch automatisieren...
    ...ist ebenfalls kein Problem. Alle gängigen Betriebssysteme bietet heutzutage Möglichkeiten dazu: Unix - cronjob, Windows - Geplante Tasks.

    Erweiterung von Ant:
    Ant ist über Java-Klassen erweiterbar. So gibt es externe 3rd-Party-Module zum fertigen Download aber man ist auch in der Lage eigene Module zu entwickeln. Das würde allerdings den Rahmen des Artikels sprengen (Bei Interesse zeige ich es vielleicht in einem zukünftigen Artikel).

    What comes next...
    Im nächsten Artikel unserer Serie wird Talla uns MSBuild näher bringen 🙂

    Anhang:
    [1] Make ist ebenfalls ein Build-Tool, mehr Informationen zu Make findet man auf http://de.wikipedia.org/wiki/Make .
    [2] CVS ist ein sehr verbreitetes Version-Control-System. Version-Control-Systeme ermöglichen eine nachvollziehbare und merge-konfliktfreie gleichzeitige Entwicklung an Software von mehreren Entwicklern, mehr Informationen zu CVS findet man auf https://www.cvshome.org .
    [3] Ant erlaubt es Tasks mittels Java selbst zu schreiben, mehr Informationen findet man im Ant-Mnaual auf http://ant.apache.org/manual/develop.html#writingowntask .

    Quellen:
    [1] http://ant.apache.org/manual/index.html



  • nich mehrere buchstaben in einem threadnamen! halt dich mal daran:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-116634.html

    Deswegen werd ich auch nich die rechtschreibprüfung machen.

    Mr. B



  • Geht es hier noch weiter? 😕



  • estartu_de schrieb:

    Geht es hier noch weiter? 😕

    Ja, bin bei der Arbeit. Siehe hier: http://www.c-plusplus.net/forum/viewtopic-var-t-is-125146.html

    MfG SideWinder



  • Soll der Artikel als "Einzelartikel" aus der Übersicht raus?
    Eigentlich schreibt ihr ja einen großen, oder? 😕



  • Werden alle getrennt veröffentlicht.

    MfG SideWinder



  • Ahja, okay dann bleibt das so. 🙂



  • Diese Woche wirds wieder sehr knapp mit schreiben, mal sehen ob ich ihn trotzdem weiterführen kann 😞

    MfG SideWinder



  • Hab jetzt den Artikel mal soweit überarbeitet. Schreibt mal rein was ihr so allgemein davon haltet (ist mein erster Artikel dieser Art). Auch fachliche Korrekturen sind natürlich erwünscht 🙂

    MfG SideWinder



  • Hem, ich hab mir das jetzt mal durch gelesen. Soweit alles verständlich, wenn ich das ganze für Java brauche. Aber wie kann ich damit meinen C++ Compiler ansteuern? Irgendwie fehlt mir das der bezug zu C++...



  • Bezug zu C++ wirst du vergeblich suchen müssen 🙂 Siehe auch: http://www.c-plusplus.net/forum/viewtopic-var-t-is-125146-and-postdays-is-0-and-postorder-is-asc-and-start-is-10.html die ersten paar Postings 😉

    MfG SideWinder



  • Hab ihn mir eben selsbt nochmal komplett durchgezogen. Vor allem im zweiten Teil ist er noch etwas zu gestaucht und es geht alles zu schnell. Auch stilistisch ist er im zweiten Teil noch schwach. Werde ich noch ändern 🙂

    MfG SideWinder



  • SideWinder schrieb:

    Bezug zu C++ wirst du vergeblich suchen müssen 🙂 Siehe auch: http://www.c-plusplus.net/forum/viewtopic-var-t-is-125146-and-postdays-is-0-and-postorder-is-asc-and-start-is-10.html die ersten paar Postings 😉

    Hem, dann solltest du das auch irgendwie in deinem Artikel ansprechen. Ich stand nämlich als Leser nach dem Artikel-Ende ziemlich im Wald. *verwirrt* Hab ja nichts dagegen, das ein Artikel sich mit Java beschäftigt, aber das sollte man in einem "C++ Magazin" schon dazu sagen, das der Leser sich darauf einrichtet.

    Hab so gedacht: ok, ist ein Java-Tool das laut Artikel-Einleitung flexibel ist. Gut werd ich halt damit meine C++ Projekte bauen können. Auch cool. Aber so wirklich hat sich das nicht bewahrheitet... hat mich eher ganz verwirrt.



  • Oh okay, dann werd ich nochmal extra darauf hinweisen 🙂

    MfG SideWinder



  • SideWinder schrieb:

    Hab ihn mir eben selsbt nochmal komplett durchgezogen. Vor allem im zweiten Teil ist er noch etwas zu gestaucht und es geht alles zu schnell. Auch stilistisch ist er im zweiten Teil noch schwach. Werde ich noch ändern 🙂

    MfG SideWinder

    Morgen, da du dich bereits selbst korrigierst ;), werd ich nur noch wenig dazu sagen. Aufbau ist gut, Beispiel auch, zweiter Teil sollte, wie du sagtest, ein wenig ausgebaut werden. Ansonsten denke ich, dass dein Artikel ein guter Start in die Build-Systeme wird. 🙂 👍



  • GPC schrieb:

    SideWinder schrieb:

    Hab ihn mir eben selsbt nochmal komplett durchgezogen. Vor allem im zweiten Teil ist er noch etwas zu gestaucht und es geht alles zu schnell. Auch stilistisch ist er im zweiten Teil noch schwach. Werde ich noch ändern 🙂

    MfG SideWinder

    Morgen, da du dich bereits selbst korrigierst ;), werd ich nur noch wenig dazu sagen. Aufbau ist gut, Beispiel auch, zweiter Teil sollte, wie du sagtest, ein wenig ausgebaut werden. Ansonsten denke ich, dass dein Artikel ein guter Start in die Build-Systeme wird. 🙂 👍

    Hab den zweiten Teil jetzt mal ausgebaut, warte auf Feedback von euch 🙂

    MfG SideWinder



  • Eins vorweg: ich hatte keine Ahnung von dem Thema, bevor ich den Artikel gelesen hab, kann also nicht beurteilen, ob da sachliche Fehler drin sind (ich denke mal nicht ;)).
    Ich kann nur sagen: super Artikel! 👍

    Nur eins kapier ich nicht: Warum machst du keine XML-Kommentare?
    So aufwendig ist das nicht und man hat Syntax-Highlighting!
    So wie das jetzt ist, haben die Kommentare die gleiche Farbe wie normaler Text, was mich irgendwie verwirrt...



  • 2. Teil ist nun auch sehr gut geworden. Hast alles, was für Einsteiger interessant wäre abgedeckt. Liest sich auch flüssig.
    Die Kommentare haben mich jetzt nicht gestört. Wegen mir kannst ihn in die Rechtschreibkorrektur packen.

    Eins noch: Sollten wir unten noch einen "What comes next:" Abschnitt einbauen, der dann immer auf den Folgeartikel verweist, so wie ich's gemacht habe? Der Artikel nach deinem wird wohl MSBuild von Talla sein.


Anmelden zum Antworten