In addition to this document, check out our tutorials, which contain a mix of slides and code: http://xmlvm.org/tutorial
XMLVM is a flexible cross-compilation framework. Instead of cross-compiling source code of high-level programming languages, XMLVM translates byte code instructions. Byte code programs are represented by XML documents and cross-compiled via XSL stylesheets. Section "Overview" provides a brief overview of the XMLVM toolchain. Section "Getting XMLVM" describes how to obtain the source code of XMLVM and Section "Compiling XMLVM" how to build XMLVM from source. The various command line options supported by XMLVM are described in Section "Invoking XMLVM".
XMLVM supports byte code instructions from different virtual machines: the Java Virtual Machine (JVM), the Common Language Runtime (CLR) that is part of the .NET framework, and the YARV byte code from Ruby 1.9. The name XMLVM is inspired by the fact that byte code instructions are represented via XML. Each byte code instruction is mapped to a corresponding XML-tag. Transformations of XMLVM programs are done via XSL stylesheets. The following Figure shows all possible paths through the XMLVM toolchain:
The first step in using XMLVM is to compile a Java or .NET source code
program to byte code. This is done with a native compiler such as Sun
javac or Microsoft's Visual Studio. The resulting byte code program (either a Java
.class file or a .NET
.exe file) is fed into the XMLVM toolchain where it is first converted to XML. XMLVMJVM denotes an XMLVM program that contains JVM byte code instructions, whereas a XMLVMCLR program contains CLR byte code instructions. XMLVMDEX makes use of Android's DEX instructions for Dalvik that is is particularly suitable for generating source of other high-level programming languages. It is possible to cross-compile XMLVMCLR to XMLVMJVM with the help of a data flow analysis (denoted as XMLVMCLR-DFA in the Figure above).
It should be noted that XMLVM is a research project and as such lacks the completeness of a commercial product. Each individual backend requires a significant effort to support different APIs. WinForms, AWT/Swing, and Cocoa Touch are all complex libraries and at this point XMLVM only supports a subset of each. The various paths through the XMLVM toolchain have different levels of maturity that should be taken into consideration when using XMLVM. The C backend is the most complete and it is possible to build complex iOS applications.
XMLVM is released under the L-GPL v2 license and is hosted at SourceForge. We currently do not offer pre-compiled binary packages. The only way to obtain XMLVM is to checkout the latest version from the Subversion repository. You will need a Subversion client to do this. If you are using a command line version of Subversion, you can checkout the trunk of the XMLVM repository via the following command:
svn co https://xmlvm.svn.sourceforge.net/svnroot/xmlvm/trunk/xmlvm
Note that this will give you a read-only version of the repository. You will be able to update (which you should do frequently) but not commit changes to the repository. If you find a bug, please send a mail to the XMLVM mailing list.
XMLVM is developed using the Eclipse IDE. You can also checkout the sources of XMLVM via Eclipse (using an appropriate Subversion plugin such as Subclipse or Subversive). The XMLVM sources contain
.classpath files so that Eclipse will recognize XMLVM as an Eclipse project. The benefit of using Eclipse is that it makes it easy to navigate the source code if you intend to study the internals of XMLVM. There are also numerous Eclipse launch configurations (in the
etc/ directory) that allow the invocation of various demos.
XMLVM depends on numerous third-party libraries such as BCEL, JDOM, and Saxon. All these libraries are also released under an Open Source license. To facilitate the compilation process, XMLVM contains binary versions (i.e., jars) of all required libraries. All third-party libraries are contained in the
lib directory. Building XMLVM from sources requires Java 1.6 as well as ant. In order to compile XMLVM from command line, simply run ant in the XMLVM root directory:
After a successful run of ant, there should be a
dist/ directory. The ant script packages all dependent libraries and XMLVM's own class files into one jar file. The only file needed to run XMLVM is the jar file
dist/xmlvm.jar. This jar file can be copied to a convenient location with the
ant install target, as presented below.
Installing / Uninstalling XMLVM
The install procedure is simple and it will ease the user interface with XMLVM libraries
- Edit file
properties/local.properties (or create it if it does not exist).
Define there the destination prefix of XMLVM in the variable
- If you do not define a specific location, the default installation path would be
For example, to install it under your home directory, add the following entry to the
The ant install command will install the files
Make sure that you have write permissions on the destination paths, e.g. run the target as root.
The executable is found under
/bin/xmlvm. Make sure to add the
/bin location to your
The uninstall procedure is similar. Make sure again that you have write permissions and then type
Java 1.6 is needed to run XMLVM. Invoking XMLVM can be done after installing in the following way:
Make sure that you have the installation location to your path, with a command similar to this:
XMLVM supports various command line options that drive the cross-compilation process. The general pattern of using XMLVM to cross-compile an application is:
--in=<input> --out=<output-directory> --target=<target>
The --in option defines the input files to be cross-compiled whereas the --out parameter designates the output directory of the cross-compiled input. The --target option finally defines for which platform XMLVM should generate code. These as well as other options are explained in detail in the following section.
Command Line Options
The behavior of XMLVM is controlled by numerous command line arguments.
xmlvm reads in one or more source files, processes them according to the command line options, and then writes out one or more destination files.
The source files are specified via one or more
--in options. If the argument passed to
--in is a directory, then this directory is traversed recursively and all files with the suffix
.xmlvm are processed. Files with other suffixes are ignored. It is possible to use wildcards to filter out certain files. It is possible to specify multiple
--in parameters. At least one
--in parameter is required.
The output generated by
xmlvm is written to a directory specified by the
--out parameter. The argument
<path> has to denote a directory. If the directory does not exist,
xmlvm will create it. All files generated by
xmlvm will be written to this directory. The only exception is when using
--target=class. In this case the resulting Java class files (ending in suffix
.class) are written to appropriate sub-directories matching their package names. Already existing files with the same name will be overwritten. If the
--out parameter is omitted, the current directory is the default.
This option defines the output format of the target. These correspond with the various backends for code generation supported by XMLVM. The different targets are explained in the following:
xmlvm: The input files are cross-compiled to XMLVM.
*.class files will be cross-compiled to XMLVMJVM.
*.exe files will be cross-compiled to XMLVMCLR.
*.xmlvm files will be copied unchanged. This option is the default for
jvm: The input files are cross-compiled to XMLVMJVM.
clr: The input files are cross-compiled to XMLVMCLR
dfa: A DFA (Data Flow Analysis) is performed on the input files. Currently the DFA will only be performed for XMLVMCLR programs. This option cannot be used in conjunction with any other code generating option.
class: The input files are cross-compiled to Java class files.
exe: The input files are cross-compiled to a .NET executable.
c: The input files are cross-compiled to C.
posix: The input files are cross-compiled to a self-contained C program that includes all dependent classes such as
python: The input files are cross-compiled to Python.
--out will contain a ready to deploy web application. The environment variable
QOOXDOO_HOME needs to point to the base directory of the Qooxdoo
qooxdoo installation. This option implies
--target=js and requires option
iphone: Cross-compiles an application to the iPhone. The output directory specified by
--out will contain a ready to compile Xcode project. This option requires the option
This option can only be used in conjunction with targets
qooxdoo. It specifies the name of the iPhone or Qooxdoo application whose name will be
none: Be completely quiet, no information is printed
error: Only errors will be printed
warning: Warning and errors will be printed
all: All debug information (including errors and warnings)
This let's you specify addition libraries that your app depends on. This is the same as what you would usually do when you add additional libraries to your classpath in order to compile a regular Java application.
One or more dependencies can be given. A dependency can be a path on the file system which contains class files or a a JAR file containing the library.
Only the classes that the app depends on are cross-compiled. Classes not required from the given dependencies will not be processed and thus will not appear in the output.
Comma separated list of extra libraries required for the specified target. (This is not to be confused with
Colon separated list of external files and directories. These resources (such as images) will be added to the cross-compiled application. If this argument ends with '/', then the contents of this directory will be copied. If it is a directory and does not end with '/', then a verbatim copy of the directory will be performed. This argument can also be used to add extra C/C++/Objective-C source files to the generated Xcode project for the iOS target.
Creates a new skeleton project to simply the use of XMLVM.
<type> can be:
iphone: iPhone project skeleton
android: Android/iPhone project skeleton
android:migrate: Migrate an existing Android project to XMLVM (needs project created by 'android create project' command)
iphone:update: Update an existing XMLVM/iPhone project to latest build scripts
android:update: Update an existing XMLVM/Android project to latest build scripts
/foo/bar is searched recursively for
*.xmlvm files. The default target is
*.class files, XMLVMJVM is generated. For
*.exe files, XMLVMCLR is generated. Files with suffix
*.xmlvm are copied to the output directory. Other files with different suffices are ignored. Since no
--out parameter was given, the default output directory is "." (the current directory).
xmlvm --in=/foo/*.class --in=/bar/*.exe --out=/bin
/foo is searched recursively for
*.class and the directory
/bar is searched recursively for
*.exe files. The default target is
xmlvm. Files with other suffices are ignored. For
*.class files, XMLVMJVM is generated. For
*.exe files, XMLVMCLR is generated. The resulting
*.xmlvm files are placed in directory
xmlvm --in=/foo --target=jvm
/foo is searched recursively for
*.xmlvm files. In all cases, the generated output will always be XMLVMJVM. For
*.exe files as well as
*.xmlvm files containing something other than XMLVMJVM will be cross-compiled XMLVMJVM.
xmlvm --in=/foo --target=class
Same as the previous example, however instead of generating XMLVMJVM files, Java
*.class files that can be executed by a Java virtual machine will be generated. The class files will be placed in appropriate sub-directories matching their package names.
xmlvm --in=/foo --target=iphone --iphone-app=TheApplication
Same as the previous example, however instead of creating Java
*.class files, an iPhone application will be generated. The output directory will contain the ready to compile Objective-C source code including all necessary auxiliary files such as
Info.plist and a
Makefile. The iPhone application will be called
TheApplication using a default icon.
xmlvm --in=/foo --target=android-on-iphone --iphone-app=TheApplication
Same as the previous example, but will also copy the Android compatibility library to the output directory. This effectively allows Java-based Android applications to be cross-compiled to the iPhone.
xmlvm --in=/foo --qx-app=TheApplication --qx-main=com.acme.Main
/foo is searched recursively for
*.xmlvm files. This option implies
With the help of XMLVM it is possible to cross-compile Java applications to native iPhone applications. The Apple license agreement does not permit the installation of a virtual machine on the iPhone. By cross-compiling a Java application to a native iPhone application, this restriction of the license agreement is therefore not violated. XMLVM can legally generate native iPhone application and it is not necessary to jailbreak a device in order to run an application cross-compiled by XMLVM.
supports Objective-C as the development language for the iPhone. The
GUI of iPhone applications is based on Cocoa Touch. If Java is to be
used as a development language for iPhone applications, two aspects need
to be addressed: the cross-compilation of Java to Objective-C and a
Java API for Cocoa Touch. The Java API for Cocoa Touch is loosely based
on the Objective-C counterpart. While XMLVM makes better use of
overloading and interface definitions for delegates to create a
strongly-typed API, the description of the various classes and methods
can be taken from Apple's official documentation.
Android is an Open Source platform for mobile devices. Initiated by Google, Android has received much attention. Android applications are developed using Java, although a special compiler converts class files to a proprietary, register-based virtual machine that is used on Android devices to execute applications. Android defines its own API for writing mobile applications. With the help of XMLVM it is possible to cross-compile Java-based Android applications to native iPhone applications. The following Figure depicts this process:
The Android application is written in Java and makes use of an Android specific API. XMLVM offers a compatibility library, written in Java, that offers the same API as Android, but only makes use of the Java-based API for Cocoa Touch mentioned earlier. During the cross-compilation process, both the application and the Android compatibility library are cross-compiled from Java to Objective-C and linked with the Cocoa Touch compatibility library to yield a native iPhone application.
As can be seen, compared to the Java-for-the-iPhone portion of XMLVM, the only additional feature added to support Android applications is the Android compatibility library. When the project is defined as an Android project, the Android compatibility library is also attached to the generated project. The Android-based iPhone application can be run in the XMLVM-specific iPhone emulator, the Apple's emulator and the Android emulator.
Under the folder
, various demo projects exist, to test XMLVM system. This section will describe only iPhone and Android based demo projects. These demo projects can be run either from the command line, or from and IDE, such as Eclipse and Netbeans. The source code of the Java-for-the-iPhone demos is located in directory
demo/iphone/, whereas the source code of the Android-to-iPhone demos are located in directory
These are self contained projects, similar with the ones created by the XMLVM skeleton process (see below under How to start a new project under XMLVM
Android demos need Android SDK to be installed. The SDK should be defined under property file properties/local.properties as:
If the Android SDK is not defined, Android demos will fail to compile.
It is possible to compile all demo projects at once by giving the command:
in the base directory of the XMLVM project. It is also possible to go to each project's directory and compile it by itself. Instructions on how to run these projects can be found under section How to run an XMLVM project
in this document. In any case, the
should already be compiled (i.e. go to the base directory of the project and type
to create it).
Here is a list of the available sample applications:
- iHelloWorld (Portrait): "Hello World" in portrait mode.
- iHelloWorld (PortraitUpsideDown): "Hello World" in upside down portrait mode.
- iHelloWorld (Landscape): "Hello World" in landscape mode.
- iHelloWorld (Fullscreen): "Hello World" in fullscreen landscape mode.
- iFireworks: iPhone version of the fireworks application.
- aFireworks: Android version of the fireworks application.
- Xokoban: Android version of the Xokoban application.
How to start a new project under XMLVM
If the user wants to start a new blank project, the
command line option can be used. Currently, there are three types of skeleton projects:
- new iPhone projects
- new Android projects
- migration of existing Android projects to the XMLVM scheme
To create a new iPhone project the
skeleton should be used as follows:
xmlvm --skeleton=iphone --out=OUTDIR --app-name=APPNAME
where OUTDIR is the output directory of the project and APPNAME is the name of the project. This template will create a new folder under OUTDIR (if it does not exist) and put all required files inside.
To create a new Android project the
skeleton should be used, as follows:
xmlvm --skeleton=android --out=OUTDIR --app-name=APPNAME
where OUTDIR is the output directory of the project and APPNAME is the name of the project. Like in the case of the iPhone project, a new Android project will be created. This project will also be compatible with projects created with the Eclipse plugin for Android, as well as the
android create project
tool. Some more configuration is required though. Please open file
, uncomment the line
and define the location of the Android SDK.
Migration of existing Android projects
If an Android project already exists, it is possible to migrate it in order to be able to use XMLVM targets in parallel with Android targets. In order for the migration to be successful, the project should be a properly set up Android project for Eclipse (without special Eclipse configuration), or a project created and managed by the
android create/update project
tool. The command to migrate an existing Android project is as follows:
xmlvm --skeleton=android:migrate --out=OUTDIR
where OUTDIR is the location of the existing Android project. If the project was created with the Android
android create project
tool, the actual
file will be backed up and a new
file will be created. In the case some special configurations or targets exist in this file, these should be manually transferred to the new
file. Note that some targets of the old file might already exist in the migration project build file,
. Please make sure that these targets are properly executed, or XMLVM project migration could not be performed.
How to configure an XMLVM project
There are two base configurations that should be taken into account, or else the XMLVM projects could not be used:
- Location of the XMLVM library. This is the property
xmlvm.sdk.jar, found in the file
nbproject/project.properties. This property is usually set automatically by the XMLVM tool.
- Location of the Android SDK, only in the case of the Android-based projects. This is the property
sdk.dir found in the file
local.properties. This property is not set automatically and you have to define it yourself. If you have migrated an Eclipse-based project, which usually does not define the location of the Android SDK, it is required to update this property, or else compilation will fail! For projects already created with the
android create project tool, the configuration of this property is usually performed automatically.
Every XMLVM project can be configured, to use specific features, mostly related to the Xcode project creation. By default the templates have used reasonable values for all properties, so that the project could be instantly usable. Configuration parameters are found in file
and are as follows:
- xmlvm.project: the Xcode project type. Valid values are:
- iphone: iPhone project skeleton
- ipad: iPad project skeleton
- ios: iPhone and iPad project skeleton
- iphone3: Legacy iPhone 3.1 project skeleton. This target is deprecated and is presented
here for backwards compatibility only. It is possible that project
compilation will fail when compiled with this target.
- xmlvm.lib: Add extra libraries required for the project. Supported libraries are only system libraries and should have a full qualified name, without path definition. If more than one library is required, then every library should be separated by the comma character. If a library name ends with tilde
~, then a weak linking will be performed by the Xcode, i.e. this library is not strongly required when building this project. In the case an android project is required, then the
android library should be defined. Examples:
- to use QuickTime library, the entry
QuickTime.framework should be defined
- to use ssl library, the entry
libssl.dylib should be defined
- to use object crt1, the entry
crt1.o should be defined
- to use both QuickTime and ssl library, the entry
QuickTime.framework,libssl.dylib should be defined
- xmlvm.resource: Add extra resources required when creating the Xcode project. This is a colon separated list of files that will be used verbatim in Xcode project. Directories can be provided too; if a directory is provided, then if the name ends with "/", the contents of this directory will be used. If not, a verbatim copy of the directory will be used. It is also possible to add source files to the project (in the form of
*.mm files). In the case a directory with source code is provided, only one level deep will be searched for source files. For this reason either specific source file should be provided, or a directory ending with "/".
- bundle.version: The version if this program
- bundle.identifier: a reverse-DNS naming scheme to identify the current project. Note that this identifier is used only for the produced iOS project and not for the Android project.
- bundle.displayname: The displayed name of this program.
- prerenderedicon: whether the project icon is already prerendered (boolean value).
- statusbarhidden: whether the status bar of the project is hidden when launched (boolean value).
- applicationexits: whether application does not run in background on suspend. Change to "false" to support multi-tasking (boolean value).
- xmlvm.trimmer: this is the project source-level optimization. By using this feature compilation time should be shorter and produced binary will be smaller. This option is not yet properly supported for Android projects. Also, in some rare cases, this optimization might break the project compilation. If this happens, please disable this optimization (boolean value).
- xmlvm.trimmer.seed: randomizing seed of the trimmer process (free integer value).
When using an Android project, there are other configurations that might be needed, like the properties found under default.properties or build.properties. These properties are not managed by the XMLVM tool but from the Android SDK, and should be properly set up in advance.
How to run an XMLVM project
When an XMLVM is properly set up, it is possible to compile it and run it as follows:
- under the Java Emulator
- by compiling with the help of Xcode
- if it is an Android project, to run the project under the Android emulator
In every case, it is either possible to set the way the project is run, and then run it, or set and run it at the same time. Every time the target is set, it is enough to run the project with the same target by issuing the command:
Run from the command line
To use the Java emulator the following command should be used:
ant use-Java run
or use the equivalent target:
Likewise, to use Xcode the following command should be used:
ant use-Xcode run
or use the equivalent target:
To run under Android emulator, use the following command:
ant use-Android run
or use the equivalent target:
In this case the debug version of the binary will be compiled and the default emulator will be used. The emulator should be defined and run already and only one instance should be present.
It is possible to set once the type of the run target like this:
All iPhone projects can be directly imported to Netbeans, as Java projects. Right now there is no support for Android projects.
Standard tools can be used to run the project (e.g. press the play button).
To select between Java emulation and Xcode project creation, select the appropriate configuration.
All projects can be imported as Java projects (for iPhone projects) or Android projects (for Android projects). It is possible to use the standard Eclipse tools in order to use these projects (e.g. press play
button to start the project). It is recommended though to use the special ant scripts instead, to perform the various tasks, or else some feature will be missing (e.g. plugins or extra resource files). The procedure is described below:
To run the ant scripts under Eclipse, the above specified targets should be defined, as follows:
- Menu Run→External Tools→External Tools Configurations...
- Select Ant Build→New button
- Under Name: give a proper name (e.g. Projectname Xcode)
- On tab Main→Buildfile: click on Browse Workspace...
- On the display dialog, select the correct project and then click on build.xml to the file on the right. Press OK.
- Click on Targets tab, and select the targets you want to use (e.g. first click on use-Xcode and then on run). Target execution order should show use-Xcode, run
- Click on Run.
The steps are similar for any other target.
These targets are saved by the Eclipse Workspace and next time can be called either from menu Run
or from the corresponding External Tools
button in the Toolbar.
Using plugins with iPhone projects
Sometimes, the desired iPhone project requires some extra code written in ObjC (or any other C-based language). This source code should be compiled along the produced iPhone code (and together with the iPhone compatibility library), while the corresponding Java class(es) should be present, in order for these objects to be visible when compiling the iPhone project.
To solve this problem, plugins where introduced to the XMLVM system. With plugins it is easy to deliver a single file (a JAR actually) with both, the java source code and the required C-based code, as well as the glue C-Java code.
A demo plugin can be found under
To make this plugin, go to the folder of the plugin and perform
will be produced under
. Take this JAR and add it to the classpath of your project. And that's it! The build scripts will take care of properly extracting the files and use them when required.
To create a custom plugin, use the demo plugin as a reference. Write your own Java glue code under
and put all files required for the Xcode project (all C/ObjC etc files) under
directory. The directory structure could be as deep as you desire, but when exporting these files to Xcode, directories will be flattened. Make sure that no file overriding will be performed, or unexpected results might appear.
If you want to make your own build scripts for plugins, make sure that the created JAR file has a root directory
with all files required by Xcode inside.