Psellos
Contemporary Development With Functional Programming

iOS Simulator Vs. OS X

April 27, 2012

As I said I would, I’ve spent the last few days getting OCamlXSim working under Lion. OCamlXSim is my name for a version of the OCaml compiler that compiles apps to run in the iOS Simulator available from Apple. For the latest version, I’ve had to make it into a real cross compiler.

iPhone with gamut example app

The previous version of OCamlXSim (2.0.1) was based on the assumption that the iOS Simulator environment is essentially identical to the 32-bit OS X environment. So OCamlXSim 2.0.1 was built as a simple OS X native 32-bit OCaml compiler (with carefully specified configuration parameters).

This was definitely something of a hack, but it worked fine for our Schnapsen app, which was developed almost entirely under the iOS Simulator. Others have used OCamlXSim 2.0.1 successfully also.

For whatever reason, this hack doesn’t work under Lion (OS X 10.7). Possibly the differences between the iOS Simulator environment and Lion are too great, or more likely we were just lucky before.

For the benefit of other frontiersmen and women working at a low level, I’ll run an experiment here with the stat() system call that shows a difference between the two environments. I’m sure there are others, but differences in the behavior of stat() were what caused my iOS Simulator apps to fail at startup under Lion.

I’m running the experiment under OS X 10.7.3 with the toolchain of Xcode 4.3.2. For what it’s worth, the experiment also shows how to compile and run iOS Simulator executables directly from the command line. This can be handy for debugging—say, if you see crashes during startup like I did.

First some (probably well known) terms:

A compiler is native if it runs in the same environment that its compiled programs will run in.

The compiler runtime is the interface layer between its compiled programs and the environment. In the experiment we use the behavior of the stat() system call as a proxy for the whole OCaml runtime.

The key point of the experiment is that the OCaml compiler, ocamlopt, is itself an OCaml program. For a native OCaml compiler, the same runtime has to work for both the compiler and its compiled programs. By “same,” I mean the same specific set of object files—not two separate compilations of the same sources.

Consider the following small program, statdo.c:

#include <stdio.h>
#include <sys/stat.h>

int main() {
    struct stat buf;
    stat("/bin/sh", &buf);
    printf("mode %o\n", buf.st_mode);
    return 0;
}

The program writes out the mode of the standard shell /bin/sh.

To compile and link this for the iOS Simulator environment, we need to define our platform and SDK, then tell the compiler to use the definitions and libraries of the Simulator:

$ export PLT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform
$ export SDK=$PLT/Developer/SDKs/iPhoneSimulator5.1.sdk
$ gcc -arch i386 -isysroot $SDK -Wl,-syslibroot,$SDK -o statdo statdo.c

To run a program in the iOS Simulator environment, you can set DYLD_ROOT_PATH to the simulator SDK. When run in the iOS Simulator environment, the program works fine:

$ DYLD_ROOT_PATH=$SDK statdo
mode 100555
$ ls -l /bin/sh
-r-xr-xr-x 1 root wheel 1371712 Apr 3 14:30 /bin/sh

statdo correctly determines the mode for /bin/sh (a regular file with 555 permissions).

However, if we want OCamlXSim to be a native compiler, this same program (representing the OCaml runtime by proxy) would need to run properly in the native OS X environment outside the Simulator. And, in fact, it doesn’t work at all:

$ statdo
mode 21176

A failure in such a crucial system call is going to cause serious problems (paradoxical error messages, unexplained crashes). The lesson is that you can’t build OCamlXSim as a simple native compiler under Lion.

In reality OCamlXSim always needed to be a cross compiler, one that runs in a different environment than its compiled programs. Since the CPU is the same in the two environments, it’s sufficient just to have two different runtimes, one for the compiler itself (outside the Simulator) and one for the compiled programs (inside the Simulator).

I built a version of OCamlXSim with these two different runtimes, and used it to compile the Gamut example app. It all seems to be working very well (knock on wood). After some more thorough testing I’ll release a new OCamlXSim (patches and binary) for Lion.

Posted by: Jeffrey

Comments

blog comments powered by Disqus