Psellos
Contemporary Development With Functional Programming

Compile OCaml for iOS Simulator

May 3, 2012

Note: This is an archived version of the OCamlXSim page, for those interested in earlier versions. The most recent version is at Compile OCaml for iOS Simulator.

This note describes how to build an OCaml 3.12.1 compiler for the iOS Simulator, an iPhone and iPad simulator available from Apple. The resulting compiler can be used to build iOS apps and run them in the simulator. I call it OCamlXSim for short. The current version is OCamlXSim 2.0.4.

If you don’t want to build the compiler yourself, you can download a prebuilt package from Psellos. The current package is named ocaml-3.12.1+xsim4.

The OCamlXSim compiler can be used to develop real-world iOS apps. I did almost all the development of the GUI for our released app Master Schnapsen/66 in the iOS Simulator. (The Schnapsen game engine was developed under Linux.)

Psellos has also put together a compiler named OCamlXARM that builds apps for iOS devices—iPhone, iPad, and iPod Touch. This lets you release your apps in the iTunes App Store after developing them in the iOS Simulator. OCamlXARM is described in Compile OCaml for iOS.

 

Our OCaml Programming page has many more resources for doing OCaml programming for iOS. For example, I have released sources for five example apps (shown in miniature at left) that you can compile and run on an iOS device or in the iOS Simulator.

This version of OCamlXSim is based on OCaml 3.12.1 and its i386 code generator. It runs under OS X 10.7 (Lion) and is based on the toolchain of Xcode 4.3.2. Previous versions of OCamlXSim, for earlier versions of OS X and Xcode, can be found in the OCaml Programming Archives.

Overview

An app running natively on an iOS device is an ARM program. However, an app running in the iOS Simulator runs as a 32-bit (i386 architecture) Mac OS X program. In other words, the Simulator doesn’t simulate an iOS device down to the hardware level. It provides a faithful copy of the iOS environment, reimplemented to run natively on the Mac.

This means that OCamlXSim needs to be a 32-bit compiler for the i386 architecture, much like the stock 32-bit OCaml compiler for OS X. In fact, the stock compiler very nearly works. The difficulty is that the stock OCaml compiler is a native compiler, i.e., it runs in the same environment as the programs that it compiles. The Simulator environment is different enough from the standard OS X environment that a native compiler doesn’t work correctly. So OCamlXSim needs to be built as a cross compiler. (I’ve written a blog post iOS Simulator Vs. OS X that gives a simple demonstration of the issues.)

The standard OCaml release isn’t designed to run as a cross compier, so it takes a little extra work to build it as one. In essence, the OCaml build system doesn’t ordinarily distinguish between generating parts of the compiler itself (which run on the host system), and generating code (including libraries) to run on the target system.

The trick I’ve used in OCamlXSim is to build two distinct copies of the OCaml runtime. The first copy is targeted at OS X, and powers the cross compiler itself. The second copy is targeted at the iOS Simulator, and powers the apps running in the iOS Simulator. By lucky chance, there are no parts of the runtime that need to work independently in both environments. As a result, the two runtimes can coexist inside a single OCaml release. (This would not be the case if, for example, I wanted to support the bytecode interpreter in Simulator apps. For now, I’m sticking with native code apps.)

Please note that a few of the command lines of the following discussion are too long to fit on a single line of a typical browser window. In a lot of cases there is no good place to split them into smaller lines, usually because of a long filename or URL. Take care that you enter them as a single line if you are typing them in by hand.

Preliminaries

To develop and run code on the iOS Simulator, you need an installation of Apple’s Xcode programming tools, which contain the iOS Simulator as one part. As I write this, the current version is Xcode 4.3.2.

If you just want to build and test iOS Simulator apps, you can download and install the previously mentioned prebuilt OCamlXSim package from Psellos and use a recent version of Xcode to build your apps. In that case, you can skip down to the Test section below to verify that your copy of OCamlXSim is installed correctly.

Apple has made it reasonably easy to develop on the Mac, by making Xcode available at no cost. You can download it from the Mac App Store. See Apple’s Xcode page for more details.

After installing Xcode, you will need to go to the Downloads page of its Preferences, and also download the “iOS 5.0 Simulator” and the “Command Line Tools.” After that, you should find a native C compiler in your path:

$ which llvm-gcc-4.2
/usr/bin/llvm-gcc-4.2

To verify that the compiler is present, ask for its version:

$ llvm-gcc-4.2 --version | head -1
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.9.00)

Get OCaml Sources and Patch

Choose a place to work (an empty directory might be good).

$ cd <good place to work>

Download the sources for the OCaml 3.12.1 release from INRIA:

$ curl -O -s http://caml.inria.fr/pub/distrib/ocaml-3.12/ocaml-3.12.1.tar.gz
$ ls -l ocaml-3.12.1.tar.gz
-rw-r--r-- 1 psellos staff 3660473 May 2 15:41 ocaml-3.12.1.tar.gz

Download the patch from Psellos:

$ curl -O -s http://psellos.com/pub/ocamlxsim/cross-2.0.4.diff
$ ls -l cross-2.0.4.diff
-rw-r--r-- 1 psellos staff 7229 May 2 15:42 cross-2.0.4.diff

To save typing, you can access these two links directly from your browser:

Unpack the OCaml sources.

$ tar -xzf ocaml-3.12.1.tar.gz
$ cd ocaml-3.12.1

Build Compiler

Apply the OCamlXSim compilation patch.

$ patch -p0 < ../cross-2.0.4.diff
patching file VERSION
patching file tools/make-package-macosx
patching file xsim-build
patching file Makefile

The patch creates a script named xsim-build that builds the OCamlXSim compiler. The script contains several definitions near the beginning that you may want to change:

export PLT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform
export SDK=/Developer/SDKs/iPhoneSimulator5.1.sdk
export XSIMTARGET=/usr/local/ocamlxsim

The PLT line gives the location of the Xcode iOS Simulator platform directory. Under Lion, Xcode is installed as an ordinary application, and the platform directory is inside it. If you have a customized Xcode installation, you may need to change this line.

The SDK line gives the location of the iOS Simulator SDK, the name of a directory within the platform directory. In Xcode 4.3.2, the SDK version is 5.1. You should probably set this to the most recent SDK that you see in your platform directory.

The XSIMTARGET line specifies the location where OCamlXSim should be installed. If you want to install the compiler somewhere other than under /usr/local/ocamlxsim, change this line.

To build OCamlXSim all in one step:

$ sh xsim-build all > xsim-build.log 2>&1

If things go well, xsim-build.log will contain around 2793 lines of output, ending with something like this:

../../boot/ocamlrun ../../tools/ocamlmklib -o dbm -oc mldbm -ocamlc '../../ocamlcomp.sh' -linkall dbm.cmo
../../ocamlcompopt.sh -c -warn-error A -g dbm.m
../../boot/ocamlrun ../../tools/ocamlmklib -o dbm -oc mldbm -ocamlopt '../../ocamlcompopt.sh' -linkall dbm.cmx

If there is a problem, it may be possible to figure out what went wrong by looking at the error messages in xsim-build.log. It’s also possible to build OCamlXSim in smaller stages—see the script for details.

Now install the compiler.

$ sudo -s
Password:
# make install
    . . .
  install /usr/local/ocamlxsim/lib/ocaml/ocamlbuild/ocamlbuild.o
  install /usr/local/ocamlxsim/man/man1/ocamlbuild.1
# exit
$

The installation process produces around 294 lines of output.

Test

To verify the installation, compile a test program.

First, set the PLT and SDK variables. You can cut and paste these lines from the xsim-build script.

$ export PLT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform
$ export SDK=/Developer/SDKs/iPhoneSimulator5.1.sdk

Create a simple test program.

$ cat > hello.ml
let main () = Printf.printf "Hello, world!\n"

let () = main ()
^D

Compile the program. The extra flags tell ocamlopt to link against the Simulator’s OS X runtime.

$ /usr/local/ocamlxsim/bin/ocamlopt -cclib -Wl,-syslibroot,$PLT$SDK -cclib -Wl,-no_pie -o hello hello.ml
$ file hello
hello: Mach-O executable i386
$ nm hello | grep sigaltstack
         U _sigaltstack

The result should be an i386 executable that has been linked to the iOS Simulator environment. One of the differences between OS X and the iOS Simulator is in the name of the sigaltstack system call. The name should appear as given here. If it appears as _sigaltstack$UNIX2003, either the compiler or the test program was not built correctly.

To run a simple program in the iOS Simulator environment, you can set DYLD_ROOT_PATH:

$ DYLD_ROOT_PATH=$PLT$SDK hello
Hello, world!

To run a program that actually does something interesting, you need the richer environment provided by the actual iOS Simulator. The instructions for the example apps show how to do this.

Further Information

The following notes show exactly how to build OCaml apps and run them in the iOS Simulator:

Gamut is a simple app that displays a small animation in all possible colors. Voronoi is a more complex app that displays dynamic colored Voronoi diagrams that you can manipulate through the touch interface. IcosaBlue shows how to use OpenGL ES—it is packaged to work both in the simulator and on real devices.

If you’re interested in running OCaml apps on real iOS devices, see the accompanying note Compile OCaml for iOS. This note has links to two other sample apps that you can try.

See the OCaml Programming page for a full list of our OCaml resources.

If you have any questions, comments, or corrections, feel free to leave them below, or email me at jeffsco@psellos.com.