O'Jacaré - User's manual
Date: 2004/06/01 15:07:00

Emmanuel Chailloux - Grégoire Henry

Table of Contents

1  Overview

O'Jacaré is a new code generator to interoperate between Java and Objective Caml through their object model.

O'Jacaré is an strongly-typed object-interface based on the camljava library by Xavier Leroy. O'Jacaré defines a basic Interface Definition Language (IDL) for classses and interfaces description, and provides a code-generator for mapping Java classes directly to O'Caml classes. O'Jacaré generates all needed wrapper classes and enables static typechecking in both worlds. Although the IDL is an intersection from these two object models, O'Jacaré allows to combine features from both.

2   Installation

O'Jacaré distribution is available from http://www.pps.jussieu.fr/~henry/ojacare/.

2.1  Requirements

You should also have installed O'Caml (http://caml.inria.fr/) and a Java SDK.

O'Jacaré depends on the library camljava from Xavier Leroy. It's available from http://pauillac.inria.fr/~xleroy/software.html#camljava. But a small patch is needed before using it with O'Jacaré (mainly for threading difficulties). Next section will explain how to install camljava for using with O'Jacaré.

2.2  The camljava library

The camljava library has been compiled on: Default Makefile are for Linux. Use make -f Makefile.osx (resp. make -f Makefile.mingw) and Makefile.config.osx (resp. Makefile.config.mingw) instead of make and Makefile.config in the following if you are using Mac OS X (resp. MinGW via cygwin).
Download camljava
Direct download link is http://caml.inria.fr/distrib/bazar-ocaml/camljava-0.2.tar.gz.
Uncompress the distribution
Once camljava-O.2 download to the toplevel directory of the O'Jacaré distribution, do:
tar -xzf camljava-0.2.tar.gz
Patch it
The patch is available in the O'Jacaré distribution. From the top directory do :
patch -p0 < camljava-0.2.diff
Configure the system
Edit the file Makefile.config to adjust it to your current installation of Java SDK (This is the critical part).
Build it
First, build it with the byte-code compiler. From the top directory do :
make all
If wanted, you can build it with the native compiler. From the top directory do :
make allopt
Install it
You could have to become super-user before running this command. From the top directory do :
make install


Test the installation
You can give your installation a small test (output should be self-explanatory).
make tst
Clean directories
Installation is complete. Time to clean up:
make clean

2.3  O'Jacaré

O'Jacaré is available on the same platforms than the camljava library.
Configure the system
Edit the file Makefile.config to adjust it to your current installation of O'Caml and camljava.
Build it
First build it with the byte-code compiler. From the toplevel directory, do:
make -C src depend
make -C src byte
If wanted, you can build it with the native compiler. From the toplevel directory, do:
make -C src opt
Install it
You could have to become super-user before running this command. From the toplevel directory, do:
make -C src install
Test the installation
Next section (3.2) could be considered as a test to your installation.
Clean directories
Installation is complete. Time to clean up:
make -C src clean

3  Compiling with O'Jacaré

3.1  Principle

The tool ojacare take as only argument the IDL file to process, and generate from it: The generated O'Caml module must be compiled with parameters -I +camljava -I +ojacare (if you choose default installation directory for both camljava and O'Jacaré).

The generated Java classes must be compiled with `ocamlc -where`/camljava/camljava.jar in you CLASSPATH (if you choose default installation directory for camljava)

Main must be linked with the jni.cma and jnihelpers.cma archives, found respectively in camljava and O'Jacaré installation directory. (Use -I +camljava jni.cma -I +ojacare jnihelpers.cma parameters as default.)

O'Jacaré provides a simple generic Makefile, see 6.4.3.

3.2  Full example

Note:

After editing the file examples/Makefile.config, the following command in directory examples/point/ will build the example as detailed in this section.
make byte

Let's use from O'Caml three Java classes : Point, ColoredPoint, and Cloud (filled with Point). In a second step, we want to specialize within O'Caml the class ColoredPoint (by using callback mechanism).

The three Java classes are supposed to be implemented within a package mypack and describe in file p.idl (see 6.4.1).

Process p.idl file with:
$ ojacare p.idl

It will generate three files: They can also be compiled:
$ ocamlc -I +camljava -I +ojacare p.mli
$ ocamlc -I +camljava -I +ojacare p.ml
$ javac -classpath "`ocamlc -where`/camljava/camljava.jar:." callback/mypack/ColoredPoint.java

Finally, taking main-point.ml as main file (6.4.2), everything can be linked:
$ ocamlc -I +camljava -I +ojacare main-point.ml
$ ocamlc -I +camljava -I +ojacare -o point jni.cma jnihelpers.cma p.cmo main-point.cmo

You can now execute ./point.

O'Jacaré can also be used from toplevel:
$ ocamlmktop -o ocaml-point -I +camljava -I +ojacare jni.cma jnihelpers.cma p.cmo
$ ./ocaml-point -I +ojacare
        Objective Caml version 3.07+2

# 

3.3  More examples

Examples in this section are available in the directory examples/ from the O'Jacaré distribution (see section 2).

Note:

After editing the file examples/Makefile.config, following commands can be used in each sub-directory.

Building with bytecode compiler, then running it:
make byte
make run-byte
Building with native version, then running it:
make opt
make run-opt
Building a custom toplevel, then running it:
make toplevel
make run-toplevel
point
Simple example with in-heritance and late-binding
rectangle
Multiple in-heritance in O'Caml from encapsulated Java classes
observer
Design-patterns
visitorML
Design-patterns
visitorJava
Visit with Java a recursive O'Caml value
ojDvi
a DVI viewer
awt
let's try building an GUI interactively from toplevel

4  IDL description

This section first describes the whole syntax of IDL. It could be read as a subset of the Java syntax with some attributes specified between brackets (name aliasing, callback mechanism, ...).

Second part explains, from an user point of view, the code generated by ojacare.

4.1  Syntax

file ::= package [package]*
  | decl [decl]*
 
package ::= package qname ; decl [decl]*
decl ::= class
  | interface
 
class ::= [ [attributes] ] [abstract] class name
    [ extends qname ]
    [ implements qname [, qname]* ]
    {
    [class_elt ;]*
    }
class_elt ::= [ [attributes] ] [static] [final] type name
  | [ [attributes] ] [static] [abstract] type name ([args])
  | [attributes] <init> ([args])
 
interface ::= [ [attributes] ] interface name
    [ extends qname [, qname]* ]
    {
    [interface_elt ;]*
    }
interface_elt ::= [ [attributes] ] type name
  | [ [attributes] ] type name ([args])
 
args ::= arg [, arg]*
arg ::= [ [attributes] ] type [name]
 
attributes ::= attribute [, attribute]*
attribute ::= name ident
  | callback
  | array
 
type ::= basetype
  | object
  | basetype [ ]
basetype ::= void
  | boolean
  | byte
  | char
  | short
  | int
  | long
  | float
  | double
  | string
object ::= qname
 
qname ::= name [. name]*
name ::= ident

4.2  Type

Figure 1 presents type correspondence for base-type.

Java IDL O'Caml
boolean boolean bool
byte byte int
char char int
short short int
int int int
long long int64
float float float
double double float
java.lang.String string string

Figure 1: Base-type correspondance


A contrario, class type are shared, and there are 2 different mappings for arrays (specified by attribute array).

Java IDL O'Caml
type [] type [] type JniArray.jArray
[array] type [] type [] type array

Figure 2: Array type correspondance


Class ['a] JniArray.jArray allows array sharing between O'Caml and Java (see sections 5.1.5 and 5.1.6 for furthers details).

4.3  Generated code

Package

As there is no import mechanism now in O'Jacaré, you can describe multiple package in one file.
package java.util;

// some classes from package java.util

package mypack;

// some classes from package mypack
They indicate where to find Java classes, but there is only one generated O'Caml module. It's named as the IDL file.

Class, abstract class, interface

IDL, as Java, allows class, abstract class and interface description.
package java.util;

class Object {
  // constructors, methods, fields, static methods, static fields 
}
interface Iterator {
  // methods, static fields
}
abstract class AbstractCollection {
  // constructors, methods, fields, static methods, static fields 
}
O'Jacaré will generate three class type : jObject, jIterator, jAbstractCollection.

When you describe two classes with the same name in different package, or when you're unhappy with automatic naming, you must use name aliasing :
package java.awt;

class Color {
  // ...
}

package mypack;

[name jMyColor] class Color {
  // ...
}
O'Jacaré will generate two class type : jColor, jMyColor.

O'Jacaré introduces class-type JniHierarchy.jTop, subtype of every generated class-type.
class type jTop =
  object
    method _get_jniobj: Jni.obj
  end

For type safety, O'Jacaré generates abstract type for JNI reference (Jni.obj) : _jni_jColor, _jni_jMyColor, ...
class type jColor =
  object
    inherit JniHierarchy.top
    method _get_jni_jColor : _jni_jColor
    (* ... *)
  end

class type jMyColor =
  object
    inherit JniHierarchy.top
    method _get_jni_jMyColor : _jni_jMyColor
    (* ... *)
  end

Method and field

package mypack;

class Point {
  int x;
  final string name;
  void rMoveTo(int);
  [name to_string] string toString();
}

class Cloud {
  Point getPoint();
}

For a field, O'Jacaré will generate accessors and modifiers methods in class type. When attribute final is specified, only accessors will be generated.
class type jPoint =
  object
    inherit JniHierarchy.top
    method _get_jni_jPoint : _jni_jPoint
    method get_x: unit -> int
    method set_x: int -> unit
    method get_name: unit -> string
    method rMoveTo: int -> unit
    method to_string: unit -> string
  end

When class type appears in a method from IDL, signature in O'Caml will use the generated class type.
class type jCloud =
  object
    inherit JniHierarchy.top
    method _get_jni_jCloud : _jni_jCloud
    method getPoint: unit -> jPoint
  end

O'Jacaré generates encapsulation / unencapsulation code within method code.

Constructor

Constructors are named <init> (in reference to JNI).
package java.util;

class Date {
  [name current_date] <init>();
  [name date_with_seconds] <init>(long date);
}
Name alias are mandatory for constructor (no overloading in O'Caml). O'Jacaré will generate an O'Caml class for each constructor in IDL.
class date_with_seconds : int64 -> jDate
class current_date : unit -> jDate

Static method and field

O'Jacaré accept static field, and static method description.
package java.awt;

class Color {
  static final Color blue;
  [name yellow] static final Color yellow;
}

Static methods and fields are mapped to global declarations. O'Jacaré prefix their name with qualified class name, unless you specify a name alias.
val java_awt_jColor__get_blue : unit -> jColor
val get_yellow : unit -> jColor

Inheritance

Sub-typing of class-type generated with O'Jacaré reflect sub-classing in IDL.
package mypack;

class Point {
  int x; int y;
  [name point] <init>(int, int);

  void moveTo(int, int);
}

interface Colored {
  string getColor();
  void setColor(string);
}

class ColoredPoint extends Point implements Colored {
  [name colored_point] <init>
  [name eq_colored_point] eq(ColoredPoint);
}

For class ColoredPoint, O'Jacaré will generate this class type:
class type jColoredPoint =
  object
    inherit jPoint
    inherit jColored
    method _get_jni_jColoredPoint : _jni_jColoredPoint
    method eq_colored_point : jColoredPoint -> bool
  end

Dynamic downcast mechanism of Java for encapsulated object is available through generated functions.
val jColoredPoint_of_top : JniHierarchy.top -> jColoredPoint

Callback attribut with class

Until now, O'Jacaré generates encapsulation code for Java classes (wrapper). I.e. calling in Java a method upon this, stay in Java's world.

O'Jacaré can take advantage of callback mechanism from camljava with the callback attribute.
package mypack;

// ...

[callback] class ColoredPoint extends Point implements Colored {
  [name colored_point] <init>(int, int, string);
  [name default_colored_point] <init>();
  // ...
}
O'Jacaré will generate one Java subclass to mypack.ColoredPoint named callback.mypack.ColoredPoint. It override each method with a callback to O'Caml equivalent.

O'Jacaré will generate two new stub classes in O'Caml (in general, as many stub as constructor in IDL).
class virtual _stub_colored_point :
  int -> int -> string -> _stub_jColoredPoint
class virtual _stub_default_colored_point : unit -> _stub_jColoredPoint
Both Java and O'Caml generated class contains a reference to the other one.

Sub-classing the stub, will allow late-binding between the two host languages.

Callback attribute with interface

The callback attribute, can also be used with interface. As there is no constructor for interface, O'Jacaré will generate only one stub in O'Caml with no argument. There is still one generated Java class.

4.4  Exception

Exceptions raised by Java are encapsulated by camljava into an O'Caml exception (Jni.Exception of Jni.obj).

5  Programming with O'Jacaré

5.1   Usage from O'Caml

Example in this section are executed in a toplevel build after processing p.idl (6.4.1) with ojacare.
$ ocamlmktop -o ocaml-point -I +camljava -I +ojacare jni.cma jnihelpers.cma p.cmo
$ ./ocaml-point -I +ojacare
        Objective Caml version 3.07+2

# 

5.1.1  Objects allocation

# let p = new point 3 4;;
val p : P.point = <obj>
# let cp = new colored_point 2 5 "vert";;
val cp : P.default_colored_point = <obj>
# let c = new empty_cloud;;
val c : unit -> P.empty_cloud = <fun>

5.1.2  Method calls

With base-type:
# p#toString ();;
- : string = "(3,4)"
# cp#toString ();;
- : string = "(2,5):vert"

With object as argument:
# c#addPoint p;;
- : unit = ()
# c#addPoint (pc :> jPoint);;
- : unit = ()
# c#toString ();;
- : string = "[(3,4), (2,5):vert]"

5.1.3  Downcast

Accepted:
# let p2 = (new colored_point 3 5 "bleu" :> jPoint);;
val p2 : P.jPoint = <obj>
# jColoredPoint_of_top (p2 :> JniHierarchy.top);;
- : P.jColoredPoint = <obj>

Rejected:
# jColoredPoint_of_top (p :> JniHierarchy.top);;
Exception: Failure "``cast error'' : jColoredPoint (mypack/ColoredPoint)".

5.1.4  Class specialization

By subclassing the generated stub:
# class spec_colored_point x y c  =
  object
    inherit _stub_colored_point x y c as super
    method getColor () = "Caml"^(super#getColor ())
  end;;
class spec_colored_point : int -> int -> string -> object ... end
# let spc = new spec_colored_point 2 3 "bleu";;
val spc : spec_colored_point = <obj>
# spc#toString ();;
- : string = "(2,3):Camlbleu"

Warning, when subclassing the wrapper, don't expect late-binding:
# class spec_colored_point x y c  =
  object
    inherit colored_point x y c as super
    method getColor () = "Caml"^(super#getColor ())
  end;;
class false_spec_colored_point : int -> int -> string -> object ... end
# let fspc = new false_spec_colored_point 2 3 "bleu";;
val fspc : false_spec_colored_point = <obj>
# fspc#toString ();;
- : string = "(2,3):bleu"

5.1.5   Arrays by sharing

Array type in IDL are shared. They are manipulated through a class defined in module JniArray.
class type ['a] jArray =
  object
    method _get_jniobj : Jni.obj
    method get : int -> 'a
    method set : int -> 'a -> unit
  end

When using array type in IDL:
package java.lang;

class String {
  char[] toCharArray();
}
O'Jacaré will generate this class type:
class type jString =
  object
    inherit JniHierarchy.top
    method _get_jni_jString : _jni_jString
    method toCharArray : unit -> int JniArray.jArray
  end

The module JniArray, provide way to initializing array from base type :
val init_boolean_jArray : int -> (int -> bool) -> bool jArray
(* ... *)
val init_double_jArray : int -> (int -> float) -> float jArray
val init_string_jArray : int -> (int -> string) -> string jArray
val init_top_jArray :
  int -> (int -> JniHierarchy.top) -> JniHierarchy.top jArray
For each class in IDL, O'Jacaré will generate an array initializer.
val jArray_init_jString : int -> (int -> jString) -> jString JniArray.jArray

5.1.6  Arrays by copy

O'Jacaré offers a mechanism for converting Java array to O'Caml arrays.
package java.lang;

class String {
  [array] char[] toCharArray();
}
The attribute array before char[], convert int JniArray.jArray to int array.
class type jString =
  object
    inherit JniHierarchy.top
    method _get_jni_jString : _jni_jString
    method toCharArray : unit -> int array
  end

5.2  Usage from Java

O'Jacaré was first for using Java from O'Caml. But there is some tips with callback mechanism for using it from Java.

5.2.1  Describing O'Caml classes

Starting with some O'Caml class.
class mlclass =
  object
    (* methods, ... *)
  end
You must then describe it with an interface in Java and a callback interface in IDL.
[callback] interface MlClass {
   // methods, ...
}
Then implements bindings O'Caml class.
class interface_mlclass =
  object
    inherit mlclass
    inherit _stub_jMlClass ()
  end

5.2.2  Simulating main in Java

Describe static main method in IDL.
class MainJava {
  [name main_java] static void main(string []);
}
Converting argv and then calling Java main from O'Caml.
let _ = 
  let argv = 
    JniArray.init_string_jArray (Array.length Sys.argv) (fun i -> Sys.argv.(i)) 
  in
  main_java argv

5.2.3  Objects allocation

Description in IDL:
[callback] interface SomeMlClass {
  // ...
}

[callback] interface MainML {
  SomeMLClass create();
  // ...
}

class MainJava {
  [name main_java] static void main(string [], MainML);
}
O'Caml implementation:
class main_ml = 
  object
    method create () = new some
    (* ... *)
  end

let _ = 
  let argv = 
    JniArray.init_string_jArray (Array.length Sys.argv) (fun i -> Sys.argv.(i)) 
  in
  main_java argv (new main_ml)

6  Appendices

6.1  Common errors

Take care of classpath, or expect the following message:
Fatal error: exception Failure("Class not found : mypack.Point.")
If your IDL is not in sync with class file at execution time, expect the following error:
Fatal error: exception Failure("Unknown method from IDL in class "mypack.Point" : "double distance()".")

6.2  Known problems

Threading
Communications between O'Caml and Java should be restrained to the main thread.
GC
Callback objects are never deallocated.

6.3  Underlying library camljava

6.3.1  Presentation

Quoting README from Xavier Leroy:

         Caml/C interface       JNI (Java Native Interface)
  Caml <------------------> C <-----------------------------> Java

Currently, CamlJava provides a low-level, weakly-typed OCaml interface 
very similar to the JNI.  Java object references are mapped to an
abstract type, and various JNI-like operations are provided to allow
Java method invocation, field access, and more.  A basic callback
facility (allowing Java code to invoke methods on Caml objects) is
also provided, although some stub Java code must be written by hand.
A good knowledge of the JNI is assumed; see Sun's
JNI book or http://java.sun.com/products/jdk/1.2/docs/guide/jni/
Then, the comments in lib/jni.mli should make sense.
This library contains: It impose a entry point in O'Caml : linking a program with jni.cma will initialize JVM at startup.

6.3.2  Usage

Examples in this section are built in an unique toplevel session:
ocamlmktop -o ocamljava -I +camljava jni.cma
./ocamljava -I +camljava
Introspection
# let class_frame = Jni.find_class "java/awt/Frame";;
val class_frame : Jni.clazz = <abstr>
# let class_button = Jni.find_class "java/awt/Button";;
val class_button : Jni.clazz = <abstr>
# let m_frame_pack = Jni.get_methodID class_frame "pack" "()V";;
val m_frame_pack : Jni.methodID = <abstr>
# let m_frame_show = Jni.get_methodID class_frame "show" "()V";;
val m_frame_show : Jni.methodID = <abstr>
Allocation and initialization
# let f = Jni.alloc_object class_frame;;
val f : Jni.obj = <abstr>
# let b = Jni.alloc_object class_button;;
val b : Jni.obj = <abstr>
# let m_frame_init = Jni.get_methodID class_frame "<init>" "(Ljava/lang/String;)V";;
val m_frame_init : Jni.methodID = <abstr>
# let m_button_init =  Jni.get_methodID class_button "<init>" "(Ljava/lang/String;)V";;
val m_button_init : Jni.methodID = <abstr>
# Jni.call_void_method f m_frame_init [|Jni.Obj (Jni.string_to_java "Greetings !")|];;
- : unit = ()
# Jni.call_void_method b m_button_init [|Jni.Obj (Jni.string_to_java "Hello World")|];;
- : unit = ()
Method calls
# let m_frame_add = Jni.get_methodID class_frame 
      "add" "(Ljava/awt/Component;)Ljava/awt/Component;";;
val m_frame_add : Jni.methodID = <abstr>
# Jni.call_object_method f m_frame_add [| Jni.Obj b |];;
- : Jni.obj = <abstr>
# Jni.call_void_method f m_frame_pack [||];;
- : unit = ()
# Jni.call_void_method f m_frame_show [||];;
- : unit = ()
Minimal dynamic type checking
# Jni.call_object_method f m_frame_add [| Jni.Camlint 0 |];;
Exception: Jni.Exception _.
# Jni.call_object_method f m_frame_add [| Jni.Obj (Jni.string_to_java "loosy component object") |];;
Bus error
# Jni.call_object_method an_object_uncompatible_with_class_frame m_frame_pack [||];;         
Bus error

6.4  Basic example

6.4.1  p.idl

File p.idl from sections 3.2 and 5.1:
package mypack;

class Point {
 
  int x;
  int y; 
  
  [name default_point] <init> ();
  [name point] <init> (int,int);
  
  void moveto(int,int);
  void rmoveto(int,int);
  string toString();
  void display();
  double distance();
  boolean eq(Point);

}

[callback] class ColoredPoint extends Point {

  [name default_colored_point] <init> ();
  [name colored_point] <init> (int,int,string);

  [name eq_colored_point] boolean eq(ColoredPoint);
  string getColor();
  void setColor(string);
}

class Cloud {
  
  [name empty_cloud] <init> ();

  void addPoint(Point);
  string toString();

}

6.4.2   main-point.ml

File main-point.ml from section 3.2:
open P

let display s = print_string s; flush stdout ;;

display "Creation d'un point p  : ";;
let p = new default_point ();;
display "OK\n";;

display "Creation d'un point p2 = (1,1) : ";;
let p2 = new point 1 1;;
display "OK\n";;

display "Envoi p#display : ";;
p#display ();;
display "Envoi p2#display : ";;
p2#display ();;

display "Envoi p#moveto 4 3 : ";;
p#moveto 4 3;;
p#display ();;

display "Envoi p#rmoveto 2 -2 : ";;
p#rmoveto 2 ~-2;;
p#display ();;
  
display "Envoi p2#toString : ";;
let s = p2#toString () in print_string s; print_newline ();;

display "Envoi p2#distance : ";;
let d = p2#distance () in print_float d; print_newline ();;

display "Envoi p2#set_x 4 : ";;
p2#set_x 4;;
p2#display ();;

display "Creation d'un point colore pc = (1,3) cyan : ";;
let pc = new colored_point 1 3 "cyan";;
display "OK\n";;

display "Creation d'un point colore pc2 = (2,3) blue : ";;
let pc2 = new colored_point 1 3 "blue";;
display "OK\n";;

display "Envoi pc#display : ";;
pc#display ();;

display "Envoi pc2#display : ";;
pc2#display ();;

display "Envoi pc2#getColor : ";;
let s = pc2#getColor () in print_string s; print_newline ();;

display "Creation d'un nuage de point : ";;
let n = new empty_cloud ();;
display "OK\n";;

display "Ajout des points p2 pc1 pc2 p1 au nuage n: ";;
n#addPoint p2;;
n#addPoint (pc :> jPoint);;
n#addPoint (pc2 :> jPoint);;
n#addPoint p;;
display "OK\n";;

display "Envoi n#toString : ";;
let s = n#toString () in print_string s; print_newline ();;

class ml_colored_point x y c  =
  object
    inherit _stub_colored_point x y c as super
    method getColor () = "Caml"^(super#getColor ())
  end;;

display "Creation d'un point callback cb1 = (5,6) blue ";;
let cb1 = new ml_colored_point 5 6 "blue";;
display "OK\n";;

display "Envoi cb1#getColor : ";;
let s = cb1#getColor () in print_string s; print_newline ();;

display "Envoi cb1#toString : ";;
let s = cb1#toString () in print_string s; print_newline ();;

display "Ajout du point cb au nuage n: ";;
n#addPoint (cb1 :> jPoint);;
display "OK\n";;

display "Envoi n#toString : ";;
let s = n#toString () in print_string s; print_newline ();;

6.4.3   Makefile

File Makefile:
#       $Id: ojacare.tex,v 1.21 2004/06/01 15:07:00 emmanuel Exp $

include ../Makefile.config

# Nom de l'éxécutable
EXEC = point

# Liste des fichiers IDL
IDL       = p

# Liste des répertoires contenant les modules et bibliotèques Caml utilisées
MLINCDIRS = 

# Liste des modules Caml 
MODULES   = 

# Liste des bibliothèques Caml à inclure à l'édition de lien
LIBRARIES = 

# Liste des bibliothèques C à inclure à l'édition de lien
CLIBS     = 

# Liste des classes Java à compiler
CLASS     = mypack/Point mypack/Colored mypack/ColoredPoint mypack/Cloud 

# Liste des classes Java ayant l'attribut callback 
CBCLASS   = mypack/ColoredPoint

include $(OJACAREDIR)/Makefile.include

File Makefile.config:
OCAMLC = ocamlc
OCAMLOPT = ocamlopt.opt 
OCAMLMKLIB = ocamlmklib
OCAMLLEX = ocamllex
OCAMLYACC = ocamlyacc
OCAMLDEP = ocamldep 
OCAMLMKTOP = ocamlmktop

OJACARE = ojacare
OJACAREDIR = $(shell $(OCAMLC) -where)/ojacare

CAMLJAVADIR = $(shell $(OCAMLC) -where)/camljava


This document was translated from LATEX by HEVEA.