Everything You Wanted to Know About How SWF get into an IPA for iOS

Flash, as a runtime, running as a browser plugin, made things simple and straightforward

  • install a plugin (the runtime)
    (or be sure the plugin is already there, detect it)
  • point it to a SWF
    that can contains code, medias, assets, etc.
  • run it

And off course AIR, another runtime, that does run inside a browser, followed the same logic

  • detect/install the AIR runtime
  • point it to an app XML and a SWF
  • run it

Now with iOS from the get go Apple with the iPhone SDK License agreement (see Terms and Conditions) put some rules in place

  • you can only interpret JavaScript code
  • and you can only interpret it through our own browser engine

which meant back in the day

  • can’t use an interpreter
  • can’t JIT code
    eg. interpret “Just In Time” code through a VM

and that blocked all the interpreters out there, not only AIR
but also Java, .NET, Python, Lua, etc.


But one thing that Apple did not forbid was binaries, your classic IPA

An .ipa ( i OS A pp Store P ackage) file is an iOS application archive file which stores an iOS app. Each .ipa file includes a binary and can only be installed on an iOS device. Files with the .ipa extension can be uncompressed by changing the extension to .zip and unzipping.

And so Adobe came up with a very clever solution, based on what they already explored with Alchemy (later renamed to CrossBridge)

CrossBridge is an open-source toolset developed by Adobe Systems, that cross-compiles C and C++ code to run in Adobe Flash Player or Adobe AIR. Projects compiled with CrossBridge run up to 10 times faster than ActionScript 3 projects. CrossBridge was also known as “Alchemy” and the “Flash Runtime C++ Compiler”, or “FlasCC”.

They reused LLVM (Low Level Virtual Machine), an open source compiler infrastructure designed for optimizing programs written in arbitrary programming languages.

With LLVM they were capable of generating machine code for various targets including x86 and ARM processors.

Side Note:
About compilers and compiling, don’t be afraid by those
compiling is just the process of transforming a set of symbols into another set of symbols
so yeah most of the compiler tools and toolchains out there are advanced and complex
but the principle stay the same, eg. transforming A into B
When you are compiling ActionScript 3.0, you are transforming the plain text symbols into a more compact binary structure that we call “bytecode” (another set of symbols).
And if you can transform A into B, you can also transform B into C, etc.

It is all explained here in this PDF
Building High Performance iPhone Applications with Flash CS5
flash_iphone_fitc_2010.pdf (8.9 MB)
(original URL: http://www.mikechambers.com/blog/files/fitc_amsterdam_2010/flash_iphone_fitc_2010.pdf)
by Mike Chambers
Principal Product Manager
Developer Relations
Flash Platform
(October 5, 2009)

So Adobe built a SWF / ABC front-end for LLVM, put another way they added an extension to LLVM that allow to input SWF/ABC symbols and so were able to reuse whatever output LLVM was already providing, in this case ARM binary that work on iOS.

and this gave the following publishing workflow

You still publish a SWF configured with an app.xml and other resources
Using the PFI (Platform Interpreter) you combien the iOS certificate to generate a native application .ipa

In the associated blog post Building Applications for the iPhone with Flash summarise it quite well

The next version of Flash Authoring will enable developers to create stand-alone iPhone applications using Flash technologies (including ActionScript 3). These applications are just like any other iPhone application and can be distributed via the Apple iTunes Application store. Indeed, there are already a number of applications created with Flash on the store today.

One thing I want to stress is that this is for standalone applications, and is not the Flash Player for mobile Safari (which is something we continue to work on). The end result is a native iPhone application, and not a SWF that runs in the browser. We compile the SWF to a native application using LLVM. There is no requirement for the Flash Player / Adobe AIR Runtime to be installed on the device or included in the application. The end result is a native iPhone application.

You can see the details of the PFI with the ADT input and output

By default, when Flash or AIR interpret a SWF it uses JIT (Just In Time) compilation
eg. from bytecode (ABC, ActionScript ByteCode) it generates machine code instruction on the fly

In computing, just-in-time ( JIT ) compilation (also dynamic translation or run-time compilations ) is a way of executing computer code that involves compilation during execution of a program – at run time – rather than before execution. Most often, this consists of source code or more commonly bytecode translation to machine code, which is then executed directly. A system implementing a JIT compiler typically continuously analyses the code being executed and identifies parts of the code where the speedup gained from compilation or recompilation would outweigh the overhead of compiling that code.

Here, to generate an IPA, the SWF is interpreted and compiled AOT (Ahead Of Time)

In computer science, ahead-of-time compilation ( AOT compilation ) is the act of compiling a higher-level programming language such as C or C++, or an intermediate representation such as Java bytecode or .NET Framework Common Intermediate Language (CIL) code, into a native (system-dependent) machine code so that the resulting binary file can execute natively.

AOT produces machine optimized code, just like a standard native compiler. The difference is that AOT transforms the bytecode of an extant virtual machine (VM) into machine code.

Here the full blown details of the AOT compilation, notice that there is a library from of the Flash Player runtime included in the application and ABC bytecode is compiled to native ARM code.

And that was at the time of Flash Player 10.1 / AIR 2.0


But it did not stop there, with AIR SDK 14.0 Adobe updated all that, and it is all explained here
Faster Compiling with AIR for iOS

Compiled Mode Overview

When packaging an AIR application for iOS:

  1. The developer’s SWF file is parsed to extract the Action Script Bytecode (abc) chunks.
  2. The abc content is then analyzed and each AS function is translated to the respective native function using the LLVM API.
  3. An object file for the target platform is generated with the help of LLVM code generation .
  4. An executable file is then created by linking the object files with AIR Runtime libraries.

The iOS platform does not support loading executable code, dynamically. This limitation, however, allows the AIR packager to employ optimization techniques that increase run-time performance. This optimization is possible because the entire code is available at compile time.

See Figure 1 for an illustration of the AIR application packaging in the compiled mode.

Legacy compiler v/s New compiler

The new compiler is built on top of the Action Script virtual machine. Following is a comparison of the re-designed compiler and the legacy compiler.

See Figures 2 and 3 for an illustration of the changes in the re-designed compiler.

legacy_compiler

And later on with AIR SDK 16.0, the legacy compiler was removed

Note : From AIR SDK version 16.0 onwards, the legacy compiler will not be supported and only the new compiler will be supported. As a result, -useLegacyAOT switch will not be honored anymore.


Guess what? it still did not stop there :stuck_out_tongue:
Developers with Flash in the browser took a heavy habit to load external SWF at runtime
but on the mobile platform and especially on iOS things are different

Remember, because of iOS licensing you can not interpret things dynamically, that’s verbotten hard by Apple

But then Adobe come with a solution, see here
Packaging and loading multiple SWFs in AIR apps on iOS (2012)

at first we had that

Until now, AIR required that when packaging in AOT mode, all the ActionScript code of an AIR iOS app should be present inside the main SWF. Any SWF other than the main SWF, that is provided at the time of packaging, is added to the final application package (IPA) as a resource . Any attempt to load a SWF (local or remote) dynamically that contains ActionScript byte code (or ABC) using either Loader.load() or Loader.loadBytes, resulted in an “Uncompiled ActionScript” error. A screenshot of the error dialog is below:

uncompiled_AS3

It was working for SWF files not containing code

Please note that if the SWF that is being loaded dynamically does not contain any ABC and contains only assets like bitmaps or audio, the SWF will be loaded successfully (even with AIR 3.4 and before). In fact, few developers have used this technique, to host asset-only SWFs on web servers and these are fetched only when needed. By downloading asset-SWFs on demand at run-time, developers have been able to reduce the size of their applications.

and so they updated the behaviour like that

The ABC code from the main SWF and all the secondary SWFs is extracted and placed in the main executable. The non-ABC parts of a SWF or assets in a SWF are kept inside the IPA (as assets). They are drawn in memory when explicitly asked using the Loader.load() call.

with those limitations

Secondary_SWF_with_ABC

Great, you could have some of the code in a secondary SWF, and the AOT compiler extract the ABC from it, merge the code into the code of the main SWF, and keep the SWF as an external asset.

And later they updated it so you could also load SWF from an remote location, see
External hosting of secondary SWFs for AIR apps on iOS

No perfect nor ideal but still better than nothing
(remember that the limitation is entirely the fault of Apple forbidding interpreters on iOS)

the process would still be the same, secondary SWF (hosted on a remote server) got its ABC extracted and merged into the main SWF, and for this to work you need to provide a URL map of those external SWF

assets/SampleSWFInfoFile.txt

assets/Level1.swf
assets/Level2.swf
assets/Level3/asset/Level3.swf

and then in your app XML

<iPhone>
       <externalSwfs>assets/SampleSWFInfoFile.txt</externalSwfs>
</iPhone>

and so

During IPA packaging, ADT extracts the ABC code from all child SWFs, adds it to the final executable and generates stripped SWFs in the “externalStrippedSwfs” folder created in the current working directory. The directory structure within the “externalStrippedSwfs” folder remains the same as specified within the text file. The generated stripped SWF’s should then be externally hosted on a web server of developer’s choice.


Voila, it’s all there is to it, all the little nitty gritty details on how your SWF files end up into an IPA so it can run on iOS and tvOS.

One last thing, about AOT, it is not the saint graal of performance
as mentioned here AOT or Interpreter

It is important to realize that ahead-of-time compilation is not a magic bullet for performance. If your application is not actionscript intensive then ahead-of-time compilation and interpreter mode may have the similar performance.

9 Likes

2 posts were split to a new topic: How to test without Apple ID

zwetan,this topic is great:grinning: