Buy any Easy Native Extensions 2nd Edition package and get our $99 iOS + Android ANE Template completely free before the end of June 2015.
- step-by-step guide to making your iOS extension in under an hour
- library for data conversion between ActionScript and native code
- tutorials
- infographics
- code included
Let me ask you a question. Let’s say you’ve written the code for your AIR Native Extension, native library, AIR library and all that. How many steps does it take to build and package this in an .ANE file?
Let’s count:
- Build your native library or libraries: one per platform that your ANE supports.
- Build your AIR library.
- If your ANE needs to support the AIR Simulator, build your default implementation.
- Extract library.swf from your AIR library:
- make a copy of your AIR library’s SWF file;
- rename that to .ZIP;
- unzip it;
- keep library.swf that came out of the .ZIP;
- delete the .ZIP and catalog.xml that came out of the .ZIP.
- Repeat step 4 for your default implementation.
- Copy all ANE ingredients to the same folder.
- Run Adobe’s ADT tool on the command line to package all of the above into an .ANE file.
I’m known for passionately hating any build process that involves more than one mouse click… So I say let’s scrap all that and replace it with clicking Build Project in Flash Builder.
In this article we’ll build a template build script that you can customize and use to package any of your ANEs. Let’s get started.
1. Create a build script file
We will be using an Ant script, which can be nicely integrated with Flash Builder and other Eclipse-based IDEs.
1. 1. Add a folder to the root of the AIR Library project for your native extension and call it build_scripts. It’s actually OK to have space in the name and call the folder ‘build scripts’, but let’s keep things simple.
1.2. Inside build_scripts create a new file and call it local.properties. Here you’ll define the paths to Adobe’s compc and adt tools. compc is the compiler that will build your AIR library and adt is the tool that you’ll use for packaging it into an ANE. Change the paths below to match where things are on your machine:
1 2 3 |
FLEX_HOME=/Applications/Adobe Flash Builder 4.6/sdks/4.6.0 COMPC=${FLEX_HOME}/bin/compc ADT=${FLEX_HOME}/bin/adt |
1.3. Add another file and call it build.properties. This file will contain parameters that are specific to your project. Having the project-specific stuff separate from the actual build script means you can reuse the build script in all of your ANE projects by replicating and customizing build.properties.
Let’s start the file with a couple of helpful comments. We’ll add some meat to that later:
1 2 3 4 5 6 7 8 9 |
# Tips: # # 1. All paths set in this file # are relative to where build.xml is. # # 2. You can override any of the values in this file by passing a new value # on the command line, prefixed with -D, when you call ant. # Example: # ant -Dbuild.debug=false |
1.4. In the same folder add a new XML, called build.xml, and have it import the two .properties files. In this file we will put together the Ant script that will do a clean build of your ANE and package it. Start with the following shell:
<project name=“ANE Build Script” default=“package ane”>
<!– Configuration files: –>
<property file=“local.properties”/>
<property file=“build.properties”/>
<!– Add property definitions here –>
<!– Add build targets here –>
</project>
In the next steps we’ll add Ant build targets and configure them.
2. Add a way of choosing between debug and release builds
When you build a native library for iOS, Mac OS or Windows, your library binary file ends up in a different folder, depending on whether you do a debug or a release build. We’ll need to be able to build the binary we want and find it, so it can be packaged with the ANE.
2.1. Add a parameter to help you kick off a debug or a release build.
Open build.properties and add the following:
1 2 |
# Set this to true for a Debug build and to false for a Release build build.debug=true |
2.2. Add targets for checking build.debug‘s value.
Add this inside the <project> entity in build.xml, in place of the highlighted
<!– Add build targets here –>:
Helper targets
************************************************************ –>
<!– Set up the build type: debug or release –>
<target name=“set build type” depends=“check debug, check release”>
<!–Ant doesn’t do if/else very well, so we do both checks: is ${build.debug} true? is ${build.debug} false?–>
</target>
<target name=“check debug” if=“${build.debug}” depends=“check release” description=“Check if ${debug} is true and if it is, set the properties below for a debug build”>
<!– iOS.library.build.type defines the folder where our iOS library will be, depending ont the build –>
<!– You can set up similar properties for Windows and Mac OS. You don’t need one for Android. –>
<property name=“iOS.library.build.type” value=“Debug”/>
</target>
<target name=“check release” unless=“${build.debug}” description=“Check if ${debug} is false and if it is, set the properties below for a release build”>
<!– iOS.library.build.type defines the folder where our iOS library will be, depending ont the build –>
<!– You can set up similar properties for Windows and Mac OS. You don’t need one for Android. –>
<property name=“iOS.library.build.type” value=“Release”/>
</target>
iOS.library.build.type is a property that helps you with two things:
- it determines whether you request a debug or a release build from Xcode;
- it helps you find the folder in your Xcode project where the built library ends up: Debug-iphoneos/ or Release-iphoneos/.
You can add similar properties for Mac OS and Windows. On Android your native .jar lib normally ends up in the same place.
3. Add targets for building your native library
3.1. Let’s start with a target that will clean your native library project. Again, the example here is for iOS and you can extend it to include other platforms:
Native Library Targets
************************************************************ –>
<!– Clean the Xcode project –>
<target name=“clean ios” depends=“set build type” description=“Clean the iOS Library”>
<exec executable=“xcodebuild” failonerror=“true” dir=“${iOS.project.root}”>
<arg line=“clean -configuration ${iOS.library.build.type}“/>
</exec>
</target>
All this does is call Xcode’s xcodebuild tool with a command line like this:
Note: This relies on Xcode being in your path. It normally is. Relax.
Note also that this target depends on the “set build type” target that we configured earlier. This means that “set build type” will be executed before “clean ios”, which will ensure that iOS.library.build.type is set to Debug or to Release.
3.2. Next, add a target that will build the native library:
<target name=“build ios” depends=“set build type” description=“Build the iOS Library”>
<property name=”iOS.project.builddir” value=“build”/>
<exec executable=“xcodebuild” failonerror=“true” dir=“${iOS.project.root}”>
<arg line=“-project ${iOS.project.name}.xcodeproj
-target ${iOS.project.name}
-configuration ${iOS.library.build.type}
SYMROOT=${iOS.project.builddir}“
/>
<!– Note: the SYMROOT path is relative to {dir}. –>
</exec>
<copy file=“${iOS.project.buildroot}/${iOS.project.builddir}/${iOS.library.build.type}-iphoneos/${iOS.library}” todir=“${iOS.project.outputdir}” overwrite=“true”/>
</target>
You can add similar targets to build your native libraries for other platforms: set executable to the name of the compiler or tool you use for building and replace the string in <arg line/> with the command line parameters that you need to pass to that compiler or tool.
3.3. And, for convenience, add a target that will let you execute the clean and build step in one go:
<target name=“rebuild ios” depends=“clean ios,build ios” description=“Do a clean build of the XCode project”/>
3.4. Add the properties that will configure these targets:
You have probably noticed that the targets you just added use a few properties that haven’t been defined yet. Let’s add them to build.properties:
1 2 3 4 5 6 |
# iOS project paths: iOS.project.name=TheNameOfYourXcodeProject iOS.project.root=path/to/your/XcodeProject/relative/to/build.xml iOS.library=lib${iOS.project.name}.a # Check Xcode > Preferences > Locations > Advanced to see where Xcode will store build products: iOS.project.buildroot=${iOS.project.root} |
Make sure you set these to your actual project name and path.
3.5. Set up a folder where build products will be collected for the ANE packaging:
There is one property we haven’t defined yet: iOS.project.outputdir. This is where your script will copy the iOS library when it gets built, so that it’s available for the next part of the script which will package the ANE. I tend to use a temporary folder for that. The structure is the same for every project I develop, so isn’t project-specific, so let’s define this directly in our build script. Add the definitions to the top of build.xml, in place of <!– Add property definitions here –>
<property name=“tempdir” value=“../temp”/>
<property name=“iOS.project.outputdir” value=“${tempdir}/ios”/>
<property name=“temp.packagedir” value=“${tempdir}/package”/>
4. Add a target for building your AIR Library
Native library built, it’s the AIR library’s turn.
4.1. The build swc target will build an AIR library that you point it to by calling Adobe’s compc compiler.
Adobe AIR Library Generic Targets
************************************************************ –>
<!– Generic target: it builds the AIR library that {library.name} and {library.root} point to. –>
<target name=“build swc” description=“Build an AIR library SWC file”>
<fileset dir=“${library.root}/src” casesensitive=“yes” id=“classfiles”>
<include name=“**/*.as”/>
</fileset>
<pathconvert property=“classlist” refid=“classfiles” pathsep=” “ dirsep=“.”>
<regexpmapper from=“.*src.(.*)\.as” to=”\1″/>
</pathconvert>
<exec executable=“${COMPC}” failonerror=“true”>
<arg line=“+configname=airmobile
-source-path ${library.root}/src
-output ${library.outputdir}/${library.name}.swc
-include-classes ${classlist}“
/>
</exec>
</target>
In most of your projects you will probably want to build two AIR libraries: a SWC that takes care of calling native code and a default SWC with simulator support. I bet that you love code repetition as much as I do… which is to say about as much as a dentist appointment. So, instead of having to make the same target for each SWC you want to build, you are going to add smaller targets that just configure and execute this one (steps 4.3. and 4.4.).
4.2. Add another generic target to extract library.swf from a given SWC file. See Recipe for packaging an ANE if you want a reminder for why we do this.
<target name=“extract swf library” depends=“build swc” description=“Extract library.swf from the SWC file”>
<property name=“library.extractdir” value=“${library.outputdir}/content”/>
<mkdir dir=“${library.extractdir}”/>
<unzip src=“${library.outputdir}/${library.name}.swc” dest=“${library.extractdir}” overwrite=“true”/>
<copy file=“${library.extractdir}/library.swf” todir=“${library.outputdir}” overwrite=“true”/>
<delete dir=“${library.extractdir}”/>
</target>
4.3. Add a target that will build your main SWC, by configuring and executing the “extract swf library” generic target, which in turn will cause “build swc” to be executed first:
<!– ************************************************************
Adobe AIR Library Targets
************************************************************ –>
<!– This target sets {library.name} and {library.root} and executes the generic target “build swc” for their values. –>
<target name=“build air library”>
<subant target=“extract swf library”>
<property name=“library.name” value=“${air.library.name}”/>
<property name=“library.root” value=“${air.library.root}”/>
<property name=“library.outputdir” value=“${tempdir}/${air.library.name}/swc”/>
<fileset dir=“.” includes=“build.xml”/>
</subant>
<property name=“air.library.outputdir” value=“${tempdir}/${air.library.name}/swc”/>
</target>
Here you’ll need to configure the parameters that tell Ant where your AIR library is and what it’s called. Add these to build.properties:
1 2 3 4 5 6 7 |
# AIR Library paths: air.library.name=YourAIRLibraryName air.library.root=path/to/your/FlashBuilderLibraryProject/relative/to/build.xml air.library.sourcedir=${air.library.root}/src #Your extension descriptor files: air.extension.descriptor=${air.library.name}-extension.xml air.platform.descriptor=${air.library.name}-ios-platformoptions.xml |
4.4. Do you have a default implementation for your ANE?
If you answered ‘I do’, repeat step 4.3. to build your default implementation SWC. Come on, you don’t expect me to do copy and paste here, right?
5. Add targets for collecting the files we’ll need to package the ANE
Are you still with me? That’s probably the most tedious bit of the whole exercise, so if you decide to abandon the article at this point, I won’t blame you.
For the three people still reading, let’s roll up our sleeves and get on with it. Mum, dad, I’ll explain what Ant is when I next speak with you on Skype…
5.1. The following two targets will make sure you have a temporary folder for packaging to copy files into. Unless it exists already.
<available property=“temp.packagedir.exists” file=“${temp.packagedir}”/>
</target>
<target name=“create package folder” depends=“does package dir exist” unless=“temp.packagedir.exists” description=“Create temporary folder for the package ingredients”>
<mkdir dir=“${temp.packagedir}”/>
</target>
5.2. The next target automates what you did by hand in steps 1.a. to 1.d. in Recipe for packaging an ANE.
<target name=“copy ios files for packaging” depends=“rebuild ios, build air library, create package folder”>
<copy file=“${air.library.sourcedir}/${air.extension.descriptor}” todir=“${temp.packagedir}”/>
<copy file=“${air.library.sourcedir}/${air.platform.descriptor}” todir=“${temp.packagedir}”/>
<copy file=“${iOS.project.outputdir}/${iOS.library}” todir=“${temp.packagedir}”/>
<copy file=“${air.library.outputdir}/${air.library.name}.swc” todir=“${temp.packagedir}”/>
<copy file=“${air.library.outputdir}/library.swf” todir=“${temp.packagedir}”/>
</target>
6. Add a target to package your ANE
Finally. Let us now automate the command line that you would normally have to run by hand. Like the rest of this example, the following will package an ANE for iOS. You can extend that to cover other platforms.
<target name=“package ane” depends=“copy ios files for packaging” description=“Package the extension into an ANE file”>
<mkdir dir=“${temp.packagedir}/ane”/>
<exec executable=“${ADT}” failonerror=“true” dir=“${temp.packagedir}”>
<arg line=“-package
-target ane ane/${ane.name}.ane
${air.extension.descriptor}
-swc ../${air.library.name}/swc/${air.library.name}.swc
-platform iPhone-ARM
-C . .
-platformoptions ${air.platform.descriptor}”
/>
</exec>
<mkdir dir=“${ane.destination}”/>
<move file=“${temp.packagedir}/ane/${ane.name}.ane” todir=“${ane.destination}” overwrite=“true”/>
<delete dir=“${tempdir}”/>
</target>
Add these last two properties to build.properties to tell Ant what your .ANE file should be called and where you want it to end up and you are done:
1 2 3 |
# File name and folder for the packaged ANE: ane.name=TheNameOfYourANEFileWithoutTheExtension ane.destination=../../ane |
7. Run the script
Are you ready?
Open a Terminal window and navigate to your build.xml file, then run
If all went to plan, you should see something like this at the end of the long log that ADT spits out:
Total time: 10 seconds
If there were build or packaging errors instead, give us a shout in the comments below. We want to help.
Hey, didn’t we say a single click build?
That’s so far a single command-line build… Don’t worry, it doesn’t end here. Being a man, well, a woman of my word, I’ll take you along that last mile, should you like to join me.
You have so far done the hard work, the rest is quick and easy: head over to Package your ANE in Flash Builder.
Malcolm Hardy
I need a build script for an Android ane build.
I bought your excellent eBook and have successfully built and tested my ane for iOS. It is for mobile printing for the Star SM220 printer.
Thanks very much.
Radoslava
Hi Malcolm,
I’m e-mailing you scripts for packaging an Android ANE and instructions on how to customize them for your project.
Really glad to hear that the book has been helpful. You’ll find the package I’ve sent you quite similar to the scripts you have made with the help of the Easy Native Extensions book, so it will probably take you no time to get your Android ANE packaging automated.
Let us know how it goes,
Radoslava
leo
i would be really interested on your ane. would you mind sharing it?
Radoslava
Hi Leo, you can find all our ANEs here: http://easynativeextensions.com/shop/
Quinn
Hi DiaDraw,
great tutorials. I actually need a set of script for all the platforms – iOS, Android, Mac OS, and Windows for one of the projects I am working on. Thank you so much for putting all this together
-Quinn
Quinn
Also I just wanted to thank you for a great introduction to Apache Ant as well
Radoslava
Glad that you find these useful. I’m e-mailing you a set of build script files for iOS, Mac OS, Android and Windows + a readme file on how to use them. Keep us posted on how these are working for you.
Radoslava
Federico
Great tutorial!! if you could send me a couple of sample scripts fo iOS and Android that would be great. Looking forward to read your books.
Thank you!!
Radoslava
Federico, thank you for the kind feedback.
I’m glad that you have found the automation tutorial useful and that you are looking to put it in practice. Those build scripts have saved me sooo many hours of frustration…
I have just e-mailed you a set of scripts for iOS and for Android, as you requested.
Please let us know how they worked for you.
Greetings,
Radoslava
The DiaDraw Team
Eric Zwar
Hi Radoslava, I used the Windows build script that you sent me – thanks.
I found two traps for me in my Windows 7 64 bit environment:
1) ANT needs a 32 bit version of the Java JDK – previously I had the 64 bit JDK installed.
2) in the local.properties file I had to add “.bat” to the adt directive – i.e. adt.bat instead of just adt.
This is the first time I have used ANT but I have to admit it is a great tool in this context!
Cheers.
b
I am getting an Error for:
“The extension NameSpace requires the SWF version 17” while compile ant. I believe it has to do w -platformoptions.xml and -extension.xml
Any thoughts?
-B
Radoslava
Hi B,
What namespaces are you using in your platformoptions.xml and extension.xml?
You can get the Adobe compiler to use a specific SWF version in two ways:
– if you are using the build scripts we sent you, open build.xml and add -swf-version=17 to the argument line for COMPC in the “build swc” target;
– if you aren’t using build sciprt, open your project’s properties, go to Flex Library Compiler and add this to Additional Compiler Arguments: -swf-version=17
Radoslava
yo
Nice. Can i get the template build scripts?
Radoslava
Hi yo,
Sure. Which platforms do you need scripts for?
Emad
Can i get the template build scripts for windows,Mac, IOS, Android?
Radoslava
Hi Emad,
I have just emailed you the build scripts which you can use to build and package ANEs for iOS, Mac OS, Android and Windows. There is a readme file in the package that explains how to use them.
Let us know how they are working for you and if any clarification is needed.
You can package a single ANE for all four platforms. For that you will need to do the following:
– list all the platforms in your extension descriptor file;
– if you package your ANE using the build scripts I have sent you, you will need to add another package target, which calls ADT for all platforms at the same time; for example, if you wanted to do iOS, Android and simulator support together, the arg line for ADT in the target may look like this:
-package
-target ane
ane/${ane.name}.ane
${air.extension.descriptor}
-swc ../${air.library.name}/swc/${air.library.name}.swc
-platform iPhone-ARM
-C . .
-platformoptions ${air.platform.descriptor}
-platform Android-ARM
-C . .
-platform default -C ${default.swcdir} library.swf
Cheers,
Radoslava
Emad
Hi Radoslave,
Thanks for scripts and i will try to build ane file to all platforms.
Regards,
Emad
morgan
Hello
Those are really helpful tutorials!
Is it possible to get the set of build scripts? Thanks a lot
Radoslava
Hi Morgan,
Which platforms will you need build scripts for?
Cheers,
Radoslava
Tom
Hi, would it be possible that you send me the build scripts for Windows ,Mac, IOS & Android?
Radoslava
Hi Tom,
I’ve just emailed you the scripts. Let us know how they are working for you.
Radoslava
sa
hi
thank for your really good explanation and website
i need android packaging script, please email it to me
Hristo
Hi sa,
I’ve just emailed you build scripts which you can use to build and package ANEs for iOS, Mac OS, Android and Windows. There is a readme file in the package that explains how to use them.
Let us know how the scripts are working for you and if any clarification is needed.
Cheers,
Hristo
Sohel
Hi,
You able to send scripts for iOS and Android?
Thanks
Hristo
Hi Sohel,
I’ve just emailed you build scripts which you can use to build and package ANEs for iOS, Mac OS, Android and Windows. There is a readme file in the package that explains how to use them.
Let us know how the scripts are working for you and if any clarification is needed.
Cheers,
Hristo
Pruthvi
Error occurred while packaging the application:
C:\Users\pc\Adobe Flash Builder 4.7\ANESampleTest\bin-debug\ANESampleTest-app.xml: error 102: Invalid namespace http://ns.adobe.com/air/application/3.4
what am i doing wrong? Plz help me
Hristo
Hi Pruthvi,
This type of error can occur in two situations:
1. You have different version than 3.4 AIR SDK installed on your machine.
Try this: open your ANESampleTest-app.xml (the one in your project folder, most likely C:\Users\pc\Adobe Flash Builder 4.7\ANESampleTest\src\ANESampleTest-app.xml, not the one in bin-debug that the error message quotes) and change the namespace version at the top to match the AIR SDK version you have installed, for example: <application xmlns=”http://ns.adobe.com/air/application/19.0″>.
2. Your Flex Builder could not find the path to the AIR SDK.
Here are some links with info how to fix this:
https://forums.adobe.com/thread/1073062?tstart=0
http://stackoverflow.com/questions/31298596/invalid-unknown-namespace-in-air-application-with-air-native-extension-ane
http://www.flashdevelop.org/community/viewtopic.php?f=13&t=10044
Hope this helps.
Cheers,
Hristo
Tom
Hi,
Can i get the template scripts for Windows, Mac, IOS and Android?
Thank you
Hristo
Hi Tom,
I’ve just emailed you the scripts. Let us know how they are working for you.
Happy festive season!
Cheers,
Hristo
Sergio
Hi,Good job!
Can i get the template build scripts for IOS and Android?
Thanks
Hristo
Hi Sergio,
I have just e-mailed you the build scripts. I hope they do a good job for you.
Get in touch if you have questions.
Cheers,
Hristo
sorrex
Hi, Hristo
thanks you for your job, it is really nice tutorial.
Im not able to build it in FlashDevelop, that I use.
Im not able to link adobe libraries that leads to missing
ExtensionContext definition. Anyway in FB I did it successfully.
Please, can I ask you for script for Windows.
I would like to see how ant can do the job.
I have no experience with it. So it time to change it
thanks in advance
Fabrice Montfort
I had the same problem. I’ve fixed it by uncommenting this line in the build.xml :
Now I can compile SWC file for my ANE library.
Hope it helps
Fabrice Montfort
Fabrice Montfort
load-config filename=".......
Radoslava
Great help, Fabrice, thank you!
Radoslava
Hi sorrex,
Apologies for the long delay! I have just emailed you the build scripts for Windows. Let us know how they are working for you.
Kirill
Very awesome tutorial!
I need template build for android, could you send it?
Thank you!
Radoslava
Hi Kirill,
I’ve just emailed you the scripts for Android and a README file with instructions for how to customise them for your projects. Let us know how they are working for you.
Cheers,
Radoslava
Collin Brown
Great tutorial! Could you send me the build template for iOS?
Hristo
Hi Collin,
I have just emailed you the build scripts for iOS.
Let us know how they are working for you.
Best,
Hristo
Cala
This is an awesome tutorial! Thanks for taking the time to write it.
Is it possible to get the build scripts for iOS and Android?
TIA!
john errith
great tutorial!
Is it possible to get the build scripts for windows Thanks!
Radoslava
Hi John, I have just sent you the scripts for Windows. I hope they still work!
Radoslava