Seit einiger Zeit habe ich ein neues Spielzeug zum Arbeiten: Der Eclipse basierte Flex Builder 3 von Adobe ermöglicht einem Softwareentwickler einen einfacheren Einstieg in die Flash-Programmierung. Die IDE ist an sich ziemlich toll für die Entwicklung, ich vermisse im Moment einzig die Refactoring Werkzeuge aus der Java Welt - aber vielleicht kommt das ja bei der nächsten Version. Als Java Entwickler findet man ziemlich schnell den Einstieg in das gut dokumentierte Flex Framework, mit seinen logisch aufgebauten Komponenten. Auch ActionScript 3 bereitet keine grossen Schwierigkeiten und man kann sehr schnell loslegen und nach ein paar wenigen Stunden produktiv arbeiten. Anders als bei Flash wird mit mit Flex nicht Design- sondern Codezentriert entwickelt.
Für Ant liefert Adobe die Flex Ant Tasks mit, womit man in gewohnter Java-Manier Projekte bauen und auch bedingt kompilieren und konfigurieren kann - davon handelt dieser Artikel.
Für die Installation müssen als erstes mit dem Eclipse Software Update die Java Development Tools installiert werden, womit man die Ant Laufzeitumgebung und auch eine graphische Ant Ansicht bekommt. In der nachfolgenden Build-Datei muss eventuell lediglich der Pfad zu den Ant-Tasks angepasst werden. Dies kann man auch alternativ in den Einstellungen von Eclipse unter “Ant > Runtime” machen, indem man die flexTasks.jar in den Klassenpfad einbindet.
Das Ergebniss der nachfolgenden Anleitung kann am Ende des Artikels als Archiv heruntergeladen werden.
Als erster Schritt legen wir im Flex Builder ein neues Projekt ’sample’ an und erstellen ein Verzeichniss build, wo alle Build relevanten Dateien ihr Zuhause finden. Als wohl wichtigste Datei wird die build.xml angelegt und anschliessen in die Ant Ansicht von Eclipse gezogen.
Eine minimale Datei kann wie folgt aussehen:
<project default="compile_test" basedir="..">
<!-- load the property file -->
<property file="build/build.properties" />
<!-- define the flex ant tasks -->
<taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />
<!-- ************************************************ -->
<!-- clean all generated files and folders -->
<!-- ************************************************ -->
<target name="clean" description="Clean all build assets">
<echo message="Deleting all artefacts"/>
<!-- clean apps -->
<delete dir="${output.folder}"/>
<!-- clean incremental cache -->
<delete file="${basedir}/src/*.cache"/>
</target>
<!-- ************************************************ -->
<!-- Compile sample application for test -->
<!-- ************************************************ -->
<target name="compile_test" description="Compiles the sample application for test">
<echo message="Compile sample application for test"/>
<mkdir dir="${output.folder}/test"/>
<antcall target="compile">
<param name="OUTPUT_NAME" value="test/sample.swf"/>
<param name="FLEX_CONFIG" value="${basedir}/build/flex-config-test.xml"/>
</antcall>
</target>
<!-- ************************************************ -->
<!-- Compile sample application for production -->
<!-- ************************************************ -->
<target name="compile_prod" description="Compiles the sample application for production">
<echo message="Compile sample application for production"/>
<mkdir dir="${output.folder}/prod"/>
<antcall target="compile">
<param name="OUTPUT_NAME" value="prod/sample.swf"/>
<param name="FLEX_CONFIG" value="${basedir}/build/flex-config-prod.xml"/>
</antcall>
</target>
<!-- ************************************************ -->
<!-- compile the flex application -->
<!-- ************************************************ -->
<target name="compile">
<echo message="Compile with config: ${FLEX_CONFIG}"/>
<mxmlc file="${basedir}/src/sample.mxml"
output="${output.folder}/${OUTPUT_NAME}"
actionscript-file-encoding="UTF-8"
keep-generated-actionscript="false"
incremental="true">
<!-- get default compiler options -->
<load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
<load-config filename="${FLEX_CONFIG}"/>
<!-- include sources -->
<source-path path-element="${FLEX_HOME}/frameworks"/>
<source-path path-element="${basedir}/src"/>
<!-- include libraries -->
<compiler.library-path dir="${FLEX_HOME}/frameworks" append="true">
<include name="libs" />
</compiler.library-path>
</mxmlc>
</target>
</project>
Das scheint ziemlich viel XML zu sein, aber auf den zweiten Blick ist das nur halb so wild. Die Build-Datei ist in folgende Aktionen aufgesplittet:
- clean - löscht den Ordner wo das SWF hineingeneriert wird und auch den Zwischenspeicher für die inkrementelle Kompilation
- compile_test - Ruft die Kompilation mit den Parametern für die Testumgebung auf
- compile_prod - Ruft die Kompilation mit den Parametern für die Produktivumgebung auf
- compile - hier wird die Applikation mit dem MXMLC Kompiler übersetzt
Im Script selber werden einige Variabel gebraucht, welche man pro Rechner anpassen muss. Ich mache die meistens so, indem ich im Source-Repository ein build.properties.sample mit Beispielvorgaben abspeichere, welche dann von jedem Entwickler angepasst und unter build.properties gespeichert werden muss.
Hier ein Beispiel:
FLEX_HOME=/Applications/Adobe Flex Builder 3/sdks/3.0.0
APP_ROOT=src
output.folder=apps
Also einfach FLEX_HOME anpassen und schon ist der erste Teil des Build-Systemes bereit und die Ant-Datei kann in der Ant-View in Eclipse geöffnet werden:

Bevor wir uns aber ans erste Kompilieren machen, sollten wir noch die Konfigurationen für die unterschiedlichen Systeme anlegen. Diese wird in Form einer XML-Datei im build Ordner gemacht:
flex-config-test.xml
<?xml version="1.0" encoding="UTF-8"?>
<flex-config>
<compiler append="true">
<debug>true</debug>
<define>
<name>CONFIG::text</name>
<value>'Testing'</value>
</define>
<define>
<name>CONFIG::button</name>
<value>true</value>
</define>
</compiler>
</flex-config>
flex-config-prod.xml
<?xml version="1.0" encoding="UTF-8"?>
<flex-config>
<compiler append="true">
<debug>true</debug>
<define>
<name>CONFIG::text</name>
<value>'Production'</value>
</define>
<define>
<name>CONFIG::button</name>
<value>false</value>
</define>
</compiler>
</flex-config>
Natürlich können wir auch für den Flex Builder eine Konfigurationsdatei anlegen, ich nenne diese flex-config-local.xml. Diese Datei wird dann für die lokale Kompilation im Flex Builder verwendet.
flex-config-local.xml
<?xml version="1.0" encoding="UTF-8"?>
<flex-config>
<compiler append="true">
<debug>true</debug>
<define>
<name>CONFIG::text</name>
<value>'Local Development'</value>
</define>
<define>
<name>CONFIG::button</name>
<value>true</value>
</define>
</compiler>
</flex-config>
Diese Datei müssen wir noch in den Projekt-Einstellungen eintragen, und zwar beim Flex Kompilers um ‘-load-config+=../build/flex-config-local.xml’ als zusätzliches Argument anhängen:

Somit lässt sich bereits ein kleines Beispiel erstellen und kompilieren, welches von der bedingten Kompilation gebrauch macht. Dazu legen wir die Datei src/sample.mxml mit folgendem Inhalt an:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="init();">
<mx:Script source="sample.as"/>
<mx:Label x="10" y="10" text="{TEXT}"/>
<mx:Button id="theButton" x="10" y="36" label="Button"/>
</mx:Application>
Zuletzt kommt noch die Actionscript 3 Datei src/sample.as hinzu:
[Bindable]
public static var TEXT:String = CONFIG::text;
private function init():void {
if (!CONFIG::button) {
theButton.visible = false;
}
}
Der Trick an der ganzen Sache ist recht einfach: Man kann auf die Deklarationen in den Konfigurationsdateien einfach zugreifen, z.B. mit…
- CONFIG::text - Holt den String aus der Konfigurationsdatei (WICHTIG: ein String muss in der Datei immer mit Hochkommatas umschlossen sein - hat mich einige Stunden gekostet!)
- CONFIG::button - wertet das Boolean aus
Des weiteren ist es auch möglich, ganze Klassen auszutauschen. Die Englische Dokumentation zur bedingten Kompilation findet sich in Adobe’s Flex 3 Hilfe.
Ausserdem kann man weitere Kompileroptionen wie Netzzugriff und Metadaten in der Konfigurationsdatei einbinden. Hier ein paar Beispiele für Einstellungen welche ist bereits verwendet habe:
Debug Informationen in das SWF Kompilieren:
<debug>true</debug>
Netzwerkzugriff ein- bzw. ausschalten. Mit ausgeschaltetem Netzwerkzugriff kann man auch lokal Daten lesen. Die kann für die Erstellung einer Flex Offline Applikation nützlich sein (Ich weiss es gibt AIR, kann aber trotzdem manchmal passend sein):
<use-network>true</use-network>
Metadaten einbinden:
<metadata>
<title>Sample</title>
<description>Sample Flex Application</description>
<publisher>Netzpiraten</publisher>
<creator>Michael Kessler</creator>
</metadata>
Die Beispiel-Applikation sieht nun folgendermassen aus, wenn man sie direkt aus dem Flex Builder heraus startet:

In einem weiteren Schritt kompilieren wir die Applikation mit Ant, indem wir ‘compile-test‘ aufrufen. Die Ausgabe in der Konsole sollte etwa so sein:
Buildfile: /Users/michi/Documents/Flex Builder 3/sample/build/build.xml
compile_test:
[echo] Compile sample application for test
compile:
[echo] Compile with config: /Users/michi/Documents/Flex Builder 3/sample/build/flex-config-test.xml
[mxmlc] Loading configuration file /Applications/Adobe Flex Builder 3/sdks/3.0.0/frameworks/flex-config.xml
[mxmlc] Loading configuration file /Users/michi/Documents/Flex Builder 3/sample/build/flex-config-test.xml
[mxmlc] /Users/michi/Documents/Flex Builder 3/sample/src/sample_363677.cache (No such file or directory)
[mxmlc] /Users/michi/Documents/Flex Builder 3/sample/apps/test/sample.swf (250033 bytes)
BUILD SUCCESSFUL
Total time: 8 seconds
Die Applikation liegt nun unter /apps/test/sample.swf und sieht folgendermassen aus, wenn man diese in einen Webbrowser zieht:

Das gleiche Prozedere mit ‘compile-prod‘:

Wenn alles geklappt hat, sollten bei dir nun folgende Ordner und Dateien im Flex Builder sein:

Prima. Klappt ja alles Bestens! Letztendlich kann das Projekt nun auch sehr einfach in einen kontinuierlichen Buildprozess eingebunden werden, z.B. mit Hudson oder CruiseControl.
Ein weiteres Zückerlein ist ein einfaches aber effektives SSH Deployment. Dazu wird die jsch Bibliothek benötigt, welche man herunterladen und in den Klassenpfad einbinden muss. Dannach muss die Ant-Datei lediglich um ein paar Zeilen erweitert werden:
<!-- ************************************************ -->
<!-- deploy the online version -->
<!-- ************************************************ -->
<target name="deploy_test" depends="clean,compile_test" description="Deploy the sample application to the test system">
<echo message="Deploy sample application to test system"/>
<scp file="${output.folder}/test/sample.swf" todir="/var/www/sample/" keyfile="${user.home}/.ssh/id_rsa" passphrase=""/>
</target>
Hat man eine passwortlose Anmeldung mittels einer SSH Public-Key-Authentifizierung eingerichtet, ist das Deployment einer neuen Version auf ein System nur einen Doppelklick entfernt.
Die Beispielapplikation kann übrigens hier heruntergeladen werden: Flex Ant Sample (331)
Happy Building & Deploying!

















Kommentare
gph, michi, Jacko_Momocini, michi, Jacko_Momocini [...]
Stephan, benjie, Florian, Peter, peter pan [...]
michi, flöschen
michi, Golfplätze Schweiz, michi, Blankster, michi [...]
michi, Christian, michi, michi, Lukas Eppler