Getting Started with OCaml on Mac OS X

The Options

Under Mac OS X, there are, at least for the base package, five different ways to go: Install the binary package from INRIA; Install via Fink; Install via MacPorts; Build via GODI; or build it manually from sources. For each of the four approaches, you will need to have at least the OS X developer tools installed -- any other requirements will be discussed below.

INRIA's binary package

This is the easiest way to set up a basic OCaml installation for OS X. For 10.4 (Tiger), simply download the PPC disk image or Intel disk image, mount the disk image, double-click on the ocaml.pkg file contained within, and follow the instructions from there. Requirements for this package are OS X 10.4.x (Tiger), with X11 and the XCode tools (v2.4) installed. It appears that that this installation was built with the TCL/TK interface. Also, X11 is not needed to compile code.

The precompiled binaries for Mac OS X of OCaml 3.10.1 PPC disk image or Intel disk imagewas compiled on Mac OS 10.5.1 with XCode tools v3.0 and is not compatible with earlier Mac OS versions).

Other versions are available for download.

Also available as a binary package, and usable with any of the OCaml installations described on this page is CocOCaml, a Cocoa application allowing for easy interaction with the OCaml toplevel environment.

Fink

Fink is the most prevalent package management system for OS X, and is based on Debian's package management system. Fink can be installed by downloading and building the source release (you will need to have the OS X Developer Tools installed before building Fink). After Fink is installed, it must be configured to use the unstable branch of the distribution tree -- this is where the OCaml packages reside.

Once Fink is installed, you can use it to install the following packages:

It is likely that Fink will need to download and install a number of other packages required to build the OCaml packages, but this will occur mostly automatically.

Godi OCaml Linking Against Fink Libraries

This method uses GODI's version of OCaml and uses Fink to provide any additional third party libraries that do not come with Mac OS X. This is done because the version of OCaml in Fink is older (3.08 in the unstable branch) than the one in Godi (3.08.1 in the stable branch). Also, Godi's package management system will recompile any packages when a dependent package is updated, ensuring that your OCaml build tree is always in good shape.

There is the issue of knowing which Fink packages have to be installed before you can install some of the Godi packages with all optioned enabled.

MacPorts

MacPorts, formerly known as DarwinPorts, is a package management system for Mac OS X based on the BSD ports system. You will need to have the OS X Developer Tools installed before installing MacPorts. MacPorts can be used to download and build the following packages:

Godi OCaml Linking Against MacPorts Libraries

Just like the Fink/Godi setup mentioned above, this method uses GODI's version of OCaml and uses MacPorts to provide any additional third party libraries that do not come with Mac OS X. This way you can let GODI take care of your OCaml build tree, and let MacPorts take care of the native libraries, such as GTK2 and PCRE.

Building from sources

Unfortunately, the packages available for both Fink and DarwinPorts don't yet include some of the more useful additions to the OCaml collection, such as Markus Mottl's PCRE-Ocaml library or Stolpmann's findlib system. In order to get those packages, one must currently build them from source.

The following packages are the most beneficial to install:

If additional components, such as OpenGL and Gtk+ or Gtk+2 have already been installed, packages such as lablgl, lablgtk, etc. can be built as well. The most flexible solution for doing this is often using Fink to install the required dependencies, and build the OCaml packages from source distributions.

Using Xcode for writing OCaml programs

There exists an Xcode plugin integrating Objective Caml developement in Xcode. This plugin is always under development and still lacks of features, however it gives useful features for developing applications:

Still being in beta it does not yet support the following:

1.0b10 (Jan 2008) added Xcode 3.0 compatibility.

Download and information

Using labltk with OS X

There are a couple of different ways one can go if they wish to use labltk with OS X. One could download and build the Tcl/Tk libraries themselves and use those libraries. However, there are two easier ways to proceed, using Fink to install Tcl/Tk, or using the Tcl/Tk Aqua Framework. There are two very important distinction between the two that one needs to consider before installing OCaml and labltk:

  1. The fink libraries require X11 to be running when any program using labltk is executed, while the Tcl/Tk Aqua libraries will execute (and look and feel) like a native OS X application
  2. As of the time of writing this, it appears as if labltk applications built with the Tcl/Tk Aqua libraries must be built as native OS X applications (and require an extra step at build time). If one requires the portability of bytecode, or needs the interactive environment of a labltk enabled toplevel, then they must use the fink libraries.

Installing the fink libraries:

Once Fink is installed and configured, install the Tcl/Tk libraries with the command fink install tcltk tcltk-dev tcltk-shlibs and wait for the build and install process to compete. Once this is done, OCaml's configure script should be able to locate the libraries and header files required to build labltk (provided fink is set up to install its packages in the /sw directory). Running the standard OCaml build will also build labltk.

Installing the Tcl/Tk Aqua libraries:

Download the Tcl/Tk Aqua package (note that this framework comes with OS X 10.4 and possibly 10.3, so you won't need to download or install the packages) and run the TclTkAquaBI.mpkg installer. Once it is installed, configure the OCaml build by using the following flags:

./configure -tkdefs \
    "-I/Library/Frameworks/Tcl.framework/Headers \
     -I/Library/Frameworks/Tk.framework/Headers" \
     -tklibs "-framework Tcl -framework Tk"

Now building OCaml will also build labltk using the Tcl/Tk Aqua libraries.

As mentioned above, any programs using labltk must be compiled using ocamlopt, and an additional step must be performed before the application can be used. For example, with the simple program, hello.ml:

 open Tk;;
 let hello () = 
     print_endline "Hello!"; flush stdout in
 let top = openTk () in
 let hb = 
     Button.create ~text:"Hello" ~command:hello top in
 pack [hb]; 
 mainLoop ()

One would compile this program with the command ocamlopt -o hello -I +labltk labltk.cmxa hello.ml

Now, to make the program work properly, one must perform one of two additional steps: adding a resource fork to the executable, or building a Mac OS X .app structure.

To add a resource fork, one needs to use the program Rez, included in the OS X Developer tools. This can be done with the following command:

/Developer/Tools/Rez -t APPL -o hello ~/dev/mac.r \
     -i /Library/Frameworks/Tcl.framework/Headers \
     -i /Library/Frameworks/Tk.framework/Headers

Where mac.r is a Rez source file. It is part of the FLTK distribution. This will add the required resource fork to the hello application. The program can be run either by typing hello at the command line or by double-clicking the app's icon (note that if it is launched by double-clicking, hello will send its output to the OS X console rather than the terminal).

Unfortunately, files with resource forks can present a problem in that utilities like cp, mv, tar, etc. will strip the resource fork from the file, breaking the application. To aleviate this problem, one can build an OS X application bundle to wrap the compiled executable.

To do this, after compiling with ocamlopt -o hello -I +labltk labltk.cmxa hello.ml, the following steps will build the bundle:

mkdir hello.app
mkdir hello.app/Contents 
mkdir hello.app/Contents/MacOS
mv hello hello.app/Contents/MacOS

Next, create a file hello.app/Contents/Info.plist with the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
  <key>CFBundleExecutable</key>
  <string>hello</string>
</dict>
</plist>

The hello application can now be run from the command line by typing open hello.app, or by double-clicking on the app's icon (again, this will send hello.app's output to the console).

Tips

Documentation. To get quick access to the documentation of a module (whatever the editor you use) use Quicksilver to index the libref/ directory of ocaml's documentation. Since ocamldoc generates the documentation of a module M in a file M.html, you can access it by invoking Quicksilver, type an abbreviation of the module's name you want and hit return to get its html file loaded in your preferred browser.

Profiling. To profile native-code programs do not compile them with the option -p (this is unsupported) simply use Shark. Shark can be invoked directly from the command line as follows :

 > shark -i -1 -q myprogram.opt args 

This will write a .mshark file in the directory that you can open with Shark.app.

 > open *.mshark

Note that if your executable doesn't run for long enough Shark won't be able to take any samples and won't report any statistics. More function names will show up in the profiles if you compile with -g.