Markus Mottl avatar Markus Mottl committed a22ac82

Upgraded to Oasis 0.4

Comments (0)

Files changed (8)

 (* OASIS_START *)
-(* DO NOT EDIT (digest: 8cda0a8640b10610e580f8ebdb4d9a3e) *)
+(* DO NOT EDIT (digest: 098585fe4c145f4cf91f22e370032538) *)
 This is the INSTALL file for the aifad distribution.
 
 This package uses OASIS to generate its build system. See section OASIS for
 ============
 
 In order to compile this package, you will need:
-* ocaml (>= 4.00)
+* ocaml
 * findlib (>= 1.3.1)
 * res
 * pcre
 Uninstalling
 ============
 
-1. Go to the root of the package 
+1. Go to the root of the package
 2. Run 'ocaml setup.ml -uninstall'
 
 OASIS
 # OASIS_START
-# DO NOT EDIT (digest: bc1e05bfc8b39b664f29dae8dbd3ebbb)
+# DO NOT EDIT (digest: 7b2408909643717852b95f994b273fee)
 
 SETUP = ocaml setup.ml
 
 test: setup.data build
 	$(SETUP) -test $(TESTFLAGS)
 
-all: 
+all:
 	$(SETUP) -all $(ALLFLAGS)
 
 install: setup.data
 reinstall: setup.data
 	$(SETUP) -reinstall $(REINSTALLFLAGS)
 
-clean: 
+clean:
 	$(SETUP) -clean $(CLEANFLAGS)
 
-distclean: 
+distclean:
 	$(SETUP) -distclean $(DISTCLEANFLAGS)
 
 setup.data:
-OASISFormat:      0.3
+OASISFormat:      0.4
 Name:             aifad
-Version:          2.0.2
+Version:          2.0.3
 Synopsis:         AIFAD - Automated Induction of Functions over Algebraic Datatypes
 Description:      AIFAD is a machine learning tool that generalizes decision tree learning to algebraic datatypes.
 Authors:          Markus Mottl <markus.mottl@gmail.com>
 Maintainers:      Markus Mottl <markus.mottl@gmail.com>
 LicenseFile:      COPYING.txt
 License:          GPL-3+
-OCamlVersion:     >= 4.00
+# TODO: uncomment once Oasis thread handling wrt. OCaml version is fixed
+#OCamlVersion:     >= 4.00
 FindlibVersion:   >= 1.3.1
 Homepage:         https://bitbucket.org/mmottl/aifad
 #Categories:
 FilesAB:          src/version.ml.ab
 
-Plugins:          META (0.3), StdFiles (0.3), DevFiles (0.3)
+Plugins:          META (0.4), StdFiles (0.4), DevFiles (0.4)
 XStdFilesREADME:  false
 
 BuildTools:       ocamlbuild, ocamldoc, menhir
 # OASIS_START
-# DO NOT EDIT (digest: a24238296c50b2a493ec227242939953)
-# Ignore VCS directories, you can use the same kind of rule outside 
-# OASIS_START/STOP if you want to exclude directories that contains 
+# DO NOT EDIT (digest: 06a16628ce2bc52135f669a9f80af292)
+# Ignore VCS directories, you can use the same kind of rule outside
+# OASIS_START/STOP if you want to exclude directories that contains
 # useless stuff for the build process
 <**/.svn>: -traverse
 <**/.svn>: not_hygienic
 <src/*.ml{,i}>: pkg_pcre
 <src/*.ml{,i}>: pkg_cfg
 # OASIS_STOP
+
+true: -traverse
+<{src,examples}/**>: traverse
+
+<**/*.ml{,i}>: warn(Aer-44), annot
+
 true: use_menhir
-<**/*.ml{,i}>: warn_A, warn_e, warn_r, annot
 #!/bin/sh
 
 # OASIS_START
-# DO NOT EDIT (digest: 425187ed8bfdbdd207fd76392dd243a7)
+# DO NOT EDIT (digest: dc86c2ad450f91ca10c931b6045d0499)
 set -e
 
 FST=true
-for i in "$@"; do 
+for i in "$@"; do
   if $FST; then
     set --
     FST=false
 (* OASIS_START *)
-(* DO NOT EDIT (digest: 2aee5d890cff309fb50309e32ba9c38c) *)
+(* DO NOT EDIT (digest: e82cdde10b6ce2191ebbec00b4e5813b) *)
 module OASISGettext = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISGettext.ml" *)
+(* # 22 "src/oasis/OASISGettext.ml" *)
+
 
   let ns_ str =
     str
 
+
   let s_ str =
     str
 
-  let f_ (str : ('a, 'b, 'c, 'd) format4) =
+
+  let f_ (str: ('a, 'b, 'c, 'd) format4) =
     str
 
+
   let fn_ fmt1 fmt2 n =
     if n = 1 then
       fmt1^^""
     else
       fmt2^^""
 
+
   let init =
     []
 
+
 end
 
 module OASISExpr = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISExpr.ml" *)
+(* # 22 "src/oasis/OASISExpr.ml" *)
+
+
 
 
 
   open OASISGettext
 
+
   type test = string 
 
+
   type flag = string 
 
+
   type t =
     | EBool of bool
     | ENot of t
     | ETest of test * string
     
 
+
   type 'a choices = (t * 'a) list 
 
+
   let eval var_get t =
     let rec eval' =
       function
     in
       eval' t
 
+
   let choose ?printer ?name var_get lst =
     let rec choose_aux =
       function
     in
       choose_aux (List.rev lst)
 
+
 end
 
 
-# 117 "myocamlbuild.ml"
+# 132 "myocamlbuild.ml"
 module BaseEnvLight = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/base/BaseEnvLight.ml" *)
+(* # 22 "src/base/BaseEnvLight.ml" *)
+
 
   module MapString = Map.Make(String)
 
+
   type t = string MapString.t
 
+
   let default_filename =
     Filename.concat
       (Sys.getcwd ())
       "setup.data"
 
+
   let load ?(allow_empty=false) ?(filename=default_filename) () =
     if Sys.file_exists filename then
       begin
              filename)
       end
 
+
   let var_get name env =
     let rec var_expand str =
       let buff =
     in
       var_expand (MapString.find name env)
 
+
   let var_choose lst env =
     OASISExpr.choose
       (fun nm -> var_get nm env)
 end
 
 
-# 215 "myocamlbuild.ml"
+# 236 "myocamlbuild.ml"
 module MyOCamlbuildFindlib = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *)
+(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *)
 
-  (** OCamlbuild extension, copied from 
+
+  (** OCamlbuild extension, copied from
     * http://brion.inria.fr/gallium/index.php/Using_ocamlfind_with_ocamlbuild
     * by N. Pouillard and others
     *
     * Updated on 2009/02/28
     *
-    * Modified by Sylvain Le Gall 
+    * Modified by Sylvain Le Gall
     *)
   open Ocamlbuild_plugin
 
+
   (* these functions are not really officially exported *)
-  let run_and_read = 
+  let run_and_read =
     Ocamlbuild_pack.My_unix.run_and_read
 
-  let blank_sep_strings = 
+
+  let blank_sep_strings =
     Ocamlbuild_pack.Lexers.blank_sep_strings
 
+
   let split s ch =
-    let x = 
-      ref [] 
+    let buf = Buffer.create 13 in
+    let x = ref [] in
+    let flush () =
+      x := (Buffer.contents buf) :: !x;
+      Buffer.clear buf
     in
-    let rec go s =
-      let pos = 
-        String.index s ch 
-      in
-        x := (String.before s pos)::!x;
-        go (String.after s (pos + 1))
-    in
-      try
-        go s
-      with Not_found -> !x
+      String.iter
+        (fun c ->
+           if c = ch then
+             flush ()
+           else
+             Buffer.add_char buf c)
+        s;
+      flush ();
+      List.rev !x
+
 
   let split_nl s = split s '\n'
 
+
   let before_space s =
     try
       String.before s (String.index s ' ')
     with Not_found -> s
 
-  (* this lists all supported packages *)
+  (* ocamlfind command *)
+  let ocamlfind x =
+    let ocamlfind_prog =
+      let env_filename = Pathname.basename BaseEnvLight.default_filename in
+      let env = BaseEnvLight.load ~filename:env_filename ~allow_empty:true () in
+      try
+        BaseEnvLight.var_get "ocamlfind" env
+      with Not_found ->
+        Printf.eprintf "W: Cannot get variable ocamlfind";
+        "ocamlfind"
+    in
+      S[Sh ocamlfind_prog; x]
+
+  (* This lists all supported packages. *)
   let find_packages () =
     List.map before_space (split_nl & run_and_read "ocamlfind list")
 
-  (* this is supposed to list available syntaxes, but I don't know how to do it. *)
+
+  (* Mock to list available syntaxes. *)
   let find_syntaxes () = ["camlp4o"; "camlp4r"]
 
-  (* ocamlfind command *)
-  let ocamlfind x = S[A"ocamlfind"; x]
 
   let dispatch =
     function
       | Before_options ->
-          (* by using Before_options one let command line options have an higher priority *)
-          (* on the contrary using After_options will guarantee to have the higher priority *)
-          (* override default commands by ocamlfind ones *)
+          (* By using Before_options one let command line options have an higher
+           * priority on the contrary using After_options will guarantee to have
+           * the higher priority override default commands by ocamlfind ones *)
           Options.ocamlc     := ocamlfind & A"ocamlc";
           Options.ocamlopt   := ocamlfind & A"ocamlopt";
           Options.ocamldep   := ocamlfind & A"ocamldep";
           Options.ocamldoc   := ocamlfind & A"ocamldoc";
-          Options.ocamlmktop := ocamlfind & A"ocamlmktop"
-                                  
+          Options.ocamlmktop := ocamlfind & A"ocamlmktop";
+          Options.ocamlmklib := ocamlfind & A"ocamlmklib"
+
       | After_rules ->
-          
-          (* When one link an OCaml library/binary/package, one should use -linkpkg *)
+
+          (* When one link an OCaml library/binary/package, one should use
+           * -linkpkg *)
           flag ["ocaml"; "link"; "program"] & A"-linkpkg";
-          
+
           (* For each ocamlfind package one inject the -package option when
            * compiling, computing dependencies, generating documentation and
            * linking. *)
-          List.iter 
+          List.iter
             begin fun pkg ->
-              flag ["ocaml"; "compile";  "pkg_"^pkg] & S[A"-package"; A pkg];
-              flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S[A"-package"; A pkg];
-              flag ["ocaml"; "doc";      "pkg_"^pkg] & S[A"-package"; A pkg];
-              flag ["ocaml"; "link";     "pkg_"^pkg] & S[A"-package"; A pkg];
-              flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S[A"-package"; A pkg];
-            end 
+              let base_args = [A"-package"; A pkg] in
+              let syn_args = [A"-syntax"; A "camlp4o"] in
+              let args =
+          (* Heuristic to identify syntax extensions: whether they end in
+           * ".syntax"; some might not *)
+                if Filename.check_suffix pkg "syntax"
+                then syn_args @ base_args
+                else base_args
+              in
+              flag ["ocaml"; "compile";  "pkg_"^pkg] & S args;
+              flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S args;
+              flag ["ocaml"; "doc";      "pkg_"^pkg] & S args;
+              flag ["ocaml"; "link";     "pkg_"^pkg] & S base_args;
+              flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S args;
+            end
             (find_packages ());
 
           (* Like -package but for extensions syntax. Morover -syntax is useless
           flag ["ocaml"; "compile";  "syntax_"^syntax] & S[A"-syntax"; A syntax];
           flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
           flag ["ocaml"; "doc";      "syntax_"^syntax] & S[A"-syntax"; A syntax];
-          flag ["ocaml"; "infer_interface"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
+          flag ["ocaml"; "infer_interface"; "syntax_"^syntax] &
+                S[A"-syntax"; A syntax];
           end (find_syntaxes ());
 
           (* The default "thread" tag is not compatible with ocamlfind.
            * Indeed, the default rules add the "threads.cma" or "threads.cmxa"
            * options when using this tag. When using the "-linkpkg" option with
            * ocamlfind, this module will then be added twice on the command line.
-           *                        
+           *
            * To solve this, one approach is to add the "-thread" option when using
            * the "threads" package using the previous plugin.
            *)
           flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]);
           flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"])
 
-      | _ -> 
+      | _ ->
           ()
-
 end
 
 module MyOCamlbuildBase = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
+(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
+
 
   (** Base functions for writing myocamlbuild.ml
       @author Sylvain Le Gall
 
 
 
+
+
   open Ocamlbuild_plugin
   module OC = Ocamlbuild_pack.Ocaml_compiler
 
+
   type dir = string 
   type file = string 
   type name = string 
   type tag = string 
 
-(* # 56 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
+
+(* # 62 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
+
 
   type t =
       {
-        lib_ocaml: (name * dir list) list;
-        lib_c:     (name * dir * file list) list; 
+        lib_ocaml: (name * dir list * string list) list;
+        lib_c:     (name * dir * file list) list;
         flags:     (tag list * (spec OASISExpr.choices)) list;
         (* Replace the 'dir: include' from _tags by a precise interdepends in
          * directory.
          *)
-        includes:  (dir * dir list) list; 
+        includes:  (dir * dir list) list;
       } 
 
+
   let env_filename =
-    Pathname.basename 
+    Pathname.basename
       BaseEnvLight.default_filename
 
+
   let dispatch_combine lst =
     fun e ->
-      List.iter 
+      List.iter
         (fun dispatch -> dispatch e)
-        lst 
+        lst
+
 
   let tag_libstubs nm =
     "use_lib"^nm^"_stubs"
 
+
   let nm_libstubs nm =
     nm^"_stubs"
 
-  let dispatch t e = 
-    let env = 
-      BaseEnvLight.load 
-        ~filename:env_filename 
+
+  let dispatch t e =
+    let env =
+      BaseEnvLight.load
+        ~filename:env_filename
         ~allow_empty:true
         ()
     in
-      match e with 
+      match e with
         | Before_options ->
             let no_trailing_dot s =
               if String.length s >= 1 && s.[0] = '.' then
             in
               List.iter
                 (fun (opt, var) ->
-                   try 
+                   try
                      opt := no_trailing_dot (BaseEnvLight.var_get var env)
                    with Not_found ->
                      Printf.eprintf "W: Cannot get variable %s" var)
                   Options.ext_dll, "ext_dll";
                 ]
 
-        | After_rules -> 
+        | After_rules ->
             (* Declare OCaml libraries *)
-            List.iter 
+            List.iter
               (function
-                 | nm, [] ->
-                     ocaml_lib nm
-                 | nm, dir :: tl ->
+                 | nm, [], intf_modules ->
+                     ocaml_lib nm;
+                     let cmis =
+                       List.map (fun m -> (String.uncapitalize m) ^ ".cmi")
+                                intf_modules in
+                     dep ["ocaml"; "link"; "library"; "file:"^nm^".cma"] cmis
+                 | nm, dir :: tl, intf_modules ->
                      ocaml_lib ~dir:dir (dir^"/"^nm);
-                     List.iter 
-                       (fun dir -> 
+                     List.iter
+                       (fun dir ->
                           List.iter
                             (fun str ->
                                flag ["ocaml"; "use_"^nm; str] (S[A"-I"; P dir]))
                             ["compile"; "infer_interface"; "doc"])
-                       tl)
+                       tl;
+                     let cmis =
+                       List.map (fun m -> dir^"/"^(String.uncapitalize m)^".cmi")
+                                intf_modules in
+                     dep ["ocaml"; "link"; "library"; "file:"^dir^"/"^nm^".cma"]
+                         cmis)
               t.lib_ocaml;
 
             (* Declare directories dependencies, replace "include" in _tags. *)
-            List.iter 
+            List.iter
               (fun (dir, include_dirs) ->
                  Pathname.define_context dir include_dirs)
               t.includes;
 
                    flag ["link"; "library"; "ocaml"; "native"; tag_libstubs lib]
                      (S[A"-cclib"; A("-l"^(nm_libstubs lib))]);
-                        
+
                    flag ["link"; "program"; "ocaml"; "byte"; tag_libstubs lib]
                      (S[A"-dllib"; A("dll"^(nm_libstubs lib))]);
 
 
                    (* TODO: be more specific about what depends on headers *)
                    (* Depends on .h files *)
-                   dep ["compile"; "c"] 
+                   dep ["compile"; "c"]
                      headers;
 
                    (* Setup search path for lib *)
-                   flag ["link"; "ocaml"; "use_"^lib] 
+                   flag ["link"; "ocaml"; "use_"^lib]
                      (S[A"-I"; P(dir)]);
               )
               t.lib_c;
               (* Add flags *)
               List.iter
               (fun (tags, cond_specs) ->
-                 let spec = 
+                 let spec =
                    BaseEnvLight.var_choose cond_specs env
                  in
                    flag tags & spec)
               t.flags
-        | _ -> 
+        | _ ->
             ()
 
+
   let dispatch_default t =
-    dispatch_combine 
+    dispatch_combine
       [
         dispatch t;
         MyOCamlbuildFindlib.dispatch;
       ]
 
+
 end
 
 
-# 476 "myocamlbuild.ml"
+# 550 "myocamlbuild.ml"
 open Ocamlbuild_plugin;;
 let package_default =
-  {MyOCamlbuildBase.lib_ocaml = []; lib_c = []; flags = []; includes = []; }
+  {MyOCamlbuildBase.lib_ocaml = []; lib_c = []; flags = []; includes = []}
   ;;
 
 let dispatch_default = MyOCamlbuildBase.dispatch_default package_default;;
 
-# 485 "myocamlbuild.ml"
+# 559 "myocamlbuild.ml"
 (* OASIS_STOP *)
 
 let () =
 (* setup.ml generated for the first time by OASIS v0.3.0 *)
 
 (* OASIS_START *)
-(* DO NOT EDIT (digest: 2a73feb843b074cf448dc099e97011da) *)
+(* DO NOT EDIT (digest: b83aa92b9657e8c0b141975ecc111ead) *)
 (*
-   Regenerated by OASIS v0.3.0
+   Regenerated by OASIS v0.4.0
    Visit http://oasis.forge.ocamlcore.org for more information and
    documentation about functions used in this file.
 *)
 module OASISGettext = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISGettext.ml" *)
+(* # 22 "src/oasis/OASISGettext.ml" *)
+
 
   let ns_ str =
     str
 
+
   let s_ str =
     str
 
-  let f_ (str : ('a, 'b, 'c, 'd) format4) =
+
+  let f_ (str: ('a, 'b, 'c, 'd) format4) =
     str
 
+
   let fn_ fmt1 fmt2 n =
     if n = 1 then
       fmt1^^""
     else
       fmt2^^""
 
+
   let init =
     []
 
+
 end
 
 module OASISContext = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISContext.ml" *)
+(* # 22 "src/oasis/OASISContext.ml" *)
+
 
   open OASISGettext
 
+
   type level =
     [ `Debug
     | `Info
     | `Warning
     | `Error]
 
+
   type t =
     {
       quiet:                 bool;
       printf:                level -> string -> unit;
     }
 
+
   let printf lvl str =
     let beg =
       match lvl with
     in
       prerr_endline (beg^str)
 
+
   let default =
     ref
       {
         printf                = printf;
       }
 
+
   let quiet =
     {!default with quiet = true}
 
 end
 
 module OASISString = struct
-(* # 1 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISString.ml" *)
-
+(* # 22 "src/oasis/OASISString.ml" *)
 
 
   (** Various string utilities.
-     
+
       Mostly inspired by extlib and batteries ExtString and BatString libraries.
 
       @author Sylvain Le Gall
     *)
 
+
   let nsplitf str f =
     if str = "" then
       []
         push ();
         List.rev !lst
 
+
   (** [nsplit c s] Split the string [s] at char [c]. It doesn't include the
       separator.
     *)
   let nsplit str c =
     nsplitf str ((=) c)
 
+
   let find ~what ?(offset=0) str =
     let what_idx = ref 0 in
-    let str_idx = ref offset in 
-      while !str_idx < String.length str && 
+    let str_idx = ref offset in
+      while !str_idx < String.length str &&
             !what_idx < String.length what do
         if str.[!str_idx] = what.[!what_idx] then
           incr what_idx
       done;
       if !what_idx <> String.length what then
         raise Not_found
-      else 
+      else
         !str_idx - !what_idx
 
-  let sub_start str len = 
+
+  let sub_start str len =
     let str_len = String.length str in
     if len >= str_len then
       ""
     else
       String.sub str len (str_len - len)
 
+
   let sub_end ?(offset=0) str len =
     let str_len = String.length str in
     if len >= str_len then
     else
       String.sub str 0 (str_len - len)
 
+
   let starts_with ~what ?(offset=0) str =
     let what_idx = ref 0 in
     let str_idx = ref offset in
     let ok = ref true in
       while !ok &&
-            !str_idx < String.length str && 
+            !str_idx < String.length str &&
             !what_idx < String.length what do
         if str.[!str_idx] = what.[!what_idx] then
           incr what_idx
       done;
       if !what_idx = String.length what then
         true
-      else 
+      else
         false
 
+
   let strip_starts_with ~what str =
     if starts_with ~what str then
       sub_start str (String.length what)
     else
       raise Not_found
 
+
   let ends_with ~what ?(offset=0) str =
     let what_idx = ref ((String.length what) - 1) in
     let str_idx = ref ((String.length str) - 1) in
     let ok = ref true in
       while !ok &&
-            offset <= !str_idx && 
+            offset <= !str_idx &&
             0 <= !what_idx do
         if str.[!str_idx] = what.[!what_idx] then
           decr what_idx
       done;
       if !what_idx = -1 then
         true
-      else 
+      else
         false
 
+
   let strip_ends_with ~what str =
     if ends_with ~what str then
       sub_end str (String.length what)
     else
       raise Not_found
 
+
   let replace_chars f s =
     let buf = String.make (String.length s) 'X' in
       for i = 0 to String.length s - 1 do
       done;
       buf
 
+
 end
 
 module OASISUtils = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISUtils.ml" *)
+(* # 22 "src/oasis/OASISUtils.ml" *)
+
 
   open OASISGettext
 
+
   module MapString = Map.Make(String)
 
+
   let map_string_of_assoc assoc =
     List.fold_left
       (fun acc (k, v) -> MapString.add k v acc)
       MapString.empty
       assoc
 
+
   module SetString = Set.Make(String)
 
+
   let set_string_add_list st lst =
     List.fold_left
       (fun acc e -> SetString.add e acc)
       st
       lst
 
+
   let set_string_of_list =
     set_string_add_list
       SetString.empty
   let compare_csl s1 s2 =
     String.compare (String.lowercase s1) (String.lowercase s2)
 
+
   module HashStringCsl =
     Hashtbl.Make
       (struct
            Hashtbl.hash (String.lowercase s)
        end)
 
+
   let varname_of_string ?(hyphen='_') s =
     if String.length s = 0 then
       begin
           String.lowercase buf
       end
 
+
   let varname_concat ?(hyphen='_') p s =
     let what = String.make 1 hyphen in
     let p =
   let is_varname str =
     str = varname_of_string str
 
+
   let failwithf fmt = Printf.ksprintf failwith fmt
 
+
 end
 
 module PropList = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/PropList.ml" *)
+(* # 22 "src/oasis/PropList.ml" *)
+
 
   open OASISGettext
 
+
   type name = string
 
+
   exception Not_set of name * string option
   exception No_printer of name
   exception Unknown_field of name * name
 
+
   let () =
     Printexc.register_printer
       (function
          | Not_set (nm, Some rsn) ->
-             Some 
+             Some
                (Printf.sprintf (f_ "Field '%s' is not set: %s") nm rsn)
          | Not_set (nm, None) ->
-             Some 
+             Some
                (Printf.sprintf (f_ "Field '%s' is not set") nm)
          | No_printer nm ->
              Some
                (Printf.sprintf (f_ "No default printer for value %s") nm)
          | Unknown_field (nm, schm) ->
-             Some 
-               (Printf.sprintf (f_ "Field %s is not defined in schema %s") nm schm)
+             Some
+               (Printf.sprintf
+                  (f_ "Field %s is not defined in schema %s") nm schm)
          | _ ->
              None)
 
+
   module Data =
   struct
-
     type t =
         (name, unit -> unit) Hashtbl.t
 
     let clear t =
       Hashtbl.clear t
 
-(* # 71 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/PropList.ml" *)
+
+(* # 78 "src/oasis/PropList.ml" *)
   end
 
+
   module Schema =
   struct
-
     type ('ctxt, 'extra) value =
         {
           get:   Data.t -> string;
       t.name
   end
 
+
   module Field =
   struct
-
     type ('ctxt, 'value, 'extra) t =
         {
           set:    Data.t -> ?context:'ctxt -> 'value -> unit;
 
     let fgets data t =
       t.gets data
-
   end
 
+
   module FieldRO =
   struct
-
     let create ?schema ?name ?parse ?print ?default ?update ?help extra =
       let fld =
         Field.create ?schema ?name ?parse ?print ?default ?update ?help extra
       in
         fun data -> Field.fget data fld
-
   end
 end
 
 module OASISMessage = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISMessage.ml" *)
+(* # 22 "src/oasis/OASISMessage.ml" *)
 
 
   open OASISGettext
   open OASISContext
 
+
   let generic_message ~ctxt lvl fmt =
     let cond =
       if ctxt.quiet then
              end)
         fmt
 
+
   let debug ~ctxt fmt =
     generic_message ~ctxt `Debug fmt
 
+
   let info ~ctxt fmt =
     generic_message ~ctxt `Info fmt
 
+
   let warning ~ctxt fmt =
     generic_message ~ctxt `Warning fmt
 
+
   let error ~ctxt fmt =
     generic_message ~ctxt `Error fmt
 
 end
 
 module OASISVersion = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISVersion.ml" *)
+(* # 22 "src/oasis/OASISVersion.ml" *)
+
 
   open OASISGettext
 
 
 
+
+
   type s = string
 
+
   type t = string 
 
+
   type comparator =
     | VGreater of t
     | VGreaterEqual of t
     | VAnd of comparator * comparator
     
 
+
   (* Range of allowed characters *)
   let is_digit c =
     '0' <= c && c <= '9'
 
+
   let is_alpha c =
     ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
 
+
   let is_special =
     function
       | '.' | '+' | '-' | '~' -> true
       | _ -> false
 
+
   let rec version_compare v1 v2 =
     if v1 <> "" || v2 <> "" then
       begin
               while !p < String.length v && is_digit v.[!p] do
                 incr p
               done;
-              let substr = 
+              let substr =
                 String.sub v !p ((String.length v) - !p)
-              in 
-              let res = 
-                match String.sub v start_p (!p - start_p) with 
+              in
+              let res =
+                match String.sub v start_p (!p - start_p) with
                   | "" -> 0
                   | s -> int_of_string s
               in
 
   let version_of_string str = str
 
+
   let string_of_version t = t
 
+
+  let version_compare_string s1 s2 =
+    version_compare (version_of_string s1) (version_of_string s2)
+
+
   let chop t =
     try
       let pos =
     with Not_found ->
       t
 
+
   let rec comparator_apply v op =
     match op with
       | VGreater cv ->
       | VAnd (op1, op2) ->
           (comparator_apply v op1) && (comparator_apply v op2)
 
+
   let rec string_of_comparator =
     function
       | VGreater v  -> "> "^(string_of_version v)
       | VAnd (c1, c2) ->
           (string_of_comparator c1)^" && "^(string_of_comparator c2)
 
+
   let rec varname_of_comparator =
     let concat p v =
       OASISUtils.varname_concat
         | VAnd (c1, c2) ->
             (varname_of_comparator c1)^"_and_"^(varname_of_comparator c2)
 
-  let version_0_3_or_after t =
-    comparator_apply t (VGreaterEqual (string_of_version "0.3"))
+
+  let rec comparator_ge v' =
+    let cmp v = version_compare v v' >= 0 in
+    function
+      | VEqual v
+      | VGreaterEqual v
+      | VGreater v -> cmp v
+      | VLesserEqual _
+      | VLesser _ -> false
+      | VOr (c1, c2) -> comparator_ge v' c1 || comparator_ge v' c2
+      | VAnd (c1, c2) -> comparator_ge v' c1 && comparator_ge v' c2
+
 
 end
 
 module OASISLicense = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISLicense.ml" *)
+(* # 22 "src/oasis/OASISLicense.ml" *)
+
 
   (** License for _oasis fields
       @author Sylvain Le Gall
 
 
 
+
+
   type license = string 
 
+
   type license_exception = string 
 
+
   type license_version =
     | Version of OASISVersion.t
     | VersionOrLater of OASISVersion.t
     | NoVersion
     
 
+
   type license_dep_5_unit =
     {
       license:   license;
     }
     
 
+
   type license_dep_5 =
     | DEP5Unit of license_dep_5_unit
     | DEP5Or of license_dep_5 list
     | DEP5And of license_dep_5 list
     
 
+
   type t =
     | DEP5License of license_dep_5
     | OtherLicense of string (* URL *)
     
 
+
 end
 
 module OASISExpr = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISExpr.ml" *)
+(* # 22 "src/oasis/OASISExpr.ml" *)
+
+
 
 
 
   open OASISGettext
 
+
   type test = string 
 
+
   type flag = string 
 
+
   type t =
     | EBool of bool
     | ENot of t
     | ETest of test * string
     
 
+
   type 'a choices = (t * 'a) list 
 
+
   let eval var_get t =
     let rec eval' =
       function
     in
       eval' t
 
+
   let choose ?printer ?name var_get lst =
     let rec choose_aux =
       function
     in
       choose_aux (List.rev lst)
 
+
 end
 
 module OASISTypes = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISTypes.ml" *)
+(* # 22 "src/oasis/OASISTypes.ml" *)
+
 
 
 
   type args          = string list 
   type command_line  = (prog * arg list) 
 
+
   type findlib_name = string 
   type findlib_full = string 
 
+
   type compiled_object =
     | Byte
     | Native
     | Best
     
 
+
   type dependency =
     | FindlibPackage of findlib_full * OASISVersion.comparator option
     | InternalLibrary of name
     
 
+
   type tool =
     | ExternalTool of name
     | InternalExecutable of name
     
 
+
   type vcs =
     | Darcs
     | Git
     | OtherVCS of url
     
 
+
   type plugin_kind =
       [  `Configure
        | `Build
        | `Extra
       ]
 
+
   type plugin_data_purpose =
       [  `Configure
        | `Build
        | `Other of string
       ]
 
+
   type 'a plugin = 'a * name * OASISVersion.t option 
 
+
   type all_plugin = plugin_kind plugin
 
+
   type plugin_data = (all_plugin * plugin_data_purpose * (unit -> unit)) list
 
-(* # 102 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISTypes.ml" *)
+
+(* # 115 "src/oasis/OASISTypes.ml" *)
+
 
   type 'a conditional = 'a OASISExpr.choices 
 
+
   type custom =
       {
         pre_command:  (command_line option) conditional;
       }
       
 
+
   type common_section =
       {
         cs_name: name;
       }
       
 
+
   type build_section =
       {
         bs_build:           bool conditional;
       }
       
 
+
   type library =
       {
         lib_modules:            string list;
         lib_findlib_containers: findlib_name list;
       } 
 
+
+  type object_ =
+      {
+        obj_modules:            string list;
+        obj_findlib_fullname:   findlib_name list option;
+      } 
+
+
   type executable =
       {
         exec_custom:          bool;
         exec_main_is:         unix_filename;
       } 
 
+
   type flag =
       {
         flag_description:  string option;
         flag_default:      bool conditional;
       } 
 
+
   type source_repository =
       {
         src_repo_type:        vcs;
         src_repo_subdir:      unix_filename option;
       } 
 
+
   type test =
       {
         test_type:               [`Test] plugin;
         test_tools:              tool list;
       } 
 
+
   type doc_format =
     | HTML of unix_filename
     | DocText
     | OtherDoc
     
 
+
   type doc =
       {
         doc_type:        [`Doc] plugin;
         doc_build_tools: tool list;
       } 
 
+
   type section =
     | Library    of common_section * build_section * library
+    | Object     of common_section * build_section * object_
     | Executable of common_section * build_section * executable
     | Flag       of common_section * flag
     | SrcRepo    of common_section * source_repository
     | Doc        of common_section * doc
     
 
+
   type section_kind =
-      [ `Library | `Executable | `Flag | `SrcRepo | `Test | `Doc ]
-
-  type package = 
+      [ `Library | `Object | `Executable | `Flag | `SrcRepo | `Test | `Doc ]
+
+
+  type package =
       {
         oasis_version:    OASISVersion.t;
         ocaml_version:    OASISVersion.comparator option;
         findlib_version:  OASISVersion.comparator option;
+        alpha_features:   string list;
+        beta_features:    string list;
         name:             package_name;
         version:          OASISVersion.t;
         license:          OASISLicense.t;
         plugin_data:      plugin_data;
       } 
 
+
 end
 
+module OASISFeatures = struct
+(* # 22 "src/oasis/OASISFeatures.ml" *)
+
+  open OASISTypes
+  open OASISUtils
+  open OASISGettext
+  open OASISVersion
+
+  module MapPlugin =
+    Map.Make
+      (struct
+         type t = plugin_kind * name
+         let compare = Pervasives.compare
+       end)
+
+  module Data =
+  struct
+    type t =
+        {
+          oasis_version: OASISVersion.t;
+          plugin_versions: OASISVersion.t option MapPlugin.t;
+          alpha_features: string list;
+          beta_features: string list;
+        }
+
+    let create oasis_version alpha_features beta_features =
+      {
+        oasis_version = oasis_version;
+        plugin_versions = MapPlugin.empty;
+        alpha_features = alpha_features;
+        beta_features = beta_features
+      }
+
+    let of_package pkg =
+      create
+        pkg.OASISTypes.oasis_version
+        pkg.OASISTypes.alpha_features
+        pkg.OASISTypes.beta_features
+
+    let add_plugin (plugin_kind, plugin_name, plugin_version) t =
+      {t with
+           plugin_versions = MapPlugin.add
+                               (plugin_kind, plugin_name)
+                               plugin_version
+                               t.plugin_versions}
+
+    let plugin_version plugin_kind plugin_name t =
+      MapPlugin.find (plugin_kind, plugin_name) t.plugin_versions
+  end
+
+  type origin =
+    | Field of string * string
+    | Section of string
+    | NoOrigin
+
+  type stage = Alpha | Beta
+
+
+  let string_of_stage =
+    function
+      | Alpha -> "alpha"
+      | Beta -> "beta"
+
+
+  let field_of_stage =
+    function
+      | Alpha -> "AlphaFeatures"
+      | Beta -> "BetaFeatures"
+
+  type publication = InDev of stage | SinceVersion of OASISVersion.t
+
+  type t =
+      {
+        name: string;
+        plugin: all_plugin option;
+        publication: publication;
+        description: unit -> string;
+      }
+
+  (* TODO: mutex protect this. *)
+  let all_features = Hashtbl.create 13
+
+
+  let since_version ver_str = SinceVersion (version_of_string ver_str)
+  let alpha = InDev Alpha
+  let beta = InDev Beta
+
+
+  let data_check t data origin =
+    let no_message = "no message" in
+
+    let check_feature features stage =
+      let has_feature = List.mem t.name features in
+      if not has_feature then
+        match origin with
+          | Field (fld, where) ->
+              Some
+                (Printf.sprintf
+                   (f_ "Field %s in %s is only available when feature %s \
+                        is in field %s.")
+                   fld where t.name (field_of_stage stage))
+          | Section sct ->
+              Some
+                (Printf.sprintf
+                   (f_ "Section %s is only available when features %s \
+                        is in field %s.")
+                   sct t.name (field_of_stage stage))
+          | NoOrigin ->
+              Some no_message
+      else
+        None
+    in
+
+    let version_is_good ~min_version version fmt =
+      let version_is_good =
+        OASISVersion.comparator_apply
+          version (OASISVersion.VGreaterEqual min_version)
+      in
+        Printf.ksprintf
+          (fun str ->
+             if version_is_good then
+               None
+             else
+               Some str)
+          fmt
+    in
+
+    match origin, t.plugin, t.publication with
+      | _, _, InDev Alpha -> check_feature data.Data.alpha_features Alpha
+      | _, _, InDev Beta -> check_feature data.Data.beta_features Beta
+      | Field(fld, where), None, SinceVersion min_version ->
+          version_is_good ~min_version data.Data.oasis_version
+            (f_ "Field %s in %s is only valid since OASIS v%s, update \
+                 OASISFormat field from '%s' to '%s' after checking \
+                 OASIS changelog.")
+            fld where (string_of_version min_version)
+            (string_of_version data.Data.oasis_version)
+            (string_of_version min_version)
+
+      | Field(fld, where), Some(plugin_knd, plugin_name, _),
+        SinceVersion min_version ->
+          begin
+            try
+              let plugin_version_current =
+                try
+                  match Data.plugin_version plugin_knd plugin_name data with
+                    | Some ver -> ver
+                    | None ->
+                        failwithf
+                          (f_ "Field %s in %s is only valid for the OASIS \
+                               plugin %s since v%s, but no plugin version is \
+                               defined in the _oasis file, change '%s' to \
+                               '%s (%s)' in your _oasis file.")
+                          fld where plugin_name (string_of_version min_version)
+                          plugin_name
+                          plugin_name (string_of_version min_version)
+                with Not_found ->
+                  failwithf
+                    (f_ "Field %s in %s is only valid when the OASIS plugin %s \
+                         is defined.")
+                    fld where plugin_name
+              in
+              version_is_good ~min_version plugin_version_current
+                (f_ "Field %s in %s is only valid for the OASIS plugin %s \
+                     since v%s, update your plugin from '%s (%s)' to \
+                     '%s (%s)' after checking the plugin's changelog.")
+                fld where plugin_name (string_of_version min_version)
+                plugin_name (string_of_version plugin_version_current)
+                plugin_name (string_of_version min_version)
+            with Failure msg ->
+              Some msg
+          end
+
+      | Section sct, None, SinceVersion min_version ->
+          version_is_good ~min_version data.Data.oasis_version
+            (f_ "Section %s is only valid for since OASIS v%s, update \
+                 OASISFormat field from '%s' to '%s' after checking OASIS \
+                 changelog.")
+            sct (string_of_version min_version)
+            (string_of_version data.Data.oasis_version)
+            (string_of_version min_version)
+
+      | Section sct, Some(plugin_knd, plugin_name, _),
+        SinceVersion min_version ->
+          begin
+            try
+              let plugin_version_current =
+                try
+                  match Data.plugin_version plugin_knd plugin_name data with
+                    | Some ver -> ver
+                    | None ->
+                        failwithf
+                          (f_ "Section %s is only valid for the OASIS \
+                               plugin %s since v%s, but no plugin version is \
+                               defined in the _oasis file, change '%s' to \
+                               '%s (%s)' in your _oasis file.")
+                          sct plugin_name (string_of_version min_version)
+                          plugin_name
+                          plugin_name (string_of_version min_version)
+                with Not_found ->
+                  failwithf
+                    (f_ "Section %s is only valid when the OASIS plugin %s \
+                         is defined.")
+                    sct plugin_name
+              in
+              version_is_good ~min_version plugin_version_current
+                (f_ "Section %s is only valid for the OASIS plugin %s \
+                     since v%s, update your plugin from '%s (%s)' to \
+                     '%s (%s)' after checking the plugin's changelog.")
+                sct plugin_name (string_of_version min_version)
+                plugin_name (string_of_version plugin_version_current)
+                plugin_name (string_of_version min_version)
+            with Failure msg ->
+              Some msg
+          end
+
+      | NoOrigin, None, SinceVersion min_version ->
+          version_is_good ~min_version data.Data.oasis_version "%s" no_message
+
+      | NoOrigin, Some(plugin_knd, plugin_name, _), SinceVersion min_version ->
+          begin
+            try
+              let plugin_version_current =
+                match Data.plugin_version plugin_knd plugin_name data with
+                  | Some ver -> ver
+                  | None -> raise Not_found
+              in
+              version_is_good ~min_version plugin_version_current
+                "%s" no_message
+            with Not_found ->
+              Some no_message
+          end
+
+
+  let data_assert t data origin =
+    match data_check t data origin with
+      | None -> ()
+      | Some str -> failwith str
+
+
+  let data_test t data =
+    match data_check t data NoOrigin with
+      | None -> true
+      | Some str -> false
+
+
+  let package_test t pkg =
+    data_test t (Data.of_package pkg)
+
+
+  let create ?plugin name publication description =
+    let () =
+      if Hashtbl.mem all_features name then
+        failwithf "Feature '%s' is already declared." name
+    in
+    let t =
+      {
+        name = name;
+        plugin = plugin;
+        publication = publication;
+        description = description;
+      }
+    in
+      Hashtbl.add all_features name t;
+      t
+
+
+  let get_stage name =
+    try
+      (Hashtbl.find all_features name).publication
+    with Not_found ->
+      failwithf (f_ "Feature %s doesn't exist.") name
+
+
+  let list () =
+    Hashtbl.fold (fun _ v acc -> v :: acc) all_features []
+
+  (*
+   * Real flags.
+   *)
+
+
+  let features =
+    create "features_fields"
+      (since_version "0.4")
+      (fun () ->
+         s_ "Enable to experiment not yet official features.")
+
+
+  let flag_docs =
+    create "flag_docs"
+      (since_version "0.3")
+      (fun () ->
+         s_ "Building docs require '-docs' flag at configure.")
+
+
+  let flag_tests =
+    create "flag_tests"
+      (since_version "0.3")
+      (fun () ->
+         s_ "Running tests require '-tests' flag at configure.")
+
+
+  let pack =
+    create "pack"
+      (since_version "0.3")
+      (fun () ->
+         s_ "Allow to create packed library.")
+
+
+  let section_object =
+    create "section_object" beta
+      (fun () ->
+         s_ "Implement an object section.")
+end
+
 module OASISUnixPath = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISUnixPath.ml" *)
+(* # 22 "src/oasis/OASISUnixPath.ml" *)
+
 
   type unix_filename = string
   type unix_dirname = string
 
+
   type host_filename = string
   type host_dirname = string
 
+
   let current_dir_name = "."
 
+
   let parent_dir_name = ".."
 
+
   let is_current_dir fn =
     fn = current_dir_name || fn = ""
 
+
   let concat f1 f2 =
     if is_current_dir f1 then
       f2
       in
         f1'^"/"^f2
 
+
   let make =
     function
       | hd :: tl ->
       | [] ->
           invalid_arg "OASISUnixPath.make"
 
+
   let dirname f =
     try
       String.sub f 0 (String.rindex f '/')
     with Not_found ->
       current_dir_name
 
+
   let basename f =
     try
       let pos_start =
     with Not_found ->
       f
 
+
   let chop_extension f =
     try
       let last_dot =
     with Not_found ->
       f
 
+
   let capitalize_file f =
     let dir = dirname f in
     let base = basename f in
     concat dir (String.capitalize base)
 
+
   let uncapitalize_file f =
     let dir = dirname f in
     let base = basename f in
     concat dir (String.uncapitalize base)
 
+
 end
 
 module OASISHostPath = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISHostPath.ml" *)
+(* # 22 "src/oasis/OASISHostPath.ml" *)
 
 
   open Filename
 
+
   module Unix = OASISUnixPath
 
+
   let make =
     function
       | [] ->
       | hd :: tl ->
           List.fold_left Filename.concat hd tl
 
+
   let of_unix ufn =
     if Sys.os_type = "Unix" then
       ufn
 end
 
 module OASISSection = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISSection.ml" *)
+(* # 22 "src/oasis/OASISSection.ml" *)
+
 
   open OASISTypes
 
-  let section_kind_common = 
+
+  let section_kind_common =
     function
-      | Library (cs, _, _) -> 
+      | Library (cs, _, _) ->
           `Library, cs
+      | Object (cs, _, _) ->
+          `Object, cs
       | Executable (cs, _, _) ->
           `Executable, cs
       | Flag (cs, _) ->
       | Doc (cs, _) ->
           `Doc, cs
 
+
   let section_common sct =
     snd (section_kind_common sct)
 
+
   let section_common_set cs =
     function
       | Library (_, bs, lib)     -> Library (cs, bs, lib)
+      | Object (_, bs, obj)      -> Object (cs, bs, obj)
       | Executable (_, bs, exec) -> Executable (cs, bs, exec)
       | Flag (_, flg)            -> Flag (cs, flg)
       | SrcRepo (_, src_repo)    -> SrcRepo (cs, src_repo)
       | Test (_, tst)            -> Test (cs, tst)
       | Doc (_, doc)             -> Doc (cs, doc)
 
+
   (** Key used to identify section
     *)
-  let section_id sct = 
-    let k, cs = 
+  let section_id sct =
+    let k, cs =
       section_kind_common sct
     in
       k, cs.cs_name
 
+
   let string_of_section sct =
     let k, nm =
       section_id sct
     in
       (match k with
-         | `Library    -> "library" 
+         | `Library    -> "library"
+         | `Object     -> "object"
          | `Executable -> "executable"
          | `Flag       -> "flag"
          | `SrcRepo    -> "src repository"
          | `Doc        -> "doc")
       ^" "^nm
 
+
   let section_find id scts =
     List.find
       (fun sct -> id = section_id sct)
       scts
 
+
   module CSection =
   struct
     type t = section
 
     let id = section_id
 
-    let compare t1 t2 = 
+    let compare t1 t2 =
       compare (id t1) (id t2)
-      
+
     let equal t1 t2 =
       (id t1) = (id t2)
 
       Hashtbl.hash (id t)
   end
 
+
   module MapSection = Map.Make(CSection)
   module SetSection = Set.Make(CSection)
 
+
 end
 
 module OASISBuildSection = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISBuildSection.ml" *)
+(* # 22 "src/oasis/OASISBuildSection.ml" *)
+
 
 end
 
 module OASISExecutable = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISExecutable.ml" *)
+(* # 22 "src/oasis/OASISExecutable.ml" *)
+
 
   open OASISTypes
 
-  let unix_exec_is (cs, bs, exec) is_native ext_dll suffix_program = 
-    let dir = 
+
+  let unix_exec_is (cs, bs, exec) is_native ext_dll suffix_program =
+    let dir =
       OASISUnixPath.concat
         bs.bs_path
         (OASISUnixPath.dirname exec.exec_main_is)
     in
-    let is_native_exec = 
+    let is_native_exec =
       match bs.bs_compiled_object with
         | Native -> true
         | Best -> is_native ()
         dir
         (cs.cs_name^(suffix_program ())),
 
-      if not is_native_exec && 
-         not exec.exec_custom && 
+      if not is_native_exec &&
+         not exec.exec_custom &&
          bs.bs_c_sources <> [] then
         Some (dir^"/dll"^cs.cs_name^"_stubs"^(ext_dll ()))
       else
         None
 
+
 end
 
 module OASISLibrary = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISLibrary.ml" *)
+(* # 22 "src/oasis/OASISLibrary.ml" *)
+
 
   open OASISTypes
   open OASISUtils
   open OASISGettext
   open OASISSection
 
-  type library_name = name
-  type findlib_part_name = name
-  type 'a map_of_findlib_part_name = 'a OASISUtils.MapString.t
-
-  exception InternalLibraryNotFound of library_name
-  exception FindlibPackageNotFound of findlib_name
-
-  type group_t =
-    | Container of findlib_name * group_t list
-    | Package of (findlib_name *
-                  common_section *
-                  build_section *
-                  library *
-                  group_t list)
 
   (* Look for a module file, considering capitalization or not. *)
-  let find_module source_file_exists (cs, bs, lib) modul =
+  let find_module source_file_exists bs modul =
     let possible_base_fn =
       List.map
         (OASISUnixPath.concat bs.bs_path)
         (`No_sources possible_base_fn)
         possible_base_fn
 
+
   let source_unix_files ~ctxt (cs, bs, lib) source_file_exists =
     List.fold_left
       (fun acc modul ->
-         match find_module source_file_exists (cs, bs, lib) modul with
+         match find_module source_file_exists bs modul with
            | `Sources (base_fn, lst) ->
                (base_fn, lst) :: acc
            | `No_sources _ ->
       []
       (lib.lib_modules @ lib.lib_internal_modules)
 
+
   let generated_unix_files
         ~ctxt
         ~is_native
         ~source_file_exists
         (cs, bs, lib) =
 
-    let find_modules lst ext = 
+    let find_modules lst ext =
       let find_module modul =
-        match find_module source_file_exists (cs, bs, lib) modul with
+        match find_module source_file_exists bs modul with
+          | `Sources (base_fn, [fn]) when ext <> "cmi"
+                                       && Filename.check_suffix fn ".mli" ->
+              None (* No implementation files for pure interface. *)
           | `Sources (base_fn, _) ->
-              [base_fn]
+              Some [base_fn]
           | `No_sources lst ->
               OASISMessage.warning
                 ~ctxt
                 (f_ "Cannot find source file matching \
                      module '%s' in library %s")
                 modul cs.cs_name;
-              lst
+              Some lst
       in
-      List.map 
-        (fun nm -> 
-           List.map 
-             (fun base_fn -> base_fn ^"."^ext)
-             (find_module nm))
+      List.fold_left
+        (fun acc nm ->
+          match find_module nm with
+            | None -> acc
+            | Some base_fns ->
+                List.map (fun base_fn -> base_fn ^"."^ext) base_fns :: acc)
+        []
         lst
     in
 
     (* The .cmx that be compiled along *)
     let cmxs =
       let should_be_built =
-        (not lib.lib_pack) && (* Do not install .cmx packed submodules *)
         match bs.bs_compiled_object with
           | Native -> true
           | Best -> is_native
           | Byte -> false
       in
         if should_be_built then
-          find_modules
-            (lib.lib_modules @ lib.lib_internal_modules)
-            "cmx"
+          if lib.lib_pack then
+            find_modules
+              [cs.cs_name]
+              "cmx"
+          else
+            find_modules
+              (lib.lib_modules @ lib.lib_internal_modules)
+              "cmx"
         else
           []
     in
         add_pack_header ([cs.cs_name^".cma"] :: acc)
       in
       let native acc =
-        let acc = 
+        let acc =
           add_pack_header
             (if has_native_dynlink then
                [cs.cs_name^".cmxs"] :: acc
            acc_nopath)
         (headers @ cmxs)
 
-  type data = common_section * build_section * library
+
+end
+
+module OASISObject = struct
+(* # 22 "src/oasis/OASISObject.ml" *)
+
+
+  open OASISTypes
+  open OASISGettext
+
+
+  let source_unix_files ~ctxt (cs, bs, obj) source_file_exists =
+    List.fold_left
+      (fun acc modul ->
+         match OASISLibrary.find_module source_file_exists bs modul with
+           | `Sources (base_fn, lst) ->
+               (base_fn, lst) :: acc
+           | `No_sources _ ->
+               OASISMessage.warning
+                 ~ctxt
+                 (f_ "Cannot find source file matching \
+                      module '%s' in object %s")
+                 modul cs.cs_name;
+               acc)
+      []
+      obj.obj_modules
+
+
+  let generated_unix_files
+        ~ctxt
+        ~is_native
+        ~source_file_exists
+        (cs, bs, obj) =
+
+    let find_module ext modul =
+      match OASISLibrary.find_module source_file_exists bs modul with
+        | `Sources (base_fn, _) -> [base_fn ^ ext]
+        | `No_sources lst ->
+          OASISMessage.warning
+            ~ctxt
+            (f_ "Cannot find source file matching \
+                 module '%s' in object %s")
+            modul cs.cs_name ;
+          lst
+    in
+
+    let header, byte, native, c_object, f =
+      match obj.obj_modules with
+        | [ m ] -> (find_module ".cmi" m,
+                    find_module ".cmo" m,
+                    find_module ".cmx" m,
+                    find_module ".o" m,
+                    fun x -> x)
+        | _ -> ([cs.cs_name ^ ".cmi"],
+                [cs.cs_name ^ ".cmo"],
+                [cs.cs_name ^ ".cmx"],
+                [cs.cs_name ^ ".o"],
+                OASISUnixPath.concat bs.bs_path)
+    in
+      List.map (List.map f) (
+        match bs.bs_compiled_object with
+          | Native ->
+              native :: c_object :: byte :: header :: []
+          | Best when is_native ->
+              native :: c_object :: byte :: header :: []
+          | Byte | Best ->
+              byte :: header :: [])
+
+
+end
+
+module OASISFindlib = struct
+(* # 22 "src/oasis/OASISFindlib.ml" *)
+
+
+  open OASISTypes
+  open OASISUtils
+  open OASISGettext
+  open OASISSection
+
+
+  type library_name = name
+  type findlib_part_name = name
+  type 'a map_of_findlib_part_name = 'a OASISUtils.MapString.t
+
+
+  exception InternalLibraryNotFound of library_name
+  exception FindlibPackageNotFound of findlib_name
+
+
+  type group_t =
+    | Container of findlib_name * group_t list
+    | Package of (findlib_name *
+                  common_section *
+                  build_section *
+                  [`Library of library | `Object of object_] *
+                  group_t list)
+
+
+  type data = common_section *
+              build_section *
+              [`Library of library | `Object of object_]
   type tree =
     | Node of (data option) * (tree MapString.t)
     | Leaf of data
 
+
   let findlib_mapping pkg =
     (* Map from library name to either full findlib name or parts + parent. *)
     let fndlb_parts_of_lib_name =
                                mp
                    end
 
+               | Object (cs, _, obj) ->
+                   begin
+                     let obj_name = cs.cs_name in
+                     if MapString.mem obj_name mp then
+                       failwithf
+                         (f_ "The object name '%s' is used more than once.")
+                         obj_name;
+                     let findlib_full_name = match obj.obj_findlib_fullname with
+                       | Some ns -> String.concat "." ns
+                       | None -> obj_name
+                     in
+                     MapString.add
+                       obj_name
+                       (`Solved findlib_full_name)
+                       mp
+                   end
+
                | Executable _ | Test _ | Flag _ | SrcRepo _ | Doc _ ->
                    mp)
           MapString.empty
         let lib_name = cs.cs_name in
           findlib_name_of_library_name lib_name
       in
-      let rec add_children nm_lst (children : tree MapString.t) =
+      let rec add_children nm_lst (children: tree MapString.t) =
         match nm_lst with
           | (hd :: tl) ->
               begin
         (fun mp ->
            function
              | Library (cs, bs, lib) ->
-                 add (cs, bs, lib) mp
+                 add (cs, bs, `Library lib) mp
+             | Object (cs, bs, obj) ->
+                 add (cs, bs, `Object obj) mp
              | _ ->
                  mp)
         MapString.empty
       findlib_name_of_library_name,
       library_name_of_findlib_name
 
+
   let findlib_of_group =
     function
       | Container (fndlb_nm, _)
       | Package (fndlb_nm, _, _, _, _) -> fndlb_nm
 
+
   let root_of_group grp =
     let rec root_lib_aux =
       (* We do a DFS in the group. *)
               (f_ "Unable to determine root library of findlib library '%s'")
               (findlib_of_group grp)
 
+
 end
 
 module OASISFlag = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISFlag.ml" *)
+(* # 22 "src/oasis/OASISFlag.ml" *)
+
 
 end
 
 module OASISPackage = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISPackage.ml" *)
+(* # 22 "src/oasis/OASISPackage.ml" *)
+
 
 end
 
 module OASISSourceRepository = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISSourceRepository.ml" *)
+(* # 22 "src/oasis/OASISSourceRepository.ml" *)
+
 
 end
 
 module OASISTest = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISTest.ml" *)
+(* # 22 "src/oasis/OASISTest.ml" *)
+
 
 end
 
 module OASISDocument = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISDocument.ml" *)
+(* # 22 "src/oasis/OASISDocument.ml" *)
+
 
 end
 
 module OASISExec = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISExec.ml" *)
+(* # 22 "src/oasis/OASISExec.ml" *)
+
 
   open OASISGettext
   open OASISUtils
   open OASISMessage
 
+
   (* TODO: I don't like this quote, it is there because $(rm) foo expands to
    * 'rm -f' foo...
    *)
         | Some f, i ->
             f i
 
+
   let run_read_output ~ctxt ?f_exit_code cmd args =
     let fn =
       Filename.temp_file "oasis-" ".txt"
         (try Sys.remove fn with _ -> ());
         raise e
 
+
   let run_read_one_line ~ctxt ?f_exit_code cmd args =
     match run_read_output ~ctxt ?f_exit_code cmd args with
       | [fst] ->
 end
 
 module OASISFileUtil = struct
-(* # 21 "/Users/mmottl/local/darwin11.3.0/src/oasis-0.3.0/src/oasis/OASISFileUtil.ml" *)
+(* # 22 "src/oasis/OASISFileUtil.ml" *)
+
 
   open OASISGettext
 
+
   let file_exists_case fn =
     let dirname = Filename.dirname fn in