LablGLES: OpenGL ES from OCaml
Posted by Jeffrey
OpenGL ES is a reduced version of the OpenGL graphics standard, suitable for use on small devices like mobile phones. My OCaml interface is provided as a set of patches to LablGL, an OCaml OpenGL interface by Jacques Garrigue and others.
You can use LablGLES to build OpenGL applications in OCaml for the iPhone and other iOS devices using OCamlXARM, a cross compiler for iOS. Starting with LablGLES 1.1.9, you can also use LablGLES to build OpenGL applications for the iOS Simulator using OcamlXSim.
As of LablGLES 1.1.4, there is also support for compiling and linking under Android. (Android patches were contributed by Paul Snively, email@example.com.)
The current version of LablGLES is 1.1.9, which is based on LablGL version 1.04. It supports OpenGL ES Version 1.1, including a few extensions necessary for iOS. If you want to use it to build iOS apps, you need an installation of Xcode, Apple’s development environment. See Apple’s developer website for details. The build shown on this page was tested with Xcode 4.0.2, but will work with any recent version of Xcode (version 3.2.5 or later, say).
The LablGLES library has been used in production on iOS. In fact the Psellos Cassino app currently available in the iTunes store is a LablGLES app.
The LablGL release contains three interfaces: to OpenGL, to Tcl/Tk, and to GLUT. Only OpenGL is readily applicable in an embedded environment; I do not build the other parts (and they are not affected by any of the patches).
To a fairly good approximation, OpenGL ES is a subset of OpenGL. Roughly speaking, then, the patches just remove the parts of LablGL that aren’t in OpenGL ES. In addition, I added support for framebuffer objects, an extension required for OpenGL ES applications on iOS devices. I also added support for PVRTC compressed textures, which again are very useful on iOS devices.
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.
Get LablGL Sources and Patches
Choose a place to work (an empty directory would be good).
$ cd <good place to work>
Download the sources for the LablGL 1.04 release:
$ curl -O -s http://wwwfun.kurims.kyoto-u.ac.jp/soft/olabl/dist/lablgl-1.04.tar.gz $ ls -l lablgl-1.04.tar.gz -rw-r--r-- 1 psellos staff 410525 Aug 16 15:41 lablgl-1.04.tar.gz
Download LablGLES patches from Psellos:
$ curl -O -s http://psellos.com/pub/lablgles/lablgles-1.1.9.diff $ ls -l lablgles-1.1.9.diff -rw-r--r-- 1 psellos staff 145726 Aug 16 15:42 lablgles-1.1.9.diff
To save typing, you can access these two links directly from your browser:
Unpack and Apply Patches
Unpack the LablGL sources.
$ tar --strip-components=1 -xzf lablgl-1.04.tar.gz
Apply the LablGLES patch.
$ patch -p0 -E < lablgles-1.1.9.diff patching file Makefile.config.iossim patching file ESVERSION patching file src/glMap.mli patching file src/gluQuadric.mli patching file src/gluMisc.mli patching file src/glu_tags.var patching file src/gluTess.ml patching file src/ml_glu.c patching file src/ml_glu.h patching file src/gluQuadric.ml . . . patching file Makefile.config.ex patching file Makefile.config.android patching file Makefile.config.mingw patching file Makefile.common patching file Makefile.config.ios patching file Makefile
The patch command lists 59 patched files. Because OpenGLES is a subset of OpenGL, around 20 of the LablGL source files are not applicable to LablGLES. The patch causes all their content to disappear, and the -E option asks for these empty files to be deleted.
Build the Library
Specific details for building LablGLES will depend a great deal on your host and target systems. Here I show how to build for iOS (iPhone and iPad) and for the iOS Simulator, using Apple’s Xcode and the two previously mentioned OCaml cross compilers, OCamlXARM and OCamlXSim.
If you’re using OCamlXARM or OCamlXSim, please make sure you have a
recent version. The LablGLES compilation requires the
preprocessor, which didn’t work in earlier versions of the cross
compilers. For OCamlXARM you want
ocaml-3.10.2+xarm12 or later. For
OCamlXSim you want
ocaml-3.12.1+xsim1 or later. If you built the
compilers yourself from source, you should have built OCamlXARM from
patches with version 1.0.12 or later. You should have built OCamlXSim
from the directions posted on July 15, 2011 or later.
The build of LablGL (and thus LablGLES) is controlled by a main
Makefile that is the same for all environments. Details for a
particular environment are defined in a file named
which is included by the main
Makefile. The LablGL release includes
several examples for different environments, named
Makefile.config.osx, and so on. The LablGLES patches create three new
files for different OpenGLES environments:
|for iPhone and iPad|
|for iOS Simulator|
The first step in building LablGLES, then, is to create a
Makefile.config file that defines the details of your environment.
Here I will show how to use use the
Makefile.config.iossim that come with LablGLES.
You will generally need to modify the Makefile to fit your local
development layout. If you are working with iOS or the iOS Simulator,
you may need to specify the location of your cross compiler or adjust
the iOS SDK version. The lines in
Makefile.config.ios looks as
The lines in
Makefile.config.iossim looks as follows:
Make sure the lines specify the location of your OCaml cross compiler
(and other utilities), and the base SDK you want to use. You probably
want to set
SDK to the most recent SDK version you have installed on
Once you have your configuration file, copy it into place and compile the library. For iOS, this looks as follows:
$ cp Makefile.config.ios Makefile.config $ make lib libopt cd src && make all LIBDIR="`ocamlc -where`" /usr/local/ocamlxarm/bin/ocamlc -pp /usr/local/ocamlxarm/bin/camlp4o var2def.ml -o var2def /usr/local/ocamlxarm/bin/ocamlc -pp /usr/local/ocamlxarm/bin/camlp4o var2switch.ml -o var2switch /usr/local/ocamlxarm/bin/ocamlrun ../src/var2def < gl_tags.var > gl_tags.h /usr/local/ocamlxarm/bin/ocamlrun ../src/var2switch -table GL_ < gl_tags.var > gl_tags.c /usr/local/ocamlxarm/bin/ocamlc -c -w s -ccopt "-c -O -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.2.sdk" ml_gl.c . . . /usr/local/ocamlxarm/bin/ocamlc -c -w s -I +labltk raw.mli /usr/local/ocamlxarm/bin/ocamlc -c -w s -I +labltk raw.ml /usr/local/ocamlxarm/bin/ocamlc -c -w s -I +labltk gl.mli /usr/local/ocamlxarm/bin/ocamlc -c -w s -I +labltk gl.ml . . . /usr/local/ocamlxarm/bin/ocamlopt -c -ccopt -isysroot -ccopt /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk -cclib -Wl,-syslibroot,/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk -I +labltk glFramebuffer.ml /usr/local/ocamlxarm/bin/ocamlmklib -ldopt -Wl,-syslibroot,/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk -o lablgles ml_gl.o ml_raw.o ml_glarray.o ml_glframe.o raw.cmx gl.cmx glLight.cmx glMat.cmx glMisc.cmx glPix.cmx glClear.cmx glTex.cmx glDraw.cmx glFunc.cmx glArray.cmx glFramebuffer.cmx -framework OpenGLES
For the iOS Simulator it looks as follows:
$ cp Makefile.config.iossim Makefile.config $ make lib libopt cd src && make all LIBDIR="`ocamlc -where`" /usr/local/ocamlxsim/bin/ocamlc -pp /usr/local/ocamlxsim/bin/camlp4o var2def.ml -o var2def . . . /usr/local/ocamlxsim/bin/ocamlmklib -ldopt -Wl,-syslibroot,/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk -o lablgles ml_gl.o ml_raw.o ml_glarray.o ml_glframe.o raw.cmx gl.cmx glLight.cmx glMat.cmx glMisc.cmx glPix.cmx glClear.cmx glTex.cmx glDraw.cmx glFunc.cmx glArray.cmx glFramebuffer.cmx -framework OpenGLES
The compilation produces around 50 lines of output, some of them quite long.
that LablGLES should be installed in a subdirectory named
create this local installation, type
$ make install cd src && make install . . .
The installation process produces around 15 lines of output. The
contents of the
release directory should look something like this:
$ ls -l release total 712 -rw-r--r-- 1 psellos staff 4492 Aug 16 15:47 build.ml -rwxr-xr-x 1 psellos staff 33028 Aug 16 15:47 dlllablgles.so -rw-r--r-- 1 psellos staff 3065 Aug 16 15:47 gl.cmi -rw-r--r-- 1 psellos staff 707 Aug 16 15:47 gl.cmx -rw-r--r-- 1 psellos staff 2719 Aug 16 15:47 gl.ml -rw-r--r-- 1 psellos staff 1874 Aug 16 15:47 gl.mli . . . -rw-r--r-- 1 psellos staff 53872 Aug 16 15:47 lablgles.a -rw-r--r-- 1 psellos staff 18325 Aug 16 15:47 lablgles.cma -rw-r--r-- 1 psellos staff 2564 Aug 16 15:47 lablgles.cmxa -rw-r--r-- 1 psellos staff 36384 Aug 16 15:47 liblablgles.a -rw-r--r-- 1 psellos staff 6258 Aug 16 15:47 raw.cmi -rw-r--r-- 1 psellos staff 1313 Aug 16 15:47 raw.cmx -rw-r--r-- 1 psellos staff 3179 Aug 16 15:47 raw.ml -rw-r--r-- 1 psellos staff 3716 Aug 16 15:47 raw.mli
To verify that the library works, try compiling and linking a small test program, such as the following:
$ cat glestest.ml let main () = begin GlPix.store (`unpack_alignment 1); GlFunc.blend_func `one `one_minus_src_alpha; Gl.enable `blend; GlTex.env (`mode `modulate); GlDraw.viewport ~x: 0 ~y: 0 ~w: 320 ~h: 460; GlMat.mode `projection; GlMat.load_identity (); GlMat.ortho ~x: (0.0, 320.0) ~y: (0.0, 460.0) ~z: (-100.0, 100.0); GlClear.color ~alpha: 1.0 (0.8, 0.333, 0.0); GlClear.clear [`color]; end let () = main ()
Now compile and link with the cross compiler. This example is for
compilation to iOS (with OCamlXARM). To test compilation to the iOS
$ /usr/local/ocamlxarm/bin/ocamlopt -I release -o glestest lablgles.cmxa glestest.ml $ file glestest glestest: Mach-O executable arm
If the compiler produces an executable, LablGLES very likely has been built correctly.
You may, instead, see an error like one of the following:
$ /usr/local/ocamlxarm/bin/ocamlopt -I release -o glestest lablgles.cmxa glestest.ml ld: library not found for -lcrt1.o collect2: ld returned 1 exit status Error during linking
$ /usr/local/ocamlxsim/bin/ocamlopt -I release -o glestest lablgles.cmxa glestest.ml ld: framework not found OpenGLES collect2: ld returned 1 exit status File "caml_startup", line 1, characters 0-1: Error: Error during linking
This means that your version of OCamlXARM or OCamlXSim has been built with an earlier version of the iOS SDK. As described on the OCamlXARM page, this is hard to avoid due to Apple’s steady release of new versions of iOS and SDKs for them.
You could rebuild OCamlXARM and OCamlXSim for the latest SDK, but the
easiest solution is to specify explicit options to
ocamlopt telling it
which SDK version to use. To use the iOS 4.3 SDK with OCamlXARM:
$ PLAT=/Developer/Platforms/iPhoneOS.platform $ PLATBIN=$PLAT/Developer/usr/bin $ SDK=$PLAT/Developer/SDKs/iPhoneOS4.3.sdk $ OCCC="$PLATBIN/gcc-4.2 -arch armv6" $ OCOPTS="-ccopt -isysroot -ccopt $SDK -cclib -Wl,-syslibroot,$SDK" $ /usr/local/ocamlxarm/bin/ocamlopt -cc "$OCCC" $OCOPTS -I release -o glestest lablgles.cmxa glestest.ml $ file glestest glestest: Mach-O executable arm
To use the iOS 4.3 SDK with OCamlXSim:
$ PLAT=/Developer/Platforms/iPhoneSimulator.platform $ SDK=$PLAT/Developer/SDKs/iPhoneSimulator4.3.sdk $ OCOPTS="-ccopt -isysroot -ccopt $SDK -cclib -Wl,-syslibroot,$SDK" $ /usr/local/ocamlxarm/bin/ocamlopt $OCOPTS -I release -o glestest lablgles.cmxa glestest.ml $ file glestest glestest: Mach-O executable i386
Although the extra options are painful to specify, you’re generally not going to be typing them in by hand. You just need to set up your build system (Makefile, Xcode, etc.) once, and it will take care of it.
Note: These compiles of
glestest.ml only test that the LablGLES library has been created
correctly. A program that actually displays graphical content requires
a little more setup. For a working example of a LablGLES app, see the
accompanying note OCaml OpenGL ES iPhone App: IcosaBlue.
As I said above, I’ve put together an example LablGLES app named IcosaBlue. The app itself is quite simple, but it demonstrates the extra Cocoa Touch classes and setup required to embed OpenGL ES graphics in an iPhone app. To make it as useful as possible, I packaged it both for the iPhone Simulator and for the iPhone device. See the IcosaBlue page for a description of how to build it and how it works.
I’m happy to get any comments, corrections, or questions at firstname.lastname@example.org.