Via Intel Software
-----
Introduction
The Intel® HTML5 App Porter Tool - BETA is an application
that helps mobile application developers to port native iOS* code into
HTML5, by automatically translating portions of the original code into
HTML5. This tool is not a complete solution to automatically port 100%
of iOS* applications, but instead it speeds up the porting process by
translating as much code and artifacts as possible.
It helps in the translation of the following artifacts:
- Objective-C* (and a subset of C) source code into JavaScript
- iOS* API types and calls into JavaScript/HTML5 objects and calls
- Layouts of views inside Xcode* Interface Builder (XIB) files into HTML + CSS files
- Xcode* project files into Microsoft* Visual Studio* 2012 projects
This document provides a high-level explanation about how the
tool works and some details about supported features. This overview will
help you determine how to process the different parts of your project
and take the best advantage from the current capabilities.
How does it work?
The Intel® HTML5 App Porter Tool - BETA is essentially a
source-to-source translator that can handle a number of conversions from
Objective-C* into JavaScript/HTML5 including the translation of APIs
calls. A number of open source projects are used as foundation for the
conversion including a modified version of Clang front-end, LayerD framework and jQuery Mobile for widgets rendering in the translated source code.
Translation of Objective-C into JavaScript
At a high level, the transformation pipeline looks like this:
This pipeline follows the following stages:
- Parsing of Objective-C* files into an intermediate AST (Abstract Syntax Tree).
- Mapping of supported iOS* API calls into equivalent JavaScript calls.
- Generation of placeholder definitions for unsupported API calls.
- Final generation of JavaScript and HTML5 files.
About coverage of API mappings
Mapping APIs from iOS* SDK into JavaScript is a task that involves a
good deal of effort. The iOS* APIs have thousands of methods and
hundreds of types. Fortunately, a rather small amount of those APIs are
in fact heavily used by most applications. The graph below conceptually
shows how many APIs need to be mapped in order to have certain level of
translation for API calls .
Currently, the Intel® HTML5 App Porter Tool - BETA supports the most used types and methods from:
- UIKit framework
- Foundation framework
Additionally, it supports a few classes of other frameworks such
as CoreGraphics. For further information on supported APIs refer to the
list of supported APIs.
Generation of placeholder definitions and TODO JavaScript files
For the APIs that the Intel® HTML5 App Porter Tool - BETA
cannot translate, the tool generates placeholder functions in "TODO"
files. In the translated application, you will find one TODO file for
each type that is used in the original application and which has API
methods not supported by the current version. For example, in the
following portion of code:
3 |
UIButton* myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; |
5 |
[myButton setTitle:text forState:UIControlStateNormal]; |
7 |
myButton.showsTouchWhenHighlighted = YES; |
If property setter for showsTouchWhenHighligthed
is not supported by the tool, it will generate the following placeholder for you to provide its implementation:
1 |
APT.Button.prototype.setShowsTouchWhenHighligthed = function (arg1) { |
3 |
if (APT.Global.THROW_IF_NOT_IMPLEMENTED) |
6 |
throw "Not implemented function: APT.Button.setShowsTouchWhenHighligthed" ; |
These placeholders are created for methods, constants, and types that
the tool does not support. Additionally, these placeholders may be
generated for APIs other than the iOS* SDK APIs. If some files from the
original application (containing class or function definitions) are not
included in the translation process, the tool may also generate
placeholders for the definitions in those missing files.
In each TODO file, you will find details about where those types,
methods, or constants are used in the original code. Moreover, for each
function or method the TODO file includes information about the type of
the arguments that were inferred by the tool. Using these TODO files,
you can complete the translation process by the providing the
placeholders with your own implementation for that API.
Translation of XIB files into HTML/CSS code
The Intel® HTML5 App Porter Tool - BETA translates most of the definitions in the Xcode* Interface Builder files (i.e.,
XIB files) into equivalent HTML/CSS code. These HTML files use JQuery*
markup to define layouts equivalent to the views in the original XIB
files. That markup is defined based on the translated version of the
view classes and can be accessed programmatically.
Moreover, most
of the events that are linked with handlers in the original application
code are also linked with their respective handles in the translated
version. All the view controller objects, connection logic between
objects and event handlers from all translated XIB files are included in
the XibBoilerplateCode.js
. Only one XibBoilerplateCode.js
file is created per application.
The figure below shows how the different components of each XIB file are translated.
This is a summary of the artifacts generated from XIB files:
- For each view inside an XIB file, a pair of HTML+CSS files is generated.
- Objects inside XIB files, such as Controllers and Delegates, and instantiation code are generated in the
XibBoilerplateCode.js
file.
- Connections between objects and events handlers for views described
inside XIB files are also implemented by generated code in the
XibBoilerplateCode.js
file.
For further information on supported widgets and properties refer to the Supported .XIB file featuressection.
Architecture of translated applications
The translated application keeps the very same high level structure
as the original one. Constructs such as Objective-C* interfaces,
categories, C structs, functions, variables, and statements are kept
without significant changes in the translated code but expressed in
JavaScript.
The execution of the Intel® HTML5 App Porter Tool – BETA produces a set of files that can be divided in four groups:
- The translated app code: These are the JavaScript files that were created as a translation from the original app Objective-C* files.
- For each translated module (i.e. each
.m
file) there should be a .js
file with a matching name.
- The default.html file is the entry point for the HTML5 app, where all the other
.js
files are included.
- Additionally, there are some JavaScript files included in the
\lib
folder that corresponds to some 3rd party libraries and Intel® HTML5 App Porter Tool – BETA library which implements most of the functionality that is not available in HTML5.
- Translated
.xib
files (if any): For each translated .xib
file there should be .html
and .css
files with matching names. These files correspond to their HTML5 version.
- “ToDo” JavaScript files: As the translation of some of the
APIs in the original app may not be supported by the current version,
empty definitions as placeholders for those not-mapped APIs are
generated in the translated HTML5 app. This “ToDo” files contain those
placeholders and are named after the class of the not-mapped APIs. For
instance, the placeholders for not-mapped methods of the
NSData
class, would be located in a file named something like todo_api_js_apt_data.js
or todo_js_nsdata.js
.
- Resources: All the resources from the original iOS* project will be copied to the root folder of the translated HTML5 app.
The generated JavaScript files have names which are practically the
same as the original ones. For example, if you have a file called AppDelegate.m
in the original application, you will end up with a file called AppDelegate.js
in the translated output. Likewise, the names of interfaces, functions,
fields, or variables are not changed, unless the differences between
Objective-C* and JavaScript require the tool to do so.
In short, the high level structure of the translated application is
practically the same as the original one. Therefore, the design and
structure of the original application will remain the same in the
translated version.
About target HTML5 APIs and libraries
The Intel® HTML5 App Porter Tool - BETA both translates the
syntax and semantics of the source language (Objective-C*) into
JavaScript and maps the iOS* SDK API calls into an equivalent
functionality in HTML5. In order to map iOS* API types and calls into
HTML5, we use the following libraries and APIs:
- The standard HTML5 API: The tool maps iOS*
types and calls into plain standard objects and functions of HTML5 API
as its main target. Most notably, considerable portions of supported
Foundation framework APIs are mapped directly into standard HTML5. When
that is not possible, the tool provides a small adaptation layer as part
of its library.
- The jQuery Mobile library: Most of the UIKit
widgets are mapped jQuery Mobile widgets or a composite of them and
standard HTML5 markup. Layouts from XIB files are also mapped to jQuery
Mobile widgets or other standard HTML5 markup.
- The Intel® HTML5 App Porter Tool - BETA library:
This is a 'thin-layer' library build on top of jQuery Mobile and HTML5
APIs and implements functionality that is no directly available in those
libraries, including Controller objects, Delegates, and logic to
encapsulate jQuery Mobile widgets. The library provides a facade very
similar to the original APIs that should be familiar to iOS* developers.
This library is distributed with the tool and included as part of the
translated code in the
lib
folder.
You should expect that future versions of the tool will incrementally
add more support for API mapping, based on further statistical analysis
and user feedback.
Translated identifier names
In Objective-C*, methods names can be composed by several parts
separated with colons (:) and the methods calls interleaved these parts
with the actual arguments. Since that peculiar syntactic construct is
not available in JavaScript, those methods names are translated by
combining all the methods parts replacing the colons (:) with
underscores (_). For example, a function called initWithColor:AndBackground:
is translated to use the name initWithColor_AndBackground
Identifier names, in general, may also be changed in the translation
if there are any conflicts in JavaScript scope. For example, if you have
duplicated names for interfaces and protocol, or one instance method
and one class method that share the same name in the same interface.
Because identifier scoping rules are different in JavaScript, you cannot
share names between fields, methods, and interfaces. In any of those
cases, the tool renames one of the clashing identifiers by prepending an
underscore (_) to the original name.
Additional tips to get the most out of the Intel® HTML5 App Porter Tool – BETA
Here is a list of recommendations to make the most of the tool.
- Keep your code modular
Having a
well-designed and architected source code may help you to take the most
advantage of the translation performed by tool. If the modules of the
original source code can be easily decoupled, tested, and refactored the
same will be true for the translated code. Having loosely coupled
modules in your original application allows you to isolate the modules
that are not translated well into JavaScript. In this way, you should be
able to simply skip those modules and only select the ones suitable for
translation.
- Avoid translating third party libraries source code with equivalents in JavaScript
For some iOS* libraries you can find replacement libraries or APIs in
JavaScript. Common examples are libraries to parse JSON, libraries to
interact with social networks, or utilities libraries such as Box2D* for
games development. If your project originally uses the source code of
third party library which has a replacement version in JavaScript, try
to use the replacement version instead of translated code, whenever it
is possible.
- Isolate low level C or any C++ code behind Objective-C* interfaces:
The tool currently supports translating from Objective-C*, only. It
covers the translation of most of C language constructs, but it does not
support some low level features such as unions, pointers, or bit
fields. Moreover, the current version does not support C++ or
Objective-C++ code. Because of this limitation, it is advisable to
encapsulate that code behind Objective-C interfaces to facilitate any
additional editing, after running the tool.
In conclusion, having a well-designed application in the first place
will make your life a lot easier when porting your code, even in a
completely manual process.
Further technical information
This section provides additional information for developers and it is not required to effectively use Intel® HTML5 App Porter Tool - BETA. You can skip this section if you are not interested in implementation details of the tool.
Implementation of the translation steps
Here, you can find some high level details of how the different processing steps of the Intel® HTML5 App Porter Tool - BETA are implemented.
Objective-C* and C files parsing
To parse Objective-C* files, the tool uses a modified version of clang parser. A custom version of the parser is needed because:
- iOS* SDK header files are not available.
- clang is only used to parse the source files (not to compile them) and dump the AST to disk.
The following picture shows the actual detailed process for parsing .m and .c files:
Missing iOS* SDK headers are inferred as part of the parsing process.
The header inference process is heuristic, so you may get parsing
errors, in some cases. Thus, you can help the front-end of the tool by
providing forward declaration of types or other definitions in header
files that are accessible to the tool.
Also, you can try the "Header Generator" module in individual files
by using the command line. In the binary folder of the tool, you will
find an executable headergenerator.exe
that rubs that process.
Objective-C* language transformation into JavaScript
The translation of Objective-C* language into JavaScript involves a
number of steps. We can divide the process in what happens in the
front-end and what is in the back-end.
Steps in the front-end:
- Parsing .m and .c into an XML AST.
- Parsing comments from .m, .c and .h files and dumping comments to disk.
- Translating Clang AST into Zoe AST and re-appending the comments.
The output of the front-end is a Zoe program. Zoe is an
intermediate abstract language used by LayerD framework; the engine that
is used to apply most of the transformations.
The back-end is fully implemented in LayerD by using compile time
classes of Zoe language that apply a number of transformations in the
AST.
Steps in the back-end:
- Handling some Objective-C* features such as properties getter/setter injection and merging of categories into Zoe classes.
- Supported iOS* API conversion into target JavaScript API.
- Injection of not supported API types, or types that were left outside of the translation by the user.
- Injection of dummy methods for missing API transformations or any other code left outside of the translation by the user.
- JavaScript code generation.
iOS* API mapping into JavaScript/HTML5
The tool supports a limited subset of iOS* API. That subset is
developed following statistical information about usage of each API.
Each release of the tool will include support for more APIs. If you miss
a particular kind of API your feedback about it will be very valuable
in our assessment of API support.
For some APIs such as Arrays and Strings the tool provides direct
mappings into native HTML5 objects and methods. The following table
shows a summary of the approach followed for each kind of currently
supported APIs.
Framework |
Mapping design guideline |
Foundation |
Direct mapping to JavaScript when possible. If direct mapping is not possible, use a new class built over standard JavaScript. |
Core Graphics |
Direct mapping to Canvas and related HTML5 APIs when possible. If
direct mapping is not possible, use a new class built over standard
JavaScript. |
UIKit Views |
Provide a similar class in package APT, such as APT.View for UIView,
APT.Label for UILabel, etc. All views are implemented using jQuery
Mobile markup and library. When there are not equivalent jQuery widgets
we build new ones in the APT library. |
UIKit Controllers and Delegates |
Because HTML5 does not provide natively controllers or delegate
objects the tool provides an implementation of base classes for
controllers and delegates inside the APT package. |
Direct mapping implies that the original code
will be transformed into plain JavaScript without any type of additional
layer. For example,
1 |
NSArray anArray = [NSArray arrayWithObjects:@ "One" ,@ "Two" ,@ "Three" ,nil]; |
3 |
var anArray = [ "One" , "Two" , "Three" ]; |
The entire API mapping happens in the back-end of the tool. This
process is implemented using compile time classes and other
infrastructure provided by the LayerD framework.
XIB files conversion into HTML/CSS
XIB files are converted in two steps:
- XIB parsing and generation of intermediate XML files.
- Intermediate XML files are converted into final HTML, CSS and JavaScript boilerplate code.
The first step generates one XML file - with extension .gld -
for each view inside the XIB file and one additional XML file with
information about other objects inside XIB files and connections between
objects and views such as outlets and event handling.
The second stage runs inside the Zoe compiler of LayerD to convert
intermediate XML files into final HTML/CSS and JavaScript boilerplate
code to duplicate all the functionality that XIB files provides in the
original project.
Generated HTML code is as similar as possible to static markup used
by jQuery Mobile library or standard HTML5 markup. For widgets that do
not have an equivalent in jQuery Mobile, HTML5, or behaves differently,
simple markup is generated and handled by classes in APT library.
Supported iOS SDK APIs for Translation
The following table details the APIs supported by the current version of the tool.
Notes:
-
Types refers to Interfaces, Protocols, Structs, Typedefs or Enums
-
Type 'C global' mean that it is not a type, but it is a supported global C function or constant
-
Colons in Objective-C names are replaced by underscores
-
Objective-C properties are detailed as a pair of getter/setter method names such as 'title' and 'setTitle'
-
Objective-C static members appear with a prefixed underscore like in '_dictionaryWithObjectsAndKeys'
-
Inherited members are not listed, but are supported. For example,
NSArray supports the 'count' method. The method 'count' is not listed in
NSMutableArray, but it is supported because it inherits from NSArray