Stanislav Zorjan - Stasha - Full Stack Software Engineer and Game Development Hobbyist - Prague


When developing aplications, developers are facing different kind of tasks: 

  • writting
  • refactoring
  • patching
  • debugging
  • testing
  • compiling
  • documenting
  • packaging
  • commiting
  • deploying
  • ...etc ... etc ...

 

All these tasks may have other subtasks. For example:

  • debugging locally or remotely with different configurations
  • compiling with different configurations for different devices and platforms
  • packaging with different configurations for different devices and platforms
  • deploying to different devices, platforms, locations
  • ...etc ...etc ...

 

This way development process may become really complex.

Fortunately we can automate lot's of this tasks using Ant.

If you don't know how to install Ant to Flash Builder (Flex), you can read:
Installing Ant to Flash Builder (Flex) 4

If you didn't use Ant before, you can read:
Using Ant in Flash Builder (Flex) 4

For much more informations about Ant, go to: 
http://ant.apache.org/

Automatng tasks means we don't have to do all the stuff manually any more, and that means: less stress :) (our best friend), consistency, less mistakes (everyones best friend), higher productivity (bosses best friend)... etc...

 

DOWNLOAD SOURCES: 
Flex - Ant Buildfile for Development, QA, Production and More

DOWNLOAD DEPENDENCIES FOR ANT: 
Commons Net (ftp support)
SvnAnt (svn support)

Dependencies must be included in Ant's Classpath
If you don't know how to add dependencies to Ant's Classpath, than you can read:
Flex - Ant - Library Dependencies

 

We are going to create Ant buildfile to automate these tasks:

Task "0_BUILD":

  • creating local QA directory (files from bin-debug folder will be copied here)
  • creating local LIVE (production) directory (files from bin-release folder wil be copied here)
  • checking out LIVE directory from svn so latest source from svn is included in build
  • compiling application for debugging
  • compiling application for release
  • creating documentation
  • uploading files to QA server from local QA directory

NOTE: We are separating bin-debug and bin-release folders from QA and LIVE folders so we can continue with development until QA version is approved.


When QA version is approved, we automate these tasks:

Task "1_PUBLISH":

  • uploading files to LIVE server from local LIVE directory
  • committing all necessary files from this release to SVN

 

These two tasks "0_BUILD" and "1_PUBLISH" are our main "weapon" to automate processes.
They rely on other tasks that can be executed independently:

  • 2_CLEAN
  • Build-Debug
  • Build-Release
  • Checkout
  • Commit Live to SVN
  • Compile-Debug
  • Compile-Release
  • Create-Dirs
  • Create-Documentation
  • Generate-Html
  • Upload to LIVE server
  • Upload to QA server

 

So, here is "build.xml" Ant buildfile:

 
<project name="My App Builder" basedir="." default="0_BUILD"> 
    <taskdef resource="flexTasks.tasks" classpath="${basedir}/libs/flexTasks.jar"/>
	 
	<property file="build.properties" />
	<property name="FLEX_HOME" value="C:\Program Files\Adobe\Adobe Flash Builder 4\sdks\4.0.0" />
	
	<path id="classpath">
		<fileset dir="${lib.dir}">
		  <include name="**/*.jar" />
		</fileset>
	</path>
		
	<typedef resource="org/tigris/subversion/svnant/svnantlib.xml" classpathref="classpath" />

	
	<target name="Create-Dirs" description="Creating local QA nad local LIVE dirs">
		<echo>Creating local QA Dir</echo>
		<mkdir dir="${local.qa}"/>
		<echo>Creating local LIVE Dir</echo>
		<mkdir dir="${local.live}"/>
	</target>
	
	<target name="Checkout" description="Checking out sources so we have latest sources before compilation">
		<echo>Checkout Source before compilation</echo>
		<input message="Please enter password for SVN" addproperty="svn.repository.password" />
		<svn username="${svn.repository.username}" password="${svn.repository.password}">
			<checkout url="${svn.repository.url}/src" destPath="${app.root}" />
		</svn>
	</target>
	
	<target name="Compile-Debug" description="Compile MXML file to debug SWF application." depends="Checkout">
		<echo>Compiling source...</echo>
		<mxmlc file="${app.root}/${app.file}.mxml" output="${app.debug}/${app.output}" debug="true" locale="${app.lang}" actionscript-file-encoding="UTF-8" incremental="true">
			
			<load-config filename="${flex.config}"/>
			<source-path path-element="${app.root}"/>
			<static-link-runtime-shared-libraries>false</static-link-runtime-shared-libraries>
			
			<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/textLayout.swc"> 
			    <url rsl-url="textLayout_1.0.0.595.swf" policy-file-url="" /> 
			</runtime-shared-library-path>
			
			<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/osmf.swc">
				<url rsl-url="osmf_flex.4.0.0.13495.swf" policy-file-url="" />
			</runtime-shared-library-path>
			
			<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/framework.swc">
				<url rsl-url="framework_4.0.0.14159.swf" policy-file-url="" />
			</runtime-shared-library-path>
			
			<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/spark.swc">
				<url rsl-url="spark_4.0.0.14159.swf" policy-file-url="" />
			</runtime-shared-library-path>
			
			<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/sparkskins.swc">
				<url rsl-url="sparkskins_4.0.0.14159.swf" policy-file-url="" />
			</runtime-shared-library-path>
			
			<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/rpc.swc">
				<url rsl-url="rpc_4.0.0.14159.swf" policy-file-url="" />
			</runtime-shared-library-path>
		</mxmlc>
			<antcall target="Generate-Html">
		    	<param name="html.output" value="${app.debug}"/>
		  	</antcall>
	</target>
	
	<target name="Compile-Release" description="Compile MXML file to release SWF application.">
		<echo>Compiling source...</echo>
		<mxmlc file="${app.root}/${app.file}.mxml" output="${app.release}/${app.output}" debug="false" locale="${app.lang}" actionscript-file-encoding="UTF-8" incremental="true">
			
			<load-config filename="${flex.config}"/>
			<source-path path-element="${app.root}"/>
			<static-link-runtime-shared-libraries>false</static-link-runtime-shared-libraries>
			
			<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/textLayout.swc"> 
			    <url rsl-url="http://fpdownload.adobe.com/pub/swz/tlf/1.0.0.595/textLayout_1.0.0.595.swz" policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/> 
			    <url rsl-url="textLayout_1.0.0.595.swz" policy-file-url="" /> 
			</runtime-shared-library-path>
			
			<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/osmf.swc">
				<url rsl-url="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.14159/osmf_flex.4.0.0.13495.swz" policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/>
				<url rsl-url="osmf_flex.4.0.0.13495.swz" policy-file-url="" />
			</runtime-shared-library-path>
			
			<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/framework.swc">
				<url rsl-url="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.14159/framework_4.0.0.14159.swz" policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/>
				<url rsl-url="framework_4.0.0.14159.swz" policy-file-url="" />
			</runtime-shared-library-path>
			
			<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/spark.swc">
				<url rsl-url="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.14159/spark_4.0.0.14159.swz" policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/>
				<url rsl-url="spark_4.0.0.14159.swz" policy-file-url="" />
			</runtime-shared-library-path>
			
			<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/sparkskins.swc">
				<url rsl-url="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.14159/sparkskins_4.0.0.14159.swz" policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/>
				<url rsl-url="sparkskins_4.0.0.14159.swz" policy-file-url="" />
			</runtime-shared-library-path>
			
			<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/rpc.swc">
				<url rsl-url="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.14159/rpc_4.0.0.14159.swz" policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/>
				<url rsl-url="rpc_4.0.0.14159.swz" policy-file-url="" />
			</runtime-shared-library-path>
		</mxmlc>
		<antcall target="Generate-Html">
	    	<param name="html.output" value="${app.release}"/>
	  	</antcall>
	</target>
	
	<target name="Build-Debug">
		<antcall target="Compile-Debug" />
		<copy todir="${app.debug}" overwrite="true" verbose="true">
			<fileset dir="${FLEX_HOME}/frameworks/rsls" excludes="*.swz"/>
		</copy>
		<echo>Copying Files from ${app.debug} to local QA dir</echo>
		<copy todir="${local.qa}" verbose="true">
			<fileset dir="${app.debug}" excludes="*.svn,*.cache"/>
		</copy>
		<antcall target="Create-Documentation" />
		<antcall target="Upload to QA server" />
	</target>
	
	<target name="Upload to QA server">
		<input message="Please enter password for QA server" addproperty="ftp.qa.password" />
		<echo>Uploading files from: ${local.qa} to QA server: ${ftp.qa.host}/${ftp.qa.remoteDir}</echo>
		<ftp server="${ftp.qa.host}"
			port="${ftp.qa.port}"
		    remotedir="${ftp.qa.remoteDir}"
		    userid="${ftp.qa.username}"
		    password="${ftp.qa.password}"
		    depends="yes" verbose="true">
		    
			<fileset dir="${local.qa}" excludes=".svn,*.cache"/>
		  </ftp>
	</target>
	
	<target name="Build-Release">
		<antcall target="Compile-Release">
			<param name="app.target" value="${local.live}"/>
		    <param name="flex.debug" value="false"/>
		</antcall>
		<copy todir="${app.release}" overwrite="true" verbose="true">
			<fileset dir="${FLEX_HOME}/frameworks/rsls" excludes="*.swf"/>
		</copy>
		<echo>Copying Files from ${app.live} to local LIVE dir</echo>
		<copy todir="${local.live}" verbose="true">
			<fileset dir="${app.release}" excludes="*.svn"/>
		</copy>
	</target>
	
	<target name="Upload to LIVE server">
		<input message="Please enter password for LIVE server" addproperty="ftp.live.password" />
		<echo>Uploading files from: ${local.qa} dir to LIVE server: ${ftp.live.host}/${ftp.live.remoteDir}</echo>
		<ftp server="${ftp.live.host}"
			port="${ftp.live.port}"
		    remotedir="${ftp.live.remoteDir}"
		    userid="${ftp.live.username}"
		    password="${ftp.live.password}"
		    depends="yes" verbose="true">
		
			<fileset dir="${local.live}" />
		</ftp>
		<antcall target="Commit Live to SVN" />
	</target>
	
	<target name="Generate-Html" description="Generate HTML wrapper">
		<html-wrapper title="${app.file}" height="100%" width="100%" application="App" swf="${app.file}" version-major="10" version-minor="0" version-revision="0" history="false" output="${html.output}"/>
		<move file="${html.output}/index.html" tofile="${html.output}/${app.file}.html"/>
	</target>
	
	<target name="Create-Documentation"> 
		<echo>Creating Documentation</echo>
        <asdoc output="${basedir}/doc" lenient="true" failonerror="true"> 
            <doc-sources path-element="${app.root}"/>  
        </asdoc> 
    </target>
	
	<target name="Commit Live to SVN">
		<echo>Committing ${local.live} to </echo>
		<input message="Please enter password for SVN" addproperty="svn.repository.password" />
		<svn username="${svn.repository.username}" password="${svn.repository.password}">
			<checkout url="${svn.repository.url}/www" destPath="${local.live}" />
			<commit message="propTest added" dir="${local.live}"/>
		</svn>
	</target>
	
	<target name="0_BUILD" depends="Create-Dirs, Build-Debug, Build-Release" description="Lanuncher for building whole debug process"/>
	<target name="1_PUBLISH" depends="Upload to LIVE server" description="Lanuncher for building whole release process"/>
	<target name="2_CLEAN"  description="Clean local QA and LIVE dirs and runs BUILD target">
		<delete dir="${local.qa}" />
		<delete dir="${local.live}" />
		<antcall target="0_BUILD" />
	</target>
	
</project>

 

And here is "build.properties" file:

# -----------------------------------------------------------------------------
# build.properties
# This file is referenced by the sample build.xml file.
# -----------------------------------------------------------------------------
lib.dir=libs
flex.config=${FLEX_HOME}/frameworks/flex-config.xml
flex.debug=true
app.lang=en_US
app.file=AntTest
app.output=AntTest.swf
app.root=src
app.debug=bin-debug
app.release=bin-release
local.qa=www_qa
local.live=www
ftp.qa.host=qa.ftphost
ftp.qa.remoteDir=www
ftp.qa.username=yourusername
ftp.qa.port=21
ftp.live.host=live.ftphost
ftp.live.remoteDir=www
ftp.live.username=yourusername
ftp.live.port=21
svn.repository.url=https://localhost:8443/svn/main/trunk/flex/AntTest/
svn.repository.username=yourusername

 

After executing "0_BUILD" task, the log should look like something like this (if you can read it :D )

Ant Log - Creating Debug Version

 

and after executing "1_PUBLISH" task, the log should look like something like this (I hope this log is more readable :D)

Ant Log - Creating Release

 

Now, only the sky is the limit :D.